Search in sources :

Example 6 with PlainInsn

use of com.android.dx.rop.code.PlainInsn in project buck by facebook.

the class Ropper method addSetupBlocks.

/**
     * Constructs and adds the blocks that perform setup for the rest of
     * the method. This includes a first block which merely contains
     * assignments from parameters to the same-numbered registers and
     * a possible second block which deals with synchronization.
     */
private void addSetupBlocks() {
    LocalVariableList localVariables = method.getLocalVariables();
    SourcePosition pos = method.makeSourcePosistion(0);
    Prototype desc = method.getEffectiveDescriptor();
    StdTypeList params = desc.getParameterTypes();
    int sz = params.size();
    InsnList insns = new InsnList(sz + 1);
    int at = 0;
    for (int i = 0; i < sz; i++) {
        Type one = params.get(i);
        LocalVariableList.Item local = localVariables.pcAndIndexToLocal(0, at);
        RegisterSpec result = (local == null) ? RegisterSpec.make(at, one) : RegisterSpec.makeLocalOptional(at, one, local.getLocalItem());
        Insn insn = new PlainCstInsn(Rops.opMoveParam(one), pos, result, RegisterSpecList.EMPTY, CstInteger.make(at));
        insns.set(i, insn);
        at += one.getCategory();
    }
    insns.set(sz, new PlainInsn(Rops.GOTO, pos, null, RegisterSpecList.EMPTY));
    insns.setImmutable();
    boolean synch = isSynchronized();
    int label = synch ? getSpecialLabel(SYNCH_SETUP_1) : 0;
    BasicBlock bb = new BasicBlock(getSpecialLabel(PARAM_ASSIGNMENT), insns, IntList.makeImmutable(label), label);
    addBlock(bb, IntList.EMPTY);
    if (synch) {
        RegisterSpec synchReg = getSynchReg();
        Insn insn;
        if (isStatic()) {
            insn = new ThrowingCstInsn(Rops.CONST_OBJECT, pos, RegisterSpecList.EMPTY, StdTypeList.EMPTY, method.getDefiningClass());
            insns = new InsnList(1);
            insns.set(0, insn);
        } else {
            insns = new InsnList(2);
            insn = new PlainCstInsn(Rops.MOVE_PARAM_OBJECT, pos, synchReg, RegisterSpecList.EMPTY, CstInteger.VALUE_0);
            insns.set(0, insn);
            insns.set(1, new PlainInsn(Rops.GOTO, pos, null, RegisterSpecList.EMPTY));
        }
        int label2 = getSpecialLabel(SYNCH_SETUP_2);
        insns.setImmutable();
        bb = new BasicBlock(label, insns, IntList.makeImmutable(label2), label2);
        addBlock(bb, IntList.EMPTY);
        insns = new InsnList(isStatic() ? 2 : 1);
        if (isStatic()) {
            insns.set(0, new PlainInsn(Rops.opMoveResultPseudo(synchReg), pos, synchReg, RegisterSpecList.EMPTY));
        }
        insn = new ThrowingInsn(Rops.MONITOR_ENTER, pos, RegisterSpecList.make(synchReg), StdTypeList.EMPTY);
        insns.set(isStatic() ? 1 : 0, insn);
        insns.setImmutable();
        bb = new BasicBlock(label2, insns, IntList.makeImmutable(0), 0);
        addBlock(bb, IntList.EMPTY);
    }
}
Also used : ThrowingCstInsn(com.android.dx.rop.code.ThrowingCstInsn) ThrowingInsn(com.android.dx.rop.code.ThrowingInsn) PlainInsn(com.android.dx.rop.code.PlainInsn) Insn(com.android.dx.rop.code.Insn) PlainCstInsn(com.android.dx.rop.code.PlainCstInsn) Prototype(com.android.dx.rop.type.Prototype) ThrowingCstInsn(com.android.dx.rop.code.ThrowingCstInsn) BasicBlock(com.android.dx.rop.code.BasicBlock) InsnList(com.android.dx.rop.code.InsnList) ThrowingInsn(com.android.dx.rop.code.ThrowingInsn) PlainCstInsn(com.android.dx.rop.code.PlainCstInsn) PlainInsn(com.android.dx.rop.code.PlainInsn) Type(com.android.dx.rop.type.Type) CstType(com.android.dx.rop.cst.CstType) StdTypeList(com.android.dx.rop.type.StdTypeList) SourcePosition(com.android.dx.rop.code.SourcePosition) RegisterSpec(com.android.dx.rop.code.RegisterSpec)

Example 7 with PlainInsn

use of com.android.dx.rop.code.PlainInsn in project buck by facebook.

the class Ropper method addSynchExceptionHandlerBlock.

/**
     * Constructs and adds, if necessary, the catch-all exception handler
     * block to deal with unwinding the lock taken on entry to a synchronized
     * method.
     */
