use of org.mapleir.flowgraph.edges.SwitchEdge in project maple-ir by LLVM-but-worse.
the class SSAGenPass method splitBlock.
private BasicBlock splitBlock(BasicBlock b, int to) {
/* eg. split the block as follows:
*
* NAME:
* stmt1
* stmt2
* stmt3
* stmt4
* stmt5
* jump L1, L2
* [jump edge to L1]
* [jump edge to L2]
* [exception edges]
*
* split at 3, create a new block (incoming
* immediate), transfer instruction from 0
* to index into new block, create immediate
* edge to old block, clone exception edges,
* redirect pred edges.
*
* 1/9/16: we also need to modify the last
* statement of the pred blocks to
* point to NAME'.
*
* NAME':
* stmt1
* stmt2
* stmt3
* [immediate to NAME]
* NAME:
* stmt4
* stmt5
* jump L1, L2
* [jump edge to L1]
* [jump edge to L2]
* [exception edges]
*/
// split block
ControlFlowGraph cfg = builder.graph;
BasicBlock newBlock = new BasicBlock(cfg, graphSize++, new LabelNode());
b.transferUp(newBlock, to);
cfg.addVertex(newBlock);
// redo ranges
for (ExceptionRange<BasicBlock> er : cfg.getRanges()) {
if (er.containsVertex(b))
er.addVertexBefore(b, newBlock);
}
// redirect b preds into newBlock and remove them.
Set<FlowEdge<BasicBlock>> oldEdges = new HashSet<>(cfg.getReverseEdges(b));
for (FlowEdge<BasicBlock> e : oldEdges) {
BasicBlock p = e.src();
FlowEdge<BasicBlock> c;
if (e instanceof TryCatchEdge) {
// b is ehandler
TryCatchEdge<BasicBlock> tce = (TryCatchEdge<BasicBlock>) e;
if (tce.dst() != tce.erange.getHandler()) {
System.err.println(builder.method.owner + "#" + builder.method.name);
System.err.println(cfg);
System.err.println("Very odd split case. please investigate");
System.err.println("Offending postsplit block: " + b);
System.err.println("Offending newblock: " + newBlock);
System.err.println("Offending edge: " + tce);
System.err.println("Offending erange: " + tce.erange);
}
if (tce.erange.getHandler() != newBlock) {
tce.erange.setHandler(newBlock);
cfg.addEdge(tce.src(), tce.clone(tce.src(), null));
cfg.removeEdge(tce.src(), tce);
}
} else {
c = e.clone(p, newBlock);
cfg.addEdge(p, c);
cfg.removeEdge(p, e);
}
// Fix flow instruction targets
if (!p.isEmpty()) {
Stmt last = p.get(p.size() - 1);
int op = last.getOpcode();
if (e instanceof ConditionalJumpEdge) {
if (op != Opcode.COND_JUMP)
throw new IllegalArgumentException("wrong flow instruction");
ConditionalJumpStmt j = (ConditionalJumpStmt) last;
// assertTarget(last, j.getTrueSuccessor(), b);
if (j.getTrueSuccessor() == b)
j.setTrueSuccessor(newBlock);
} else if (e instanceof UnconditionalJumpEdge) {
if (op != Opcode.UNCOND_JUMP)
throw new IllegalArgumentException("wrong flow instruction");
UnconditionalJumpStmt j = (UnconditionalJumpStmt) last;
assertTarget(j, j.getTarget(), b);
j.setTarget(newBlock);
} else if (e instanceof SwitchEdge) {
if (op != Opcode.SWITCH_JUMP)
throw new IllegalArgumentException("wrong flow instruction.");
SwitchStmt s = (SwitchStmt) last;
for (Entry<Integer, BasicBlock> en : s.getTargets().entrySet()) {
BasicBlock t = en.getValue();
if (t == b) {
en.setValue(newBlock);
}
}
}
}
}
if (!checkCloneHandler(newBlock)) {
System.err.println(cfg);
System.err.println(newBlock.getDisplayName());
System.err.println(b.getDisplayName());
throw new IllegalStateException("the new block should always need a handler..?");
}
// clone exception edges
for (FlowEdge<BasicBlock> e : cfg.getEdges(b)) {
if (e.getType() == FlowEdges.TRYCATCH) {
// second param is discarded (?)
TryCatchEdge<BasicBlock> c = ((TryCatchEdge<BasicBlock>) e).clone(newBlock, null);
cfg.addEdge(newBlock, c);
}
}
// create immediate to newBlock
cfg.addEdge(newBlock, new ImmediateEdge<>(newBlock, b));
// update assigns
Set<Local> assignedLocals = new HashSet<>();
for (Stmt stmt : b) if (stmt.getOpcode() == Opcode.LOCAL_STORE)
assignedLocals.add(((CopyVarStmt) stmt).getVariable().getLocal());
for (Stmt stmt : newBlock) {
if (stmt.getOpcode() == Opcode.LOCAL_STORE) {
Local copyLocal = ((CopyVarStmt) stmt).getVariable().getLocal();
Set<BasicBlock> set = builder.assigns.get(copyLocal);
set.add(newBlock);
if (!assignedLocals.contains(copyLocal))
set.remove(b);
}
}
return newBlock;
}
use of org.mapleir.flowgraph.edges.SwitchEdge in project maple-ir by LLVM-but-worse.
the class GenerationPass method process.
protected void process(LabelNode label) {
/* it may not be properly initialised yet, however. */
BasicBlock block = builder.graph.getBlock(label);
/* if it is, we don't need to process it. */
if (block != null && finished.get(block.getNumericId())) {
return;
} else if (block == null) {
block = makeBlock(label);
} else {
// i.e. not finished.
}
preprocess(block);
/* populate instructions. */
int codeIndex = insns.indexOf(label);
finished.set(block.getNumericId());
while (codeIndex < insns.size() - 1) {
AbstractInsnNode ain = insns.get(++codeIndex);
int type = ain.type();
if (ain.opcode() != -1) {
process(block, ain);
}
if (type == LABEL) {
// split into new block
BasicBlock immediate = resolveTarget((LabelNode) ain);
builder.graph.addEdge(block, new ImmediateEdge<>(block, immediate));
break;
} else if (type == JUMP_INSN) {
JumpInsnNode jin = (JumpInsnNode) ain;
BasicBlock target = resolveTarget(jin.label);
if (jin.opcode() == JSR) {
throw new UnsupportedOperationException("jsr " + builder.method);
} else if (jin.opcode() == GOTO) {
builder.graph.addEdge(block, new UnconditionalJumpEdge<>(block, target));
} else {
builder.graph.addEdge(block, new ConditionalJumpEdge<>(block, target, jin.opcode()));
int nextIndex = codeIndex + 1;
AbstractInsnNode nextInsn = insns.get(nextIndex);
if (!(nextInsn instanceof LabelNode)) {
LabelNode newLabel = new LabelNode();
insns.insert(ain, newLabel);
nextInsn = newLabel;
}
// create immediate successor reference if it's not already done
BasicBlock immediate = resolveTarget((LabelNode) nextInsn);
builder.graph.addEdge(block, new ImmediateEdge<>(block, immediate));
}
break;
} else if (type == LOOKUPSWITCH_INSN) {
LookupSwitchInsnNode lsin = (LookupSwitchInsnNode) ain;
for (int i = 0; i < lsin.keys.size(); i++) {
BasicBlock target = resolveTarget(lsin.labels.get(i));
builder.graph.addEdge(block, new SwitchEdge<>(block, target, lsin, lsin.keys.get(i)));
}
BasicBlock dflt = resolveTarget(lsin.dflt);
builder.graph.addEdge(block, new DefaultSwitchEdge<>(block, dflt, lsin));
break;
} else if (type == TABLESWITCH_INSN) {
TableSwitchInsnNode tsin = (TableSwitchInsnNode) ain;
for (int i = tsin.min; i <= tsin.max; i++) {
BasicBlock target = resolveTarget(tsin.labels.get(i - tsin.min));
builder.graph.addEdge(block, new SwitchEdge<>(block, target, tsin, i));
}
BasicBlock dflt = resolveTarget(tsin.dflt);
builder.graph.addEdge(block, new DefaultSwitchEdge<>(block, dflt, tsin));
break;
} else if (isExitOpcode(ain.opcode())) {
break;
}
}
// TODO: check if it should have an immediate.
BasicBlock im = block.getImmediate();
if (im != null) /* && !queue.contains(im)*/
{
// System.out.println("Updating " + block.getId() + " -> " + im.getId());
// System.out.println(" Pre: " + currentStack);
update_target_stack(block, im, currentStack);
// System.out.println(" Pos: " + currentStack);
}
}
Aggregations