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

Unified 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 side-by-side diff with in-line comments
Download patch
« no previous file with comments | « runtime/vm/compiler.cc ('k') | runtime/vm/flow_graph_builder.cc » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: runtime/vm/flow_graph_builder.h
diff --git a/runtime/vm/flow_graph_builder.h b/runtime/vm/flow_graph_builder.h
new file mode 100644
index 0000000000000000000000000000000000000000..df32ae7bfe32ba3281a451798b463ca89324274a
--- /dev/null
+++ b/runtime/vm/flow_graph_builder.h
@@ -0,0 +1,222 @@
+// Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+#ifndef VM_FLOW_GRAPH_BUILDER_H_
+#define VM_FLOW_GRAPH_BUILDER_H_
+
+#include "vm/allocation.h"
+#include "vm/ast.h"
+#include "vm/growable_array.h"
+#include "vm/intermediate_language.h"
+
+namespace dart {
+
+class Instruction;
+class ParsedFunction;
+
+// Build a flow graph from a parsed function's AST.
+class FlowGraphBuilder: public ValueObject {
+ public:
+ explicit FlowGraphBuilder(const ParsedFunction& parsed_function)
+ : parsed_function_(parsed_function),
+ bailout_reason_(NULL),
+ postorder_() { }
+
+ void BuildGraph();
+
+ const ParsedFunction& parsed_function() const { return parsed_function_; }
+
+ bool HasBailedOut() const { return bailout_reason_ != NULL; }
+ void Bailout(const char* reason) {
+ // Cannot give a NULL reason because we use it to detect bailout.
+ ASSERT(!HasBailedOut() && (reason != NULL));
+ bailout_reason_ = reason;
+ }
+ void TraceBailout() const;
+ void PrintGraph() const;
+
+ private:
+ const ParsedFunction& parsed_function_;
+ const char* bailout_reason_;
+ GrowableArray<Instruction*> postorder_;
+};
+
+
+#define DEFINE_VISIT(type, name) virtual void Visit##type(type* node);
+
+class TestGraphVisitor;
+
+// Translate an AstNode to a control-flow graph fragment for its effects
+// (e.g., a statement or an expression in an effect context). Implements a
+// function from an AstNode and next temporary index to a graph fragment
+// with a single entry and at most one exit. The fragment is represented by
+// an (entry, exit) pair of Instruction pointers:
+//
+// - (NULL, NULL): an empty and open graph fragment
+// - (i0, NULL): a closed graph fragment which has only non-local exits
+// - (i0, i1): an open graph fragment
+class EffectGraphVisitor : public AstNodeVisitor {
+ public:
+ EffectGraphVisitor(FlowGraphBuilder* owner, intptr_t temp_index)
+ : owner_(owner),
+ temp_index_(temp_index),
+ entry_(NULL),
+ exit_(NULL) { }
+
+ NODE_LIST(DEFINE_VISIT)
+
+ FlowGraphBuilder* owner() const { return owner_; }
+ intptr_t temp_index() const { return temp_index_; }
+ Instruction* entry() const { return entry_; }
+ Instruction* exit() const { return exit_; }
+
+ bool is_empty() const { return entry_ == NULL; }
+ bool is_open() const { return is_empty() || exit_ != NULL; }
+
+ void Bailout(const char* reason);
+
+ // Append a graph fragment to this graph. Assumes this graph is open.
+ void Append(const EffectGraphVisitor& other_fragment);
+ // Append a single instruction. Assumes this graph is open.
+ void AddInstruction(Instruction* instruction);
+
+ // Append a 'diamond' branch and join to this graph, depending on which
+ // parts are reachable. Assumes this graph is open.
+ void Join(const TestGraphVisitor& test_fragment,
+ const EffectGraphVisitor& true_fragment,
+ const EffectGraphVisitor& false_fragment);
+
+ // Append a 'while loop' test and back edge to this graph, depending on
+ // which parts are reachable. Afterward, the graph exit is the false
+ // successor of the loop condition.
+ void TieLoop(const TestGraphVisitor& test_fragment,
+ const EffectGraphVisitor& body_fragment);
+
+ protected:
+ // Implement the core part of the translation of expression node types.
+ AssertAssignableComp* TranslateAssignable(const AssignableNode& node);
+ InstanceCallComp* TranslateBinaryOp(const BinaryOpNode& node);
+ InstanceCallComp* TranslateComparison(const ComparisonNode& node);
+ StoreLocalComp* TranslateStoreLocal(const StoreLocalNode& node);
+ StaticCallComp* TranslateStaticCall(const StaticCallNode& node);
+
+ void CloseFragment() { exit_ = NULL; }
+ intptr_t AllocateTempIndex() { return temp_index_++; }
+
+ private:
+ // Helper to append a Do instruction to the graph.
+ void DoComputation(Computation* computation) {
+ AddInstruction(new DoInstr(computation));
+ }
+
+ // Shared global state.
+ FlowGraphBuilder* owner_;
+
+ // Input parameters.
+ intptr_t temp_index_;
+
+ // Output parameters.
+ Instruction* entry_;
+ Instruction* exit_;
+};
+
+
+// Translate an AstNode to a control-flow graph fragment for both its effects
+// and value (e.g., for an expression in a value context). Implements a
+// function from an AstNode and next temporary index to a graph fragment (as
+// in the EffectGraphVisitor), a next temporary index, and an intermediate
+// language Value.
+class ValueGraphVisitor : public EffectGraphVisitor {
+ public:
+ ValueGraphVisitor(FlowGraphBuilder* owner, intptr_t temp_index)
+ : EffectGraphVisitor(owner, temp_index), value_(NULL) { }
+
+ NODE_LIST(DEFINE_VISIT)
+
+ Value* value() const { return value_; }
+
+ private:
+ // Helper to set the output state to return a Value.
+ void ReturnValue(Value* value) { value_ = value; }
+
+ // Helper to append a Bind instruction to the graph and return its
+ // temporary value (i.e., set the output parameters).
+ void ReturnValueOf(Computation* computation) {
+ AddInstruction(new BindInstr(temp_index(), computation));
+ value_ = new TempValue(AllocateTempIndex());
+ }
+
+ // Output parameters.
+ Value* value_;
+};
+
+
+// Translate an AstNode to a control-flow graph fragment for both its
+// effects and true/false control flow (e.g., for an expression in a test
+// context). The resulting graph is always closed (even if it is empty)
+// Successor control flow is explicitly set by a pair of pointers to
+// TargetEntryInstr*.
+//
+// To distinguish between the graphs with only nonlocal exits and graphs
+// with both true and false exits, there are a pair of TargetEntryInstr**:
+//
+// - Both NULL: only non-local exits, truly closed
+// - Neither NULL: true and false successors at the given addresses
+//
+// We expect that AstNode in test contexts either have only nonlocal exits
+// or else control flow has both true and false successors.
+class TestGraphVisitor : public EffectGraphVisitor {
+ public:
+ TestGraphVisitor(FlowGraphBuilder* owner, intptr_t temp_index)
+ : EffectGraphVisitor(owner, temp_index),
+ true_successor_address_(NULL),
+ false_successor_address_(NULL) {
+ }
+
+ NODE_LIST(DEFINE_VISIT)
+
+ bool can_be_true() const {
+ // Either both successors are set or neither is set.
+ ASSERT((true_successor_address_ == NULL) ==
+ (false_successor_address_ == NULL));
+ return true_successor_address_ != NULL;
+ }
+ bool can_be_false() const {
+ // Either both successors are set or neither is set.
+ ASSERT((true_successor_address_ == NULL) ==
+ (false_successor_address_ == NULL));
+ return false_successor_address_ != NULL;
+ }
+
+ TargetEntryInstr** true_successor_address() const {
+ ASSERT(can_be_true());
+ return true_successor_address_;
+ }
+ TargetEntryInstr** false_successor_address() const {
+ ASSERT(can_be_false());
+ return false_successor_address_;
+ }
+
+ private:
+ // Construct and concatenate a Branch instruction to this graph fragment.
+ // Closes the fragment and sets the output parameters.
+ void BranchOnValue(Value* value);
+
+ // Helper to bind a computation and branch on its value.
+ void BranchOnValueOf(Computation* computation) {
+ AddInstruction(new BindInstr(temp_index(), computation));
+ BranchOnValue(new TempValue(temp_index()));
+ }
+
+ // Output parameters.
+ TargetEntryInstr** true_successor_address_;
+ TargetEntryInstr** false_successor_address_;
+};
+
+#undef DEFINE_VISIT
+
+
+} // namespace dart
+
+#endif // VM_FLOW_GRAPH_BUILDER_H_
« 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