Search in sources :

Example 61 with BasicBlock

use of org.mapleir.ir.cfg.BasicBlock in project maple-ir by LLVM-but-worse.

the class SreedharDestructor method init.

// ============================================================================================================= //
// =============================================== Initialization ============================================== //
// ============================================================================================================= //
private void init() {
    // init pccs
    for (CopyPhiStmt copyPhi : defuse.phiDefs.values()) {
        Local phiTarget = copyPhi.getVariable().getLocal();
        pccs.getNonNull(phiTarget).add(phiTarget);
        // System.out.println("Initphi " + phiTarget);
        for (Entry<BasicBlock, Expr> phiEntry : copyPhi.getExpression().getArguments().entrySet()) {
            if (phiEntry.getValue().getOpcode() != LOCAL_LOAD)
                throw new IllegalArgumentException("Phi arg is not local; instead is " + phiEntry.getValue().getClass().getSimpleName());
            Local phiSource = ((VarExpr) phiEntry.getValue()).getLocal();
            pccs.getNonNull(phiSource).add(phiSource);
        // System.out.println("Initphi " + phiSource);
        }
    }
    // System.out.println();
    // compute liveness
    (liveness = new SSABlockLivenessAnalyser(cfg)).compute();
    // writer.add("liveness", new LivenessDecorator<ControlFlowGraph, BasicBlock, FlowEdge<BasicBlock>>().setLiveness(liveness));
    buildInterference();
}
Also used : VarExpr(org.mapleir.ir.code.expr.VarExpr) Expr(org.mapleir.ir.code.Expr) PhiExpr(org.mapleir.ir.code.expr.PhiExpr) BasicBlock(org.mapleir.ir.cfg.BasicBlock) Local(org.mapleir.ir.locals.Local) VarExpr(org.mapleir.ir.code.expr.VarExpr) CopyPhiStmt(org.mapleir.ir.code.stmt.copy.CopyPhiStmt)

Example 62 with BasicBlock

use of org.mapleir.ir.cfg.BasicBlock in project maple-ir by LLVM-but-worse.

the class SreedharDestructor method resolvePhiSource.

private Local resolvePhiSource(Local xi, BasicBlock lk, Type phiType) {
    // Insert spill copy
    Local spill = insertEnd(xi, lk, phiType);
    // Update liveness
    GenericBitSet<Local> liveOut = liveness.out(lk);
    liveOut.add(spill);
    // xi can be removed from liveOut iff it isn't live into any succ or used in any succ phi.
    for (BasicBlock lj : succsCache.getNonNull(lk)) {
        if (!liveness.in(lj).contains(xi))
            removeFromOut: {
                for (int i = 0; i < lj.size() && lj.get(i).getOpcode() == Opcode.PHI_STORE; i++) if (((VarExpr) ((CopyPhiStmt) lj.get(i)).getExpression().getArguments().get(lk)).getLocal() == xi)
                    break removeFromOut;
                // poor man's for-else loop
                liveOut.remove(xi);
            }
    }
    // Reflexively update interference
    interfere.getNonNull(spill).addAll(liveOut);
    for (Local l : liveOut) interfere.get(l).add(spill);
    return spill;
}
Also used : BasicBlock(org.mapleir.ir.cfg.BasicBlock) Local(org.mapleir.ir.locals.Local) CopyPhiStmt(org.mapleir.ir.code.stmt.copy.CopyPhiStmt)

Example 63 with BasicBlock

use of org.mapleir.ir.cfg.BasicBlock in project maple-ir by LLVM-but-worse.

the class DefUseVerifier method verify0.

