提交 5502d93c 编写于 作者: S Skylot

fix: additional checks before insert move to help type inference (#843)

上级 073fd76a
......@@ -208,7 +208,7 @@ public class MethodNode extends LineAttrNode implements ILoadable, ICodeNode {
}
return argsTypes;
} catch (Exception e) {
addWarningComment("Failed to parse method signature: " + sp.getSignature(), e);
addWarnComment("Failed to parse method signature: " + sp.getSignature(), e);
return null;
}
}
......@@ -698,11 +698,11 @@ public class MethodNode extends LineAttrNode implements ILoadable, ICodeNode {
ErrorsCounter.methodWarn(this, warnStr);
}
public void addWarningComment(String warn) {
addWarningComment(warn, null);
public void addWarnComment(String warn) {
addWarnComment(warn, null);
}
public void addWarningComment(String warn, @Nullable Throwable exc) {
public void addWarnComment(String warn, @Nullable Throwable exc) {
String commentStr = "JADX WARN: " + warn;
addAttr(AType.COMMENTS, commentStr);
if (exc != null) {
......
......@@ -64,7 +64,7 @@ public class DebugInfoApplyVisitor extends AbstractVisitor {
mth.getSVars().forEach(var -> {
ArgType type = var.getTypeInfo().getType();
if (!type.isTypeKnown()) {
mth.addComment("JADX WARNING: type inference failed for: " + var.getDetailedVarInfo(mth));
mth.addWarnComment("Type inference failed for: " + var.getDetailedVarInfo(mth));
}
});
}
......
......@@ -72,7 +72,9 @@ public final class TypeInferenceVisitor extends AbstractVisitor {
if (!resolved) {
boolean moveAdded = false;
for (SSAVar var : new ArrayList<>(mth.getSVars())) {
moveAdded |= tryInsertAdditionalInsn(mth, var);
if (tryInsertAdditionalInsn(mth, var)) {
moveAdded = true;
}
}
if (moveAdded) {
InitCodeVariables.rerun(mth);
......@@ -361,50 +363,67 @@ public final class TypeInferenceVisitor extends AbstractVisitor {
}
}
for (PhiInsn phiInsn : usedInPhiList) {
if (!insertMoveForPhi(mth, phiInsn, var)) {
if (!insertMoveForPhi(mth, phiInsn, var, false)) {
return false;
}
}
// all check passed => apply
for (PhiInsn phiInsn : usedInPhiList) {
insertMoveForPhi(mth, phiInsn, var, true);
}
mth.addComment("JADX INFO: additional move instructions added (" + usedInPhiList.size() + ") to help type inference");
return true;
}
private boolean insertMoveForPhi(MethodNode mth, PhiInsn phiInsn, SSAVar var) {
private boolean insertMoveForPhi(MethodNode mth, PhiInsn phiInsn, SSAVar var, boolean apply) {
int argsCount = phiInsn.getArgsCount();
for (int argIndex = 0; argIndex < argsCount; argIndex++) {
RegisterArg reg = phiInsn.getArg(argIndex);
if (reg.getSVar() == var) {
BlockNode blockNode = phiInsn.getBlockByArgIndex(argIndex);
InsnNode lastInsn = BlockUtils.getLastInsn(blockNode);
if (lastInsn != null && BlockSplitter.isSeparate(lastInsn.getType())) {
// can't insert move in block with separate instruction
// trying previous block
List<BlockNode> preds = blockNode.getPredecessors();
if (preds.size() == 1) {
blockNode = preds.get(0);
} else {
mth.addWarn("Failed to insert additional move for type inference");
return false;
}
BlockNode startBlock = phiInsn.getBlockByArgIndex(argIndex);
BlockNode blockNode = checkBlockForInsnInsert(startBlock);
if (blockNode == null) {
mth.addWarnComment("Failed to insert an additional move for type inference into block " + startBlock);
return false;
}
if (apply) {
int regNum = reg.getRegNum();
RegisterArg resultArg = reg.duplicate(regNum, null);
SSAVar newSsaVar = mth.makeNewSVar(regNum, resultArg);
RegisterArg arg = reg.duplicate(regNum, var);
InsnNode moveInsn = new InsnNode(InsnType.MOVE, 1);
moveInsn.setResult(resultArg);
moveInsn.addArg(arg);
moveInsn.add(AFlag.SYNTHETIC);
blockNode.getInstructions().add(moveInsn);
phiInsn.replaceArg(reg, reg.duplicate(regNum, newSsaVar));
}
int regNum = reg.getRegNum();
RegisterArg resultArg = reg.duplicate(regNum, null);
SSAVar newSsaVar = mth.makeNewSVar(regNum, resultArg);
RegisterArg arg = reg.duplicate(regNum, var);
InsnNode moveInsn = new InsnNode(InsnType.MOVE, 1);
moveInsn.setResult(resultArg);
moveInsn.addArg(arg);
moveInsn.add(AFlag.SYNTHETIC);
blockNode.getInstructions().add(moveInsn);
phiInsn.replaceArg(reg, reg.duplicate(regNum, newSsaVar));
return true;
}
}
return false;
}
@Nullable
private BlockNode checkBlockForInsnInsert(BlockNode blockNode) {
if (blockNode.isSynthetic()) {
return null;
}
InsnNode lastInsn = BlockUtils.getLastInsn(blockNode);
if (lastInsn != null && BlockSplitter.isSeparate(lastInsn.getType())) {
// can't insert move in a block with 'separate' instruction => try previous block by simple path
List<BlockNode> preds = blockNode.getPredecessors();
if (preds.size() == 1) {
return checkBlockForInsnInsert(preds.get(0));
}
return null;
}
return blockNode;
}
private boolean tryWiderObjects(MethodNode mth, SSAVar var) {
Set<ArgType> objTypes = new LinkedHashSet<>();
for (ITypeBound bound : var.getTypeInfo().getBounds()) {
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册