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),
66f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch        break_environment_(nullptr),
67f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch        assigned_(nullptr) {}
68b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
69b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Primitive control commands.
70014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  void BeginLoop(BitVector* assigned, bool is_osr = false);
71014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  void Continue();
72b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  void EndBody();
73b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  void EndLoop();
74b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
75014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  // Primitive support for break.
76014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  void Break() final;
77b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
78f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  // Loop exit support. Used to introduce explicit loop exit control
79f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  // node and variable markers.
80f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  void ExitLoop(Node** extra_value_to_rename = nullptr);
81f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch
82014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  // Compound control commands for conditional break.
83b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  void BreakUnless(Node* condition);
84014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  void BreakWhen(Node* condition);
85b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
86b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch private:
87b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Environment* loop_environment_;      // Environment of the loop header.
88b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Environment* continue_environment_;  // Environment after the loop body.
89b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Environment* break_environment_;     // Environment after the loop exits.
90f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  BitVector* assigned_;                // Assigned values in the environment.
91b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch};
92b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
93b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
94b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// Tracks control flow for a switch statement.
95014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochclass SwitchBuilder final : public ControlBuilder {
96b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch public:
97014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  explicit SwitchBuilder(AstGraphBuilder* builder, int case_count)
98b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      : ControlBuilder(builder),
99014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        body_environment_(nullptr),
100014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        label_environment_(nullptr),
101014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        break_environment_(nullptr),
102b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        body_environments_(case_count, zone()) {}
103b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
104b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Primitive control commands.
105b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  void BeginSwitch();
106b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  void BeginLabel(int index, Node* condition);
107b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  void EndLabel();
108b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  void DefaultAt(int index);
109b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  void BeginCase(int index);
110b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  void EndCase();
111b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  void EndSwitch();
112b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
113b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Primitive support for break.
114014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  void Break() final;
115b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
116b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // The number of cases within a switch is statically known.
117958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  size_t case_count() const { return body_environments_.size(); }
118b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
119b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch private:
120b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Environment* body_environment_;   // Environment after last case body.
121b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Environment* label_environment_;  // Environment for next label condition.
122b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Environment* break_environment_;  // Environment after the switch exits.
123958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  ZoneVector<Environment*> body_environments_;
124b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch};
125b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
126b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
127b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// Tracks control flow for a block statement.
128014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochclass BlockBuilder final : public ControlBuilder {
129b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch public:
130014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  explicit BlockBuilder(AstGraphBuilder* builder)
131014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      : ControlBuilder(builder), break_environment_(nullptr) {}
132b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
133b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Primitive control commands.
134b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  void BeginBlock();
135b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  void EndBlock();
136b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
137b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Primitive support for break.
138014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  void Break() final;
139014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
140014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  // Compound control commands for conditional break.
141014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  void BreakWhen(Node* condition, BranchHint = BranchHint::kNone);
142014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  void BreakUnless(Node* condition, BranchHint hint = BranchHint::kNone);
143b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
144b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch private:
145b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Environment* break_environment_;  // Environment after the block exits.
146b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch};
147958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
148958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier}  // namespace compiler
149958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier}  // namespace internal
150958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier}  // namespace v8
151b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
152b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#endif  // V8_COMPILER_CONTROL_BUILDERS_H_
153