Search in sources :

Example 1 with ConditionalJumpStmt

use of org.mapleir.ir.code.stmt.ConditionalJumpStmt 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;
}
Also used : LabelNode(org.objectweb.asm.tree.LabelNode) TryCatchEdge(org.mapleir.flowgraph.edges.TryCatchEdge) SwitchStmt(org.mapleir.ir.code.stmt.SwitchStmt) CopyVarStmt(org.mapleir.ir.code.stmt.copy.CopyVarStmt) PopStmt(org.mapleir.ir.code.stmt.PopStmt) ThrowStmt(org.mapleir.ir.code.stmt.ThrowStmt) UnconditionalJumpStmt(org.mapleir.ir.code.stmt.UnconditionalJumpStmt) Stmt(org.mapleir.ir.code.Stmt) CopyPhiStmt(org.mapleir.ir.code.stmt.copy.CopyPhiStmt) ConditionalJumpStmt(org.mapleir.ir.code.stmt.ConditionalJumpStmt) AbstractCopyStmt(org.mapleir.ir.code.stmt.copy.AbstractCopyStmt) UnconditionalJumpEdge(org.mapleir.flowgraph.edges.UnconditionalJumpEdge) FlowEdge(org.mapleir.flowgraph.edges.FlowEdge) SwitchStmt(org.mapleir.ir.code.stmt.SwitchStmt) SwitchEdge(org.mapleir.flowgraph.edges.SwitchEdge) CopyVarStmt(org.mapleir.ir.code.stmt.copy.CopyVarStmt) BasicBlock(org.mapleir.ir.cfg.BasicBlock) BasicLocal(org.mapleir.ir.locals.impl.BasicLocal) Local(org.mapleir.ir.locals.Local) VersionedLocal(org.mapleir.ir.locals.impl.VersionedLocal) Constraint(org.mapleir.ir.cfg.builder.ssaopt.Constraint) UnconditionalJumpStmt(org.mapleir.ir.code.stmt.UnconditionalJumpStmt) ConditionalJumpStmt(org.mapleir.ir.code.stmt.ConditionalJumpStmt) ConditionalJumpEdge(org.mapleir.flowgraph.edges.ConditionalJumpEdge) ControlFlowGraph(org.mapleir.ir.cfg.ControlFlowGraph)

Example 2 with ConditionalJumpStmt

use of org.mapleir.ir.code.stmt.ConditionalJumpStmt in project maple-ir by LLVM-but-worse.

the class ConstantExpressionReorderPass method transform.

private int transform(ControlFlowGraph ir) {
    int i = 0;
    for (BasicBlock b : ir.vertices()) {
        for (Stmt stmt : b) {
            if (stmt.getOpcode() == COND_JUMP) {
                ConditionalJumpStmt cjs = (ConditionalJumpStmt) stmt;
                Expr r = cjs.getRight();
                Expr l = cjs.getLeft();
                ComparisonType type = cjs.getComparisonType();
                if (type == ComparisonType.EQ || type == ComparisonType.NE) {
                    if (shouldReorder(r, l)) {
                        cjs.setRight(null);
                        cjs.setLeft(null);
                        cjs.setLeft(r);
                        cjs.setRight(l);
                        i++;
                    }
                }
            }
            for (Expr e : stmt.enumerateOnlyChildren()) {
                if (e.getOpcode() == ARITHMETIC) {
                    ArithmeticExpr arith = (ArithmeticExpr) e;
                    Expr r = arith.getRight();
                    Expr l = arith.getLeft();
                    Operator op = arith.getOperator();
                    if (!op.doesOrderMatter()) {
                        if (shouldReorder(r, l)) {
                            arith.setRight(null);
                            arith.setLeft(null);
                            arith.setLeft(r);
                            arith.setRight(l);
                            i++;
                        }
                    }
                }
            }
        }
    }
    return i;
}
Also used : ConditionalJumpStmt(org.mapleir.ir.code.stmt.ConditionalJumpStmt) Operator(org.mapleir.ir.code.expr.ArithmeticExpr.Operator) ComparisonType(org.mapleir.ir.code.stmt.ConditionalJumpStmt.ComparisonType) ArithmeticExpr(org.mapleir.ir.code.expr.ArithmeticExpr) Expr(org.mapleir.ir.code.Expr) ArithmeticExpr(org.mapleir.ir.code.expr.ArithmeticExpr) BasicBlock(org.mapleir.ir.cfg.BasicBlock) Stmt(org.mapleir.ir.code.Stmt) ConditionalJumpStmt(org.mapleir.ir.code.stmt.ConditionalJumpStmt)