private void addSynchExceptionHandlerBlock() {
    if (!synchNeedsExceptionHandler) {
        /*
             * The method being converted either isn't synchronized or
             * can't possibly throw exceptions in its main body, so
             * there's no need for a synchronized method exception
             * handler.
             */
        return;
    }
    SourcePosition pos = method.makeSourcePosistion(0);
    RegisterSpec exReg = RegisterSpec.make(0, Type.THROWABLE);
    BasicBlock bb;
    Insn insn;
    InsnList insns = new InsnList(2);
    insn = new PlainInsn(Rops.opMoveException(Type.THROWABLE), pos, exReg, RegisterSpecList.EMPTY);
    insns.set(0, insn);
    insn = new ThrowingInsn(Rops.MONITOR_EXIT, pos, RegisterSpecList.make(getSynchReg()), StdTypeList.EMPTY);
    insns.set(1, insn);
    insns.setImmutable();
    int label2 = getSpecialLabel(SYNCH_CATCH_2);
    bb = new BasicBlock(getSpecialLabel(SYNCH_CATCH_1), insns, IntList.makeImmutable(label2), label2);
    addBlock(bb, IntList.EMPTY);
    insns = new InsnList(1);
    insn = new ThrowingInsn(Rops.THROW, pos, RegisterSpecList.make(exReg), StdTypeList.EMPTY);
    insns.set(0, insn);
    insns.setImmutable();
    bb = new BasicBlock(label2, insns, IntList.EMPTY, -1);
    addBlock(bb, IntList.EMPTY);
}
Also used : PlainInsn(com.android.dx.rop.code.PlainInsn) ThrowingCstInsn(com.android.dx.rop.code.ThrowingCstInsn) ThrowingInsn(com.android.dx.rop.code.ThrowingInsn) PlainInsn(com.android.dx.rop.code.PlainInsn) Insn(com.android.dx.rop.code.Insn) PlainCstInsn(com.android.dx.rop.code.PlainCstInsn) SourcePosition(com.android.dx.rop.code.SourcePosition) BasicBlock(com.android.dx.rop.code.BasicBlock) InsnList(com.android.dx.rop.code.InsnList) ThrowingInsn(com.android.dx.rop.code.ThrowingInsn) RegisterSpec(com.android.dx.rop.code.RegisterSpec)

Example 8 with PlainInsn

use of com.android.dx.rop.code.PlainInsn in project buck by facebook.

the class RegisterAllocator method insertMoveBefore.

/**
     * Inserts a move instruction for a specified SSA register before a
     * specified instruction, creating a new SSA register and adjusting the
     * interference graph in the process. The insn currently must be the
     * last insn in a block.
     *
     * @param insn {@code non-null;} insn to insert move before, must
     * be last insn in block
     * @param reg {@code non-null;} SSA register to duplicate
     * @return {@code non-null;} spec of new SSA register created by move
     */
protected final RegisterSpec insertMoveBefore(SsaInsn insn, RegisterSpec reg) {
    SsaBasicBlock block = insn.getBlock();
    ArrayList<SsaInsn> insns = block.getInsns();
    int insnIndex = insns.indexOf(insn);
    if (insnIndex < 0) {
        throw new IllegalArgumentException("specified insn is not in this block");
    }
    if (insnIndex != insns.size() - 1) {
        /*
             * Presently, the interference updater only works when
             * adding before the last insn, and the last insn must have no
             * result
             */
        throw new IllegalArgumentException("Adding move here not supported:" + insn.toHuman());
    }
    /*
         * Get new register and make new move instruction.
         */
    // The new result must not have an associated local variable.
    RegisterSpec newRegSpec = RegisterSpec.make(ssaMeth.makeNewSsaReg(), reg.getTypeBearer());
    SsaInsn toAdd = SsaInsn.makeFromRop(new PlainInsn(Rops.opMove(newRegSpec.getType()), SourcePosition.NO_INFO, newRegSpec, RegisterSpecList.make(reg)), block);
    insns.add(insnIndex, toAdd);
    int newReg = newRegSpec.getReg();
    /*
         * Adjust interference graph based on what's live out of the current
         * block and what's used by the final instruction.
         */
    IntSet liveOut = block.getLiveOutRegs();
    IntIterator liveOutIter = liveOut.iterator();
    while (liveOutIter.hasNext()) {
        interference.add(newReg, liveOutIter.next());
    }
    // Everything that's a source in the last insn interferes.
    RegisterSpecList sources = insn.getSources();
    int szSources = sources.size();
    for (int i = 0; i < szSources; i++) {
        interference.add(newReg, sources.get(i).getReg());
    }
    ssaMeth.onInsnsChanged();
    return newRegSpec;
}
Also used : PlainInsn(com.android.dx.rop.code.PlainInsn) IntIterator(com.android.dx.util.IntIterator) IntSet(com.android.dx.util.IntSet) SsaBasicBlock(com.android.dx.ssa.SsaBasicBlock) NormalSsaInsn(com.android.dx.ssa.NormalSsaInsn) SsaInsn(com.android.dx.ssa.SsaInsn) RegisterSpecList(com.android.dx.rop.code.RegisterSpecList) RegisterSpec(com.android.dx.rop.code.RegisterSpec)

Example 9 with PlainInsn

