Build the Control Flow Graph
(List<Instruction> instructions)
| 87 | * Build the Control Flow Graph |
| 88 | */ |
| 89 | public DirectedGraph<BasicBlock> build(List<Instruction> instructions) { |
| 90 | // Map of label & basic blocks which are waiting for a bb with that label |
| 91 | Map<Label, List<BasicBlock>> forwardRefs = new HashMap<Label, List<BasicBlock>>(); |
| 92 | |
| 93 | // List of bbs that have a 'return' instruction |
| 94 | List<BasicBlock> returnBBs = new ArrayList<BasicBlock>(); |
| 95 | |
| 96 | // List of bbs that have a 'throw' instruction |
| 97 | List<BasicBlock> exceptionBBs = new ArrayList<BasicBlock>(); |
| 98 | |
| 99 | // Stack of nested rescue regions |
| 100 | Stack<ExceptionRegion> nestedExceptionRegions = new Stack<ExceptionRegion>(); |
| 101 | |
| 102 | // List of all rescued regions |
| 103 | List<ExceptionRegion> allExceptionRegions = new ArrayList<ExceptionRegion>(); |
| 104 | |
| 105 | // Dummy entry basic block (see note at end to see why) |
| 106 | entryBB = createBB(nestedExceptionRegions); |
| 107 | |
| 108 | // First real bb |
| 109 | BasicBlock firstBB = createBB(nestedExceptionRegions); |
| 110 | |
| 111 | // Build the rest! |
| 112 | BasicBlock currBB = firstBB; |
| 113 | BasicBlock newBB; |
| 114 | boolean bbEnded = false; |
| 115 | boolean nextBBIsFallThrough = true; |
| 116 | for (Instruction i : instructions) { |
| 117 | if (i instanceof LabelInstr) { |
| 118 | Label l = ((LabelInstr) i).getLabel(); |
| 119 | newBB = createBB(l, nestedExceptionRegions); |
| 120 | |
| 121 | // Jump instruction bbs dont add an edge to the succeeding bb by default |
| 122 | if (nextBBIsFallThrough) graph.addEdge(currBB, newBB, EdgeType.FALL_THROUGH); |
| 123 | currBB = newBB; |
| 124 | bbEnded = false; |
| 125 | nextBBIsFallThrough = true; |
| 126 | |
| 127 | // Add forward reference edges |
| 128 | List<BasicBlock> frefs = forwardRefs.get(l); |
| 129 | if (frefs != null) { |
| 130 | for (BasicBlock b : frefs) { |
| 131 | graph.addEdge(b, newBB, EdgeType.REGULAR); |
| 132 | } |
| 133 | } |
| 134 | } else if (bbEnded && !(i instanceof ExceptionRegionEndMarker)) { |
| 135 | newBB = createBB(nestedExceptionRegions); |
| 136 | // Jump instruction bbs dont add an edge to the succeeding bb by default |
| 137 | if (nextBBIsFallThrough) graph.addEdge(currBB, newBB, EdgeType.FALL_THROUGH); // currBB cannot be null! |
| 138 | currBB = newBB; |
| 139 | bbEnded = false; |
| 140 | nextBBIsFallThrough = true; |
| 141 | } |
| 142 | |
| 143 | if (i instanceof ExceptionRegionStartMarker) { |
| 144 | // We dont need the instruction anymore -- so it is not added to the CFG. |
| 145 | ExceptionRegionStartMarker ersmi = (ExceptionRegionStartMarker) i; |
| 146 | ExceptionRegion rr = new ExceptionRegion(ersmi.getLabel(), currBB); |
no test coverage detected