Index: pkg/compiler/lib/src/ssa/graph_builder.dart |
diff --git a/pkg/compiler/lib/src/ssa/graph_builder.dart b/pkg/compiler/lib/src/ssa/graph_builder.dart |
new file mode 100644 |
index 0000000000000000000000000000000000000000..9da63208c2044172a5841a8c2d695b884f1eb75e |
--- /dev/null |
+++ b/pkg/compiler/lib/src/ssa/graph_builder.dart |
@@ -0,0 +1,87 @@ |
+// Copyright (c) 2016, 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. |
+ |
+import 'nodes.dart'; |
+ |
+/// Base class for objects that build up an SSA graph. |
+/// |
+/// This contains helpers for building the graph and tracking information about |
+/// the current state of the graph being built. |
+abstract class GraphBuilder { |
+ /// Holds the resulting SSA graph. |
+ final HGraph graph = new HGraph(); |
+ |
+ HBasicBlock _current; |
+ |
+ /// The current block to add instructions to. Might be null, if we are |
+ /// visiting dead code, but see [isReachable]. |
+ HBasicBlock get current => _current; |
+ |
+ void set current(c) { |
+ isReachable = c != null; |
+ _current = c; |
+ } |
+ |
+ /// The most recently opened block. Has the same value as [current] while |
+ /// the block is open, but unlike [current], it isn't cleared when the |
+ /// current block is closed. |
+ HBasicBlock lastOpenedBlock; |
+ |
+ /// Indicates whether the current block is dead (because it has a throw or a |
+ /// return further up). If this is false, then [current] may be null. If the |
+ /// block is dead then it may also be aborted, but for simplicity we only |
+ /// abort on statement boundaries, not in the middle of expressions. See |
+ /// [isAborted]. |
+ bool isReachable = true; |
+ |
+ HBasicBlock addNewBlock() { |
+ HBasicBlock block = graph.addNewBlock(); |
+ // If adding a new block during building of an expression, it is due to |
+ // conditional expressions or short-circuit logical operators. |
+ return block; |
+ } |
+ |
+ void open(HBasicBlock block) { |
+ block.open(); |
+ current = block; |
+ lastOpenedBlock = block; |
+ } |
+ |
+ HBasicBlock close(HControlFlow end) { |
+ HBasicBlock result = current; |
+ current.close(end); |
+ current = null; |
+ return result; |
+ } |
+ |
+ HBasicBlock closeAndGotoExit(HControlFlow end) { |
+ HBasicBlock result = current; |
+ current.close(end); |
+ current = null; |
+ result.addSuccessor(graph.exit); |
+ return result; |
+ } |
+ |
+ void goto(HBasicBlock from, HBasicBlock to) { |
+ from.close(new HGoto()); |
+ from.addSuccessor(to); |
+ } |
+ |
+ bool isAborted() { |
+ return current == null; |
+ } |
+ |
+ /// Creates a new block, transitions to it from any current block, and |
+ /// opens the new block. |
+ HBasicBlock openNewBlock() { |
+ HBasicBlock newBlock = addNewBlock(); |
+ if (!isAborted()) goto(current, newBlock); |
+ open(newBlock); |
+ return newBlock; |
+ } |
+ |
+ void add(HInstruction instruction) { |
+ current.add(instruction); |
+ } |
+} |