use of com.android.dx.rop.code.PlainInsn in project buck by facebook.

the class SsaMethod method deleteInsns.

/**
     * Deletes all insns in the set from this method.
     *
     * @param deletedInsns {@code non-null;} insns to delete
     */
public void deleteInsns(Set<SsaInsn> deletedInsns) {
    for (SsaBasicBlock block : getBlocks()) {
        ArrayList<SsaInsn> insns = block.getInsns();
        for (int i = insns.size() - 1; i >= 0; i--) {
            SsaInsn insn = insns.get(i);
            if (deletedInsns.contains(insn)) {
                onInsnRemoved(insn);
                insns.remove(i);
            }
        }
        // Check to see if we need to add a GOTO
        int insnsSz = insns.size();
        SsaInsn lastInsn = (insnsSz == 0) ? null : insns.get(insnsSz - 1);
        if (block != getExitBlock() && (insnsSz == 0 || lastInsn.getOriginalRopInsn() == null || lastInsn.getOriginalRopInsn().getOpcode().getBranchingness() == Rop.BRANCH_NONE)) {
            // We managed to eat a throwable insn
            Insn gotoInsn = new PlainInsn(Rops.GOTO, SourcePosition.NO_INFO, null, RegisterSpecList.EMPTY);
            insns.add(SsaInsn.makeFromRop(gotoInsn, block));
            // Remove secondary successors from this block
            BitSet succs = block.getSuccessors();
            for (int i = succs.nextSetBit(0); i >= 0; i = succs.nextSetBit(i + 1)) {
                if (i != block.getPrimarySuccessorIndex()) {
                    block.removeSuccessor(i);
                }
            }
        }
    }
}
Also used : PlainInsn(com.android.dx.rop.code.PlainInsn) Insn(com.android.dx.rop.code.Insn) PlainInsn(com.android.dx.rop.code.PlainInsn) BitSet(java.util.BitSet)

Example 10 with PlainInsn

use of com.android.dx.rop.code.PlainInsn in project buck by facebook.

the class ConstCollector method fixLocalAssignment.

/**
     * Inserts mark-locals if necessary when changing a register. If
     * the definition of {@code origReg} is associated with a local
     * variable, then insert a mark-local for {@code newReg} just below
     * it. We expect the definition of  {@code origReg} to ultimately
     * be removed by the dead code eliminator
     *
     * @param origReg {@code non-null;} original register
     * @param newReg {@code non-null;} new register that will replace
     * {@code origReg}
     */
private void fixLocalAssignment(RegisterSpec origReg, RegisterSpec newReg) {
    for (SsaInsn use : ssaMeth.getUseListForRegister(origReg.getReg())) {
        RegisterSpec localAssignment = use.getLocalAssignment();
        if (localAssignment == null) {
            continue;
        }
        if (use.getResult() == null) {
            /*
                 * This is a mark-local. it will be updated when all uses
                 * are updated.
                 */
            continue;
        }
        LocalItem local = localAssignment.getLocalItem();
        // Un-associate original use.
        use.setResultLocal(null);
        // Now add a mark-local to the new reg immediately after.
        newReg = newReg.withLocalItem(local);
        SsaInsn newInsn = SsaInsn.makeFromRop(new PlainInsn(Rops.opMarkLocal(newReg), SourcePosition.NO_INFO, null, RegisterSpecList.make(newReg)), use.getBlock());
        ArrayList<SsaInsn> insns = use.getBlock().getInsns();
        insns.add(insns.indexOf(use) + 1, newInsn);
    }
}
Also used : PlainInsn(com.android.dx.rop.code.PlainInsn) LocalItem(com.android.dx.rop.code.LocalItem) RegisterSpec(com.android.dx.rop.code.RegisterSpec)

Aggregations

PlainInsn (com.android.dx.rop.code.PlainInsn)17 Insn (com.android.dx.rop.code.Insn)10 PlainCstInsn (com.android.dx.rop.code.PlainCstInsn)9 RegisterSpec (com.android.dx.rop.code.RegisterSpec)9 ThrowingCstInsn (com.android.dx.rop.code.ThrowingCstInsn)8 ThrowingInsn (com.android.dx.rop.code.ThrowingInsn)7 RegisterSpecList (com.android.dx.rop.code.RegisterSpecList)6 SourcePosition (com.android.dx.rop.code.SourcePosition)6 BasicBlock (com.android.dx.rop.code.BasicBlock)5 InsnList (com.android.dx.rop.code.InsnList)5 Rop (com.android.dx.rop.code.Rop)5 CstType (com.android.dx.rop.cst.CstType)3 FillArrayDataInsn (com.android.dx.rop.code.FillArrayDataInsn)2 StdTypeList (com.android.dx.rop.type.StdTypeList)2 Type (com.android.dx.rop.type.Type)2 IntList (com.android.dx.util.IntList)2 BitSet (java.util.BitSet)2 CstInsn (com.android.dx.rop.code.CstInsn)1 LocalItem (com.android.dx.rop.code.LocalItem)1 SwitchInsn (com.android.dx.rop.code.SwitchInsn)1