public static void verify0(ControlFlowGraph cfg) {
    LocalsPool lp = cfg.getLocals();
    Map<Local, AbstractCopyStmt> defs = new HashMap<>();
    NullPermeableHashMap<VersionedLocal, Set<VarExpr>> uses = new NullPermeableHashMap<>(SetCreator.getInstance());
    for (BasicBlock b : cfg.vertices()) {
        for (Stmt stmt : b) {
            if (stmt.getOpcode() == Opcode.LOCAL_STORE || stmt.getOpcode() == Opcode.PHI_STORE) {
                AbstractCopyStmt copy = (AbstractCopyStmt) stmt;
                defs.put(copy.getVariable().getLocal(), copy);
            }
            for (Expr e : stmt.enumerateOnlyChildren()) {
                if (e.getOpcode() == Opcode.LOCAL_LOAD) {
                    VarExpr v = (VarExpr) e;
                    uses.getNonNull((VersionedLocal) v.getLocal()).add(v);
                }
            }
        }
    }
    {
        Set<Local> dlocals = new HashSet<>();
        dlocals.addAll(defs.keySet());
        dlocals.addAll(lp.defs.keySet());
        for (Local l : dlocals) {
            if (!defs.containsKey(l)) {
                throw new IllegalStateException("(other): def of " + l);
            }
            if (!lp.defs.containsKey(l)) {
                throw new IllegalStateException("(real): def of " + l);
            }
            AbstractCopyStmt copy1 = defs.get(l);
            AbstractCopyStmt copy2 = lp.defs.get(l);
            if (copy1 != copy2) {
                throw new IllegalStateException("dtest: " + copy1 + " :: " + copy2);
            }
        }
    }
    {
        Set<VersionedLocal> ulocals = new HashSet<>();
        ulocals.addAll(uses.keySet());
        ulocals.addAll(lp.uses.keySet());
        for (VersionedLocal l : ulocals) {
            /*if(!uses.containsKey(l)) {
					throw new IllegalStateException("(other): use of " + l);
				}
				
				if(!lp.uses.containsKey(l)) {
					throw new IllegalStateException("(real): use of " + l);
				}*/
            Set<VarExpr> uses1 = uses.get(l);
            Set<VarExpr> uses2 = lp.uses.get(l);
            if (uses1 == null) {
                if (uses2.size() != 0) {
                    throw new IllegalStateException(String.format("utest1: %s, u1:null :: u2:%d", l, uses2.size()));
                }
            } else if (uses2 == null) {
                if (uses1.size() == 0) {
                    throw new IllegalStateException(String.format("utest2: %s, u1:%d :: u2:null", l, uses1.size()));
                }
            } else {
                if (uses2.size() != uses1.size()) {
                    throw new IllegalStateException(String.format("utest3: %s, u1:%d :: u2:%d", l, uses1.size(), uses2.size()));
                }
            }
        }
    }
}
Also used : VersionedLocal(org.mapleir.ir.locals.impl.VersionedLocal) Set(java.util.Set) HashSet(java.util.HashSet) HashMap(java.util.HashMap) NullPermeableHashMap(org.mapleir.stdlib.collections.map.NullPermeableHashMap) BasicBlock(org.mapleir.ir.cfg.BasicBlock) Local(org.mapleir.ir.locals.Local) VersionedLocal(org.mapleir.ir.locals.impl.VersionedLocal) Stmt(org.mapleir.ir.code.Stmt) AbstractCopyStmt(org.mapleir.ir.code.stmt.copy.AbstractCopyStmt) LocalsPool(org.mapleir.ir.locals.LocalsPool) VarExpr(org.mapleir.ir.code.expr.VarExpr) Expr(org.mapleir.ir.code.Expr) NullPermeableHashMap(org.mapleir.stdlib.collections.map.NullPermeableHashMap) AbstractCopyStmt(org.mapleir.ir.code.stmt.copy.AbstractCopyStmt) VarExpr(org.mapleir.ir.code.expr.VarExpr)

Example 64 with BasicBlock

use of org.mapleir.ir.cfg.BasicBlock 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)

Example 65 with BasicBlock

use of org.mapleir.ir.cfg.BasicBlock in project maple-ir by LLVM-but-worse.

the class GenerationPass method range.

private static List<BasicBlock> range(List<BasicBlock> gblocks, int start, int end) {
    if (start > end) {
        throw new IllegalArgumentException("start > end: " + start + " > " + end);
    }
    BasicBlock startBlock = null, endBlock = null;
    int startIndex = 0, endIndex = 0;
    // String startName = StringHelper.createBlockName(start);
    // String endName = StringHelper.createBlockName(end);
    int blockIndex = 0;
    for (BasicBlock b : gblocks) {
        if (b.getNumericId() == start) {
            startBlock = b;
            startIndex = blockIndex;
        }
        if (b.getNumericId() == end) {
            endBlock = b;
            endIndex = blockIndex;
        }
        if (startBlock != null && endBlock != null) {
            break;
        }
        blockIndex++;
    }
    if (startBlock == null || endBlock == null) {
        throw new UnsupportedOperationException("start or end null, " + start + " " + end);
    } else if (startIndex > endIndex) {
        throw new IllegalArgumentException("startIndex > endIndex: " + startIndex + " > " + endIndex);
    }
    List<BasicBlock> blocks = new ArrayList<>();
    for (int i = startIndex; i <= endIndex; i++) {
        BasicBlock block = gblocks.get(i);
        if (block == null) {
            throw new IllegalArgumentException("block " + StringHelper.createBlockName(i) + "not in range");
        }
        blocks.add(block);
    }
    return blocks;
}
Also used : BasicBlock(org.mapleir.ir.cfg.BasicBlock)

Aggregations

BasicBlock (org.mapleir.ir.cfg.BasicBlock)70 Stmt (org.mapleir.ir.code.Stmt)37 Expr (org.mapleir.ir.code.Expr)34 Local (org.mapleir.ir.locals.Local)30 VarExpr (org.mapleir.ir.code.expr.VarExpr)29 CopyPhiStmt (org.mapleir.ir.code.stmt.copy.CopyPhiStmt)25 AbstractCopyStmt (org.mapleir.ir.code.stmt.copy.AbstractCopyStmt)24 CopyVarStmt (org.mapleir.ir.code.stmt.copy.CopyVarStmt)22 PhiExpr (org.mapleir.ir.code.expr.PhiExpr)19 VersionedLocal (org.mapleir.ir.locals.impl.VersionedLocal)19 HashSet (java.util.HashSet)12 ControlFlowGraph (org.mapleir.ir.cfg.ControlFlowGraph)11 UnconditionalJumpStmt (org.mapleir.ir.code.stmt.UnconditionalJumpStmt)10 InvocationExpr (org.mapleir.ir.code.expr.invoke.InvocationExpr)9 BasicLocal (org.mapleir.ir.locals.impl.BasicLocal)9 NullPermeableHashMap (org.mapleir.stdlib.collections.map.NullPermeableHashMap)9 ConditionalJumpStmt (org.mapleir.ir.code.stmt.ConditionalJumpStmt)8 Type (org.objectweb.asm.Type)7 ArrayList (java.util.ArrayList)6 ConstantExpr (org.mapleir.ir.code.expr.ConstantExpr)6