OLD | NEW |
(Empty) | |
| 1 // Copyright (c) 2016, 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 import 'nodes.dart'; |
| 6 |
| 7 /// Base class for objects that build up an SSA graph. |
| 8 /// |
| 9 /// This contains helpers for building the graph and tracking information about |
| 10 /// the current state of the graph being built. |
| 11 abstract class GraphBuilder { |
| 12 /// Holds the resulting SSA graph. |
| 13 final HGraph graph = new HGraph(); |
| 14 |
| 15 HBasicBlock _current; |
| 16 |
| 17 /// The current block to add instructions to. Might be null, if we are |
| 18 /// visiting dead code, but see [isReachable]. |
| 19 HBasicBlock get current => _current; |
| 20 |
| 21 void set current(c) { |
| 22 isReachable = c != null; |
| 23 _current = c; |
| 24 } |
| 25 |
| 26 /// The most recently opened block. Has the same value as [current] while |
| 27 /// the block is open, but unlike [current], it isn't cleared when the |
| 28 /// current block is closed. |
| 29 HBasicBlock lastOpenedBlock; |
| 30 |
| 31 /// Indicates whether the current block is dead (because it has a throw or a |
| 32 /// return further up). If this is false, then [current] may be null. If the |
| 33 /// block is dead then it may also be aborted, but for simplicity we only |
| 34 /// abort on statement boundaries, not in the middle of expressions. See |
| 35 /// [isAborted]. |
| 36 bool isReachable = true; |
| 37 |
| 38 HBasicBlock addNewBlock() { |
| 39 HBasicBlock block = graph.addNewBlock(); |
| 40 // If adding a new block during building of an expression, it is due to |
| 41 // conditional expressions or short-circuit logical operators. |
| 42 return block; |
| 43 } |
| 44 |
| 45 void open(HBasicBlock block) { |
| 46 block.open(); |
| 47 current = block; |
| 48 lastOpenedBlock = block; |
| 49 } |
| 50 |
| 51 HBasicBlock close(HControlFlow end) { |
| 52 HBasicBlock result = current; |
| 53 current.close(end); |
| 54 current = null; |
| 55 return result; |
| 56 } |
| 57 |
| 58 HBasicBlock closeAndGotoExit(HControlFlow end) { |
| 59 HBasicBlock result = current; |
| 60 current.close(end); |
| 61 current = null; |
| 62 result.addSuccessor(graph.exit); |
| 63 return result; |
| 64 } |
| 65 |
| 66 void goto(HBasicBlock from, HBasicBlock to) { |
| 67 from.close(new HGoto()); |
| 68 from.addSuccessor(to); |
| 69 } |
| 70 |
| 71 bool isAborted() { |
| 72 return current == null; |
| 73 } |
| 74 |
| 75 /// Creates a new block, transitions to it from any current block, and |
| 76 /// opens the new block. |
| 77 HBasicBlock openNewBlock() { |
| 78 HBasicBlock newBlock = addNewBlock(); |
| 79 if (!isAborted()) goto(current, newBlock); |
| 80 open(newBlock); |
| 81 return newBlock; |
| 82 } |
| 83 |
| 84 void add(HInstruction instruction) { |
| 85 current.add(instruction); |
| 86 } |
| 87 } |
OLD | NEW |