use of org.mapleir.ir.cfg.BasicBlock in project maple-ir by LLVM-but-worse.
the class SreedharDestructor method insertStart.
// replace the phi target xi with xi' and place a temp copy xi = xi' after all phi statements.
private Local insertStart(PhiResource res, Type type) {
BasicBlock li = res.block;
Local xi = res.local;
if (li.isEmpty())
throw new IllegalStateException("Trying to resolve phi target interference in empty block " + li);
Local spill = locals.makeLatestVersion(xi);
int i;
for (i = 0; i < li.size() && li.get(i).getOpcode() == Opcode.PHI_STORE; i++) {
CopyPhiStmt copyPhi = (CopyPhiStmt) li.get(i);
VarExpr copyTarget = copyPhi.getVariable();
if (copyTarget.getLocal() == xi)
copyTarget.setLocal(spill);
}
li.add(i, new CopyVarStmt(new VarExpr(xi, type), new VarExpr(spill, type)));
return spill;
}
use of org.mapleir.ir.cfg.BasicBlock in project maple-ir by LLVM-but-worse.
the class SreedharDestructor method buildInterference.
private void buildInterference() {
for (BasicBlock b : cfg.vertices()) {
// not a copy!
GenericBitSet<Local> in = liveness.in(b);
// not a copy!
GenericBitSet<Local> out = liveness.out(b);
// in interfere in
for (Local l : in) interfere.getNonNull(l).addAll(in);
// out interfere out
for (Local l : out) interfere.getNonNull(l).addAll(out);
// backwards traverse for dealing with variables that are defined and used in the same block
GenericBitSet<Local> intraLive = out.copy();
ListIterator<Stmt> it = b.listIterator(b.size());
while (it.hasPrevious()) {
Stmt stmt = it.previous();
if (stmt instanceof CopyVarStmt) {
CopyVarStmt copy = (CopyVarStmt) stmt;
Local defLocal = copy.getVariable().getLocal();
intraLive.remove(defLocal);
}
for (Expr child : stmt.enumerateOnlyChildren()) {
if (stmt.getOpcode() == LOCAL_LOAD) {
Local usedLocal = ((VarExpr) child).getLocal();
if (intraLive.add(usedLocal)) {
interfere.getNonNull(usedLocal).addAll(intraLive);
for (Local l : intraLive) interfere.get(l).add(usedLocal);
}
}
}
}
}
// System.out.println("Interference:");
// for (Entry<Local, GenericBitSet<Local>> entry : interfere.entrySet())
// System.out.println(" " + entry.getKey() + " : " + entry.getValue());
// System.out.println();
}
use of org.mapleir.ir.cfg.BasicBlock in project maple-ir by LLVM-but-worse.
the class SSAGenPass method aggregateInitialisers.
private void aggregateInitialisers() {
for (BasicBlock b : builder.graph.vertices()) {
for (Stmt stmt : new ArrayList<>(b)) {
if (stmt.getOpcode() == Opcode.POP) {
PopStmt pop = (PopStmt) stmt;
Expr expr = pop.getExpression();
if (expr.getOpcode() == Opcode.INVOKE) {
InvocationExpr invoke = (InvocationExpr) expr;
if (invoke.getCallType() == InvocationExpr.CallType.SPECIAL && invoke.getName().equals("<init>")) {
Expr inst = invoke.getPhysicalReceiver();
if (inst.getOpcode() == Opcode.LOCAL_LOAD) {
VarExpr var = (VarExpr) inst;
VersionedLocal local = (VersionedLocal) var.getLocal();
AbstractCopyStmt def = pool.defs.get(local);
Expr rhs = def.getExpression();
if (rhs.getOpcode() == Opcode.ALLOC_OBJ) {
// replace pop(x.<init>()) with x := new Klass();
// remove x := new Klass;
// here we are assuming that the new object
// can't be used until it is initialised.
Expr[] args = invoke.getParameterExprs();
// we want to reuse the exprs, so free it first.
pop.deleteAt(0);
Expr[] newArgs = Arrays.copyOf(args, args.length);
for (int i = args.length - 1; i >= 0; i--) {
args[i].unlink();
}
// remove the old def
def.delete();
int index = b.indexOf(pop);
// add a copy statement before the pop (x = newExpr)
InitialisedObjectExpr newExpr = new InitialisedObjectExpr(invoke.getOwner(), invoke.getDesc(), newArgs);
CopyVarStmt newCvs = new CopyVarStmt(var, newExpr);
pool.defs.put(local, newCvs);
pool.uses.get(local).remove(var);
b.add(index, newCvs);
// remove the pop statement
b.remove(pop);
// update the latestval constraints
LatestValue lval = latest.get(local);
if (lval.hasConstraints()) {
/* need to check this out (shouldn't happen) */
System.out.println("Constraints:");
for (Constraint c : lval.getConstraints()) {
System.out.println(" " + c);
}
throw new IllegalStateException(lval.toString());
} else {
lval.makeConstraints(newExpr);
}
}
} else if (inst.getOpcode() == Opcode.ALLOC_OBJ) {
// replace pop(new Klass.<init>(args)) with pop(new Klass(args))
// UninitialisedObjectExpr obj = (UninitialisedObjectExpr) inst;
Expr[] args = invoke.getParameterExprs();
// we want to reuse the exprs, so free it first.
invoke.unlink();
for (Expr e : args) {
e.unlink();
}
Expr[] newArgs = Arrays.copyOf(args, args.length);
InitialisedObjectExpr newExpr = new InitialisedObjectExpr(invoke.getOwner(), invoke.getDesc(), newArgs);
// replace pop contents
// no changes to defs or uses
pop.setExpression(newExpr);
} else {
System.err.println(b);
System.err.println("Stmt: " + stmt.getDisplayName() + ". " + stmt);
System.err.println("Inst: " + inst);
System.err.println(builder.graph);
throw new RuntimeException("interesting1 " + inst.getClass());
}
}
}
}
}
}
}
use of org.mapleir.ir.cfg.BasicBlock 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.ir.cfg.BasicBlock in project maple-ir by LLVM-but-worse.
the class SSAGenPass method splitRanges.
private void splitRanges() {
// produce cleaner cfg
List<BasicBlock> order = new ArrayList<>(builder.graph.vertices());
NullPermeableHashMap<BasicBlock, Set<Local>> splits = new NullPermeableHashMap<>(SetCreator.getInstance());
for (ExceptionRange<BasicBlock> er : builder.graph.getRanges()) {
BasicBlock h = er.getHandler();
handlers.add(h);
Set<Local> ls = new HashSet<>(liveness.in(h));
for (BasicBlock b : er.get()) {
splits.getNonNull(b).addAll(ls);
}
}
for (Entry<BasicBlock, Set<Local>> e : splits.entrySet()) {
BasicBlock b = e.getKey();
Set<Local> ls = e.getValue();
ArrayList<Stmt> stmtsCopy = new ArrayList<>(b);
int i = 0;
boolean checkSplit = false;
for (int i1 = 0; i1 < stmtsCopy.size(); i1++) {
Stmt stmt = stmtsCopy.get(i1);
if (b.size() == i)
throw new IllegalStateException("s");
if (checkSplit && stmt.getOpcode() == Opcode.LOCAL_STORE) {
CopyVarStmt copy = (CopyVarStmt) stmt;
VarExpr v = copy.getVariable();
if (ls.contains(v.getLocal())) {
BasicBlock n = splitBlock(b, i);
order.add(order.indexOf(b), n);
i = 0;
checkSplit = false;
}
} else {
// do not split if we have only seen simple or synthetic copies (catch copy is synthetic)
if (stmt instanceof CopyVarStmt) {
CopyVarStmt copy = (CopyVarStmt) stmt;
int opc = copy.getExpression().getOpcode();
if (!copy.isSynthetic() && opc != Opcode.LOCAL_LOAD && opc != Opcode.CATCH) {
checkSplit = true;
}
} else {
checkSplit = true;
}
}
i++;
}
}
builder.graph.naturalise(order);
int po = 0;
for (BasicBlock b : SimpleDfs.preorder(builder.graph, builder.graph.getEntries().iterator().next())) {
insertion.put(b, 0);
process.put(b, 0);
preorder.put(b, po++);
}
}
Aggregations