package org.dynjs.ir.representations; import java.util.ArrayList; import java.util.List; import org.dynjs.ir.Instruction; import org.dynjs.ir.operands.Label; import org.jruby.dirgra.ExplicitVertexID; public class BasicBlock implements ExplicitVertexID, Comparable { private int id; // ID of Basic Block private CFG cfg; // CFG for this BasicBlock private Label label; // All basic blocks have a starting label private List<Instruction> instructions; // List of non-label instructions private boolean isRescueEntry; // Is this basic block entry of a rescue? private Instruction[] instructionsArray; public BasicBlock(CFG cfg, Label label) { this.label = label; this.cfg = cfg; this.id = cfg.getNextBBID(); isRescueEntry = false; initInstrs(); } private void initInstrs() { instructions = new ArrayList<>(); instructionsArray = null; } @Override public int getID() { return id; } public Label getLabel() { return label; } @Override public int hashCode() { return id; } public boolean isEntryBB() { return cfg.getEntryBB() == this; } public boolean isExitBB() { return cfg.getExitBB() == this; } public void markRescueEntryBB() { this.isRescueEntry = true; } public boolean isRescueEntry() { return this.isRescueEntry; } public void addInstr(Instruction i) { instructions.add(i); } public List<Instruction> getInstructions() { return instructions; } public int instrCount() { return instructions.size(); } public Instruction[] getInstructionsArray() { if (instructionsArray == null) instructionsArray = instructions.toArray(new Instruction[instructions.size()]); return instructionsArray; } public Instruction getLastInstr() { int n = instructions.size(); return (n == 0) ? null : instructions.get(n-1); } public boolean removeInstr(Instruction i) { return i == null? false : instructions.remove(i); } public boolean isEmpty() { return instructions.isEmpty(); } @Override public int compareTo(Object o) { BasicBlock other = (BasicBlock) o; if (id == other.id) return 0; if (id < other.id) return -1; return 1; } public void swallowBB(BasicBlock foodBB) { instructions.addAll(foodBB.getInstructions()); } @Override public String toString() { return "BB [" + id + ":" + label + "]"; } public String toStringInstrs() { StringBuilder buf = new StringBuilder(toString() + "\n"); for (Instruction instr : getInstructions()) { buf.append('\t').append(instr).append('\n'); } return buf.toString(); } public String dump(String indent) { StringBuilder buf = new StringBuilder(indent + toString() + "\n"); for (Instruction instr : getInstructions()) { buf.append(instr.dump(indent + " ")).append('\n'); } return buf.toString(); } }