Search in sources :

Example 1 with SwitchEdge

use of org.mapleir.flowgraph.edges.SwitchEdge 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 SwitchEdge

use of org.mapleir.flowgraph.edges.SwitchEdge in project maple-ir by LLVM-but-worse.

the class GenerationPass method process.

protected void process(LabelNode label) {
    /* it may not be properly initialised yet, however. */
    BasicBlock block = builder.graph.getBlock(label);
    /* if it is, we don't need to process it. */
    if (block != null && finished.get(block.getNumericId())) {
        return;
    } else if (block == null) {
        block = makeBlock(label);
    } else {
    // i.e. not finished.
    }
    preprocess(block);
    /* populate instructions. */
    int codeIndex = insns.indexOf(label);
    finished.set(block.getNumericId());
    while (codeIndex < insns.size() - 1) {
        AbstractInsnNode ain = insns.get(++codeIndex);
        int type = ain.type();
        if (ain.opcode() != -1) {
            process(block, ain);
        }
        if (type == LABEL) {
            // split into new block
            BasicBlock immediate = resolveTarget((LabelNode) ain);
            builder.graph.addEdge(block, new ImmediateEdge<>(block, immediate));
            break;
        } else if (type == JUMP_INSN) {
            JumpInsnNode jin = (JumpInsnNode) ain;
            BasicBlock target = resolveTarget(jin.label);
            if (jin.opcode() == JSR) {
                throw new UnsupportedOperationException("jsr " + builder.method);
            } else if (jin.opcode() == GOTO) {
                builder.graph.addEdge(block, new UnconditionalJumpEdge<>(block, target));
            } else {
                builder.graph.addEdge(block, new ConditionalJumpEdge<>(block, target, jin.opcode()));
                int nextIndex = codeIndex + 1;
                AbstractInsnNode nextInsn = insns.get(nextIndex);
                if (!(nextInsn instanceof LabelNode)) {
                    LabelNode newLabel = new LabelNode();
                    insns.insert(ain, newLabel);
                    nextInsn = newLabel;
                }
                // create immediate successor reference if it's not already done
                BasicBlock immediate = resolveTarget((LabelNode) nextInsn);
                builder.graph.addEdge(block, new ImmediateEdge<>(block, immediate));
            }
            break;
        } else if (type == LOOKUPSWITCH_INSN) {
            LookupSwitchInsnNode lsin = (LookupSwitchInsnNode) ain;
            for (int i = 0; i < lsin.keys.size(); i++) {
                BasicBlock target = resolveTarget(lsin.labels.get(i));
                builder.graph.addEdge(block, new SwitchEdge<>(block, target, lsin, lsin.keys.get(i)));
            }
            BasicBlock dflt = resolveTarget(lsin.dflt);
            builder.graph.addEdge(block, new DefaultSwitchEdge<>(block, dflt, lsin));
            break;
        } else if (type == TABLESWITCH_INSN) {
            TableSwitchInsnNode tsin = (TableSwitchInsnNode) ain;
            for (int i = tsin.min; i <= tsin.max; i++) {
                BasicBlock target = resolveTarget(tsin.labels.get(i - tsin.min));
                builder.graph.addEdge(block, new SwitchEdge<>(block, target, tsin, i));
            }
            BasicBlock dflt = resolveTarget(tsin.dflt);
            builder.graph.addEdge(block, new DefaultSwitchEdge<>(block, dflt, tsin));
            break;
        } else if (isExitOpcode(ain.opcode())) {
            break;
        }
    }
    // TODO: check if it should have an immediate.
    BasicBlock im = block.getImmediate();
    if (im != null) /* && !queue.contains(im)*/
    {
        // System.out.println("Updating " + block.getId() + " -> " + im.getId());
        // System.out.println("  Pre: " + currentStack);
        update_target_stack(block, im, currentStack);
    // System.out.println("  Pos: " + currentStack);
    }
}
Also used : DefaultSwitchEdge(org.mapleir.flowgraph.edges.DefaultSwitchEdge) SwitchEdge(org.mapleir.flowgraph.edges.SwitchEdge) BasicBlock(org.mapleir.ir.cfg.BasicBlock) AbstractInsnNode(org.objectweb.asm.tree.AbstractInsnNode) DefaultSwitchEdge(org.mapleir.flowgraph.edges.DefaultSwitchEdge)

Aggregations

SwitchEdge (org.mapleir.flowgraph.edges.SwitchEdge)2 BasicBlock (org.mapleir.ir.cfg.BasicBlock)2 ConditionalJumpEdge (org.mapleir.flowgraph.edges.ConditionalJumpEdge)1 DefaultSwitchEdge (org.mapleir.flowgraph.edges.DefaultSwitchEdge)1 FlowEdge (org.mapleir.flowgraph.edges.FlowEdge)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 Stmt (org.mapleir.ir.code.Stmt)1 ConditionalJumpStmt (org.mapleir.ir.code.stmt.ConditionalJumpStmt)1 PopStmt (org.mapleir.ir.code.stmt.PopStmt)1 SwitchStmt (org.mapleir.ir.code.stmt.SwitchStmt)1 ThrowStmt (org.mapleir.ir.code.stmt.ThrowStmt)1 UnconditionalJumpStmt (org.mapleir.ir.code.stmt.UnconditionalJumpStmt)1 AbstractCopyStmt (org.mapleir.ir.code.stmt.copy.AbstractCopyStmt)1 CopyPhiStmt (org.mapleir.ir.code.stmt.copy.CopyPhiStmt)1 CopyVarStmt (org.mapleir.ir.code.stmt.copy.CopyVarStmt)1 Local (org.mapleir.ir.locals.Local)1 BasicLocal (org.mapleir.ir.locals.impl.BasicLocal)1