1b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// Copyright 2013 the V8 project authors. All rights reserved.
2b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// Use of this source code is governed by a BSD-style license that can be
3b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// found in the LICENSE file.
4b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
5b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#ifndef V8_COMPILER_CONTROL_BUILDERS_H_
6b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#define V8_COMPILER_CONTROL_BUILDERS_H_
7b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
8014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch#include "src/compiler/ast-graph-builder.h"
9b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#include "src/compiler/node.h"
10b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
11b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochnamespace v8 {
12b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochnamespace internal {
13b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochnamespace compiler {
14b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
15b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// Base class for all control builders. Also provides a common interface for
16014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch// control builders to handle 'break' statements when they are used to model
17014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch// breakable statements.
18b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochclass ControlBuilder {
19b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch public:
20014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  explicit ControlBuilder(AstGraphBuilder* builder) : builder_(builder) {}
21b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  virtual ~ControlBuilder() {}
22b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
23014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  // Interface for break.
24b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  virtual void Break() { UNREACHABLE(); }
25b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
26b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch protected:
27014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  typedef AstGraphBuilder Builder;
28014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  typedef AstGraphBuilder::Environment Environment;
29b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
30958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  Zone* zone() const { return builder_->local_zone(); }
31b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Environment* environment() { return builder_->environment(); }
32b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  void set_environment(Environment* env) { builder_->set_environment(env); }
33014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  Node* the_hole() const { return builder_->jsgraph()->TheHoleConstant(); }
34b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
35b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Builder* builder_;
36b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch};
37b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
38b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
39b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// Tracks control flow for a conditional statement.
40014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochclass IfBuilder final : public ControlBuilder {
41b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch public:
42014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  explicit IfBuilder(AstGraphBuilder* builder)
43b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      : ControlBuilder(builder),
44014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        then_environment_(nullptr),
45014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        else_environment_(nullptr) {}
46b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
47b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Primitive control commands.
48958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  void If(Node* condition, BranchHint hint = BranchHint::kNone);
49b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  void Then();
50b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  void Else();
51b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  void End();
52b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
53b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch private:
54b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Environment* then_environment_;  // Environment after the 'then' body.
55b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Environment* else_environment_;  // Environment for the 'else' body.
56b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch};
57b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
58b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
59b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// Tracks control flow for an iteration statement.
60014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochclass LoopBuilder final : public ControlBuilder {
61b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch public:
62014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  explicit LoopBuilder(AstGraphBuilder* builder)
63b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      : ControlBuilder(builder),
64014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        loop_environment_(nullptr),
65014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        continue_environment_(nullptr),
66014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        break_environment_(nullptr) {}
67b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
68b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Primitive control commands.
69014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  void BeginLoop(BitVector* assigned, bool is_osr = false);
70014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  void Continue();
71b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  void EndBody();
72b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  void EndLoop();
73b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
74014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  // Primitive support for break.
75014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  void Break() final;
76b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
77014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  // Compound control commands for conditional break.
78b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  void BreakUnless(Node* condition);
79014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  void BreakWhen(Node* condition);
80b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
81b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch private:
82b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Environment* loop_environment_;      // Environment of the loop header.
83b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Environment* continue_environment_;  // Environment after the loop body.
84b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Environment* break_environment_;     // Environment after the loop exits.
85b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch};
86b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
87b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
88b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// Tracks control flow for a switch statement.
89014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochclass SwitchBuilder final : public ControlBuilder {
90b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch public:
91014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  explicit SwitchBuilder(AstGraphBuilder* builder, int case_count)
92b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      : ControlBuilder(builder),
93014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        body_environment_(nullptr),
94014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        label_environment_(nullptr),
95014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        break_environment_(nullptr),
96b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        body_environments_(case_count, zone()) {}
97b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
98b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Primitive control commands.
99b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  void BeginSwitch();
100b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  void BeginLabel(int index, Node* condition);
101b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  void EndLabel();
102b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  void DefaultAt(int index);
103b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  void BeginCase(int index);
104b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  void EndCase();
105b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  void EndSwitch();
106b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
107b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Primitive support for break.
108014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  void Break() final;
109b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
110b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // The number of cases within a switch is statically known.
111958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  size_t case_count() const { return body_environments_.size(); }
112b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
113b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch private:
114b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Environment* body_environment_;   // Environment after last case body.
115b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Environment* label_environment_;  // Environment for next label condition.
116b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Environment* break_environment_;  // Environment after the switch exits.
117958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  ZoneVector<Environment*> body_environments_;
118b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch};
119b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
120b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
121b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// Tracks control flow for a block statement.
122014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochclass BlockBuilder final : public ControlBuilder {
123b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch public:
124014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  explicit BlockBuilder(AstGraphBuilder* builder)
125014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      : ControlBuilder(builder), break_environment_(nullptr) {}
126b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
127b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Primitive control commands.
128b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  void BeginBlock();
129b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  void EndBlock();
130b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
131b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Primitive support for break.
132014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  void Break() final;
133014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
134014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  // Compound control commands for conditional break.
135014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  void BreakWhen(Node* condition, BranchHint = BranchHint::kNone);
136014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  void BreakUnless(Node* condition, BranchHint hint = BranchHint::kNone);
137b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
138b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch private:
139b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Environment* break_environment_;  // Environment after the block exits.
140b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch};
141958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
142014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
143014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch// Tracks control flow for a try-catch statement.
144014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochclass TryCatchBuilder final : public ControlBuilder {
145014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch public:
146014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  explicit TryCatchBuilder(AstGraphBuilder* builder)
147014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      : ControlBuilder(builder),
148014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        catch_environment_(nullptr),
149014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        exit_environment_(nullptr),
150014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        exception_node_(nullptr) {}
151014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
152014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  // Primitive control commands.
153014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  void BeginTry();
154014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  void Throw(Node* exception);
155014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  void EndTry();
156014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  void EndCatch();
157014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
158014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  // Returns the exception value inside the 'catch' body.
159014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  Node* GetExceptionNode() const { return exception_node_; }
160014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
161014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch private:
162014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  Environment* catch_environment_;  // Environment for the 'catch' body.
163014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  Environment* exit_environment_;   // Environment after the statement.
164014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  Node* exception_node_;            // Node for exception in 'catch' body.
165014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch};
166014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
167014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
168014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch// Tracks control flow for a try-finally statement.
169014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochclass TryFinallyBuilder final : public ControlBuilder {
170014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch public:
171014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  explicit TryFinallyBuilder(AstGraphBuilder* builder)
172014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      : ControlBuilder(builder),
173014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        finally_environment_(nullptr),
174014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        token_node_(nullptr),
175014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        value_node_(nullptr) {}
176014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
177014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  // Primitive control commands.
178014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  void BeginTry();
179014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  void LeaveTry(Node* token, Node* value);
180014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  void EndTry(Node* token, Node* value);
181014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  void EndFinally();
182014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
183014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  // Returns the dispatch token value inside the 'finally' body.
184014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  Node* GetDispatchTokenNode() const { return token_node_; }
185014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
186014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  // Returns the saved result value inside the 'finally' body.
187014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  Node* GetResultValueNode() const { return value_node_; }
188014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
189014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch private:
190014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  Environment* finally_environment_;  // Environment for the 'finally' body.
191014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  Node* token_node_;                  // Node for token in 'finally' body.
192014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  Node* value_node_;                  // Node for value in 'finally' body.
193014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch};
194014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
195958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier}  // namespace compiler
196958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier}  // namespace internal
197958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier}  // namespace v8
198b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
199b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#endif  // V8_COMPILER_CONTROL_BUILDERS_H_
200