use of jadx.core.dex.nodes.BlockNode in project jadx by skylot.
the class LoopRegionVisitor method checkForIndexedLoop.
/**
* Check for indexed loop.
*/
private static boolean checkForIndexedLoop(MethodNode mth, LoopRegion loopRegion, IfCondition condition) {
BlockNode loopEndBlock = loopRegion.getInfo().getEnd();
InsnNode incrInsn = BlockUtils.getLastInsn(BlockUtils.skipSyntheticPredecessor(loopEndBlock));
if (incrInsn == null) {
return false;
}
RegisterArg incrArg = incrInsn.getResult();
if (incrArg == null || incrArg.getSVar() == null || !incrArg.getSVar().isUsedInPhi()) {
return false;
}
List<PhiInsn> phiInsnList = incrArg.getSVar().getUsedInPhi();
if (phiInsnList.size() != 1) {
return false;
}
PhiInsn phiInsn = phiInsnList.get(0);
if (phiInsn.getArgsCount() != 2 || !phiInsn.containsVar(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 || initInsn.contains(AFlag.DONT_GENERATE) || 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<>();
incrInsn.getRegisterArgs(args);
for (RegisterArg iArg : args) {
try {
if (assignOnlyInLoop(mth, loopRegion, iArg)) {
return false;
}
} catch (StackOverflowError error) {
throw new JadxOverflowException("LoopRegionVisitor.assignOnlyInLoop endless recursion");
}
}
// all checks passed
initInsn.add(AFlag.DONT_GENERATE);
incrInsn.add(AFlag.DONT_GENERATE);
LoopType arrForEach = checkArrayForEach(mth, loopRegion, initInsn, incrInsn, condition);
loopRegion.setType(arrForEach != null ? arrForEach : new ForLoop(initInsn, incrInsn));
return true;
}
use of jadx.core.dex.nodes.BlockNode in project jadx by skylot.
the class BlockProcessor method computeBlockDF.
private static void computeBlockDF(MethodNode mth, BlockNode block) {
if (block.getDomFrontier() != null) {
return;
}
List<BlockNode> blocks = mth.getBasicBlocks();
BitSet domFrontier = null;
for (BlockNode s : block.getSuccessors()) {
if (s.getIDom() != block) {
if (domFrontier == null) {
domFrontier = new BitSet(blocks.size());
}
domFrontier.set(s.getId());
}
}
for (BlockNode c : block.getDominatesOn()) {
BitSet frontier = c.getDomFrontier();
if (frontier == null) {
throw new JadxRuntimeException("Dominance frontier not calculated for dominated block: " + c + ", from: " + block);
}
for (int p = frontier.nextSetBit(0); p >= 0; p = frontier.nextSetBit(p + 1)) {
if (blocks.get(p).getIDom() != block) {
if (domFrontier == null) {
domFrontier = new BitSet(blocks.size());
}
domFrontier.set(p);
}
}
}
if (domFrontier == null || domFrontier.isEmpty()) {
domFrontier = EMPTY;
}
block.setDomFrontier(domFrontier);
}
use of jadx.core.dex.nodes.BlockNode in project jadx by skylot.
the class BlockProcessor method splitReturn.
/**
* Splice return block if several predecessors presents
*/
private static boolean splitReturn(MethodNode mth, BlockNode returnBlock) {
if (returnBlock.contains(AFlag.SYNTHETIC) || returnBlock.contains(AFlag.ORIG_RETURN) || returnBlock.contains(AType.EXC_HANDLER)) {
return false;
}
List<BlockNode> preds = returnBlock.getPredecessors();
if (preds.size() < 2) {
return false;
}
InsnNode returnInsn = BlockUtils.getLastInsn(returnBlock);
if (returnInsn == null) {
return false;
}
if (returnInsn.getArgsCount() == 1 && returnBlock.getInstructions().size() == 1 && !isReturnArgAssignInPred(preds, returnInsn)) {
return false;
}
boolean first = true;
for (BlockNode pred : new ArrayList<>(preds)) {
if (first) {
returnBlock.add(AFlag.ORIG_RETURN);
first = false;
} else {
BlockNode newRetBlock = BlockSplitter.startNewBlock(mth, -1);
newRetBlock.add(AFlag.SYNTHETIC);
newRetBlock.add(AFlag.RETURN);
for (InsnNode oldInsn : returnBlock.getInstructions()) {
InsnNode copyInsn = oldInsn.copyWithoutSsa();
copyInsn.add(AFlag.SYNTHETIC);
newRetBlock.getInstructions().add(copyInsn);
}
BlockSplitter.replaceConnection(pred, returnBlock, newRetBlock);
}
}
return true;
}
use of jadx.core.dex.nodes.BlockNode in project jadx by skylot.
the class BlockProcessor method mergeConstAndReturnBlocks.
private static void mergeConstAndReturnBlocks(MethodNode mth, BlockNode retBlock, BlockNode pred) {
pred.getInstructions().addAll(retBlock.getInstructions());
pred.copyAttributesFrom(retBlock);
BlockSplitter.removeConnection(pred, retBlock);
retBlock.getInstructions().clear();
retBlock.add(AFlag.REMOVE);
BlockNode exitBlock = mth.getExitBlock();
BlockSplitter.removeConnection(retBlock, exitBlock);
BlockSplitter.connect(pred, exitBlock);
pred.updateCleanSuccessors();
}
use of jadx.core.dex.nodes.BlockNode in project jadx by skylot.
the class BlockProcessor method updateExitBlockConnections.
private static void updateExitBlockConnections(MethodNode mth) {
BlockNode exitBlock = mth.getExitBlock();
BlockSplitter.removePredecessors(exitBlock);
for (BlockNode block : mth.getBasicBlocks()) {
if (block != exitBlock && block.getSuccessors().isEmpty() && !block.contains(AFlag.REMOVE)) {
BlockSplitter.connect(block, exitBlock);
}
}
}
Aggregations