Browse Source

Keep track of original IL ranges

pull/10/head
David Srbecký 15 years ago
parent
commit
11d53ebdca
  1. 7
      ICSharpCode.Decompiler/Ast/AstMethodBodyBuilder.cs
  2. 6
      ICSharpCode.Decompiler/ILAst/ILAstBuilder.cs
  3. 2
      ICSharpCode.Decompiler/ILAst/ILAstOptimizer.cs
  4. 51
      ICSharpCode.Decompiler/ILAst/ILAstTypes.cs

7
ICSharpCode.Decompiler/Ast/AstMethodBodyBuilder.cs

@ -117,7 +117,8 @@ namespace Decompiler
if (node is ILLabel) { if (node is ILLabel) {
yield return new Ast.LabelStatement { Label = ((ILLabel)node).Name }; yield return new Ast.LabelStatement { Label = ((ILLabel)node).Name };
} else if (node is ILExpression) { } else if (node is ILExpression) {
object codeExpr = TransformExpression((ILExpression)node); List<ILRange> ilRanges = ((ILExpression)node).GetILRanges();
AstNode codeExpr = TransformExpression((ILExpression)node).WithAnnotation(ilRanges);
if (codeExpr != null) { if (codeExpr != null) {
if (codeExpr is Ast.Expression) { if (codeExpr is Ast.Expression) {
yield return new Ast.ExpressionStatement { Expression = (Ast.Expression)codeExpr }; yield return new Ast.ExpressionStatement { Expression = (Ast.Expression)codeExpr };
@ -197,7 +198,7 @@ namespace Decompiler
return args; return args;
} }
object TransformExpression(ILExpression expr) AstNode TransformExpression(ILExpression expr)
{ {
List<Ast.Expression> args = TransformExpressionArguments(expr); List<Ast.Expression> args = TransformExpressionArguments(expr);
return TransformByteCode(methodDef, expr, args); return TransformByteCode(methodDef, expr, args);
@ -260,7 +261,7 @@ namespace Decompiler
*/ */
} }
static object TransformByteCode(MethodDefinition methodDef, ILExpression byteCode, List<Ast.Expression> args) static AstNode TransformByteCode(MethodDefinition methodDef, ILExpression byteCode, List<Ast.Expression> args)
{ {
try { try {
AstNode ret = TransformByteCode_Internal(methodDef, byteCode, args); AstNode ret = TransformByteCode_Internal(methodDef, byteCode, args);

6
ICSharpCode.Decompiler/ILAst/ILAstBuilder.cs

@ -32,6 +32,7 @@ namespace Decompiler
{ {
public ILLabel Label; // Non-null only if needed public ILLabel Label; // Non-null only if needed
public int Offset; public int Offset;
public int EndOffset;
public OpCode OpCode; public OpCode OpCode;
public object Operand; public object Operand;
public int? PopCount; // Null means pop all public int? PopCount; // Null means pop all
@ -118,6 +119,7 @@ namespace Decompiler
MethodBodyRocks.ExpandMacro(ref opCode, ref operand, methodDef.Body); MethodBodyRocks.ExpandMacro(ref opCode, ref operand, methodDef.Body);
ByteCode byteCode = new ByteCode() { ByteCode byteCode = new ByteCode() {
Offset = inst.Offset, Offset = inst.Offset,
EndOffset = inst.Next != null ? inst.Next.Offset : methodDef.Body.CodeSize,
OpCode = opCode, OpCode = opCode,
Operand = operand, Operand = operand,
PopCount = inst.GetPopCount(), PopCount = inst.GetPopCount(),
@ -360,6 +362,7 @@ namespace Decompiler
MethodBodyRocks.ExpandMacro(ref opCode, ref operand, methodDef.Body); MethodBodyRocks.ExpandMacro(ref opCode, ref operand, methodDef.Body);
ILExpression expr = new ILExpression(opCode, operand); ILExpression expr = new ILExpression(opCode, operand);
expr.ILRanges.Add(new ILRange() { From = byteCode.Offset, To = byteCode.EndOffset });
// Label for this instruction // Label for this instruction
if (byteCode.Label != null) { if (byteCode.Label != null) {
@ -417,6 +420,9 @@ namespace Decompiler
bool canInline; bool canInline;
allowInline.TryGetValue((ILVariable)arg.Operand, out canInline); allowInline.TryGetValue((ILVariable)arg.Operand, out canInline);
if (arg.Operand == currExpr.Operand && canInline) { if (arg.Operand == currExpr.Operand && canInline) {
// Assigne the ranges for optimized away instrustions somewhere
currExpr.Arguments[0].ILRanges.AddRange(currExpr.ILRanges);
currExpr.Arguments[0].ILRanges.AddRange(nextExpr.Arguments[j].ILRanges);
ast.RemoveAt(i); ast.RemoveAt(i);
nextExpr.Arguments[j] = currExpr.Arguments[0]; // Inline the stloc body nextExpr.Arguments[j] = currExpr.Arguments[0]; // Inline the stloc body
i -= 2; // Try the same index again i -= 2; // Try the same index again

2
ICSharpCode.Decompiler/ILAst/ILAstOptimizer.cs

@ -55,6 +55,7 @@ namespace Decompiler.ControlFlow
void SplitToMovableBlocks(ILBlock block) void SplitToMovableBlocks(ILBlock block)
{ {
// Remve no-ops // Remve no-ops
// TODO: Assign the no-op range to someting
block.Body = block.Body.Where(n => !(n is ILExpression && ((ILExpression)n).OpCode == OpCodes.Nop)).ToList(); block.Body = block.Body.Where(n => !(n is ILExpression && ((ILExpression)n).OpCode == OpCodes.Nop)).ToList();
List<ILNode> moveableBlocks = new List<ILNode>(); List<ILNode> moveableBlocks = new List<ILNode>();
@ -417,6 +418,7 @@ namespace Decompiler.ControlFlow
void SimpleGotoRemoval(ILBlock ast) void SimpleGotoRemoval(ILBlock ast)
{ {
// TODO: Assign IL ranges from br to something else
var blocks = ast.GetSelfAndChildrenRecursive<ILBlock>().ToList(); var blocks = ast.GetSelfAndChildrenRecursive<ILBlock>().ToList();
foreach(ILBlock block in blocks) { foreach(ILBlock block in blocks) {
for (int i = 0; i < block.Body.Count; i++) { for (int i = 0; i < block.Body.Count; i++) {

51
ICSharpCode.Decompiler/ILAst/ILAstTypes.cs

@ -1,11 +1,11 @@
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Text; using System.Linq;
using System.Text;
using Decompiler.ControlFlow; using Decompiler.ControlFlow;
using Mono.Cecil; using Mono.Cecil;
using Mono.Cecil.Cil; using Mono.Cecil.Cil;
using Cecil = Mono.Cecil; using Cecil = Mono.Cecil;
namespace Decompiler namespace Decompiler
{ {
@ -119,17 +119,31 @@ namespace Decompiler
} }
} }
public class ILRange
{
public int From;
public int To; // Exlusive
public override string ToString()
{
return string.Format("{0}-{1}", From, To);
}
}
public class ILExpression: ILNode public class ILExpression: ILNode
{ {
public OpCode OpCode { get; set; } public OpCode OpCode { get; set; }
public object Operand { get; set; } public object Operand { get; set; }
public List<ILExpression> Arguments { get; set; } public List<ILExpression> Arguments { get; set; }
// Mapping to the original instructions (useful for debugging)
public List<ILRange> ILRanges { get; set; }
public ILExpression(OpCode opCode, object operand, params ILExpression[] args) public ILExpression(OpCode opCode, object operand, params ILExpression[] args)
{ {
this.OpCode = opCode; this.OpCode = opCode;
this.Operand = operand; this.Operand = operand;
this.Arguments = new List<ILExpression>(args); this.Arguments = new List<ILExpression>(args);
this.ILRanges = new List<ILRange>(1);
} }
public IEnumerable<ILLabel> GetBranchTargets() public IEnumerable<ILLabel> GetBranchTargets()
@ -143,6 +157,27 @@ namespace Decompiler
} }
} }
public List<ILRange> GetILRanges()
{
List<ILRange> ranges = new List<ILRange>();
foreach(ILExpression expr in this.GetSelfAndChildrenRecursive<ILExpression>()) {
ranges.AddRange(expr.ILRanges);
}
ranges = ranges.OrderBy(r => r.From).ToList();
for (int i = 0; i < ranges.Count - 1;) {
ILRange curr = ranges[i];
ILRange next = ranges[i + 1];
// Merge consequtive ranges if they intersect
if (curr.From <= next.From && next.From <= curr.To) {
curr.To = Math.Max(curr.To, next.To);
ranges.RemoveAt(i + 1);
} else {
i++;
}
}
return ranges;
}
public override IEnumerable<ILNode> GetChildren() public override IEnumerable<ILNode> GetChildren()
{ {
return Arguments; return Arguments;

Loading…
Cancel
Save