Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(373)

Side by Side Diff: runtime/vm/flow_graph_builder.h

Issue 9414003: Initial implementation of a flow-graph builder for Dart's AST. (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: Rely on assumption that code can reach both branches of a condition. Created 8 years, 10 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « runtime/vm/compiler.cc ('k') | runtime/vm/flow_graph_builder.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
(Empty)
1 // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file
2 // for details. All rights reserved. Use of this source code is governed by a
3 // BSD-style license that can be found in the LICENSE file.
4
5 #ifndef VM_FLOW_GRAPH_BUILDER_H_
6 #define VM_FLOW_GRAPH_BUILDER_H_
7
8 #include "vm/allocation.h"
9 #include "vm/ast.h"
10 #include "vm/growable_array.h"
11 #include "vm/intermediate_language.h"
12
13 namespace dart {
14
15 class Instruction;
16 class ParsedFunction;
17
18 // Build a flow graph from a parsed function's AST.
19 class FlowGraphBuilder: public ValueObject {
20 public:
21 explicit FlowGraphBuilder(const ParsedFunction& parsed_function)
22 : parsed_function_(parsed_function),
23 bailout_reason_(NULL),
24 postorder_() { }
25
26 void BuildGraph();
27
28 const ParsedFunction& parsed_function() const { return parsed_function_; }
29
30 bool HasBailedOut() const { return bailout_reason_ != NULL; }
31 void Bailout(const char* reason) {
32 // Cannot give a NULL reason because we use it to detect bailout.
33 ASSERT(!HasBailedOut() && (reason != NULL));
34 bailout_reason_ = reason;
35 }
36 void TraceBailout() const;
37 void PrintGraph() const;
38
39 private:
40 const ParsedFunction& parsed_function_;
41 const char* bailout_reason_;
42 GrowableArray<Instruction*> postorder_;
43 };
44
45
46 #define DEFINE_VISIT(type, name) virtual void Visit##type(type* node);
47
48 class TestGraphVisitor;
49
50 // Translate an AstNode to a control-flow graph fragment for its effects
51 // (e.g., a statement or an expression in an effect context). Implements a
52 // function from an AstNode and next temporary index to a graph fragment
53 // with a single entry and at most one exit. The fragment is represented by
54 // an (entry, exit) pair of Instruction pointers:
55 //
56 // - (NULL, NULL): an empty and open graph fragment
57 // - (i0, NULL): a closed graph fragment which has only non-local exits
58 // - (i0, i1): an open graph fragment
59 class EffectGraphVisitor : public AstNodeVisitor {
60 public:
61 EffectGraphVisitor(FlowGraphBuilder* owner, intptr_t temp_index)
62 : owner_(owner),
63 temp_index_(temp_index),
64 entry_(NULL),
65 exit_(NULL) { }
66
67 NODE_LIST(DEFINE_VISIT)
68
69 FlowGraphBuilder* owner() const { return owner_; }
70 intptr_t temp_index() const { return temp_index_; }
71 Instruction* entry() const { return entry_; }
72 Instruction* exit() const { return exit_; }
73
74 bool is_empty() const { return entry_ == NULL; }
75 bool is_open() const { return is_empty() || exit_ != NULL; }
76
77 void Bailout(const char* reason);
78
79 // Append a graph fragment to this graph. Assumes this graph is open.
80 void Append(const EffectGraphVisitor& other_fragment);
81 // Append a single instruction. Assumes this graph is open.
82 void AddInstruction(Instruction* instruction);
83
84 // Append a 'diamond' branch and join to this graph, depending on which
85 // parts are reachable. Assumes this graph is open.
86 void Join(const TestGraphVisitor& test_fragment,
87 const EffectGraphVisitor& true_fragment,
88 const EffectGraphVisitor& false_fragment);
89
90 // Append a 'while loop' test and back edge to this graph, depending on
91 // which parts are reachable. Afterward, the graph exit is the false
92 // successor of the loop condition.
93 void TieLoop(const TestGraphVisitor& test_fragment,
94 const EffectGraphVisitor& body_fragment);
95
96 protected:
97 // Implement the core part of the translation of expression node types.
98 AssertAssignableComp* TranslateAssignable(const AssignableNode& node);
99 InstanceCallComp* TranslateBinaryOp(const BinaryOpNode& node);
100 InstanceCallComp* TranslateComparison(const ComparisonNode& node);
101 StoreLocalComp* TranslateStoreLocal(const StoreLocalNode& node);
102 StaticCallComp* TranslateStaticCall(const StaticCallNode& node);
103
104 void CloseFragment() { exit_ = NULL; }
105 intptr_t AllocateTempIndex() { return temp_index_++; }
106
107 private:
108 // Helper to append a Do instruction to the graph.
109 void DoComputation(Computation* computation) {
110 AddInstruction(new DoInstr(computation));
111 }
112
113 // Shared global state.
114 FlowGraphBuilder* owner_;
115
116 // Input parameters.
117 intptr_t temp_index_;
118
119 // Output parameters.
120 Instruction* entry_;
121 Instruction* exit_;
122 };
123
124
125 // Translate an AstNode to a control-flow graph fragment for both its effects
126 // and value (e.g., for an expression in a value context). Implements a
127 // function from an AstNode and next temporary index to a graph fragment (as
128 // in the EffectGraphVisitor), a next temporary index, and an intermediate
129 // language Value.
130 class ValueGraphVisitor : public EffectGraphVisitor {
131 public:
132 ValueGraphVisitor(FlowGraphBuilder* owner, intptr_t temp_index)
133 : EffectGraphVisitor(owner, temp_index), value_(NULL) { }
134
135 NODE_LIST(DEFINE_VISIT)
136
137 Value* value() const { return value_; }
138
139 private:
140 // Helper to set the output state to return a Value.
141 void ReturnValue(Value* value) { value_ = value; }
142
143 // Helper to append a Bind instruction to the graph and return its
144 // temporary value (i.e., set the output parameters).
145 void ReturnValueOf(Computation* computation) {
146 AddInstruction(new BindInstr(temp_index(), computation));
147 value_ = new TempValue(AllocateTempIndex());
148 }
149
150 // Output parameters.
151 Value* value_;
152 };
153
154
155 // Translate an AstNode to a control-flow graph fragment for both its
156 // effects and true/false control flow (e.g., for an expression in a test
157 // context). The resulting graph is always closed (even if it is empty)
158 // Successor control flow is explicitly set by a pair of pointers to
159 // TargetEntryInstr*.
160 //
161 // To distinguish between the graphs with only nonlocal exits and graphs
162 // with both true and false exits, there are a pair of TargetEntryInstr**:
163 //
164 // - Both NULL: only non-local exits, truly closed
165 // - Neither NULL: true and false successors at the given addresses
166 //
167 // We expect that AstNode in test contexts either have only nonlocal exits
168 // or else control flow has both true and false successors.
169 class TestGraphVisitor : public EffectGraphVisitor {
170 public:
171 TestGraphVisitor(FlowGraphBuilder* owner, intptr_t temp_index)
172 : EffectGraphVisitor(owner, temp_index),
173 true_successor_address_(NULL),
174 false_successor_address_(NULL) {
175 }
176
177 NODE_LIST(DEFINE_VISIT)
178
179 bool can_be_true() const {
180 // Either both successors are set or neither is set.
181 ASSERT((true_successor_address_ == NULL) ==
182 (false_successor_address_ == NULL));
183 return true_successor_address_ != NULL;
184 }
185 bool can_be_false() const {
186 // Either both successors are set or neither is set.
187 ASSERT((true_successor_address_ == NULL) ==
188 (false_successor_address_ == NULL));
189 return false_successor_address_ != NULL;
190 }
191
192 TargetEntryInstr** true_successor_address() const {
193 ASSERT(can_be_true());
194 return true_successor_address_;
195 }
196 TargetEntryInstr** false_successor_address() const {
197 ASSERT(can_be_false());
198 return false_successor_address_;
199 }
200
201 private:
202 // Construct and concatenate a Branch instruction to this graph fragment.
203 // Closes the fragment and sets the output parameters.
204 void BranchOnValue(Value* value);
205
206 // Helper to bind a computation and branch on its value.
207 void BranchOnValueOf(Computation* computation) {
208 AddInstruction(new BindInstr(temp_index(), computation));
209 BranchOnValue(new TempValue(temp_index()));
210 }
211
212 // Output parameters.
213 TargetEntryInstr** true_successor_address_;
214 TargetEntryInstr** false_successor_address_;
215 };
216
217 #undef DEFINE_VISIT
218
219
220 } // namespace dart
221
222 #endif // VM_FLOW_GRAPH_BUILDER_H_
OLDNEW
« no previous file with comments | « runtime/vm/compiler.cc ('k') | runtime/vm/flow_graph_builder.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698