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 @@ -117,7 +117,8 @@ namespace Decompiler
if (node is ILLabel) {
yield return new Ast.LabelStatement { Label = ((ILLabel)node).Name };
} 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 is Ast.Expression) {
yield return new Ast.ExpressionStatement { Expression = (Ast.Expression)codeExpr };
@ -197,7 +198,7 @@ namespace Decompiler @@ -197,7 +198,7 @@ namespace Decompiler
return args;
}
object TransformExpression(ILExpression expr)
AstNode TransformExpression(ILExpression expr)
{
List<Ast.Expression> args = TransformExpressionArguments(expr);
return TransformByteCode(methodDef, expr, args);
@ -260,7 +261,7 @@ namespace Decompiler @@ -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 {
AstNode ret = TransformByteCode_Internal(methodDef, byteCode, args);

6
ICSharpCode.Decompiler/ILAst/ILAstBuilder.cs

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

2
ICSharpCode.Decompiler/ILAst/ILAstOptimizer.cs

@ -55,6 +55,7 @@ namespace Decompiler.ControlFlow @@ -55,6 +55,7 @@ namespace Decompiler.ControlFlow
void SplitToMovableBlocks(ILBlock block)
{
// 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();
List<ILNode> moveableBlocks = new List<ILNode>();
@ -417,6 +418,7 @@ namespace Decompiler.ControlFlow @@ -417,6 +418,7 @@ namespace Decompiler.ControlFlow
void SimpleGotoRemoval(ILBlock ast)
{
// TODO: Assign IL ranges from br to something else
var blocks = ast.GetSelfAndChildrenRecursive<ILBlock>().ToList();
foreach(ILBlock block in blocks) {
for (int i = 0; i < block.Body.Count; i++) {

51
ICSharpCode.Decompiler/ILAst/ILAstTypes.cs

@ -1,11 +1,11 @@ @@ -1,11 +1,11 @@
using System;
using System.Collections.Generic;
using System.Text;
using Decompiler.ControlFlow;
using Mono.Cecil;
using Mono.Cecil.Cil;
using Cecil = Mono.Cecil;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Decompiler.ControlFlow;
using Mono.Cecil;
using Mono.Cecil.Cil;
using Cecil = Mono.Cecil;
namespace Decompiler
{
@ -119,17 +119,31 @@ 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 OpCode OpCode { get; set; }
public object Operand { 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)
{
this.OpCode = opCode;
this.Operand = operand;
this.Arguments = new List<ILExpression>(args);
this.ILRanges = new List<ILRange>(1);
}
public IEnumerable<ILLabel> GetBranchTargets()
@ -143,6 +157,27 @@ namespace Decompiler @@ -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()
{
return Arguments;

Loading…
Cancel
Save