com.android.dx.rop.code.Rops Java Examples

The following examples show how to use com.android.dx.rop.code.Rops. You can vote up the ones you like or vote down the ones you don't like, and go to the original project or source file by following the links above each example. You may check out the related API usage on the sidebar.
Example #1
Source File: SsaToRop.java    From Box with Apache License 2.0 6 votes vote down vote up
/**
 * Removes all blocks containing only GOTOs from the control flow.
 * Although much of this work will be done later when converting
 * from rop to dex, not all simplification cases can be handled
 * there. Furthermore, any no-op block between the exit block and
 * blocks containing the real return or throw statements must be
 * removed.
 */
private void removeEmptyGotos() {
    final ArrayList<SsaBasicBlock> blocks = ssaMeth.getBlocks();

    ssaMeth.forEachBlockDepthFirst(false, new SsaBasicBlock.Visitor() {
        @Override
        public void visitBlock(SsaBasicBlock b, SsaBasicBlock parent) {
            ArrayList<SsaInsn> insns = b.getInsns();

            if ((insns.size() == 1)
                    && (insns.get(0).getOpcode() == Rops.GOTO)) {
                BitSet preds = (BitSet) b.getPredecessors().clone();

                for (int i = preds.nextSetBit(0); i >= 0;
                        i = preds.nextSetBit(i + 1)) {
                    SsaBasicBlock pb = blocks.get(i);
                    pb.replaceSuccessor(b.getIndex(),
                            b.getPrimarySuccessorIndex());
                }
            }
        }
    });
}
 
Example #2
Source File: SsaToRop.java    From Box with Apache License 2.0 6 votes vote down vote up
/**
 * Removes all blocks containing only GOTOs from the control flow.
 * Although much of this work will be done later when converting
 * from rop to dex, not all simplification cases can be handled
 * there. Furthermore, any no-op block between the exit block and
 * blocks containing the real return or throw statements must be
 * removed.
 */
private void removeEmptyGotos() {
    final ArrayList<SsaBasicBlock> blocks = ssaMeth.getBlocks();

    ssaMeth.forEachBlockDepthFirst(false, new SsaBasicBlock.Visitor() {
        @Override
        public void visitBlock(SsaBasicBlock b, SsaBasicBlock parent) {
            ArrayList<SsaInsn> insns = b.getInsns();

            if ((insns.size() == 1)
                    && (insns.get(0).getOpcode() == Rops.GOTO)) {
                BitSet preds = (BitSet) b.getPredecessors().clone();

                for (int i = preds.nextSetBit(0); i >= 0;
                        i = preds.nextSetBit(i + 1)) {
                    SsaBasicBlock pb = blocks.get(i);
                    pb.replaceSuccessor(b.getIndex(),
                            b.getPrimarySuccessorIndex());
                }
            }
        }
    });
}
 
Example #3
Source File: SsaToRop.java    From J2ME-Loader with Apache License 2.0 6 votes vote down vote up
/**
  * Removes all blocks containing only GOTOs from the control flow.
  * Although much of this work will be done later when converting
  * from rop to dex, not all simplification cases can be handled
  * there. Furthermore, any no-op block between the exit block and
  * blocks containing the real return or throw statements must be
  * removed.
  */
 private void removeEmptyGotos() {
     final ArrayList<SsaBasicBlock> blocks = ssaMeth.getBlocks();

     ssaMeth.forEachBlockDepthFirst(false, new SsaBasicBlock.Visitor() {
         @Override
public void visitBlock(SsaBasicBlock b, SsaBasicBlock parent) {
             ArrayList<SsaInsn> insns = b.getInsns();

             if ((insns.size() == 1)
                     && (insns.get(0).getOpcode() == Rops.GOTO)) {
                 BitSet preds = (BitSet) b.getPredecessors().clone();

                 for (int i = preds.nextSetBit(0); i >= 0;
                         i = preds.nextSetBit(i + 1)) {
                     SsaBasicBlock pb = blocks.get(i);
                     pb.replaceSuccessor(b.getIndex(),
                             b.getPrimarySuccessorIndex());
                 }
             }
         }
     });
 }
 
Example #4
Source File: SsaToRop.java    From buck with Apache License 2.0 6 votes vote down vote up
/**
 * Removes all blocks containing only GOTOs from the control flow.
 * Although much of this work will be done later when converting
 * from rop to dex, not all simplification cases can be handled
 * there. Furthermore, any no-op block between the exit block and
 * blocks containing the real return or throw statements must be
 * removed.
 */
