boolean bbEnded = false;
boolean nextBBIsFallThrough = true;
for (Instr i : instrs) {
Operation iop = i.getOperation();
if (iop == Operation.LABEL) {
Label l = ((LabelInstr) i).label;
newBB = createBB(l, nestedExceptionRegions);
// Jump instruction bbs dont add an edge to the succeeding bb by default
if (nextBBIsFallThrough) graph.addEdge(currBB, newBB, EdgeType.FALL_THROUGH);
currBB = newBB;
bbEnded = false;
nextBBIsFallThrough = true;
// Add forward reference edges
List<BasicBlock> frefs = forwardRefs.get(l);
if (frefs != null) {
for (BasicBlock b : frefs) {
graph.addEdge(b, newBB, EdgeType.REGULAR);
}
}
} else if (bbEnded && (iop != Operation.EXC_REGION_END)) {
newBB = createBB(nestedExceptionRegions);
// Jump instruction bbs dont add an edge to the succeeding bb by default
if (nextBBIsFallThrough) graph.addEdge(currBB, newBB, EdgeType.FALL_THROUGH); // currBB cannot be null!
currBB = newBB;
bbEnded = false;
nextBBIsFallThrough = true;
}
if (i instanceof ExceptionRegionStartMarkerInstr) {
// SSS: Do we need this anymore?
// currBB.addInstr(i);
ExceptionRegionStartMarkerInstr ersmi = (ExceptionRegionStartMarkerInstr) i;
ExceptionRegion rr = new ExceptionRegion(ersmi.firstRescueBlockLabel, ersmi.ensureBlockLabel);
rr.addBB(currBB);
allExceptionRegions.add(rr);
if (nestedExceptionRegions.empty()) {
outermostERs.add(rr);
} else {
nestedExceptionRegions.peek().addNestedRegion(rr);
}
nestedExceptionRegions.push(rr);
} else if (i instanceof ExceptionRegionEndMarkerInstr) {
// SSS: Do we need this anymore?
// currBB.addInstr(i);
nestedExceptionRegions.pop().setEndBB(currBB);
} else if (iop.endsBasicBlock()) {
bbEnded = true;
currBB.addInstr(i);
Label tgt;
nextBBIsFallThrough = false;
if (i instanceof BranchInstr) {
tgt = ((BranchInstr) i).getJumpTarget();
nextBBIsFallThrough = true;
} else if (i instanceof JumpInstr) {
tgt = ((JumpInstr) i).getJumpTarget();
} else if (iop.isReturn()) { // BREAK, RETURN, CLOSURE_RETURN
tgt = null;
returnBBs.add(currBB);
} else if (i instanceof ThrowExceptionInstr) {
tgt = null;
exceptionBBs.add(currBB);
} else if (i instanceof JumpIndirectInstr) {
tgt = null;
Set<Label> retAddrs = retAddrMap.get(((JumpIndirectInstr) i).getJumpTarget());
for (Label l : retAddrs) {
addEdge(currBB, l, forwardRefs);
}
// Record the target bb for the retaddr var for any set_addr instrs that appear later and use the same retaddr var
retAddrTargetMap.put(((JumpIndirectInstr) i).getJumpTarget(), currBB);
} else {
throw new RuntimeException("Unhandled case in CFG builder for basic block ending instr: " + i);
}
if (tgt != null) addEdge(currBB, tgt, forwardRefs);
} else if (iop != Operation.LABEL) {
currBB.addInstr(i);
}
if (i instanceof SetReturnAddressInstr) {
Variable v = ((SetReturnAddressInstr) i).getResult();
Label tgtLbl = ((SetReturnAddressInstr) i).getReturnAddr();
BasicBlock tgtBB = retAddrTargetMap.get(v);
// If we have the target bb, add the edge
// If not, record it for fixup later
if (tgtBB != null) {
addEdge(tgtBB, tgtLbl, forwardRefs);