Search in sources :

Example 1 with ForLoop

use of jadx.core.dex.regions.loops.ForLoop in project jadx by skylot.

the class LoopRegionVisitor method checkForIndexedLoop.

/**
	 * Check for indexed loop.
	 */
private static boolean checkForIndexedLoop(MethodNode mth, LoopRegion loopRegion, IfCondition condition) {
    InsnNode incrInsn = RegionUtils.getLastInsn(loopRegion);
    if (incrInsn == null) {
        return false;
    }
    RegisterArg incrArg = incrInsn.getResult();
    if (incrArg == null || incrArg.getSVar() == null || !incrArg.getSVar().isUsedInPhi()) {
        return false;
    }
    PhiInsn phiInsn = incrArg.getSVar().getUsedInPhi();
    if (phiInsn == null || phiInsn.getArgsCount() != 2 || !phiInsn.getArg(1).equals(incrArg) || incrArg.getSVar().getUseCount() != 1) {
        return false;
    }
    RegisterArg arg = phiInsn.getResult();
    List<RegisterArg> condArgs = condition.getRegisterArgs();
    if (!condArgs.contains(arg) || arg.getSVar().isUsedInPhi()) {
        return false;
    }
    RegisterArg initArg = phiInsn.getArg(0);
    InsnNode initInsn = initArg.getAssignInsn();
    if (initInsn == null || initArg.getSVar().getUseCount() != 1) {
        return false;
    }
    if (!usedOnlyInLoop(mth, loopRegion, arg)) {
        return false;
    }
    // can't make loop if argument from increment instruction is assign in loop
    List<RegisterArg> args = new LinkedList<RegisterArg>();
    incrInsn.getRegisterArgs(args);
    for (RegisterArg iArg : args) {
        if (assignOnlyInLoop(mth, loopRegion, iArg)) {
            return false;
        }
    }
    // all checks passed
    initInsn.add(AFlag.SKIP);
    incrInsn.add(AFlag.SKIP);
    LoopType arrForEach = checkArrayForEach(mth, initInsn, incrInsn, condition);
    if (arrForEach != null) {
        loopRegion.setType(arrForEach);
        return true;
    }
    loopRegion.setType(new ForLoop(initInsn, incrInsn));
    return true;
}
Also used : InsnNode(jadx.core.dex.nodes.InsnNode) RegisterArg(jadx.core.dex.instructions.args.RegisterArg) PhiInsn(jadx.core.dex.instructions.PhiInsn) ForLoop(jadx.core.dex.regions.loops.ForLoop) LoopType(jadx.core.dex.regions.loops.LoopType) LinkedList(java.util.LinkedList)

Example 2 with ForLoop

use of jadx.core.dex.regions.loops.ForLoop in project jadx by skylot.

the class RegionGen method makeLoop.

private CodeWriter makeLoop(LoopRegion region, CodeWriter code) throws CodegenException {
    BlockNode header = region.getHeader();
    if (header != null) {
        List<InsnNode> headerInsns = header.getInstructions();
        if (headerInsns.size() > 1) {
            ErrorsCounter.methodError(mth, "Found not inlined instructions from loop header");
            int last = headerInsns.size() - 1;
            for (int i = 0; i < last; i++) {
                InsnNode insn = headerInsns.get(i);
                makeInsn(insn, code);
            }
        }
    }
    LoopLabelAttr labelAttr = region.getInfo().getStart().get(AType.LOOP_LABEL);
    if (labelAttr != null) {
        code.startLine(mgen.getNameGen().getLoopLabel(labelAttr)).add(':');
    }
    IfCondition condition = region.getCondition();
    if (condition == null) {
        // infinite loop
        code.startLine("while (true) {");
        makeRegionIndent(code, region.getBody());
        code.startLine('}');
        return code;
    }
    ConditionGen conditionGen = new ConditionGen(this);
    LoopType type = region.getType();
    if (type != null) {
        if (type instanceof ForLoop) {
            ForLoop forLoop = (ForLoop) type;
            code.startLine("for (");
            makeInsn(forLoop.getInitInsn(), code, Flags.INLINE);
            code.add("; ");
            conditionGen.add(code, condition);
            code.add("; ");
            makeInsn(forLoop.getIncrInsn(), code, Flags.INLINE);
            code.add(") {");
            makeRegionIndent(code, region.getBody());
            code.startLine('}');
            return code;
        }
        if (type instanceof ForEachLoop) {
            ForEachLoop forEachLoop = (ForEachLoop) type;
            code.startLine("for (");
            declareVar(code, forEachLoop.getVarArg());
            code.add(" : ");
            addArg(code, forEachLoop.getIterableArg(), false);
            code.add(") {");
            makeRegionIndent(code, region.getBody());
            code.startLine('}');
            return code;
        }
        throw new JadxRuntimeException("Unknown loop type: " + type.getClass());
    }
    if (region.isConditionAtEnd()) {
        code.startLine("do {");
        makeRegionIndent(code, region.getBody());
        code.startLine("} while (");
        conditionGen.add(code, condition);
        code.add(");");
    } else {
        code.startLine("while (");
        conditionGen.add(code, condition);
        code.add(") {");
        makeRegionIndent(code, region.getBody());
        code.startLine('}');
    }
    return code;
}
Also used : BlockNode(jadx.core.dex.nodes.BlockNode) InsnNode(jadx.core.dex.nodes.InsnNode) ForLoop(jadx.core.dex.regions.loops.ForLoop) LoopLabelAttr(jadx.core.dex.attributes.nodes.LoopLabelAttr) LoopType(jadx.core.dex.regions.loops.LoopType) JadxRuntimeException(jadx.core.utils.exceptions.JadxRuntimeException) IfCondition(jadx.core.dex.regions.conditions.IfCondition) ForEachLoop(jadx.core.dex.regions.loops.ForEachLoop)

Aggregations

InsnNode (jadx.core.dex.nodes.InsnNode)2 ForLoop (jadx.core.dex.regions.loops.ForLoop)2 LoopType (jadx.core.dex.regions.loops.LoopType)2 LoopLabelAttr (jadx.core.dex.attributes.nodes.LoopLabelAttr)1 PhiInsn (jadx.core.dex.instructions.PhiInsn)1 RegisterArg (jadx.core.dex.instructions.args.RegisterArg)1 BlockNode (jadx.core.dex.nodes.BlockNode)1 IfCondition (jadx.core.dex.regions.conditions.IfCondition)1 ForEachLoop (jadx.core.dex.regions.loops.ForEachLoop)1 JadxRuntimeException (jadx.core.utils.exceptions.JadxRuntimeException)1 LinkedList (java.util.LinkedList)1