private void removeEmptyGotos() {
    final ArrayList<SsaBasicBlock> blocks = ssaMeth.getBlocks();

    ssaMeth.forEachBlockDepthFirst(false, new SsaBasicBlock.Visitor() {
        public void visitBlock(SsaBasicBlock b, SsaBasicBlock parent) {
            ArrayList<SsaInsn> insns = b.getInsns();

            if ((insns.size() == 1)
                    && (insns.get(0).getOpcode() == Rops.GOTO)) {
                BitSet preds = (BitSet) b.getPredecessors().clone();

                for (int i = preds.nextSetBit(0); i >= 0;
                        i = preds.nextSetBit(i + 1)) {
                    SsaBasicBlock pb = blocks.get(i);
                    pb.replaceSuccessor(b.getIndex(),
                            b.getPrimarySuccessorIndex());
                }
            }
        }
    });
}
 
Example #5
Source File: Ropper.java    From Box with Apache License 2.0 5 votes vote down vote up
/**
 * Removes all {@code move-return-address} instructions, returning a new
 * {@code InsnList} if necessary. The {@code move-return-address}
 * insns are dead code after subroutines have been inlined.
 *
 * @param insns {@code InsnList} that may contain
 * {@code move-return-address} insns
 * @return {@code InsnList} with {@code move-return-address} removed
 */
private InsnList filterMoveReturnAddressInsns(InsnList insns) {
    int sz;
    int newSz = 0;

    // First see if we need to filter, and if so what the new size will be
    sz = insns.size();
    for (int i = 0; i < sz; i++) {
        if (insns.get(i).getOpcode() != Rops.MOVE_RETURN_ADDRESS) {
            newSz++;
        }
    }

    if (newSz == sz) {
        return insns;
    }

    // Make a new list without the MOVE_RETURN_ADDRESS insns
    InsnList newInsns = new InsnList(newSz);

    int newIndex = 0;
    for (int i = 0; i < sz; i++) {
        Insn insn = insns.get(i);
        if (insn.getOpcode() != Rops.MOVE_RETURN_ADDRESS) {
            newInsns.set(newIndex++, insn);
        }
    }

    newInsns.setImmutable();
    return newInsns;
}
 
Example #6
Source File: SCCP.java    From Box with Apache License 2.0 5 votes vote down vote up
/**
 * Replaces branches that have constant conditions with gotos
 */
private void replaceBranches() {
    for (SsaInsn insn : branchWorklist) {
        // Find if a successor block is never executed
        int oldSuccessor = -1;
        SsaBasicBlock block = insn.getBlock();
        int successorSize = block.getSuccessorList().size();
        for (int i = 0; i < successorSize; i++) {
            int successorBlock = block.getSuccessorList().get(i);
            if (!executableBlocks.get(successorBlock)) {
                oldSuccessor = successorBlock;
            }
        }

        /*
         * Prune branches that have already been handled and ones that no
         * longer have constant conditions (no nonexecutable successors)
         */
        if (successorSize != 2 || oldSuccessor == -1) continue;

        // Replace branch with goto
        Insn originalRopInsn = insn.getOriginalRopInsn();
        block.replaceLastInsn(new PlainInsn(Rops.GOTO,
            originalRopInsn.getPosition(), null, RegisterSpecList.EMPTY));
        block.removeSuccessor(oldSuccessor);
    }
}
 
Example #7
Source File: Ropper.java    From buck with Apache License 2.0 5 votes vote down vote up
/**
 * Removes all {@code move-return-address} instructions, returning a new
 * {@code InsnList} if necessary. The {@code move-return-address}
 * insns are dead code after subroutines have been inlined.
 *
 * @param insns {@code InsnList} that may contain
 * {@code move-return-address} insns
 * @return {@code InsnList} with {@code move-return-address} removed
 */
private InsnList filterMoveReturnAddressInsns(InsnList insns) {
    int sz;
    int newSz = 0;

    // First see if we need to filter, and if so what the new size will be
    sz = insns.size();
    for (int i = 0; i < sz; i++) {
        if (insns.get(i).getOpcode() != Rops.MOVE_RETURN_ADDRESS) {
            newSz++;
        }
    }

    if (newSz == sz) {
        return insns;
    }

    // Make a new list without the MOVE_RETURN_ADDRESS insns
    InsnList newInsns = new InsnList(newSz);

    int newIndex = 0;
    for (int i = 0; i < sz; i++) {
        Insn insn = insns.get(i);
        if (insn.getOpcode() != Rops.MOVE_RETURN_ADDRESS) {
            newInsns.set(newIndex++, insn);
        }
    }

    newInsns.setImmutable();
    return newInsns;
}
 
