use of org.mapleir.ir.code.stmt.copy.CopyPhiStmt in project maple-ir by LLVM-but-worse.
the class SSAGenPass method reduceClass.
private void reduceClass(Set<CopyPhiStmt> cc, CopyPhiStmt preferred) {
Set<CopyPhiStmt> useless = new HashSet<>(cc);
useless.remove(preferred);
VersionedLocal phiLocal = (VersionedLocal) preferred.getVariable().getLocal();
/* all the *dead* phi class locals */
Set<VersionedLocal> deadLocals = new HashSet<>();
for (CopyPhiStmt def : useless) {
VersionedLocal local = (VersionedLocal) def.getVariable().getLocal();
deadLocals.add(local);
for (Expr e : def.enumerateOnlyChildren()) {
if (e.getOpcode() == Opcode.LOCAL_LOAD) {
VarExpr v = (VarExpr) e;
VersionedLocal vl = (VersionedLocal) v.getLocal();
pool.uses.get(vl).remove(v);
}
}
// System.out.println(" killing " + def);
def.delete();
}
for (VersionedLocal vl : deadLocals) {
Set<VarExpr> deadVExprs = pool.uses.get(vl);
for (VarExpr v : deadVExprs) {
/* v.getLocal() == vl, i.e. dead phi local.
* Replace each dead var with the real one. */
v.setLocal(phiLocal);
pool.uses.get(phiLocal).add(v);
}
/* all dead. */
/*pool.uses.get(vl)*/
deadVExprs.clear();
pool.defs.remove(vl);
}
}
use of org.mapleir.ir.code.stmt.copy.CopyPhiStmt in project maple-ir by LLVM-but-worse.
the class SSAGenPass method searchImpl.
private void searchImpl(BasicBlock b) {
Iterator<Stmt> it = b.iterator();
while (it.hasNext()) {
Stmt stmt = it.next();
int opcode = stmt.getOpcode();
if (opcode == Opcode.POP) {
PopStmt pop = (PopStmt) stmt;
if (!ConstraintUtil.isUncopyable(pop.getExpression())) {
it.remove();
continue;
}
}
if (opcode == Opcode.PHI_STORE) {
/* We can rename these any time as these
* are visited before all other statements
* in a block (since they are always
* the starting statements of a block, if
* that block contains phi statements).
*/
CopyPhiStmt copy = (CopyPhiStmt) stmt;
generate(copy);
} else {
/* Translates locals into their latest SSA
* versioned locals.
*
* Do this before a LOCAL_STORE (x = ...)
* so that the target local isn't defined
* before the use so that copies in the
* form x = x; do not get mangled into
* x0 = x0 after SSA renaming.
*
* We rename phi args later as the source
* local can originate from exotic blocks.
*/
translate(stmt, true, false);
}
if (opcode == Opcode.LOCAL_STORE) {
/* Generate the target local after
* renaming the source pool.uses.
*/
CopyVarStmt copy = (CopyVarStmt) stmt;
generate(copy);
}
}
}
use of org.mapleir.ir.code.stmt.copy.CopyPhiStmt in project maple-ir by LLVM-but-worse.
the class SSAGenPass method fixPhiArgs.
private void fixPhiArgs(BasicBlock b, BasicBlock succ) {
for (Stmt stmt : succ) {
if (stmt.getOpcode() == Opcode.PHI_STORE) {
CopyPhiStmt copy = (CopyPhiStmt) stmt;
PhiExpr phi = copy.getExpression();
Expr e = phi.getArgument(b);
if (e.getOpcode() == Opcode.LOCAL_LOAD) {
VarExpr v = (VarExpr) e;
translate(v, true, true);
VersionedLocal ssaL = (VersionedLocal) v.getLocal();
Type t = types.get(ssaL);
copy.getVariable().setType(t);
phi.setType(t);
} else {
throw new IllegalArgumentException(phi + ", " + e);
}
} else {
/* No need to search the rest of the block
* after we have visited the phis as they
* precede all other statements.
*/
break;
}
}
}
use of org.mapleir.ir.code.stmt.copy.CopyPhiStmt in project maple-ir by LLVM-but-worse.
the class SSAGenPass method updatePhiArgTypes.
private void updatePhiArgTypes(Set<BasicBlock> vis) {
// update types for phi args
for (BasicBlock b : order) {
for (Stmt s : b) {
if (s.getOpcode() != Opcode.PHI_STORE) {
break;
}
CopyPhiStmt cps = (CopyPhiStmt) s;
for (Entry<BasicBlock, Expr> e : cps.getExpression().getArguments().entrySet()) {
BasicBlock src = e.getKey();
if (vis.contains(src))
continue;
VarExpr v = (VarExpr) e.getValue();
Local l = v.getLocal();
// what if the def is never reached?
AbstractCopyStmt def = pool.defs.get(l);
v.setType(def.getType());
}
}
}
}
use of org.mapleir.ir.code.stmt.copy.CopyPhiStmt in project maple-ir by LLVM-but-worse.
the class SSAGenPass method insertPhis.
private void insertPhis(BasicBlock b, Local l, int i, LinkedList<BasicBlock> queue) {
if (b == null || b == builder.head) {
// exit
return;
}
Local newl = builder.graph.getLocals().get(l.getIndex(), 0, l.isStack());
for (BasicBlock x : doms.iteratedFrontier(b)) {
if (insertion.get(x) < i) {
// pruned SSA
if (liveness.in(x).contains(l)) {
if ((l == svar0) && handlers.contains(x)) /* == faster than contains. */
{
/* Note: this is quite subtle. Since there is a
* copy, (svar0 = catch()) at the start of each
* handler block, technically any natural flowing
* svar0 definition is killed upon entry to the
* block, so it is not considered live. One way to
* check if the variable is live-in, therefore, is
* by checking whether svar0 is live-out of the
* catch() definition. We handle it here, since
* the previous liveness check which is used for
* pruned SSA will fail in this case. */
/* Ok fuck that that, it's considered live-in
* even if there is a catch()::
* #see SSaBlockLivenessAnalyser.precomputeBlock*/
boolean naturalFlow = false;
for (FlowEdge<BasicBlock> e : builder.graph.getReverseEdges(x)) {
if (e.getType() != FlowEdges.TRYCATCH) {
naturalFlow = true;
break;
}
}
if (naturalFlow) {
CopyVarStmt catcher = null;
for (Stmt stmt : x) {
if (stmt.getOpcode() == Opcode.LOCAL_STORE) {
CopyVarStmt copy = (CopyVarStmt) stmt;
Expr e = copy.getExpression();
if (e.getOpcode() == Opcode.CATCH) {
catcher = copy;
break;
}
}
}
if (catcher == null) {
/* Handler but no catch copy?
* This can't happen since svar0 is
* the only reserved register for
* catch copies, and this block cannot
* be visited twice to insert a phi or
* psi(ephi) node. */
throw new IllegalStateException(x.getDisplayName());
}
/* Map<BasicBlock, Expression> vls = new HashMap<>();
for(FlowEdge<BasicBlock> fe : builder.graph.getReverseEdges(x)) {
vls.put(fe.src, new VarExpr(newl, null));
}
vls.put(x, catcher.getExpression().copy());
catcher.delete();
PhiExpr phi = new PhiExceptionExpr(vls);
CopyPhiStmt assign = new CopyPhiStmt(new VarExpr(l, null), phi);
x.add(0, assign); */
throw new UnsupportedOperationException(builder.method.toString());
}
}
if (builder.graph.getReverseEdges(x).size() > 1) {
Map<BasicBlock, Expr> vls = new HashMap<>();
for (FlowEdge<BasicBlock> fe : builder.graph.getReverseEdges(x)) {
vls.put(fe.src(), new VarExpr(newl, null));
}
PhiExpr phi = new PhiExpr(vls);
CopyPhiStmt assign = new CopyPhiStmt(new VarExpr(l, null), phi);
x.add(0, assign);
}
}
insertion.put(x, i);
if (process.get(x) < i) {
process.put(x, i);
queue.add(x);
}
}
}
}
Aggregations