Remove nop blocks
This commit is contained in:
parent
a3c9221410
commit
0b5d4d864c
|
@ -143,6 +143,18 @@ namespace de4dot.blocks {
|
|||
replaceLastInstrsWithBranch(1, target);
|
||||
}
|
||||
|
||||
public void setNewFallThrough(Block newFallThrough) {
|
||||
disconnectFromFallThrough();
|
||||
fallThrough = newFallThrough;
|
||||
newFallThrough.sources.Add(this);
|
||||
}
|
||||
|
||||
public void setNewTarget(int index, Block newTarget) {
|
||||
disconnectFromBlock(targets[index]);
|
||||
targets[index] = newTarget;
|
||||
newTarget.sources.Add(this);
|
||||
}
|
||||
|
||||
public void removeDeadBlock() {
|
||||
if (sources.Count != 0)
|
||||
throw new ApplicationException("Trying to remove a non-dead block");
|
||||
|
@ -284,5 +296,15 @@ namespace de4dot.blocks {
|
|||
public bool isConditionalBranch() {
|
||||
return LastInstr.isConditionalBranch();
|
||||
}
|
||||
|
||||
public bool isNopBlock() {
|
||||
if (!isFallThrough())
|
||||
return false;
|
||||
foreach (var instr in instructions) {
|
||||
if (instr.OpCode.Code != Code.Nop)
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -183,6 +183,7 @@ namespace de4dot.blocks {
|
|||
}
|
||||
|
||||
public void repartitionBlocks() {
|
||||
mergeNopBlocks();
|
||||
foreach (var scopeBlock in getAllScopeBlocks(methodBlocks)) {
|
||||
try {
|
||||
scopeBlock.repartitionBlocks();
|
||||
|
@ -194,5 +195,61 @@ namespace de4dot.blocks {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
void mergeNopBlocks() {
|
||||
var allBlocks = methodBlocks.getAllBlocks();
|
||||
|
||||
var nopBlocks = new Dictionary<Block, bool>();
|
||||
foreach (var nopBlock in allBlocks) {
|
||||
if (nopBlock.isNopBlock())
|
||||
nopBlocks[nopBlock] = true;
|
||||
}
|
||||
|
||||
if (nopBlocks.Count == 0)
|
||||
return;
|
||||
|
||||
for (int i = 0; i < 10; i++) {
|
||||
bool changed = false;
|
||||
|
||||
foreach (var block in allBlocks) {
|
||||
Block nopBlockTarget;
|
||||
|
||||
nopBlockTarget = getNopBlockTarget(nopBlocks, block, block.FallThrough);
|
||||
if (nopBlockTarget != null) {
|
||||
block.setNewFallThrough(nopBlockTarget);
|
||||
changed = true;
|
||||
}
|
||||
|
||||
if (block.Targets != null) {
|
||||
for (int targetIndex = 0; targetIndex < block.Targets.Count; targetIndex++) {
|
||||
nopBlockTarget = getNopBlockTarget(nopBlocks, block, block.Targets[targetIndex]);
|
||||
if (nopBlockTarget == null)
|
||||
continue;
|
||||
block.setNewTarget(targetIndex, nopBlockTarget);
|
||||
changed = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!changed)
|
||||
break;
|
||||
}
|
||||
|
||||
foreach (var nopBlock in nopBlocks.Keys) {
|
||||
var scopeBlock = (ScopeBlock)nopBlock.Parent;
|
||||
scopeBlock.removeDeadBlock(nopBlock);
|
||||
}
|
||||
}
|
||||
|
||||
static Block getNopBlockTarget(Dictionary<Block, bool> nopBlocks, Block source, Block nopBlock) {
|
||||
if (nopBlock == null || !nopBlocks.ContainsKey(nopBlock) || source == nopBlock.FallThrough)
|
||||
return null;
|
||||
if (((ScopeBlock)nopBlock.Parent).BaseBlocks[0] == nopBlock)
|
||||
return null;
|
||||
var target = nopBlock.FallThrough;
|
||||
if (nopBlock.Parent != target.Parent)
|
||||
return null;
|
||||
return target;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue
Block a user