Example #8
Source File: ConstCollector.java    From Box with Apache License 2.0 5 votes vote down vote up
/**
 * 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);
    }
}
 
Example #9
Source File: SsaToRop.java    From Box with Apache License 2.0 5 votes vote down vote up
/**
 * Validates that a basic block is a valid end predecessor. It must
 * end in a RETURN or a THROW. Throws a runtime exception on error.
 *
 * @param b {@code non-null;} block to validate
 * @throws RuntimeException on error
 */
private void verifyValidExitPredecessor(SsaBasicBlock b) {
    ArrayList<SsaInsn> insns = b.getInsns();
    SsaInsn lastInsn = insns.get(insns.size() - 1);
    Rop opcode = lastInsn.getOpcode();

    if (opcode.getBranchingness() != Rop.BRANCH_RETURN
            && opcode != Rops.THROW) {
        throw new RuntimeException("Exit predecessor must end"
                + " in valid exit statement.");
    }
}
 
Example #10
Source File: SsaBasicBlock.java    From Box with Apache License 2.0 5 votes vote down vote up
/**
 * Adds a move instruction after the phi insn block.
 *
 * @param result move destination
 * @param source move source
 */
public void addMoveToBeginning (RegisterSpec result, RegisterSpec source) {
    if (result.getReg() == source.getReg()) {
        // Sometimes we end up with no-op moves. Ignore them here.
        return;
    }

    RegisterSpecList sources = RegisterSpecList.make(source);
    NormalSsaInsn toAdd = new NormalSsaInsn(
            new PlainInsn(Rops.opMove(result.getType()),
                    SourcePosition.NO_INFO, result, sources), this);

    insns.add(getCountPhiInsns(), toAdd);
    movesFromPhisAtBeginning++;
}
 
Example #11
Source File: Ropper.java    From Box with Apache License 2.0 5 votes vote down vote up
/**
 * Removes all {@code move-return-address} instructions, returning a new
 * {@code InsnList} if necessary. The {@code move-return-address}
 * insns are dead code after subroutines have been inlined.
 *
 * @param insns {@code InsnList} that may contain
 * {@code move-return-address} insns
 * @return {@code InsnList} with {@code move-return-address} removed
 */
private InsnList filterMoveReturnAddressInsns(InsnList insns) {
    int sz;
    int newSz = 0;

    // First see if we need to filter, and if so what the new size will be
    sz = insns.size();
    for (int i = 0; i < sz; i++) {
        if (insns.get(i).getOpcode() != Rops.MOVE_RETURN_ADDRESS) {
            newSz++;
        }
    }

    if (newSz == sz) {
        return insns;
    }

    // Make a new list without the MOVE_RETURN_ADDRESS insns
    InsnList newInsns = new InsnList(newSz);

    int newIndex = 0;
    for (int i = 0; i < sz; i++) {
        Insn insn = insns.get(i);
        if (insn.getOpcode() != Rops.MOVE_RETURN_ADDRESS) {
            newInsns.set(newIndex++, insn);
        }
    }

    newInsns.setImmutable();
    return newInsns;
}
 
Example #12
Source File: SCCP.java    From Box with Apache License 2.0 5 votes vote down vote up
/**
 * Replaces branches that have constant conditions with gotos
 */
private void replaceBranches() {
    for (SsaInsn insn : branchWorklist) {
        // Find if a successor block is never executed
        int oldSuccessor = -1;
        SsaBasicBlock block = insn.getBlock();
        int successorSize = block.getSuccessorList().size();
        for (int i = 0; i < successorSize; i++) {
            int successorBlock = block.getSuccessorList().get(i);
            if (!executableBlocks.get(successorBlock)) {
                oldSuccessor = successorBlock;
            }
        }

        /*
         * Prune branches that have already been handled and ones that no
         * longer have constant conditions (no nonexecutable successors)
         */
        if (successorSize != 2 || oldSuccessor == -1) continue;

        // Replace branch with goto
        Insn originalRopInsn = insn.getOriginalRopInsn();
        block.replaceLastInsn(new PlainInsn(Rops.GOTO,
            originalRopInsn.getPosition(), null, RegisterSpecList.EMPTY));
        block.removeSuccessor(oldSuccessor);
    }
}
 
