Browse Source

Merge branch 'master' of git://github.com/icsharpcode/ILSpy into Debugger

pull/191/merge
Eusebiu Marcu 15 years ago
parent
commit
32c3941e27
  1. 35
      ICSharpCode.Decompiler/Ast/TextOutputFormatter.cs
  2. 2
      ICSharpCode.Decompiler/ICSharpCode.Decompiler.csproj
  3. 105
      ICSharpCode.Decompiler/ILAst/ILAstOptimizer.cs
  4. 19
      ICSharpCode.Decompiler/ILAst/ILAstTypes.cs
  5. 111
      ICSharpCode.Decompiler/ILAst/InitializerPeepholeTransforms.cs
  6. 120
      ICSharpCode.Decompiler/ILAst/Pattern.cs
  7. 112
      ICSharpCode.Decompiler/ILAst/PatternMatching.cs
  8. 80
      ICSharpCode.Decompiler/ILAst/YieldReturnDecompiler.cs

35
ICSharpCode.Decompiler/Ast/TextOutputFormatter.cs

@ -132,29 +132,28 @@ namespace ICSharpCode.Decompiler.Ast
var n = node.Ancestors.FirstOrDefault(a => a.Annotation<MemberMapping>() != null); var n = node.Ancestors.FirstOrDefault(a => a.Annotation<MemberMapping>() != null);
if (n != default(AstType)) { if (n != default(AstType)) {
MemberMapping mapping = n.Annotation<MemberMapping>(); MemberMapping mapping = n.Annotation<MemberMapping>();
// var map = mapping.MemberCodeMappings.Find(s => s.SourceCodeLine == output.CurrentLine);
foreach (var range in ranges) { foreach (var range in ranges) {
var map = mapping.MemberCodeMappings.Find(s => s.SourceCodeLine == output.CurrentLine); // // check if the range is in previous mapping
// var prevmap = mapping.MemberCodeMappings.Find(m => m.ILInstructionOffset.From <= range.From &&
if (map == null) { // m.ILInstructionOffset.To >= range.To);
// check if the range is in previous mapping //
var prevmap = mapping.MemberCodeMappings.Find(m => m.ILInstructionOffset.From <= range.From && // if (prevmap != null)
m.ILInstructionOffset.To >= range.To); // continue;
//
if (prevmap != null) // if (map == null) {
continue; mapping.MemberCodeMappings.Add(/*map = */new SourceCodeMapping {
mapping.MemberCodeMappings.Add(new SourceCodeMapping {
ILInstructionOffset = range, ILInstructionOffset = range,
SourceCodeLine = output.CurrentLine, SourceCodeLine = output.CurrentLine,
MemberMapping = mapping MemberMapping = mapping
}); });
} else { // } else {
if (map.ILInstructionOffset.From > range.From) // if (map.ILInstructionOffset.From > range.From)
map.ILInstructionOffset.From = range.From; // map.ILInstructionOffset.From = range.From;
if (map.ILInstructionOffset.To < range.To) // if (map.ILInstructionOffset.To < range.To)
map.ILInstructionOffset.To = range.To; // map.ILInstructionOffset.To = range.To;
} // }
} }
} }
} }

2
ICSharpCode.Decompiler/ICSharpCode.Decompiler.csproj

@ -97,7 +97,7 @@
<Compile Include="ILAst\ILCodes.cs" /> <Compile Include="ILAst\ILCodes.cs" />
<Compile Include="ILAst\ILInlining.cs" /> <Compile Include="ILAst\ILInlining.cs" />
<Compile Include="ILAst\LoopsAndConditions.cs" /> <Compile Include="ILAst\LoopsAndConditions.cs" />
<Compile Include="ILAst\Pattern.cs" /> <Compile Include="ILAst\PatternMatching.cs" />
<Compile Include="ILAst\PeepholeTransform.cs" /> <Compile Include="ILAst\PeepholeTransform.cs" />
<Compile Include="ILAst\TypeAnalysis.cs" /> <Compile Include="ILAst\TypeAnalysis.cs" />
<Compile Include="ILAst\YieldReturnDecompiler.cs" /> <Compile Include="ILAst\YieldReturnDecompiler.cs" />