Example 3 with ConditionalJumpStmt

use of org.mapleir.ir.code.stmt.ConditionalJumpStmt in project maple-ir by LLVM-but-worse.

the class ConstantExpressionEvaluatorPass method processMethod.

private void processMethod(MethodNode m, IPConstAnalysisVisitor vis, ControlFlowGraph cfg) {
    for (BasicBlock b : new HashSet<>(cfg.vertices())) {
        for (int i = 0; i < b.size(); i++) {
            Stmt stmt = b.get(i);
            // simplify conditional branches.
            if (stmt.getOpcode() == COND_JUMP) {
                // todo: satisfiability analysis
                ConditionalJumpStmt cond = (ConditionalJumpStmt) stmt;
                Boolean result = evaluateConditional(vis, cfg, cond);
                if (result != null) {
                    eliminateBranch(cfg, cond.getBlock(), cond, i, result);
                    branchesEvaluated++;
                }
            }
            // evaluate arithmetic.
            for (CodeUnit cu : stmt.enumerateExecutionOrder()) {
                if (cu instanceof Expr) {
                    Expr e = (Expr) cu;
                    CodeUnit par = e.getParent();
                    if (par != null) {
                        Expr val = simplifyArithmetic(cfg.getLocals(), e);
                        if (val != null) {
                            exprsEvaluated++;
                            cfg.overwrite(par, e, val);
                        }
                    }
                }
            }
        }
    }
}
Also used : ConditionalJumpStmt(org.mapleir.ir.code.stmt.ConditionalJumpStmt) ConstantExpr(org.mapleir.ir.code.expr.ConstantExpr) ArithmeticExpr(org.mapleir.ir.code.expr.ArithmeticExpr) VarExpr(org.mapleir.ir.code.expr.VarExpr) Expr(org.mapleir.ir.code.Expr) BasicBlock(org.mapleir.ir.cfg.BasicBlock) HashSet(java.util.HashSet) UnconditionalJumpStmt(org.mapleir.ir.code.stmt.UnconditionalJumpStmt) Stmt(org.mapleir.ir.code.Stmt) ConditionalJumpStmt(org.mapleir.ir.code.stmt.ConditionalJumpStmt) AbstractCopyStmt(org.mapleir.ir.code.stmt.copy.AbstractCopyStmt) CodeUnit(org.mapleir.ir.code.CodeUnit)

Aggregations

BasicBlock (org.mapleir.ir.cfg.BasicBlock)3 Stmt (org.mapleir.ir.code.Stmt)3 ConditionalJumpStmt (org.mapleir.ir.code.stmt.ConditionalJumpStmt)3 Expr (org.mapleir.ir.code.Expr)2 ArithmeticExpr (org.mapleir.ir.code.expr.ArithmeticExpr)2 UnconditionalJumpStmt (org.mapleir.ir.code.stmt.UnconditionalJumpStmt)2 AbstractCopyStmt (org.mapleir.ir.code.stmt.copy.AbstractCopyStmt)2 HashSet (java.util.HashSet)1 ConditionalJumpEdge (org.mapleir.flowgraph.edges.ConditionalJumpEdge)1 FlowEdge (org.mapleir.flowgraph.edges.FlowEdge)1 SwitchEdge (org.mapleir.flowgraph.edges.SwitchEdge)1 TryCatchEdge (org.mapleir.flowgraph.edges.TryCatchEdge)1 UnconditionalJumpEdge (org.mapleir.flowgraph.edges.UnconditionalJumpEdge)1 ControlFlowGraph (org.mapleir.ir.cfg.ControlFlowGraph)1 Constraint (org.mapleir.ir.cfg.builder.ssaopt.Constraint)1 CodeUnit (org.mapleir.ir.code.CodeUnit)1 Operator (org.mapleir.ir.code.expr.ArithmeticExpr.Operator)1 ConstantExpr (org.mapleir.ir.code.expr.ConstantExpr)1 VarExpr (org.mapleir.ir.code.expr.VarExpr)1 ComparisonType (org.mapleir.ir.code.stmt.ConditionalJumpStmt.ComparisonType)1