Example #13
Source File: ConstCollector.java    From Box with Apache License 2.0 5 votes vote down vote up
/**
 * 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);
    }
}
 
Example #14
Source File: SsaToRop.java    From Box with Apache License 2.0 5 votes vote down vote up
/**
 * Validates that a basic block is a valid end predecessor. It must
 * end in a RETURN or a THROW. Throws a runtime exception on error.
 *
 * @param b {@code non-null;} block to validate
 * @throws RuntimeException on error
 */
private void verifyValidExitPredecessor(SsaBasicBlock b) {
    ArrayList<SsaInsn> insns = b.getInsns();
    SsaInsn lastInsn = insns.get(insns.size() - 1);
    Rop opcode = lastInsn.getOpcode();

    if (opcode.getBranchingness() != Rop.BRANCH_RETURN
            && opcode != Rops.THROW) {
        throw new RuntimeException("Exit predecessor must end"
                + " in valid exit statement.");
    }
}
 
Example #15
Source File: SsaBasicBlock.java    From Box with Apache License 2.0 5 votes vote down vote up
/**
 * Adds a move instruction after the phi insn block.
 *
 * @param result move destination
 * @param source move source
 */
public void addMoveToBeginning (RegisterSpec result, RegisterSpec source) {
    if (result.getReg() == source.getReg()) {
        // Sometimes we end up with no-op moves. Ignore them here.
        return;
    }

    RegisterSpecList sources = RegisterSpecList.make(source);
    NormalSsaInsn toAdd = new NormalSsaInsn(
            new PlainInsn(Rops.opMove(result.getType()),
                    SourcePosition.NO_INFO, result, sources), this);

    insns.add(getCountPhiInsns(), toAdd);
    movesFromPhisAtBeginning++;
}
 
Example #16
Source File: Code.java    From lua-for-android with BSD 3-Clause "New" or "Revised" License 5 votes vote down vote up
/**
 * Copies the constant value {@code value} to {@code target}. The constant
 * must be a primitive, String, Class, TypeId, or null.
 */
public <T> void loadConstant(Local<T> target, T value) {
    Rop rop = value == null
            ? Rops.CONST_OBJECT_NOTHROW
            : Rops.opConst(target.type.ropType);
    if (rop.getBranchingness() == BRANCH_NONE) {
        addInstruction(new PlainCstInsn(rop, sourcePosition, target.spec(),
                RegisterSpecList.EMPTY, Constants.getConstant(value)));
    } else {
        addInstruction(new ThrowingCstInsn(rop, sourcePosition,
                RegisterSpecList.EMPTY, catches, Constants.getConstant(value)));
        moveResult(target, true);
    }
}
 
Example #17
Source File: Code.java    From lua-for-android with BSD 3-Clause "New" or "Revised" License 5 votes vote down vote up
/**
 * Compare floats or doubles. This stores -1 in {@code target} if {@code
 * a < b}, 0 in {@code target} if {@code a == b} and 1 in target if {@code
 * a > b}. This stores {@code nanValue} in {@code target} if either value
 * is {@code NaN}.
 */
public <T extends Number> void compareFloatingPoint(
        Local<Integer> target, Local<T> a, Local<T> b, int nanValue) {
    Rop rop;
    if (nanValue == 1) {
        rop = Rops.opCmpg(a.type.ropType);
    } else if (nanValue == -1) {
        rop = Rops.opCmpl(a.type.ropType);
    } else {
        throw new IllegalArgumentException("expected 1 or -1 but was " + nanValue);
    }
    addInstruction(new PlainInsn(rop, sourcePosition, target.spec(),
            RegisterSpecList.make(a.spec(), b.spec())));
}
 
Example #18
Source File: SsaToRop.java    From buck with Apache License 2.0 5 votes vote down vote up
/**
 * Validates that a basic block is a valid end predecessor. It must
 * end in a RETURN or a THROW. Throws a runtime exception on error.
 *
 * @param b {@code non-null;} block to validate
 * @throws RuntimeException on error
 */
private void verifyValidExitPredecessor(SsaBasicBlock b) {
    ArrayList<SsaInsn> insns = b.getInsns();
    SsaInsn lastInsn = insns.get(insns.size() - 1);
    Rop opcode = lastInsn.getOpcode();

    if (opcode.getBranchingness() != Rop.BRANCH_RETURN
            && opcode != Rops.THROW) {
        throw new RuntimeException("Exit predecessor must end"
                + " in valid exit statement.");
    }
}
 
