use of org.mapleir.ir.code.stmt.copy.CopyVarStmt in project maple-ir by LLVM-but-worse.
the class IPAnalysis method visitMethod.
@Override
protected void visitMethod(MethodNode m) {
// Callbacks
for (IPAnalysisVisitor v : visitors) {
v.preVisitMethod(this, m);
}
// Do not trace library calls
if (context.getApplication().isLibraryClass(m.owner.name)) {
return;
}
// Create a mapping between the actual variable table indices and the parameter
// indices in the method descriptor.
boolean isStatic = (m.access & Opcodes.ACC_STATIC) != 0;
int paramCount = Type.getArgumentTypes(m.desc).length;
int off = (isStatic ? 0 : 1);
int synthCount = paramCount + off;
List<List<Expr>> lists = new ArrayList<>(synthCount);
int[] idxs = new int[synthCount];
// Scan for synthetic copies to populate indices
ControlFlowGraph cfg = context.getIRCache().getFor(m);
BasicBlock entry = cfg.getEntries().iterator().next();
/* static:
* first arg = 0
*
* non-static:
* this = 0
* first arg = 1*/
int paramIndex = 0;
for (Stmt stmt : entry) {
if (stmt.getOpcode() == LOCAL_STORE) {
CopyVarStmt cvs = (CopyVarStmt) stmt;
if (cvs.isSynthetic()) {
int varIndex = cvs.getVariable().getLocal().getIndex();
if (!isStatic && varIndex == 0)
continue;
idxs[paramIndex++] = varIndex;
continue;
}
}
break;
}
for (int j = 0; j < paramCount; j++) {
lists.add(new ArrayList<>());
}
paramIndices.put(m, idxs);
parameterInputs.put(m, lists);
callers.put(m, new HashSet<>());
// Callbacks
for (IPAnalysisVisitor v : visitors) {
v.postVisitMethod(this, m);
}
}
use of org.mapleir.ir.code.stmt.copy.CopyVarStmt 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);
}
}
}
}
use of org.mapleir.ir.code.stmt.copy.CopyVarStmt in project maple-ir by LLVM-but-worse.
the class BoissinotDestructor method sequentialize.
private void sequentialize(BasicBlock b) {
// TODO: just rebuild the instruction list
LinkedHashMap<ParallelCopyVarStmt, Integer> p = new LinkedHashMap<>();
for (int i = 0; i < b.size(); i++) {
Stmt stmt = b.get(i);
if (stmt instanceof ParallelCopyVarStmt)
p.put((ParallelCopyVarStmt) stmt, i);
}
if (p.isEmpty())
return;
int indexOffset = 0;
Local spill = locals.makeLatestVersion(p.entrySet().iterator().next().getKey().pairs.get(0).targ);
for (Entry<ParallelCopyVarStmt, Integer> e : p.entrySet()) {
ParallelCopyVarStmt pcvs = e.getKey();
int index = e.getValue();
if (pcvs.pairs.size() == 0)
throw new IllegalArgumentException("pcvs is empty");
else if (pcvs.pairs.size() == 1) {
// constant sequentialize for trivial parallel copies
CopyPair pair = pcvs.pairs.get(0);
CopyVarStmt newCopy = new CopyVarStmt(new VarExpr(pair.targ, pair.type), new VarExpr(pair.source, pair.type));
b.set(index + indexOffset, newCopy);
} else {
List<CopyVarStmt> sequentialized = pcvs.sequentialize(spill);
b.remove(index + indexOffset--);
for (CopyVarStmt cvs : sequentialized) {
// warning: O(N^2) operation
b.add(index + ++indexOffset, cvs);
}
}
}
}
use of org.mapleir.ir.code.stmt.copy.CopyVarStmt in project maple-ir by LLVM-but-worse.
the class GenerationPass method handler.
protected void handler(TryCatchBlockNode tc) {
LabelNode label = tc.handler;
BasicBlock handler = resolveTarget(label);
marks.add(tc.start);
marks.add(tc.end);
if (getInputStackFor(handler) != null) {
// System.err.println("Double handler: " + handler.getId() + " " + tc);
return;
}
ExpressionStack stack = new ExpressionStack(16);
setInputStack(handler, stack);
CaughtExceptionExpr expr = new CaughtExceptionExpr(tc.type);
Type type = expr.getType();
VarExpr var = _var_expr(0, type, true);
CopyVarStmt stmt = copy(var, expr, handler);
handler.add(stmt);
stack.push(load_stack(0, type));
queue(label);
stacks.set(handler.getNumericId());
}
Aggregations