use of org.mapleir.ir.cfg.BasicBlock in project maple-ir by LLVM-but-worse.
the class DeadCodeEliminationPass method process.
public void process(ControlFlowGraph cfg) {
LocalsPool lp = cfg.getLocals();
boolean c;
do {
c = false;
SimpleDfs<BasicBlock> dfs = new SimpleDfs<>(cfg, cfg.getEntries().iterator().next(), SimpleDfs.PRE);
List<BasicBlock> pre = dfs.getPreOrder();
for (BasicBlock b : new HashSet<>(cfg.vertices())) {
if (!pre.contains(b)) {
// System.out.println("proc1: " + b);
for (FlowEdge<BasicBlock> fe : new HashSet<>(cfg.getEdges(b))) {
cfg.exciseEdge(fe);
}
// System.out.println("removed: ");
for (Stmt stmt : b) {
// System.out.println(" " + (b.indexOf(stmt)) + ". " + stmt);
if (stmt instanceof AbstractCopyStmt) {
AbstractCopyStmt copy = (AbstractCopyStmt) stmt;
lp.defs.remove(copy.getVariable().getLocal());
// System.out.println(" kill1 " + copy.getVariable().getLocal());
}
for (Expr e : stmt.enumerateOnlyChildren()) {
if (e.getOpcode() == Opcode.LOCAL_LOAD) {
VarExpr v = (VarExpr) e;
lp.uses.get(v.getLocal()).remove(v);
// System.out.println(" kill2 " + v.getLocal());
}
}
}
cfg.removeVertex(b);
deadBlocks++;
c = true;
} else {
// System.out.println("proc2: " + b);
UnconditionalJumpEdge<BasicBlock> uncond = null;
for (FlowEdge<BasicBlock> fe : cfg.getEdges(b)) {
if (fe.getType() == FlowEdges.UNCOND) {
uncond = (UnconditionalJumpEdge<BasicBlock>) fe;
}
}
if (uncond != null) {
BasicBlock dst = uncond.dst();
List<BasicBlock> verts = new ArrayList<>(cfg.vertices());
if (verts.indexOf(b) + 1 == verts.indexOf(dst)) {
ImmediateEdge<BasicBlock> im = new ImmediateEdge<>(b, dst);
cfg.exciseEdge(uncond);
cfg.addEdge(b, im);
Stmt stmt = b.remove(b.size() - 1);
if (stmt.getOpcode() != Opcode.UNCOND_JUMP) {
throw new IllegalStateException(b + " : " + stmt);
}
immediateJumps++;
c = true;
}
}
// if(cfg.getMethod().toString().equals("cf.k(IIIIII)V")) {}
Iterator<Stmt> it = b.iterator();
while (it.hasNext()) {
Stmt stmt = it.next();
if (stmt.getOpcode() == Opcode.LOCAL_STORE) {
AbstractCopyStmt copy = (AbstractCopyStmt) stmt;
if (copy.isSynthetic()) {
continue;
}
Local l = copy.getVariable().getLocal();
LocalsPool pool = cfg.getLocals();
// System.out.println("copy: "+ copy);
if (!ConstraintUtil.isUncopyable(copy.getExpression()) && pool.uses.get(l).size() == 0) {
for (Expr e : copy.getExpression().enumerateWithSelf()) {
if (e.getOpcode() == Opcode.LOCAL_LOAD) {
VarExpr v = (VarExpr) e;
Local l2 = v.getLocal();
pool.uses.remove(l2);
}
}
pool.uses.remove(l);
pool.defs.remove(l);
it.remove();
deadLocals++;
c = true;
}
} else if (stmt.getOpcode() == Opcode.NOP) {
it.remove();
c = true;
}
}
}
}
// for now
} while (c);
}
use of org.mapleir.ir.cfg.BasicBlock in project maple-ir by LLVM-but-worse.
the class LiftConstructorCallsPass method split.
private void split(ControlFlowGraph cfg, BasicBlock b, Stmt at) {
BasicBlock newBlock = new BasicBlock(cfg, cfg.vertices().size() + 1, new LabelNode());
cfg.addVertex(newBlock);
System.out.println(ControlFlowGraph.printBlock(b));
System.out.println(" to " + at);
int index = b.indexOf(at) + 1;
int size = b.size();
for (int i = index; i < size; i++) {
Stmt stmt = b.remove(index);
stmt.setBlock(newBlock);
newBlock.add(stmt);
}
}
use of org.mapleir.ir.cfg.BasicBlock in project maple-ir by LLVM-but-worse.
the class LiftConstructorCallsPass method tryLift.
private boolean tryLift(MethodNode m, ControlFlowGraph cfg) {
Local lvar0_0 = cfg.getLocals().get(0, 0, false);
/* only contains synthetic copies */
BasicBlock entry = cfg.getEntries().iterator().next();
for (BasicBlock b : cfg.vertices()) {
for (Stmt stmt : b) {
for (Expr e : stmt.enumerateOnlyChildren()) {
if (e.getOpcode() == INVOKE) {
InvocationExpr invoke = (InvocationExpr) e;
if (invoke.getOwner().equals(m.owner.superName) && invoke.getName().equals("<init>")) {
Expr p1 = invoke.getPhysicalReceiver();
if (p1.getOpcode() == LOCAL_LOAD && ((VarExpr) p1).getLocal() == lvar0_0) {
Set<FlowEdge<BasicBlock>> predsEdges = cfg.getReverseEdges(b);
FlowEdge<BasicBlock> incoming;
if (predsEdges.size() == 1 && ((incoming = predsEdges.iterator().next()).getType() == FlowEdges.IMMEDIATE) && incoming.src() == entry) {
// BasicBlock liftBlock = new BasicBlock(cfg, cfg.vertices().size() + 1, new LabelNode());
/* split the block before the invocation and
* insert a new block. */
split(cfg, b, stmt);
return true;
} else {
System.err.printf(" warn(nolift) for %s in %n%s%n", invoke, ControlFlowGraph.printBlock(b));
System.err.printf(" preds: %s%n", predsEdges);
}
} else {
throw new IllegalStateException(String.format("broken super call: %s", invoke));
}
}
}
}
}
}
return false;
}
use of org.mapleir.ir.cfg.BasicBlock 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.cfg.BasicBlock in project maple-ir by LLVM-but-worse.
the class MethodRenamerPass method rename.
public static void rename(AnalysisContext cxt, Map<MethodNode, String> remapped, boolean warn) {
ApplicationClassSource source = cxt.getApplication();
InvocationResolver resolver = cxt.getInvocationResolver();
for (ClassNode cn : source.iterate()) {
{
if (cn.outerMethod != null) {
// ClassNode owner = tree.getClass(cn.outerClass);
System.out.println("Outer: " + cn.outerClass + "." + cn.outerMethod + " " + cn.outerMethodDesc);
cn.outerClass = null;
cn.outerMethod = null;
cn.outerMethodDesc = null;
// System.out.println(owner.name);
// do {
// for(MethodNode m : owner.methods) {
// System.out.println(m);
// if(m.name.equals(cn.outerMethod) && m.desc.equals(cn.outerMethodDesc)) {
// System.out.println("m: " + m);
// }
// }
// owner = tree.getClass(owner.superName);
// System.out.println(cn.superName);
// System.out.println(owner);
// } while(owner != null);
}
}
Set<Expr> visited = new HashSet<>();
for (MethodNode m : cn.methods) {
ControlFlowGraph cfg = cxt.getIRCache().getFor(m);
for (BasicBlock b : cfg.vertices()) {
for (Stmt stmt : b) {
for (Expr e : stmt.enumerateOnlyChildren()) {
if (e.getOpcode() == Opcode.INVOKE) {
InvocationExpr invoke = (InvocationExpr) e;
if (visited.contains(invoke)) {
throw new RuntimeException(invoke.toString());
}
visited.add(invoke);
if (invoke.getOwner().startsWith("[")) {
System.err.println(" ignore array object invoke: " + invoke + ", owner: " + invoke.getOwner());
continue;
}
if (invoke.isStatic()) {
MethodNode site = resolver.resolveStaticCall(invoke.getOwner(), invoke.getName(), invoke.getDesc());
if (site != null) {
if (remapped.containsKey(site)) {
invoke.setName(remapped.get(site));
} else {
if (warn && mustMark(source, invoke.getOwner())) {
System.err.println(" invalid site(s): " + invoke);
}
}
} else {
if (mustMark(source, invoke.getOwner())) {
System.err.printf(" can't resolve(s) %s ; %s.%s %s%n", invoke, invoke.getOwner(), invoke.getName(), invoke.getDesc());
if (invoke.getOwner().equals("hey")) {
for (MethodNode mm : cxt.getApplication().findClassNode(invoke.getOwner()).methods) {
System.out.println(mm);
}
throw new UnsupportedOperationException();
}
}
}
} else {
// Set<MethodNode> sites = resolver.resolveVirtualCalls(invoke.getOwner(), invoke.getName(), invoke.getDesc());
// Set<ClassNode> classes = source.getStructures().dfsTree(cn, true, true, true);
// Set<MethodNode> sites = getVirtualMethods(cxt, classes, invoke.getName(), invoke.getDesc());
Set<MethodNode> sites = resolver.getHierarchyMethodChain(source.findClassNode(invoke.getOwner()), invoke.getName(), invoke.getDesc(), true);
if (sites.size() > 0) {
/* all of the sites must be linked by the same name,
* so we can use any to find the new name. */
boolean anyContains = false;
boolean allContains = true;
for (MethodNode s : sites) {
anyContains |= remapped.containsKey(s);
allContains &= remapped.containsKey(s);
}
if (anyContains && !allContains) {
System.err.println("mismatch: ");
// System.err.println(classes);
System.err.println(sites);
throw new RuntimeException();
}
MethodNode site = sites.iterator().next();
if (remapped.containsKey(site)) {
invoke.setName(remapped.get(site));
} else {
if (warn && !site.name.equals("<init>") && canRename(cxt, sites)) {
System.err.println(" invalid site(v): " + invoke + ", " + sites);
}
}
} else {
if (mustMark(source, invoke.getOwner())) {
System.err.println(" can't resolve(v) " + invoke + ", owner: " + invoke.getOwner() + " desc " + invoke.getDesc());
// System.err.println(" classes: " + classes);
}
}
}
} else if (e.getOpcode() == Opcode.DYNAMIC_INVOKE) {
throw new UnsupportedOperationException();
}
}
}
}
}
}
/* Rename the methods after as we need to resolve
* them using the old names during the invocation
* analysis above. */
for (Entry<MethodNode, String> e : remapped.entrySet()) {
// System.out.printf("%s -> %s%n", e.getKey(), e.getValue());
e.getKey().name = e.getValue();
}
}
Aggregations