Example #19
Source File: Code.java    From lua-for-android with BSD 3-Clause "New" or "Revised" License 5 votes vote down vote up
/**
 * Calls the constructor {@code constructor} using {@code args} and assigns
 * the new instance to {@code target}.
 */
public <T> void newInstance(Local<T> target, MethodId<T, Void> constructor, Local<?>... args) {
    if (target == null) {
        throw new IllegalArgumentException();
    }
    addInstruction(new ThrowingCstInsn(Rops.NEW_INSTANCE, sourcePosition,
            RegisterSpecList.EMPTY, catches, constructor.declaringType.constant));
    moveResult(target, true);
    invokeDirect(constructor, null, target, args);
}
 
Example #20
Source File: ConstCollector.java    From buck with Apache License 2.0 5 votes vote down vote up
/**
 * 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);
    }
}
 
Example #21
Source File: Code.java    From lua-for-android with BSD 3-Clause "New" or "Revised" License 5 votes vote down vote up
private Rop getCastRop(com.android.dx.rop.type.Type sourceType,
                       com.android.dx.rop.type.Type targetType) {
    if (sourceType.getBasicType() == BT_INT) {
        switch (targetType.getBasicType()) {
            case BT_SHORT:
                return Rops.TO_SHORT;
            case BT_CHAR:
                return Rops.TO_CHAR;
            case BT_BYTE:
                return Rops.TO_BYTE;
        }
    }
    return Rops.opConv(targetType, sourceType);
}
 
Example #22
Source File: Code.java    From dexmaker with Apache License 2.0 5 votes vote down vote up
/**
 * Returns from a {@code void} method. After a return it is an error to
 * define further instructions after a return without first {@link #mark
 * marking} an existing unmarked label.
 */
public void returnVoid() {
    if (!method.returnType.equals(TypeId.VOID)) {
        throw new IllegalArgumentException("declared " + method.returnType
                + " but returned void");
    }
    addInstruction(new PlainInsn(Rops.RETURN_VOID, sourcePosition, null,
            RegisterSpecList.EMPTY));
}
 
Example #23
Source File: Code.java    From lua-for-android with BSD 3-Clause "New" or "Revised" License 5 votes vote down vote up
/**
 * Returns the value in {@code result} to the calling method. After a return
 * it is an error to define further instructions after a return without
 * first {@link #mark marking} an existing unmarked label.
 */
public void returnValue(Local<?> result) {
    if (!result.type.equals(method.returnType)) {
        // TODO: this is probably too strict.
        throw new IllegalArgumentException("declared " + method.returnType
                + " but returned " + result.type);
    }
    addInstruction(new PlainInsn(Rops.opReturn(result.type.ropType), sourcePosition,
            null, RegisterSpecList.make(result.spec())));
}
 
Example #24
Source File: SCCP.java    From buck with Apache License 2.0 5 votes vote down vote up
/**
 * Replaces branches that have constant conditions with gotos
 */
private void replaceBranches() {
    for (SsaInsn insn : branchWorklist) {
        // Find if a successor block is never executed
        int oldSuccessor = -1;
        SsaBasicBlock block = insn.getBlock();
        int successorSize = block.getSuccessorList().size();
        for (int i = 0; i < successorSize; i++) {
            int successorBlock = block.getSuccessorList().get(i);
            if (!executableBlocks.get(successorBlock)) {
                oldSuccessor = successorBlock;
            }
        }

        /*
         * Prune branches that have already been handled and ones that no
         * longer have constant conditions (no nonexecutable successors)
         */
        if (successorSize != 2 || oldSuccessor == -1) continue;

        // Replace branch with goto
        Insn originalRopInsn = insn.getOriginalRopInsn();
        block.replaceLastInsn(new PlainInsn(Rops.GOTO,
            originalRopInsn.getPosition(), null, RegisterSpecList.EMPTY));
        block.removeSuccessor(oldSuccessor);
    }
}
 
Example #25
Source File: Ropper.java    From J2ME-Loader with Apache License 2.0 5 votes vote down vote up
/**
 * Removes all {@code move-return-address} instructions, returning a new
 * {@code InsnList} if necessary. The {@code move-return-address}
 * insns are dead code after subroutines have been inlined.
 *
 * @param insns {@code InsnList} that may contain
 * {@code move-return-address} insns
 * @return {@code InsnList} with {@code move-return-address} removed
 */
