diff --git a/ICSharpCode.Decompiler/CSharp/CSharpDecompiler.cs b/ICSharpCode.Decompiler/CSharp/CSharpDecompiler.cs
index 814ff656c..73bdfe398 100644
--- a/ICSharpCode.Decompiler/CSharp/CSharpDecompiler.cs
+++ b/ICSharpCode.Decompiler/CSharp/CSharpDecompiler.cs
@@ -115,6 +115,7 @@ namespace ICSharpCode.Decompiler.CSharp
}
},
new DelegateConstruction(),
+ new AssignVariableNames()
};
}
@@ -127,11 +128,11 @@ namespace ICSharpCode.Decompiler.CSharp
new ConvertConstructorCallIntoInitializer(), // must run after DeclareVariables
new DecimalConstantTransform(),
new IntroduceUsingDeclarations(),
- new FixNameCollisions(),
//new IntroduceExtensionMethods(context), // must run after IntroduceUsingDeclarations
//new IntroduceQueryExpressions(context), // must run after IntroduceExtensionMethods
//new CombineQueryExpressions(context),
//new FlattenSwitchBlocks(),
+ new FixNameCollisions(),
};
public CancellationToken CancellationToken { get; set; }
@@ -612,8 +613,11 @@ namespace ICSharpCode.Decompiler.CSharp
void DecompileBody(MethodDefinition methodDefinition, IMethod method, EntityDeclaration entityDecl, ITypeResolveContext decompilationContext)
{
var specializingTypeSystem = typeSystem.GetSpecializingTypeSystem(decompilationContext);
- ILFunction function = ILFunction.Read(specializingTypeSystem, methodDefinition, CancellationToken);
-
+ var ilReader = new ILReader(specializingTypeSystem);
+ ilReader.UseDebugSymbols = settings.UseDebugSymbols;
+ var function = ilReader.ReadIL(methodDefinition.Body, CancellationToken);
+ function.CheckInvariant(ILPhase.Normal);
+
if (entityDecl != null) {
int i = 0;
var parameters = function.Variables.Where(v => v.Kind == VariableKind.Parameter).ToDictionary(v => v.Index);
diff --git a/ICSharpCode.Decompiler/CSharp/ExpressionBuilder.cs b/ICSharpCode.Decompiler/CSharp/ExpressionBuilder.cs
index 5f2ed7bf4..e960aaac9 100644
--- a/ICSharpCode.Decompiler/CSharp/ExpressionBuilder.cs
+++ b/ICSharpCode.Decompiler/CSharp/ExpressionBuilder.cs
@@ -1415,8 +1415,8 @@ namespace ICSharpCode.Decompiler.CSharp
case BlockType.CollectionInitializer:
case BlockType.ObjectInitializer:
return TranslateObjectAndCollectionInitializer(block);
- case BlockType.CompoundOperator:
- return TranslateCompoundOperator(block);
+ case BlockType.PostfixOperator:
+ return TranslatePostfixOperator(block);
default:
return ErrorExpression("Unknown block type: " + block.Type);
}
@@ -1584,7 +1584,7 @@ namespace ICSharpCode.Decompiler.CSharp
.WithRR(new ArrayCreateResolveResult(new ArrayType(compilation, type, dimensions), newArr.Indices.Select(i => Translate(i).ResolveResult).ToArray(), elementResolveResults));
}
- TranslatedExpression TranslateCompoundOperator(Block block)
+ TranslatedExpression TranslatePostfixOperator(Block block)
{
var targetInst = (block.Instructions.ElementAtOrDefault(0) as StLoc)?.Value;
var inst = (block.Instructions.ElementAtOrDefault(1) as StLoc)?.Value as BinaryNumericInstruction;
diff --git a/ICSharpCode.Decompiler/CSharp/StatementBuilder.cs b/ICSharpCode.Decompiler/CSharp/StatementBuilder.cs
index 3d97733d3..a55b3e957 100644
--- a/ICSharpCode.Decompiler/CSharp/StatementBuilder.cs
+++ b/ICSharpCode.Decompiler/CSharp/StatementBuilder.cs
@@ -24,6 +24,7 @@ using ICSharpCode.Decompiler.CSharp.Syntax;
using ICSharpCode.Decompiler.Semantics;
using ICSharpCode.Decompiler.TypeSystem;
using ICSharpCode.Decompiler.Util;
+using System;
using System.Threading;
namespace ICSharpCode.Decompiler.CSharp
@@ -307,10 +308,10 @@ namespace ICSharpCode.Decompiler.CSharp
continueStmt.Remove();
return new DoWhileStatement {
EmbeddedStatement = blockStatement,
- Condition = exprBuilder.TranslateCondition(loop.Condition)
+ Condition = exprBuilder.TranslateCondition(CombineConditions(loop.Conditions))
};
case LoopKind.For:
- conditionExpr = exprBuilder.TranslateCondition(loop.Condition);
+ conditionExpr = exprBuilder.TranslateCondition(loop.Conditions[0]);
blockStatement = ConvertAsBlock(loop.Body);
var forBody = ConvertBlockContainer(blockStatement, container, loop.AdditionalBlocks, true);
var forStmt = new ForStatement() {
@@ -334,7 +335,7 @@ namespace ICSharpCode.Decompiler.CSharp
if (!loop.Body.HasFlag(InstructionFlags.EndPointUnreachable))
blockStatement.Add(new BreakStatement());
}
- if (loop.Condition == null) {
+ if (loop.Conditions == null) {
conditionExpr = new PrimitiveExpression(true);
Debug.Assert(continueCount < container.EntryPoint.IncomingEdgeCount);
Debug.Assert(blockStatement.Statements.First() is LabelStatement);
@@ -343,7 +344,7 @@ namespace ICSharpCode.Decompiler.CSharp
blockStatement.Statements.First().Remove();
}
} else {
- conditionExpr = exprBuilder.TranslateCondition(loop.Condition);
+ conditionExpr = exprBuilder.TranslateCondition(loop.Conditions[0]);
blockStatement = ConvertBlockContainer(blockStatement, container, loop.AdditionalBlocks, true);
}
if (blockStatement.LastOrDefault() is ContinueStatement stmt)
@@ -352,6 +353,18 @@ namespace ICSharpCode.Decompiler.CSharp
}
}
+ private ILInstruction CombineConditions(ILInstruction[] conditions)
+ {
+ ILInstruction condition = null;
+ foreach (var c in conditions) {
+ if (condition == null)
+ condition = new LogicNot(c);
+ else
+ condition = IfInstruction.LogicAnd(new LogicNot(c), condition);
+ }
+ return condition;
+ }
+
BlockStatement ConvertBlockContainer(BlockContainer container, bool isLoop)
{
return ConvertBlockContainer(new BlockStatement(), container, container.Blocks, isLoop);
diff --git a/ICSharpCode.Decompiler/ICSharpCode.Decompiler.csproj b/ICSharpCode.Decompiler/ICSharpCode.Decompiler.csproj
index 923bb7f24..29a7a9858 100644
--- a/ICSharpCode.Decompiler/ICSharpCode.Decompiler.csproj
+++ b/ICSharpCode.Decompiler/ICSharpCode.Decompiler.csproj
@@ -288,6 +288,7 @@
+
diff --git a/ICSharpCode.Decompiler/IL/DetectedLoop.cs b/ICSharpCode.Decompiler/IL/DetectedLoop.cs
index 890dea2f0..c7bb97263 100644
--- a/ICSharpCode.Decompiler/IL/DetectedLoop.cs
+++ b/ICSharpCode.Decompiler/IL/DetectedLoop.cs
@@ -29,7 +29,7 @@ namespace ICSharpCode.Decompiler.IL
{
public BlockContainer Container { get; }
public LoopKind Kind { get; private set; }
- public ILInstruction Condition { get; private set; }
+ public ILInstruction[] Conditions { get; private set; }
public Block IncrementBlock { get; private set; }
public Block ContinueJumpTarget { get; private set; } // jumps to this block are "continue;" jumps
public ILInstruction Body { get; private set; } // null in case of DoWhile
@@ -64,19 +64,15 @@ namespace ICSharpCode.Decompiler.IL
return new DetectedLoop(container).DetectLoopInternal();
}
- private static Block FindDoWhileConditionBlock(BlockContainer container, out ILInstruction condition)
+ private static Block FindDoWhileConditionBlock(BlockContainer container, List conditions)
{
- condition = null;
foreach (var b in container.Blocks) {
if (b.Instructions.Last().MatchBranch(container.EntryPoint)) {
// potentially the do-while-condition block
int i = b.Instructions.Count - 2;
while (i >= 0 && b.Instructions[i] is IfInstruction ifInst
&& ifInst.TrueInst.MatchLeave(container) && ifInst.FalseInst.MatchNop()) {
- if (condition == null)
- condition = new LogicNot(ifInst.Condition);
- else
- condition = IfInstruction.LogicAnd(new LogicNot(ifInst.Condition), condition);
+ conditions.Add(ifInst.Condition);
i--;
}
if (i == -1) {
@@ -105,7 +101,7 @@ namespace ICSharpCode.Decompiler.IL
if (IncrementBlock != null)
ContinueJumpTarget = IncrementBlock;
}
- Condition = conditionInst;
+ Conditions = new[] { conditionInst };
Body = trueInst;
if (IncrementBlock != null) {
// for-loop
@@ -117,12 +113,13 @@ namespace ICSharpCode.Decompiler.IL
} else {
// do-while or while(true)-loop
if (Container.EntryPoint.IncomingEdgeCount == 2) {
- Block conditionBlock = FindDoWhileConditionBlock(Container, out var conditionInst2);
+ var conditions = new List();
+ Block conditionBlock = FindDoWhileConditionBlock(Container, conditions);
if (conditionBlock != null) {
Kind = LoopKind.DoWhile;
ContinueJumpTarget = conditionBlock;
Body = null;
- Condition = conditionInst2;
+ Conditions = conditions.ToArray();
AdditionalBlocks = Container.Blocks.Where(b => b != conditionBlock).ToArray();
}
}
diff --git a/ICSharpCode.Decompiler/IL/Instructions/ILFunction.cs b/ICSharpCode.Decompiler/IL/Instructions/ILFunction.cs
index 93b134239..f076d2e79 100644
--- a/ICSharpCode.Decompiler/IL/Instructions/ILFunction.cs
+++ b/ICSharpCode.Decompiler/IL/Instructions/ILFunction.cs
@@ -151,18 +151,5 @@ namespace ICSharpCode.Decompiler.IL
Variables.Add(variable);
return variable;
}
-
- public static ILFunction Read(IDecompilerTypeSystem context, IMethod method, CancellationToken cancellationToken = default(CancellationToken))
- {
- return Read(context, (MethodDefinition)context.GetCecil(method), cancellationToken);
- }
-
- public static ILFunction Read(IDecompilerTypeSystem context, MethodDefinition methodDefinition, CancellationToken cancellationToken = default(CancellationToken))
- {
- var ilReader = new ILReader(context);
- var function = ilReader.ReadIL(methodDefinition.Body, cancellationToken);
- function.CheckInvariant(ILPhase.Normal);
- return function;
- }
}
}
diff --git a/ICSharpCode.Decompiler/IL/Transforms/AssignVariableNames.cs b/ICSharpCode.Decompiler/IL/Transforms/AssignVariableNames.cs
new file mode 100644
index 000000000..da549e2db
--- /dev/null
+++ b/ICSharpCode.Decompiler/IL/Transforms/AssignVariableNames.cs
@@ -0,0 +1,348 @@
+// Copyright (c) 2017 Siegfried Pammer
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy of this
+// software and associated documentation files (the "Software"), to deal in the Software
+// without restriction, including without limitation the rights to use, copy, modify, merge,
+// publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons
+// to whom the Software is furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in all copies or
+// substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
+// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
+// PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE
+// FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
+// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+// DEALINGS IN THE SOFTWARE.
+
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+using ICSharpCode.Decompiler.IL;
+using ICSharpCode.Decompiler.Semantics;
+using ICSharpCode.Decompiler.TypeSystem;
+using ICSharpCode.Decompiler.Util;
+
+namespace ICSharpCode.Decompiler.IL.Transforms
+{
+ public class AssignVariableNames : IILTransform
+ {
+ static readonly Dictionary typeNameToVariableNameDict = new Dictionary {
+ { "System.Boolean", "flag" },
+ { "System.Byte", "b" },
+ { "System.SByte", "b" },
+ { "System.Int16", "num" },
+ { "System.Int32", "num" },
+ { "System.Int64", "num" },
+ { "System.UInt16", "num" },
+ { "System.UInt32", "num" },
+ { "System.UInt64", "num" },
+ { "System.Single", "num" },
+ { "System.Double", "num" },
+ { "System.Decimal", "num" },
+ { "System.String", "text" },
+ { "System.Object", "obj" },
+ { "System.Char", "c" }
+ };
+
+ ILTransformContext context;
+ string[] currentFieldNames;
+ Dictionary mapping;
+ Dictionary reservedVariableNames;
+ const char maxLoopVariableName = 'n';
+
+ public void Run(ILFunction function, ILTransformContext context)
+ {
+ this.context = context;
+ currentFieldNames = function.Method.DeclaringType.Fields.Select(f => f.Name).ToArray();
+ reservedVariableNames = new Dictionary();
+ foreach (ILFunction f in function.Descendants.OfType().Reverse()) {
+ PerformAssignment(f);
+ }
+ }
+
+ void PerformAssignment(ILFunction function)
+ {
+ foreach (var p in function.Method.Parameters)
+ AddExistingName(p.Name);
+ foreach (var v in function.Variables) {
+ switch (v.Kind) {
+ case VariableKind.Parameter:
+ case VariableKind.StackSlot: // keep generated names
+ AddExistingName(v.Name);
+ break;
+ default:
+ string varName = v.Name;
+ if (context.Settings.UseDebugSymbols) {
+ if (string.IsNullOrEmpty(varName) || varName.StartsWith("V_", StringComparison.Ordinal) || !IsValidName(varName)) {
+ // don't use the name from the debug symbols if it looks like a generated name
+ v.Name = null;
+ } else {
+ // use the name from the debug symbols
+ // (but ensure we don't use the same name for two variables)
+ v.Name = GetAlternativeName(varName);
+ }
+ } else {
+ v.Name = null;
+ }
+ break;
+ }
+ }
+ // Now generate names:
+ var mapping = new Dictionary(ILVariableEqualityComparer.Instance);
+ foreach (var inst in function.Descendants.OfType()) {
+ var v = inst.Variable;
+ if (!mapping.TryGetValue(v, out string name)) {
+ if (string.IsNullOrEmpty(v.Name))
+ v.Name = GenerateNameForVariable(v, function.Body);
+ mapping.Add(v, v.Name);
+ } else {
+ v.Name = name;
+ }
+ }
+ }
+
+ static bool IsValidName(string varName)
+ {
+ if (string.IsNullOrEmpty(varName))
+ return false;
+ if (!(char.IsLetter(varName[0]) || varName[0] == '_'))
+ return false;
+ for (int i = 1; i < varName.Length; i++) {
+ if (!(char.IsLetterOrDigit(varName[i]) || varName[i] == '_'))
+ return false;
+ }
+ return true;
+ }
+
+ public string GetAlternativeName(string oldVariableName)
+ {
+ if (oldVariableName.Length == 1 && oldVariableName[0] >= 'i' && oldVariableName[0] <= maxLoopVariableName) {
+ for (char c = 'i'; c <= maxLoopVariableName; c++) {
+ if (!reservedVariableNames.ContainsKey(c.ToString())) {
+ reservedVariableNames.Add(c.ToString(), 1);
+ return c.ToString();
+ }
+ }
+ }
+
+ int number;
+ string nameWithoutDigits = SplitName(oldVariableName, out number);
+
+ if (!reservedVariableNames.ContainsKey(nameWithoutDigits)) {
+ reservedVariableNames.Add(nameWithoutDigits, number - 1);
+ }
+ int count = ++reservedVariableNames[nameWithoutDigits];
+ if (count != 1) {
+ return nameWithoutDigits + count.ToString();
+ } else {
+ return nameWithoutDigits;
+ }
+ }
+
+ string GenerateNameForVariable(ILVariable variable, ILInstruction methodBody)
+ {
+ string proposedName = null;
+ if (variable.Type.IsKnownType(KnownTypeCode.Int32)) {
+ // test whether the variable might be a loop counter
+ bool isLoopCounter = false;
+ foreach (BlockContainer possibleLoop in methodBody.Descendants.OfType().Reverse()) {
+ if (possibleLoop.EntryPoint.IncomingEdgeCount == 1) continue;
+ var loop = DetectedLoop.DetectLoop(possibleLoop);
+ if (loop.Kind != LoopKind.For) continue;
+ var condition = loop.Conditions?[0];
+ while (condition is LogicNot not)
+ condition = not.Argument;
+ if (condition is Comp comp) {
+ switch (comp.Kind) {
+ case ComparisonKind.GreaterThan:
+ case ComparisonKind.GreaterThanOrEqual:
+ case ComparisonKind.LessThan:
+ case ComparisonKind.LessThanOrEqual:
+ if (comp.Left.MatchLdLoc(variable)) {
+ isLoopCounter = true;
+ }
+ break;
+ }
+ }
+ }
+ if (isLoopCounter) {
+ // For loop variables, use i,j,k,l,m,n
+ for (char c = 'i'; c <= maxLoopVariableName; c++) {
+ if (!reservedVariableNames.ContainsKey(c.ToString())) {
+ proposedName = c.ToString();
+ break;
+ }
+ }
+ }
+ }
+ if (string.IsNullOrEmpty(proposedName)) {
+ var proposedNameForStores = variable.StoreInstructions.OfType()
+ .Select(expr => GetNameFromInstruction(expr.Value))
+ .Except(currentFieldNames).ToList();
+ if (proposedNameForStores.Count == 1) {
+ proposedName = proposedNameForStores[0];
+ }
+ }
+ if (string.IsNullOrEmpty(proposedName)) {
+ var proposedNameForLoads = variable.LoadInstructions
+ .Select(arg => GetNameForArgument(arg.Parent, arg.ChildIndex))
+ .Except(currentFieldNames).ToList();
+ if (proposedNameForLoads.Count == 1) {
+ proposedName = proposedNameForLoads[0];
+ }
+ }
+ if (string.IsNullOrEmpty(proposedName)) {
+ proposedName = GetNameByType(variable.Type);
+ }
+
+ // remove any numbers from the proposed name
+ int number;
+ proposedName = SplitName(proposedName, out number);
+
+ if (!reservedVariableNames.ContainsKey(proposedName)) {
+ reservedVariableNames.Add(proposedName, 0);
+ }
+ int count = ++reservedVariableNames[proposedName];
+ if (count > 1) {
+ return proposedName + count.ToString();
+ } else {
+ return proposedName;
+ }
+ }
+
+ static string GetNameFromInstruction(ILInstruction inst)
+ {
+ switch (inst) {
+ case LdObj ldobj:
+ IField field;
+ if (ldobj.Target is LdFlda ldflda)
+ field = ldflda.Field;
+ else if (ldobj.Target is LdsFlda ldsflda)
+ field = ldsflda.Field;
+ else
+ break;
+ return CleanUpVariableName(field.Name);
+ case CallInstruction call:
+ if (call is NewObj) break;
+ IMethod m = call.Method;
+ if (m.Name.StartsWith("get_", StringComparison.OrdinalIgnoreCase) && m.Parameters.Count == 0) {
+ // use name from properties, but not from indexers
+ return CleanUpVariableName(m.Name.Substring(4));
+ } else if (m.Name.StartsWith("Get", StringComparison.OrdinalIgnoreCase) && m.Name.Length >= 4 && char.IsUpper(m.Name[3])) {
+ // use name from Get-methods
+ return CleanUpVariableName(m.Name.Substring(3));
+ }
+ break;
+ }
+ return null;
+ }
+
+ static string GetNameForArgument(ILInstruction parent, int i)
+ {
+ switch (parent) {
+ case StObj stobj:
+ IField field;
+ if (stobj.Target is LdFlda ldflda)
+ field = ldflda.Field;
+ else if (stobj.Target is LdsFlda ldsflda)
+ field = ldsflda.Field;
+ else
+ break;
+ return CleanUpVariableName(field.Name);
+ case CallInstruction call:
+ IMethod m = call.Method;
+ if (m.Parameters.Count == 1 && i == call.Arguments.Count - 1) {
+ // argument might be value of a setter
+ if (m.Name.StartsWith("set_", StringComparison.OrdinalIgnoreCase)) {
+ return CleanUpVariableName(m.Name.Substring(4));
+ } else if (m.Name.StartsWith("Set", StringComparison.OrdinalIgnoreCase) && m.Name.Length >= 4 && char.IsUpper(m.Name[3])) {
+ return CleanUpVariableName(m.Name.Substring(3));
+ }
+ }
+ var p = m.Parameters.ElementAtOrDefault((!(call is NewObj) && !m.IsStatic) ? i - 1 : i);
+ if (p != null && !string.IsNullOrEmpty(p.Name))
+ return CleanUpVariableName(p.Name);
+ break;
+ case Return ret:
+ return "result";
+ }
+ return null;
+ }
+
+ string GetNameByType(IType type)
+ {
+ var git = type as ParameterizedType;
+ if (git != null && git.FullName == "System.Nullable`1" && git.TypeArguments.Count == 1) {
+ type = git.TypeArguments[0];
+ }
+
+ string name;
+ if (type is ArrayType) {
+ name = "array";
+ } else if (type is PointerType) {
+ name = "ptr";
+ } else if (type.IsAnonymousType()) {
+ name = "anon";
+ } else if (type.Name.EndsWith("Exception", StringComparison.Ordinal)) {
+ name = "ex";
+ } else if (!typeNameToVariableNameDict.TryGetValue(type.FullName, out name)) {
+ name = type.Name;
+ // remove the 'I' for interfaces
+ if (name.Length >= 3 && name[0] == 'I' && char.IsUpper(name[1]) && char.IsLower(name[2]))
+ name = name.Substring(1);
+ name = CleanUpVariableName(name);
+ }
+ return name;
+ }
+
+ void AddExistingName(string name)
+ {
+ if (string.IsNullOrEmpty(name))
+ return;
+ string nameWithoutDigits = SplitName(name, out int number);
+ if (reservedVariableNames.TryGetValue(nameWithoutDigits, out int existingNumber)) {
+ reservedVariableNames[nameWithoutDigits] = Math.Max(number, existingNumber);
+ } else {
+ reservedVariableNames.Add(nameWithoutDigits, number);
+ }
+ }
+
+ static string SplitName(string name, out int number)
+ {
+ // First, identify whether the name already ends with a number:
+ int pos = name.Length;
+ while (pos > 0 && name[pos - 1] >= '0' && name[pos - 1] <= '9')
+ pos--;
+ if (pos < name.Length) {
+ if (int.TryParse(name.Substring(pos), out number)) {
+ return name.Substring(0, pos);
+ }
+ }
+ number = 1;
+ return name;
+ }
+
+ static string CleanUpVariableName(string name)
+ {
+ // remove the backtick (generics)
+ int pos = name.IndexOf('`');
+ if (pos >= 0)
+ name = name.Substring(0, pos);
+
+ // remove field prefix:
+ if (name.Length > 2 && name.StartsWith("m_", StringComparison.Ordinal))
+ name = name.Substring(2);
+ else if (name.Length > 1 && name[0] == '_' && (char.IsLetter(name[1]) || name[1] == '_'))
+ name = name.Substring(1);
+
+ if (name.Length == 0)
+ return "obj";
+ else
+ return char.ToLower(name[0]) + name.Substring(1);
+ }
+ }
+}
diff --git a/ICSharpCode.Decompiler/IL/Transforms/DelegateConstruction.cs b/ICSharpCode.Decompiler/IL/Transforms/DelegateConstruction.cs
index 119707ebc..3d49bf927 100644
--- a/ICSharpCode.Decompiler/IL/Transforms/DelegateConstruction.cs
+++ b/ICSharpCode.Decompiler/IL/Transforms/DelegateConstruction.cs
@@ -139,9 +139,13 @@ namespace ICSharpCode.Decompiler.IL.Transforms
var targetMethod = ((IInstructionWithMethodOperand)value.Arguments[1]).Method;
if (IsAnonymousMethod(decompilationContext.CurrentTypeDefinition, targetMethod)) {
target = value.Arguments[0];
+ var methodDefinition = (Mono.Cecil.MethodDefinition)context.TypeSystem.GetCecil(targetMethod);
var localTypeSystem = context.TypeSystem.GetSpecializingTypeSystem(new SimpleTypeResolveContext(targetMethod));
- var function = ILFunction.Read(localTypeSystem, targetMethod, context.CancellationToken);
-
+ var ilReader = new ILReader(localTypeSystem);
+ ilReader.UseDebugSymbols = context.Settings.UseDebugSymbols;
+ var function = ilReader.ReadIL(methodDefinition.Body, context.CancellationToken);
+ function.CheckInvariant(ILPhase.Normal);
+
var contextPrefix = targetMethod.Name;
foreach (ILVariable v in function.Variables.Where(v => v.Kind != VariableKind.Parameter)) {
v.Name = contextPrefix + v.Name;
diff --git a/ILSpy.BamlDecompiler/ConnectMethodDecompiler.cs b/ILSpy.BamlDecompiler/ConnectMethodDecompiler.cs
index f4ddec62c..51accc294 100644
--- a/ILSpy.BamlDecompiler/ConnectMethodDecompiler.cs
+++ b/ILSpy.BamlDecompiler/ConnectMethodDecompiler.cs
@@ -56,8 +56,9 @@ namespace ILSpy.BamlDecompiler
// decompile method and optimize the switch
var typeSystem = new DecompilerTypeSystem(method.Module);
- ILFunction function = ILFunction.Read(typeSystem, method);
-
+ var ilReader = new ILReader(typeSystem);
+ var function = ilReader.ReadIL(method.Body);
+
var context = new ILTransformContext { Settings = new DecompilerSettings(), TypeSystem = typeSystem };
function.RunTransforms(CSharpDecompiler.GetILTransforms(), context);