mirror of https://github.com/icsharpcode/ILSpy.git
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
108 lines
2.8 KiB
108 lines
2.8 KiB
using System; |
|
using System.Collections.Generic; |
|
|
|
using Mono.Cecil.Cil; |
|
|
|
namespace Decompiler.ControlFlow |
|
{ |
|
public class MethodBodyGraph: Node |
|
{ |
|
BasicBlock methodEntry; |
|
|
|
public BasicBlock MethodEntry { |
|
get { return methodEntry; } |
|
} |
|
|
|
public MethodBodyGraph(StackExpressionCollection exprs) |
|
{ |
|
if (exprs.Count == 0) throw new ArgumentException("Count == 0", "exprs"); |
|
|
|
BasicBlock basicBlock = null; |
|
for(int i = 0; i < exprs.Count; i++) { |
|
// Start new basic block if |
|
// - this is first expression |
|
// - last expression was branch |
|
// - this expression is branch target |
|
if (i == 0 || exprs[i - 1].BranchTarget != null || exprs[i].BranchesHere.Count > 0){ |
|
basicBlock = new BasicBlock(); |
|
this.Childs.Add(basicBlock); |
|
} |
|
basicBlock.Body.Add(exprs[i]); |
|
exprs[i].BasicBlock = basicBlock; |
|
} |
|
|
|
// Add fall-through links to BasicBlocks |
|
for(int i = 0; i < exprs.Count - 1; i++) { |
|
BasicBlock node = exprs[i].BasicBlock; |
|
BasicBlock target = exprs[i + 1].BasicBlock; |
|
|
|
// Still same basic block - ignore |
|
if (node == target) continue; |
|
|
|
// Non-conditional branch does not fall-through |
|
if (exprs[i].LastByteCode.OpCode.Code == Code.Br) continue; |
|
|
|
node.FallThroughBasicBlock = target; |
|
target.BasicBlockPredecessors.Add(node); |
|
} |
|
|
|
// Add branch links to BasicBlocks |
|
for(int i = 0; i < exprs.Count; i++) { |
|
if (exprs[i].BranchTarget != null) { |
|
BasicBlock node = exprs[i].BasicBlock; |
|
BasicBlock target = exprs[i].BranchTarget.BasicBlock; |
|
|
|
node.BranchBasicBlock = target; |
|
target.BasicBlockPredecessors.Add(node); |
|
} |
|
} |
|
|
|
this.methodEntry = (BasicBlock)this.HeadChild; |
|
} |
|
} |
|
|
|
public class AcyclicGraph: Node |
|
{ |
|
} |
|
|
|
public class Loop: Node |
|
{ |
|
} |
|
|
|
public class BasicBlock: Node |
|
{ |
|
List<StackExpression> body = new List<StackExpression>(); |
|
List<BasicBlock> basicBlockPredecessors = new List<BasicBlock>(); |
|
BasicBlock fallThroughBasicBlock; |
|
BasicBlock branchBasicBlock; |
|
|
|
public List<StackExpression> Body { |
|
get { return body; } |
|
} |
|
|
|
public List<BasicBlock> BasicBlockPredecessors { |
|
get { return basicBlockPredecessors; } |
|
} |
|
|
|
public BasicBlock FallThroughBasicBlock { |
|
get { return fallThroughBasicBlock; } |
|
set { fallThroughBasicBlock = value; } |
|
} |
|
|
|
public BasicBlock BranchBasicBlock { |
|
get { return branchBasicBlock; } |
|
set { branchBasicBlock = value; } |
|
} |
|
|
|
public IEnumerable<BasicBlock> BasicBlockSuccessors { |
|
get { |
|
if (this.FallThroughBasicBlock != null) { |
|
yield return this.FallThroughBasicBlock; |
|
} |
|
if (this.BranchBasicBlock != null) { |
|
yield return this.BranchBasicBlock; |
|
} |
|
} |
|
} |
|
} |
|
}
|
|
|