| 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);
|
| + }
|
| +}
|
|
|