use of jadx.core.dex.instructions.ArithNode in project jadx by skylot.
the class LoopRegionVisitor method checkArrayForEach.
private static LoopType checkArrayForEach(MethodNode mth, InsnNode initInsn, InsnNode incrInsn, IfCondition condition) {
if (!(incrInsn instanceof ArithNode)) {
return null;
}
ArithNode arithNode = (ArithNode) incrInsn;
if (arithNode.getOp() != ArithOp.ADD) {
return null;
}
InsnArg lit = incrInsn.getArg(1);
if (!lit.isLiteral() || ((LiteralArg) lit).getLiteral() != 1) {
return null;
}
if (initInsn.getType() != InsnType.CONST || !initInsn.getArg(0).isLiteral() || ((LiteralArg) initInsn.getArg(0)).getLiteral() != 0) {
return null;
}
InsnArg condArg = incrInsn.getArg(0);
if (!condArg.isRegister()) {
return null;
}
SSAVar sVar = ((RegisterArg) condArg).getSVar();
List<RegisterArg> args = sVar.getUseList();
if (args.size() != 3 || args.get(2) != condArg) {
return null;
}
condArg = args.get(0);
RegisterArg arrIndex = args.get(1);
InsnNode arrGetInsn = arrIndex.getParentInsn();
if (arrGetInsn == null || arrGetInsn.getType() != InsnType.AGET) {
return null;
}
if (!condition.isCompare()) {
return null;
}
Compare compare = condition.getCompare();
if (compare.getOp() != IfOp.LT || compare.getA() != condArg) {
return null;
}
InsnNode len;
InsnArg bCondArg = compare.getB();
if (bCondArg.isInsnWrap()) {
len = ((InsnWrapArg) bCondArg).getWrapInsn();
} else if (bCondArg.isRegister()) {
len = ((RegisterArg) bCondArg).getAssignInsn();
} else {
return null;
}
if (len == null || len.getType() != InsnType.ARRAY_LENGTH) {
return null;
}
InsnArg arrayArg = len.getArg(0);
if (!arrayArg.equals(arrGetInsn.getArg(0))) {
return null;
}
RegisterArg iterVar = arrGetInsn.getResult();
if (iterVar == null) {
return null;
}
// array for each loop confirmed
len.add(AFlag.SKIP);
arrGetInsn.add(AFlag.SKIP);
InstructionRemover.unbindInsn(mth, len);
// inline array variable
CodeShrinker.shrinkMethod(mth);
if (arrGetInsn.contains(AFlag.WRAPPED)) {
InsnArg wrapArg = BlockUtils.searchWrappedInsnParent(mth, arrGetInsn);
if (wrapArg != null && wrapArg.getParentInsn() != null) {
wrapArg.getParentInsn().replaceArg(wrapArg, iterVar);
} else {
LOG.debug(" checkArrayForEach: Wrapped insn not found: {}, mth: {}", arrGetInsn, mth);
}
}
return new ForEachLoop(iterVar, len.getArg(0));
}
use of jadx.core.dex.instructions.ArithNode in project jadx by skylot.
the class SimplifyVisitor method simplifyArith.
private static InsnNode simplifyArith(InsnNode insn) {
ArithNode arith = (ArithNode) insn;
if (arith.getArgsCount() != 2) {
return null;
}
InsnArg litArg = null;
InsnArg secondArg = arith.getArg(1);
if (secondArg.isInsnWrap()) {
InsnNode wr = ((InsnWrapArg) secondArg).getWrapInsn();
if (wr.getType() == InsnType.CONST) {
litArg = wr.getArg(0);
}
} else if (secondArg.isLiteral()) {
litArg = secondArg;
}
if (litArg != null) {
long lit = ((LiteralArg) litArg).getLiteral();
// fix 'c + (-1)' => 'c - (1)'
if (arith.getOp() == ArithOp.ADD && lit < 0) {
return new ArithNode(ArithOp.SUB, arith.getResult(), insn.getArg(0), InsnArg.lit(-lit, litArg.getType()));
}
}
return null;
}
use of jadx.core.dex.instructions.ArithNode in project jadx by skylot.
the class ModVisitor method replaceStep.
private static void replaceStep(MethodNode mth, InstructionRemover remover) {
ClassNode parentClass = mth.getParentClass();
for (BlockNode block : mth.getBasicBlocks()) {
remover.setBlock(block);
int size = block.getInstructions().size();
for (int i = 0; i < size; i++) {
InsnNode insn = block.getInstructions().get(i);
switch(insn.getType()) {
case INVOKE:
processInvoke(mth, block, i, remover);
break;
case CONST:
case CONST_STR:
case CONST_CLASS:
{
FieldNode f;
if (insn.getType() == InsnType.CONST_STR) {
String s = ((ConstStringNode) insn).getString();
f = parentClass.getConstField(s);
} else if (insn.getType() == InsnType.CONST_CLASS) {
ArgType t = ((ConstClassNode) insn).getClsType();
f = parentClass.getConstField(t);
} else {
f = parentClass.getConstFieldByLiteralArg((LiteralArg) insn.getArg(0));
}
if (f != null) {
InsnNode inode = new IndexInsnNode(InsnType.SGET, f.getFieldInfo(), 0);
inode.setResult(insn.getResult());
replaceInsn(block, i, inode);
}
break;
}
case SWITCH:
SwitchNode sn = (SwitchNode) insn;
for (int k = 0; k < sn.getCasesCount(); k++) {
FieldNode f = parentClass.getConstField(sn.getKeys()[k]);
if (f != null) {
sn.getKeys()[k] = f;
}
}
break;
case NEW_ARRAY:
// create array in 'fill-array' instruction
int next = i + 1;
if (next < size) {
InsnNode ni = block.getInstructions().get(next);
if (ni.getType() == InsnType.FILL_ARRAY) {
ni.getResult().merge(mth.dex(), insn.getResult());
ArgType arrType = ((NewArrayNode) insn).getArrayType();
((FillArrayNode) ni).mergeElementType(mth.dex(), arrType.getArrayElement());
remover.add(insn);
}
}
break;
case FILL_ARRAY:
InsnNode filledArr = makeFilledArrayInsn(mth, (FillArrayNode) insn);
replaceInsn(block, i, filledArr);
break;
case MOVE_EXCEPTION:
processMoveException(mth, block, insn, remover);
break;
case ARITH:
ArithNode arithNode = (ArithNode) insn;
if (arithNode.getArgsCount() == 2) {
InsnArg litArg = arithNode.getArg(1);
if (litArg.isLiteral()) {
FieldNode f = parentClass.getConstFieldByLiteralArg((LiteralArg) litArg);
if (f != null) {
InsnNode fGet = new IndexInsnNode(InsnType.SGET, f.getFieldInfo(), 0);
insn.replaceArg(litArg, InsnArg.wrapArg(fGet));
}
}
}
break;
default:
break;
}
}
remover.perform();
}
}
use of jadx.core.dex.instructions.ArithNode in project jadx by skylot.
the class PrepareForCodeGen method checkInsn.
/**
* Remove parenthesis for wrapped insn in arith '+' or '-'
* ('(a + b) +c' => 'a + b + c')
*/
private static void checkInsn(InsnNode insn) {
if (insn.getType() == InsnType.ARITH) {
ArithNode arith = (ArithNode) insn;
ArithOp op = arith.getOp();
if (op == ArithOp.ADD || op == ArithOp.SUB) {
for (int i = 0; i < 2; i++) {
InsnArg arg = arith.getArg(i);
if (arg.isInsnWrap()) {
InsnNode wrapInsn = ((InsnWrapArg) arg).getWrapInsn();
wrapInsn.add(AFlag.DONT_WRAP);
checkInsn(wrapInsn);
}
}
}
} else {
for (InsnArg arg : insn.getArguments()) {
if (arg.isInsnWrap()) {
InsnNode wrapInsn = ((InsnWrapArg) arg).getWrapInsn();
checkInsn(wrapInsn);
}
}
}
}
use of jadx.core.dex.instructions.ArithNode in project jadx by skylot.
the class ConditionGen method isArgWrapNeeded.
private static boolean isArgWrapNeeded(InsnArg arg) {
if (!arg.isInsnWrap()) {
return false;
}
InsnNode insn = ((InsnWrapArg) arg).getWrapInsn();
InsnType insnType = insn.getType();
if (insnType == InsnType.ARITH) {
switch(((ArithNode) insn).getOp()) {
case ADD:
case SUB:
case MUL:
case DIV:
case REM:
return false;
}
} else {
switch(insnType) {
case INVOKE:
case SGET:
case IGET:
case AGET:
case CONST:
case ARRAY_LENGTH:
return false;
default:
return true;
}
}
return true;
}
Aggregations