105
ICSharpCode.Decompiler/ILAst/ILAstOptimizer.cs

@ -445,7 +445,9 @@ namespace ICSharpCode.Decompiler.ILAst
labelGlobalRefCount.GetOrDefault(condBBLabel) == 1 && labelGlobalRefCount.GetOrDefault(condBBLabel) == 1 &&
labelGlobalRefCount.GetOrDefault(rightBBLabel) == 1 && labelGlobalRefCount.GetOrDefault(rightBBLabel) == 1 &&
labelGlobalRefCount.GetOrDefault(endBBLabel) == 2 && labelGlobalRefCount.GetOrDefault(endBBLabel) == 2 &&
scope.ContainsAll(condBB, rightBB, endBB) scope.Contains(condBB) &&
scope.Contains(rightBB) &&
scope.Contains(endBB)
) )
{ {
head.Body[head.Body.Count - 1] = new ILExpression(ILCode.Stloc, v, new ILExpression(ILCode.NullCoalescing, null, leftExpr, rightExpr)); head.Body[head.Body.Count - 1] = new ILExpression(ILCode.Stloc, v, new ILExpression(ILCode.NullCoalescing, null, leftExpr, rightExpr));
@ -639,98 +641,6 @@ namespace ICSharpCode.Decompiler.ILAst
public static class ILAstOptimizerExtensionMethods public static class ILAstOptimizerExtensionMethods
{ {
public static bool Match(this ILNode node, ILCode code)
{
ILExpression expr = node as ILExpression;
return expr != null && expr.Prefixes == null && expr.Code == code;
}
public static bool Match<T>(this ILNode node, ILCode code, out T operand)
{
ILExpression expr = node as ILExpression;
if (expr != null && expr.Prefixes == null && expr.Code == code) {
operand = (T)expr.Operand;
Debug.Assert(expr.Arguments.Count == 0);
return true;
}
operand = default(T);
return false;
}
public static bool Match(this ILNode node, ILCode code, out List<ILExpression> args)
{
ILExpression expr = node as ILExpression;
if (expr != null && expr.Prefixes == null && expr.Code == code) {
Debug.Assert(expr.Operand == null);
args = expr.Arguments;
return true;
}
args = null;
return false;
}
public static bool Match(this ILNode node, ILCode code, out ILExpression arg)
{
List<ILExpression> args;
if (node.Match(code, out args) && args.Count == 1) {
arg = args[0];
return true;
}
arg = null;
return false;
}
public static bool Match<T>(this ILNode node, ILCode code, out T operand, out List<ILExpression> args)
{
ILExpression expr = node as ILExpression;
if (expr != null && expr.Prefixes == null && expr.Code == code) {
operand = (T)expr.Operand;
args = expr.Arguments;
return true;
}
operand = default(T);
args = null;
return false;
}
public static bool Match<T>(this ILNode node, ILCode code, out T operand, out ILExpression arg)
{
List<ILExpression> args;
if (node.Match(code, out operand, out args) && args.Count == 1) {
arg = args[0];
return true;
}
arg = null;
return false;
}
public static bool Match<T>(this ILNode node, ILCode code, out T operand, out ILExpression arg1, out ILExpression arg2)
{
List<ILExpression> args;
if (node.Match(code, out operand, out args) && args.Count == 2) {
arg1 = args[0];
arg2 = args[1];
return true;
}
arg1 = null;
arg2 = null;
return false;
}
public static bool Match<T>(this ILBasicBlock bb, ILCode code, out T operand, out ILExpression arg, out ILLabel fallLabel)
{
if (bb.Body.Count == 1) {
if (bb.Body[0].Match(code, out operand, out arg)) {
fallLabel = bb.FallthoughGoto != null ? (ILLabel)bb.FallthoughGoto.Operand : null;
return true;
}
}
operand = default(T);
arg = null;
fallLabel = null;
return false;
}
/// <summary> /// <summary>
/// Perform one pass of a given optimization on this block. /// Perform one pass of a given optimization on this block.
/// This block must consist of only basicblocks. /// This block must consist of only basicblocks.
@ -807,15 +717,6 @@ namespace ICSharpCode.Decompiler.ILAst
return ret; return ret;
} }
public static bool ContainsAll<T>(this List<T> list, params T[] items)
{
foreach (T item in items) {
if (!list.Contains(item))
return false;
}
return true;
}
public static void RemoveOrThrow<T>(this ICollection<T> collection, T item) public static void RemoveOrThrow<T>(this ICollection<T> collection, T item)
{ {
if (!collection.Remove(item)) if (!collection.Remove(item))

19
ICSharpCode.Decompiler/ILAst/ILAstTypes.cs

@ -319,25 +319,6 @@ namespace ICSharpCode.Decompiler.ILAst
} }
} }
public virtual bool Match(ILNode other)
{
ILExpression expr = other as ILExpression;
return expr != null && this.Code == expr.Code
&& (this.Operand == AnyOperand || object.Equals(this.Operand, expr.Operand))
&& Match(this.Arguments, expr.Arguments);
}
protected static bool Match(IList<ILExpression> a, IList<ILExpression> b)
{
if (a.Count != b.Count)
return false;
for (int i = 0; i < a.Count; i++) {
if (!a[i].Match(b[i]))
return false;
}
return true;
}
public override void WriteTo(ITextOutput output) public override void WriteTo(ITextOutput output)
{ {
if (Operand is ILVariable && ((ILVariable)Operand).IsGenerated) { if (Operand is ILVariable && ((ILVariable)Operand).IsGenerated) {

111
ICSharpCode.Decompiler/ILAst/InitializerPeepholeTransforms.cs

@ -17,57 +17,72 @@ namespace ICSharpCode.Decompiler.ILAst
readonly ILBlock method; readonly ILBlock method;
#region Array Initializers #region Array Initializers
StoreToVariable newArrPattern;
ILCall initializeArrayPattern;
public InitializerPeepholeTransforms(ILBlock method) public InitializerPeepholeTransforms(ILBlock method)
{ {
this.method = method; this.method = method;
newArrPattern = new StoreToVariable(new ILExpression(
ILCode.Newarr, ILExpression.AnyOperand, new ILExpression(ILCode.Ldc_I4, ILExpression.AnyOperand)));
initializeArrayPattern = new ILCall(
"System.Runtime.CompilerServices.RuntimeHelpers", "InitializeArray",
new LoadFromVariable(newArrPattern), new ILExpression(ILCode.Ldtoken, ILExpression.AnyOperand));
} }
public void TransformArrayInitializers(ILBlock block, ref int i) public void TransformArrayInitializers(ILBlock block, ref int i)
{ {
if (!newArrPattern.Match(block.Body[i])) ILVariable v, v2, v3;
return; ILExpression newarrExpr;
ILExpression newArrInst = ((ILExpression)block.Body[i]).Arguments[0]; TypeReference arrayType;
int arrayLength = (int)newArrInst.Arguments[0].Operand; ILExpression lengthExpr;
if (arrayLength == 0) int arrayLength;
return; if (block.Body[i].Match(ILCode.Stloc, out v, out newarrExpr) &&
if (initializeArrayPattern.Match(block.Body.ElementAtOrDefault(i + 1))) { newarrExpr.Match(ILCode.Newarr, out arrayType, out lengthExpr) &&
if (HandleStaticallyInitializedArray(newArrPattern, block, i, newArrInst, arrayLength)) { lengthExpr.Match(ILCode.Ldc_I4, out arrayLength) &&
i -= new ILInlining(method).InlineInto(block, i + 1, aggressive: true) - 1; arrayLength > 0)
{
MethodReference methodRef;
ILExpression methodArg1;
ILExpression methodArg2;
FieldDefinition field;
if (block.Body.ElementAtOrDefault(i + 1).Match(ILCode.Call, out methodRef, out methodArg1, out methodArg2) &&
methodRef.DeclaringType.FullName == "System.Runtime.CompilerServices.RuntimeHelpers" &&
methodRef.Name == "InitializeArray" &&
methodArg1.Match(ILCode.Ldloc, out v2) &&
v == v2 &&
methodArg2.Match(ILCode.Ldtoken, out field) &&
field != null && field.InitialValue != null)
{
ILExpression[] newArr = new ILExpression[arrayLength];
if (DecodeArrayInitializer(TypeAnalysis.GetTypeCode(arrayType), field.InitialValue, newArr)) {
block.Body[i] = new ILExpression(ILCode.Stloc, v, new ILExpression(ILCode.InitArray, arrayType, newArr));
block.Body.RemoveAt(i + 1);
i -= new ILInlining(method).InlineInto(block, i + 1, aggressive: true) - 1;
return;
}
} }
return;
}
List<ILExpression> operands = new List<ILExpression>();
int numberOfInstructionsToRemove = 0;
for (int j = i + 1; j < block.Body.Count; j++) {
ILExpression expr = block.Body[j] as ILExpression;
if (expr == null || !IsStoreToArray(expr.Code))
break;
if (!(expr.Arguments[0].Code == ILCode.Ldloc && expr.Arguments[0].Operand == newArrPattern.LastVariable))
break;
if (expr.Arguments[1].Code != ILCode.Ldc_I4)
break;
int pos = (int)expr.Arguments[1].Operand;
const int maxConsecutiveDefaultValueExpressions = 10; const int maxConsecutiveDefaultValueExpressions = 10;
if (pos < operands.Count || pos > operands.Count + maxConsecutiveDefaultValueExpressions) List<ILExpression> operands = new List<ILExpression>();
break; int numberOfInstructionsToRemove = 0;
while (operands.Count < pos) for (int j = i + 1; j < block.Body.Count; j++) {
operands.Add(new ILExpression(ILCode.DefaultValue, newArrInst.Operand)); ILExpression expr = block.Body[j] as ILExpression;
operands.Add(expr.Arguments[2]); int pos;
numberOfInstructionsToRemove++; if (expr != null &&
} IsStoreToArray(expr.Code) &&
if (operands.Count == arrayLength) { expr.Arguments[0].Match(ILCode.Ldloc, out v3) &&
((ILExpression)block.Body[i]).Arguments[0] = new ILExpression( v == v3 &&
ILCode.InitArray, newArrInst.Operand, operands.ToArray()); expr.Arguments[1].Match(ILCode.Ldc_I4, out pos) &&
block.Body.RemoveRange(i + 1, numberOfInstructionsToRemove); pos >= operands.Count &&
i -= new ILInlining(method).InlineInto(block, i + 1, aggressive: true) - 1; pos <= operands.Count + maxConsecutiveDefaultValueExpressions)
{
while (operands.Count < pos)
operands.Add(new ILExpression(ILCode.DefaultValue, arrayType));
operands.Add(expr.Arguments[2]);
numberOfInstructionsToRemove++;
} else {
break;
}
}
if (operands.Count == arrayLength) {
((ILExpression)block.Body[i]).Arguments[0] = new ILExpression(ILCode.InitArray, arrayType, operands);
block.Body.RemoveRange(i + 1, numberOfInstructionsToRemove);
i -= new ILInlining(method).InlineInto(block, i + 1, aggressive: true) - 1;
}
} }
} }
@ -89,20 +104,6 @@ namespace ICSharpCode.Decompiler.ILAst
} }
} }
static bool HandleStaticallyInitializedArray(StoreToVariable newArrPattern, ILBlock block, int i, ILExpression newArrInst, int arrayLength)
{
FieldDefinition field = ((ILExpression)block.Body[i + 1]).Arguments[1].Operand as FieldDefinition;
if (field == null || field.InitialValue == null)
return false;
ILExpression[] newArr = new ILExpression[arrayLength];
if (DecodeArrayInitializer(TypeAnalysis.GetTypeCode(newArrInst.Operand as TypeReference), field.InitialValue, newArr)) {
block.Body[i] = new ILExpression(ILCode.Stloc, newArrPattern.LastVariable, new ILExpression(ILCode.InitArray, newArrInst.Operand, newArr));
block.Body.RemoveAt(i + 1);
return true;
}
return false;
}
static bool DecodeArrayInitializer(TypeCode elementType, byte[] initialValue, ILExpression[] output) static bool DecodeArrayInitializer(TypeCode elementType, byte[] initialValue, ILExpression[] output)
{ {
switch (elementType) { switch (elementType) {

120
ICSharpCode.Decompiler/ILAst/Pattern.cs

@ -1,120 +0,0 @@
// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt)
// This code is distributed under MIT X11 license (for details please see \doc\license.txt)
using System;
using Mono.Cecil;
namespace ICSharpCode.Decompiler.ILAst
{
public interface IVariablePattern
{
bool MatchVariable(ILVariable v);
}
public class StoreToVariable : ILExpression, IVariablePattern
{
public bool MustBeGenerated;
public ILExpression LastMatch;
public ILVariable LastVariable {
get {
return LastMatch != null ? LastMatch.Operand as ILVariable : null;
}
}
public StoreToVariable(ILExpression arg) : base(ILCode.Pattern, null, arg)
{
}
public override bool Match(ILNode other)
{
ILExpression expr = other as ILExpression;
if (expr != null && expr.Code == ILCode.Stloc && (!MustBeGenerated || ((ILVariable)expr.Operand).IsGenerated) && Match(this.Arguments, expr.Arguments)) {
this.LastMatch = expr;
return true;
} else {
return false;
}
}
bool IVariablePattern.MatchVariable(ILVariable v)
{
return v == LastMatch.Operand;
}
}
public class LoadFromVariable : ILExpression
{
readonly IVariablePattern v;
public LoadFromVariable(IVariablePattern v) : base(ILCode.Pattern, null)
{
this.v = v;
}
public override bool Match(ILNode other)
{
ILExpression expr = other as ILExpression;
return expr != null && expr.Code == ILCode.Ldloc && v.MatchVariable(expr.Operand as ILVariable);
}
}
public class LoadFromArgument : ILExpression
{
int index;
public static readonly LoadFromArgument This = new LoadFromArgument(-1);
public LoadFromArgument(int index) : base(ILCode.Pattern, null)
{
this.index = index;
}
public override bool Match(ILNode other)
{
ILExpression expr = other as ILExpression;
return expr != null && expr.Code == ILCode.Ldarg && ((ParameterDefinition)expr.Operand).Index == index;
}
}
public class AnyILExpression : ILExpression
{
public ILExpression LastMatch;
public AnyILExpression() : base(ILCode.Pattern, null)
{
}
public override bool Match(ILNode other)
{
if (other is ILExpression) {
LastMatch = (ILExpression)other;
return true;
} else {
return false;
}
}
}
public class ILCall : ILExpression
{
string fullClassName;
string methodName;
public ILCall(string fullClassName, string methodName, params ILExpression[] args) : base(ILCode.Pattern, null, args)
{
this.fullClassName = fullClassName;
this.methodName = methodName;
}
public override bool Match(ILNode other)
{
ILExpression expr = other as ILExpression;
if (expr != null && expr.Code == ILCode.Call) {
MethodReference r = (MethodReference)expr.Operand;
if (r.Name == methodName && r.DeclaringType.FullName == fullClassName)
return Match(this.Arguments, expr.Arguments);
}
return false;
}
}
}

112
ICSharpCode.Decompiler/ILAst/PatternMatching.cs

@ -0,0 +1,112 @@
// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt)
// This code is distributed under MIT X11 license (for details please see \doc\license.txt)
using System;
using System.Collections.Generic;
using System.Diagnostics;
using Mono.Cecil;
namespace ICSharpCode.Decompiler.ILAst
{
public static class PatternMatching
{
public static bool Match(this ILNode node, ILCode code)
{
ILExpression expr = node as ILExpression;
return expr != null && expr.Prefixes == null && expr.Code == code;
}
public static bool Match<T>(this ILNode node, ILCode code, out T operand)
{
ILExpression expr = node as ILExpression;
if (expr != null && expr.Prefixes == null && expr.Code == code) {
operand = (T)expr.Operand;
Debug.Assert(expr.Arguments.Count == 0);
return true;
}
operand = default(T);
return false;
}
public static bool Match(this ILNode node, ILCode code, out List<ILExpression> args)
{
ILExpression expr = node as ILExpression;
if (expr != null && expr.Prefixes == null && expr.Code == code) {
Debug.Assert(expr.Operand == null);
args = expr.Arguments;
return true;
}
args = null;
return false;
}
public static bool Match(this ILNode node, ILCode code, out ILExpression arg)
{
List<ILExpression> args;
if (node.Match(code, out args) && args.Count == 1) {
arg = args[0];
return true;
}
arg = null;
return false;
}
public static bool Match<T>(this ILNode node, ILCode code, out T operand, out List<ILExpression> args)
{
ILExpression expr = node as ILExpression;
if (expr != null && expr.Prefixes == null && expr.Code == code) {
operand = (T)expr.Operand;
args = expr.Arguments;
return true;
}
operand = default(T);
args = null;
return false;
}
public static bool Match<T>(this ILNode node, ILCode code, out T operand, out ILExpression arg)
{
List<ILExpression> args;
if (node.Match(code, out operand, out args) && args.Count == 1) {
arg = args[0];
return true;
}
arg = null;
return false;
}
public static bool Match<T>(this ILNode node, ILCode code, out T operand, out ILExpression arg1, out ILExpression arg2)
{
List<ILExpression> args;
if (node.Match(code, out operand, out args) && args.Count == 2) {
arg1 = args[0];
arg2 = args[1];
return true;
}
arg1 = null;
arg2 = null;
return false;
}
public static bool Match<T>(this ILBasicBlock bb, ILCode code, out T operand, out ILExpression arg, out ILLabel fallLabel)
{
if (bb.Body.Count == 1) {
if (bb.Body[0].Match(code, out operand, out arg)) {
fallLabel = bb.FallthoughGoto != null ? (ILLabel)bb.FallthoughGoto.Operand : null;
return true;
}
}
operand = default(T);
arg = null;
fallLabel = null;
return false;
}
public static bool MatchThis(this ILNode node)
{
ParameterDefinition parDef;
return node.Match(ILCode.Ldarg, out parDef) && parDef.Index == -1;
}
}
}

80
ICSharpCode.Decompiler/ILAst/YieldReturnDecompiler.cs

@ -181,11 +181,17 @@ namespace ICSharpCode.Decompiler.ILAst
{ {
ILBlock method = CreateILAst(enumeratorCtor); ILBlock method = CreateILAst(enumeratorCtor);
ILExpression stfldPattern = new ILExpression(ILCode.Stfld, ILExpression.AnyOperand, LoadFromArgument.This, new LoadFromArgument(0));
foreach (ILNode node in method.Body) { foreach (ILNode node in method.Body) {
if (stfldPattern.Match(node)) { FieldReference field;
stateField = GetFieldDefinition(((ILExpression)node).Operand as FieldReference); ILExpression instExpr;
ILExpression stExpr;
ParameterDefinition arg;
if (node.Match(ILCode.Stfld, out field, out instExpr, out stExpr) &&
instExpr.MatchThis() &&
stExpr.Match(ILCode.Ldarg, out arg) &&
arg.Index == 0)
{
stateField = GetFieldDefinition(field);
} }
} }
if (stateField == null) if (stateField == null)
@ -210,8 +216,6 @@ namespace ICSharpCode.Decompiler.ILAst
#endregion #endregion
#region Figure out what the 'current' field is (analysis of get_Current()) #region Figure out what the 'current' field is (analysis of get_Current())
static readonly ILExpression returnFieldFromThisPattern = new ILExpression(ILCode.Ret, null, new ILExpression(ILCode.Ldfld, ILExpression.AnyOperand, LoadFromArgument.This));
/// <summary> /// <summary>
/// Looks at the enumerator's get_Current method and figures out which of the fields holds the current value. /// Looks at the enumerator's get_Current method and figures out which of the fields holds the current value.
/// </summary> /// </summary>
@ -223,18 +227,29 @@ namespace ICSharpCode.Decompiler.ILAst
ILBlock method = CreateILAst(getCurrentMethod); ILBlock method = CreateILAst(getCurrentMethod);
if (method.Body.Count == 1) { if (method.Body.Count == 1) {
// release builds directly return the current field // release builds directly return the current field
if (returnFieldFromThisPattern.Match(method.Body[0])) { ILExpression retExpr;
currentField = GetFieldDefinition(((ILExpression)method.Body[0]).Arguments[0].Operand as FieldReference); FieldReference field;
ILExpression ldFromObj;
if (method.Body[0].Match(ILCode.Ret, out retExpr) &&
retExpr.Match(ILCode.Ldfld, out field, out ldFromObj) &&
ldFromObj.MatchThis())
{
currentField = GetFieldDefinition(field);
} }
} else { } else if (method.Body.Count == 2) {
StoreToVariable v = new StoreToVariable(new ILExpression(ILCode.Ldfld, ILExpression.AnyOperand, LoadFromArgument.This)); ILVariable v, v2;
if (v.Match(method.Body[0])) { ILExpression stExpr;
int i = 1; FieldReference field;
if (i == method.Body.Count - 1) { ILExpression ldFromObj;
if (new ILExpression(ILCode.Ret, null, new LoadFromVariable(v)).Match(method.Body[i])) { ILExpression retExpr;
currentField = GetFieldDefinition(((ILExpression)method.Body[0]).Arguments[0].Operand as FieldReference); if (method.Body[0].Match(ILCode.Stloc, out v, out stExpr) &&
} stExpr.Match(ILCode.Ldfld, out field, out ldFromObj) &&
} ldFromObj.MatchThis() &&
method.Body[1].Match(ILCode.Ret, out retExpr) &&
retExpr.Match(ILCode.Ldloc, out v2) &&
v == v2)
{
currentField = GetFieldDefinition(field);
} }
} }
if (currentField == null) if (currentField == null)
@ -251,16 +266,19 @@ namespace ICSharpCode.Decompiler.ILAst
if (getEnumeratorMethod == null) if (getEnumeratorMethod == null)
return; // no mappings (maybe it's just an IEnumerator implementation?) return; // no mappings (maybe it's just an IEnumerator implementation?)
ILExpression mappingPattern = new ILExpression(
ILCode.Stfld, ILExpression.AnyOperand, new AnyILExpression(),
new ILExpression(ILCode.Ldfld, ILExpression.AnyOperand, LoadFromArgument.This));
ILBlock method = CreateILAst(getEnumeratorMethod); ILBlock method = CreateILAst(getEnumeratorMethod);
foreach (ILNode node in method.Body) { foreach (ILNode node in method.Body) {
if (mappingPattern.Match(node)) { FieldReference stField;
ILExpression stfld = (ILExpression)node; ILExpression stToObj;
FieldDefinition storedField = GetFieldDefinition(stfld.Operand as FieldReference); ILExpression stExpr;
FieldDefinition loadedField = GetFieldDefinition(stfld.Arguments[1].Operand as FieldReference); FieldReference ldField;
ILExpression ldFromObj;
if (node.Match(ILCode.Stfld, out stField, out stToObj, out stExpr) &&
stExpr.Match(ILCode.Ldfld, out ldField, out ldFromObj) &&
ldFromObj.MatchThis())
{
FieldDefinition storedField = GetFieldDefinition(stField);
FieldDefinition loadedField = GetFieldDefinition(ldField);
if (storedField != null && loadedField != null) { if (storedField != null && loadedField != null) {
ParameterDefinition mappedParameter; ParameterDefinition mappedParameter;
if (fieldToParameterMap.TryGetValue(loadedField, out mappedParameter)) if (fieldToParameterMap.TryGetValue(loadedField, out mappedParameter))
@ -671,7 +689,7 @@ namespace ICSharpCode.Decompiler.ILAst
ILExpression disposeArg; ILExpression disposeArg;
if (!faultBlock.Body[0].Match(ILCode.Call, out disposeMethodRef, out disposeArg)) if (!faultBlock.Body[0].Match(ILCode.Call, out disposeMethodRef, out disposeArg))
throw new YieldAnalysisFailedException(); throw new YieldAnalysisFailedException();
if (GetMethodDefinition(disposeMethodRef) != disposeMethod || !LoadFromArgument.This.Match(disposeArg)) if (GetMethodDefinition(disposeMethodRef) != disposeMethod || !disposeArg.MatchThis())
throw new YieldAnalysisFailedException(); throw new YieldAnalysisFailedException();
if (!faultBlock.Body[1].Match(ILCode.Endfinally)) if (!faultBlock.Body[1].Match(ILCode.Endfinally))
throw new YieldAnalysisFailedException(); throw new YieldAnalysisFailedException();
@ -757,7 +775,7 @@ namespace ICSharpCode.Decompiler.ILAst
// Copy all instructions from the old body to newBody. // Copy all instructions from the old body to newBody.
for (int pos = startPos; pos < bodyLength; pos++) { for (int pos = startPos; pos < bodyLength; pos++) {
ILExpression expr = body[pos] as ILExpression; ILExpression expr = body[pos] as ILExpression;
if (expr != null && expr.Code == ILCode.Stfld && LoadFromArgument.This.Match(expr.Arguments[0])) { if (expr != null && expr.Code == ILCode.Stfld && expr.Arguments[0].MatchThis()) {
// Handle stores to 'state' or 'current' // Handle stores to 'state' or 'current'
if (GetFieldDefinition(expr.Operand as FieldReference) == stateField) { if (GetFieldDefinition(expr.Operand as FieldReference) == stateField) {
if (expr.Arguments[1].Code != ILCode.Ldc_I4) if (expr.Arguments[1].Code != ILCode.Ldc_I4)
@ -794,7 +812,7 @@ namespace ICSharpCode.Decompiler.ILAst
} else { } else {
throw new YieldAnalysisFailedException(); throw new YieldAnalysisFailedException();
} }
} else if (expr != null && expr.Code == ILCode.Call && expr.Arguments.Count == 1 && LoadFromArgument.This.Match(expr.Arguments[0])) { } else if (expr != null && expr.Code == ILCode.Call && expr.Arguments.Count == 1 && expr.Arguments[0].MatchThis()) {
MethodDefinition method = GetMethodDefinition(expr.Operand as MethodReference); MethodDefinition method = GetMethodDefinition(expr.Operand as MethodReference);
if (method == null) if (method == null)
throw new YieldAnalysisFailedException(); throw new YieldAnalysisFailedException();
@ -857,7 +875,7 @@ namespace ICSharpCode.Decompiler.ILAst
FieldReference stfld; FieldReference stfld;
List<ILExpression> args; List<ILExpression> args;
if (block.Body.Count > 0 && block.Body[0].Match(ILCode.Stfld, out stfld, out args)) { if (block.Body.Count > 0 && block.Body[0].Match(ILCode.Stfld, out stfld, out args)) {
if (GetFieldDefinition(stfld) == stateField && LoadFromArgument.This.Match(args[0])) if (GetFieldDefinition(stfld) == stateField && args[0].MatchThis())
block.Body.RemoveAt(0); block.Body.RemoveAt(0);
} }
// Convert ret to endfinally // Convert ret to endfinally
@ -879,7 +897,7 @@ namespace ICSharpCode.Decompiler.ILAst
if (field != null) { if (field != null) {
switch (expr.Code) { switch (expr.Code) {
case ILCode.Ldfld: case ILCode.Ldfld:
if (LoadFromArgument.This.Match(expr.Arguments[0])) { if (expr.Arguments[0].MatchThis()) {
if (fieldToParameterMap.ContainsKey(field)) { if (fieldToParameterMap.ContainsKey(field)) {
expr.Code = ILCode.Ldarg; expr.Code = ILCode.Ldarg;
expr.Operand = fieldToParameterMap[field]; expr.Operand = fieldToParameterMap[field];
@ -891,7 +909,7 @@ namespace ICSharpCode.Decompiler.ILAst
} }
break; break;
case ILCode.Stfld: case ILCode.Stfld:
if (LoadFromArgument.This.Match(expr.Arguments[0])) { if (expr.Arguments[0].MatchThis()) {
if (fieldToParameterMap.ContainsKey(field)) { if (fieldToParameterMap.ContainsKey(field)) {
expr.Code = ILCode.Starg; expr.Code = ILCode.Starg;
expr.Operand = fieldToParameterMap[field]; expr.Operand = fieldToParameterMap[field];

Loading…
Cancel
Save