private InsnList filterMoveReturnAddressInsns(InsnList insns) {
    int sz;
    int newSz = 0;

    // First see if we need to filter, and if so what the new size will be
    sz = insns.size();
    for (int i = 0; i < sz; i++) {
        if (insns.get(i).getOpcode() != Rops.MOVE_RETURN_ADDRESS) {
            newSz++;
        }
    }

    if (newSz == sz) {
        return insns;
    }

    // Make a new list without the MOVE_RETURN_ADDRESS insns
    InsnList newInsns = new InsnList(newSz);

    int newIndex = 0;
    for (int i = 0; i < sz; i++) {
        Insn insn = insns.get(i);
        if (insn.getOpcode() != Rops.MOVE_RETURN_ADDRESS) {
            newInsns.set(newIndex++, insn);
        }
    }

    newInsns.setImmutable();
    return newInsns;
}
 
Example #26
Source File: SCCP.java    From J2ME-Loader with Apache License 2.0 5 votes vote down vote up
/**
 * Replaces branches that have constant conditions with gotos
 */
private void replaceBranches() {
    for (SsaInsn insn : branchWorklist) {
        // Find if a successor block is never executed
        int oldSuccessor = -1;
        SsaBasicBlock block = insn.getBlock();
        int successorSize = block.getSuccessorList().size();
        for (int i = 0; i < successorSize; i++) {
            int successorBlock = block.getSuccessorList().get(i);
            if (!executableBlocks.get(successorBlock)) {
                oldSuccessor = successorBlock;
            }
        }

        /*
         * Prune branches that have already been handled and ones that no
         * longer have constant conditions (no nonexecutable successors)
         */
        if (successorSize != 2 || oldSuccessor == -1) continue;

        // Replace branch with goto
        Insn originalRopInsn = insn.getOriginalRopInsn();
        block.replaceLastInsn(new PlainInsn(Rops.GOTO,
            originalRopInsn.getPosition(), null, RegisterSpecList.EMPTY));
        block.removeSuccessor(oldSuccessor);
    }
}
 
Example #27
Source File: Code.java    From dexmaker with Apache License 2.0 5 votes vote down vote up
private Rop getCastRop(com.android.dx.rop.type.Type sourceType,
        com.android.dx.rop.type.Type targetType) {
    if (sourceType.getBasicType() == BT_INT) {
        switch (targetType.getBasicType()) {
        case BT_SHORT:
            return Rops.TO_SHORT;
        case BT_CHAR:
            return Rops.TO_CHAR;
        case BT_BYTE:
            return Rops.TO_BYTE;
        }
    }
    return Rops.opConv(targetType, sourceType);
}
 
Example #28
Source File: ConstCollector.java    From J2ME-Loader with Apache License 2.0 5 votes vote down vote up
/**
 * 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);
    }
}
 
Example #29
Source File: Code.java    From dexmaker with Apache License 2.0 5 votes vote down vote up
/**
 * Returns the value in {@code result} to the calling method. After a return
 * it is an error to define further instructions after a return without
 * first {@link #mark marking} an existing unmarked label.
 */
public void returnValue(Local<?> result) {
    if (!result.type.equals(method.returnType)) {
        // TODO: this is probably too strict.
        throw new IllegalArgumentException("declared " + method.returnType
                + " but returned " + result.type);
    }
    addInstruction(new PlainInsn(Rops.opReturn(result.type.ropType), sourcePosition,
            null, RegisterSpecList.make(result.spec())));
}
 
Example #30
Source File: SsaToRop.java    From J2ME-Loader with Apache License 2.0 5 votes vote down vote up
/**
 * Validates that a basic block is a valid end predecessor. It must
 * end in a RETURN or a THROW. Throws a runtime exception on error.
 *
 * @param b {@code non-null;} block to validate
 * @throws RuntimeException on error
 */
private void verifyValidExitPredecessor(SsaBasicBlock b) {
    ArrayList<SsaInsn> insns = b.getInsns();
    SsaInsn lastInsn = insns.get(insns.size() - 1);
    Rop opcode = lastInsn.getOpcode();

    if (opcode.getBranchingness() != Rop.BRANCH_RETURN
            && opcode != Rops.THROW) {
        throw new RuntimeException("Exit predecessor must end"
                + " in valid exit statement.");
    }
}