Add instructions that clear the stack

This commit is contained in:
de4dot 2011-10-20 01:43:33 +02:00
parent c643755267
commit c3d6e25ad7

View File

@ -53,6 +53,9 @@ namespace de4dot.blocks.cflow {
allDeadInstructions.Add(i); allDeadInstructions.Add(i);
break; break;
case Code.Leave:
case Code.Leave_S:
case Code.Endfinally:
case Code.Pop: case Code.Pop:
instructionExpressionFinder.init(block, false); instructionExpressionFinder.init(block, false);
if (!instructionExpressionFinder.find(i)) if (!instructionExpressionFinder.find(i))
@ -327,46 +330,45 @@ namespace de4dot.blocks.cflow {
if (index < 0) if (index < 0)
return false; return false;
if (addIt)
addIndex(index);
var startInstr = block.Instructions[index]; var startInstr = block.Instructions[index];
int startInstrPushes, startInstrPops; int startInstrPushes, startInstrPops;
calculateStackUsage(startInstr.Instruction, false, out startInstrPushes, out startInstrPops); calculateStackUsage(startInstr.Instruction, false, out startInstrPushes, out startInstrPops);
// Don't add it if it clears the stack (eg. leave)
if (addIt && startInstrPops >= 0)
addIndex(index);
if (startInstrPops == 0) if (startInstrPops == 0)
return true; return true;
if (startInstrPops < 0)
return false; // Eg. leave
while (index > 0) { while (index > 0) {
var instr = block.Instructions[index - 1]; var instr = block.Instructions[index - 1];
if (startInstrPops == 0 && instr.OpCode.OpCodeType != OpCodeType.Prefix) if (startInstrPops == 0 && instr.OpCode.OpCodeType != OpCodeType.Prefix)
break; break;
index--;
int pushes, pops; int pushes, pops;
calculateStackUsage(instr.Instruction, methodHasReturnValue, out pushes, out pops); calculateStackUsage(instr.Instruction, methodHasReturnValue, out pushes, out pops);
if (pops < 0) if (pops < 0)
return false; // eg. leave break; // eg. leave
index--;
if (pops > 0) { // if instr uses any args if (pops > 0) { // if instr uses any args
bool otherExpr = pops > 0 && pushes == 0; bool otherExpr = pops > 0 && pushes == 0;
if (!find(ref index, addIt && !otherExpr)) if (!find(ref index, addIt && !otherExpr))
return false; break;
} }
else if (pushes != 0 || pops != 0) { else if (pushes != 0 || pops != 0) {
if (addIt) if (addIt)
addIndex(index); addIndex(index);
} }
if (pushes > 0) { if (pushes > 0 && startInstrPops >= 0) {
if (pushes > startInstrPops) if (pushes > startInstrPops)
return false; return false;
startInstrPops -= pushes; startInstrPops -= pushes;
} }
} }
return startInstrPops == 0; return startInstrPops <= 0;
} }
void addIndex(int index) { void addIndex(int index) {