diff --git a/ICSharpCode.Decompiler/CSharp/CSharpDecompiler.cs b/ICSharpCode.Decompiler/CSharp/CSharpDecompiler.cs
index 0d4a9278a..ecefef5f1 100644
--- a/ICSharpCode.Decompiler/CSharp/CSharpDecompiler.cs
+++ b/ICSharpCode.Decompiler/CSharp/CSharpDecompiler.cs
@@ -80,8 +80,8 @@ namespace ICSharpCode.Decompiler.CSharp
new ILInlining(),
new DetectPinnedRegions(), // must run after inlining but before non-critical control flow transforms
new InlineReturnTransform(),
- //new YieldReturnDecompiler(), // must run after inlining but before loop detection
- //new AsyncAwaitDecompiler(), // must run after inlining but before loop detection
+ new YieldReturnDecompiler(), // must run after inlining but before loop detection
+ new AsyncAwaitDecompiler(), // must run after inlining but before loop detection
new DetectCatchWhenConditionBlocks(), // must run after inlining but before loop detection
new DetectExitPoints(canIntroduceExitForReturn: false),
new EarlyExpressionTransforms(),
@@ -222,8 +222,8 @@ namespace ICSharpCode.Decompiler.CSharp
return true;
if (settings.AnonymousMethods && methodHandle.HasGeneratedName(metadata) && methodHandle.IsCompilerGenerated(metadata))
return true;
- /*if (settings.AsyncAwait && AsyncAwaitDecompiler.IsCompilerGeneratedMainMethod(module, (MethodDefinitionHandle)member))
- return true;*/
+ if (settings.AsyncAwait && AsyncAwaitDecompiler.IsCompilerGeneratedMainMethod(module, (MethodDefinitionHandle)member))
+ return true;
return false;
case HandleKind.TypeDefinition:
var typeHandle = (TypeDefinitionHandle)member;
@@ -232,10 +232,10 @@ namespace ICSharpCode.Decompiler.CSharp
if (!type.GetDeclaringType().IsNil) {
if (settings.AnonymousMethods && IsClosureType(type, metadata))
return true;
- /*if (settings.YieldReturn && YieldReturnDecompiler.IsCompilerGeneratorEnumerator(type))
+ if (settings.YieldReturn && YieldReturnDecompiler.IsCompilerGeneratorEnumerator(typeHandle, metadata))
+ return true;
+ if (settings.AsyncAwait && AsyncAwaitDecompiler.IsCompilerGeneratedStateMachine(typeHandle, metadata))
return true;
- if (settings.AsyncAwait && AsyncAwaitDecompiler.IsCompilerGeneratedStateMachine(type))
- return true;*/
if (settings.FixedBuffers && name.StartsWith("<", StringComparison.Ordinal) && name.Contains("__FixedBuffer"))
return true;
} else if (type.IsCompilerGenerated(metadata)) {
diff --git a/ICSharpCode.Decompiler/ICSharpCode.Decompiler.csproj b/ICSharpCode.Decompiler/ICSharpCode.Decompiler.csproj
index 1dde7e4dd..230758a12 100644
--- a/ICSharpCode.Decompiler/ICSharpCode.Decompiler.csproj
+++ b/ICSharpCode.Decompiler/ICSharpCode.Decompiler.csproj
@@ -282,6 +282,9 @@
+
+
+
diff --git a/ICSharpCode.Decompiler/IL/ControlFlow/AsyncAwaitDecompiler.cs b/ICSharpCode.Decompiler/IL/ControlFlow/AsyncAwaitDecompiler.cs
index 2980cf6c1..9b24962c2 100644
--- a/ICSharpCode.Decompiler/IL/ControlFlow/AsyncAwaitDecompiler.cs
+++ b/ICSharpCode.Decompiler/IL/ControlFlow/AsyncAwaitDecompiler.cs
@@ -24,6 +24,7 @@ using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
+using System.Reflection.Metadata;
namespace ICSharpCode.Decompiler.IL.ControlFlow
{
@@ -32,19 +33,20 @@ namespace ICSharpCode.Decompiler.IL.ControlFlow
///
class AsyncAwaitDecompiler : IILTransform
{
- public static bool IsCompilerGeneratedStateMachine(Mono.Cecil.TypeDefinition type)
+ public static bool IsCompilerGeneratedStateMachine(TypeDefinitionHandle type, MetadataReader metadata)
{
- if (!(type.DeclaringType != null && type.IsCompilerGenerated()))
+ TypeDefinition td;
+ if (type.IsNil || !type.IsCompilerGenerated(metadata) || (td = metadata.GetTypeDefinition(type)).GetDeclaringType().IsNil)
return false;
- foreach (var i in type.Interfaces) {
- var iface = i.InterfaceType;
- if (iface.Namespace == "System.Runtime.CompilerServices" && iface.Name == "IAsyncStateMachine")
+ foreach (var i in td.GetInterfaceImplementations()) {
+ var tr = metadata.GetInterfaceImplementation(i).Interface.GetFullTypeName(metadata);
+ if (!tr.IsNested && tr.TopLevelTypeName.Namespace == "System.Runtime.CompilerServices" && tr.TopLevelTypeName.Name == "IAsyncStateMachine")
return true;
}
return false;
}
- public static bool IsCompilerGeneratedMainMethod(Metadata.PEFile module, System.Reflection.Metadata.MethodDefinitionHandle method)
+ public static bool IsCompilerGeneratedMainMethod(Metadata.PEFile module, MethodDefinitionHandle method)
{
var metadata = module.GetMetadataReader();
var definition = metadata.GetMethodDefinition(method);
@@ -60,6 +62,7 @@ namespace ICSharpCode.Decompiler.IL.ControlFlow
}
ILTransformContext context;
+ MetadataReader metadata;
// These fields are set by MatchTaskCreationPattern()
IType taskType; // return type of the async method
@@ -95,6 +98,7 @@ namespace ICSharpCode.Decompiler.IL.ControlFlow
if (!context.Settings.AsyncAwait)
return; // abort if async/await decompilation is disabled
this.context = context;
+ this.metadata = context.TypeSystem.GetMetadata();
fieldToParameterMap.Clear();
cachedFieldToParameterMap.Clear();
awaitBlocks.Clear();
@@ -328,7 +332,9 @@ namespace ICSharpCode.Decompiler.IL.ControlFlow
///
void AnalyzeMoveNext()
{
- var moveNextMethod = context.TypeSystem.GetCecil(stateMachineType)?.Methods.FirstOrDefault(f => f.Name == "MoveNext");
+ if (stateMachineType.MetadataToken.IsNil)
+ throw new SymbolicAnalysisFailedException();
+ var moveNextMethod = metadata.GetTypeDefinition((TypeDefinitionHandle)stateMachineType.MetadataToken).GetMethods().FirstOrDefault(f => metadata.GetString(metadata.GetMethodDefinition(f).Name)== "MoveNext");
if (moveNextMethod == null)
throw new SymbolicAnalysisFailedException();
moveNextFunction = YieldReturnDecompiler.CreateILAst(moveNextMethod, context);
diff --git a/ICSharpCode.Decompiler/IL/ControlFlow/YieldReturnDecompiler.cs b/ICSharpCode.Decompiler/IL/ControlFlow/YieldReturnDecompiler.cs
index 5b7b846f6..be97cf60f 100644
--- a/ICSharpCode.Decompiler/IL/ControlFlow/YieldReturnDecompiler.cs
+++ b/ICSharpCode.Decompiler/IL/ControlFlow/YieldReturnDecompiler.cs
@@ -20,11 +20,11 @@ using ICSharpCode.Decompiler.CSharp;
using ICSharpCode.Decompiler.IL.Transforms;
using ICSharpCode.Decompiler.TypeSystem;
using ICSharpCode.Decompiler.Util;
-using Mono.Cecil;
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
+using System.Reflection.Metadata;
namespace ICSharpCode.Decompiler.IL.ControlFlow
{
@@ -42,24 +42,25 @@ namespace ICSharpCode.Decompiler.IL.ControlFlow
// for a description of this step.
ILTransformContext context;
+ MetadataReader metadata;
/// The type that contains the function being decompiled.
- TypeDefinition currentType;
+ TypeDefinitionHandle currentType;
/// The compiler-generated enumerator class.
/// Set in MatchEnumeratorCreationPattern()
- TypeDefinition enumeratorType;
+ TypeDefinitionHandle enumeratorType;
/// The constructor of the compiler-generated enumerator class.
/// Set in MatchEnumeratorCreationPattern()
- MethodDefinition enumeratorCtor;
+ MethodDefinitionHandle enumeratorCtor;
/// Set in MatchEnumeratorCreationPattern()
bool isCompiledWithMono;
/// The dispose method of the compiler-generated enumerator class.
/// Set in ConstructExceptionTable()
- MethodDefinition disposeMethod;
+ MethodDefinitionHandle disposeMethod;
/// The field in the compiler-generated class holding the current state of the state machine
/// Set in AnalyzeCtor() for MS, MatchEnumeratorCreationPattern() or AnalyzeMoveNext() for Mono
@@ -105,9 +106,10 @@ namespace ICSharpCode.Decompiler.IL.ControlFlow
if (!context.Settings.YieldReturn)
return; // abort if enumerator decompilation is disabled
this.context = context;
- this.currentType = function.CecilMethod.DeclaringType;
- this.enumeratorType = null;
- this.enumeratorCtor = null;
+ this.metadata = context.TypeSystem.GetMetadata();
+ this.currentType = metadata.GetMethodDefinition((MethodDefinitionHandle)context.Function.Method.MetadataToken).GetDeclaringType();
+ this.enumeratorType = default;
+ this.enumeratorCtor = default;
this.stateField = null;
this.currentField = null;
this.fieldToParameterMap.Clear();
@@ -303,10 +305,10 @@ namespace ICSharpCode.Decompiler.IL.ControlFlow
return false;
if (!(initialState == -2 || initialState == 0))
return false;
- enumeratorCtor = context.TypeSystem.GetCecil(newObj.Method) as MethodDefinition;
- enumeratorType = enumeratorCtor?.DeclaringType;
- return enumeratorType?.DeclaringType == currentType
- && IsCompilerGeneratorEnumerator(enumeratorType);
+ enumeratorCtor = (MethodDefinitionHandle)newObj.Method.MetadataToken;
+ enumeratorType = enumeratorCtor.IsNil ? default : metadata.GetMethodDefinition(enumeratorCtor).GetDeclaringType();
+ return (enumeratorType.IsNil ? default : metadata.GetTypeDefinition(enumeratorType).GetDeclaringType()) == currentType
+ && IsCompilerGeneratorEnumerator(enumeratorType, metadata);
}
bool MatchMonoEnumeratorCreationNewObj(ILInstruction inst)
@@ -316,19 +318,20 @@ namespace ICSharpCode.Decompiler.IL.ControlFlow
return false;
if (newObj.Arguments.Count != 0)
return false;
- enumeratorCtor = context.TypeSystem.GetCecil(newObj.Method) as MethodDefinition;
- enumeratorType = enumeratorCtor?.DeclaringType;
- return enumeratorType?.DeclaringType == currentType
- && IsCompilerGeneratorEnumerator(enumeratorType);
+ enumeratorCtor = (MethodDefinitionHandle)newObj.Method.MetadataToken;
+ enumeratorType = enumeratorCtor.IsNil ? default : metadata.GetMethodDefinition(enumeratorCtor).GetDeclaringType();
+ return (enumeratorType.IsNil ? default : metadata.GetTypeDefinition(enumeratorType).GetDeclaringType()) == currentType
+ && IsCompilerGeneratorEnumerator(enumeratorType, metadata);
}
- public static bool IsCompilerGeneratorEnumerator(TypeDefinition type)
+ public static bool IsCompilerGeneratorEnumerator(TypeDefinitionHandle type, MetadataReader metadata)
{
- if (!(type?.DeclaringType != null && type.IsCompilerGenerated()))
+ TypeDefinition td;
+ if (type.IsNil || !type.IsCompilerGenerated(metadata) || (td = metadata.GetTypeDefinition(type)).GetDeclaringType().IsNil)
return false;
- foreach (var i in type.Interfaces) {
- var tr = i.InterfaceType;
- if (tr.Namespace == "System.Collections" && tr.Name == "IEnumerator")
+ foreach (var i in td.GetInterfaceImplementations()) {
+ var tr = metadata.GetInterfaceImplementation(i).Interface.GetFullTypeName(metadata);
+ if (!tr.IsNested && tr.TopLevelTypeName.Namespace == "System.Collections" && tr.TopLevelTypeName.Name == "IEnumerator")
return true;
}
return false;
@@ -359,12 +362,15 @@ namespace ICSharpCode.Decompiler.IL.ControlFlow
///
/// Creates ILAst for the specified method, optimized up to before the 'YieldReturn' step.
///
- internal static ILFunction CreateILAst(MethodDefinition method, ILTransformContext context)
+ internal static ILFunction CreateILAst(MethodDefinitionHandle method, ILTransformContext context)
{
- if (method == null || !method.HasBody)
+ var typeSystem = context.TypeSystem;
+ var metadata = typeSystem.GetMetadata();
+ if (method.IsNil || !method.HasBody(metadata))
throw new SymbolicAnalysisFailedException();
- var typeSystem = context.TypeSystem;
+ var methodDef = metadata.GetMethodDefinition(method);
+
var sdtp = typeSystem as SpecializingDecompilerTypeSystem;
if (sdtp != null) {
typeSystem = new SpecializingDecompilerTypeSystem(
@@ -376,7 +382,7 @@ namespace ICSharpCode.Decompiler.IL.ControlFlow
)
);
}
- var il = new ILReader(typeSystem).ReadIL(method.Body, context.CancellationToken);
+ var il = new ILReader(typeSystem).ReadIL(typeSystem.ModuleDefinition, method, typeSystem.ModuleDefinition.Reader.GetMethodBody(methodDef.RelativeVirtualAddress), context.CancellationToken);
il.RunTransforms(CSharpDecompiler.EarlyILTransforms(true),
new ILTransformContext(il, typeSystem, context.Settings) {
CancellationToken = context.CancellationToken,
@@ -392,9 +398,9 @@ namespace ICSharpCode.Decompiler.IL.ControlFlow
///
void AnalyzeCurrentProperty()
{
- MethodDefinition getCurrentMethod = enumeratorType.Methods.FirstOrDefault(
- m => m.Name.StartsWith("System.Collections.Generic.IEnumerator", StringComparison.Ordinal)
- && m.Name.EndsWith(".get_Current", StringComparison.Ordinal));
+ MethodDefinitionHandle getCurrentMethod = metadata.GetTypeDefinition(enumeratorType).GetMethods().FirstOrDefault(
+ m => metadata.GetString(metadata.GetMethodDefinition(m).Name).StartsWith("System.Collections.Generic.IEnumerator", StringComparison.Ordinal)
+ && metadata.GetString(metadata.GetMethodDefinition(m).Name).EndsWith(".get_Current", StringComparison.Ordinal));
Block body = SingleBlock(CreateILAst(getCurrentMethod, context).Body);
if (body == null)
throw new SymbolicAnalysisFailedException();
@@ -426,10 +432,10 @@ namespace ICSharpCode.Decompiler.IL.ControlFlow
#region Figure out the mapping of IEnumerable fields to IEnumerator fields (analysis of GetEnumerator())
void ResolveIEnumerableIEnumeratorFieldMapping()
{
- MethodDefinition getEnumeratorMethod = enumeratorType.Methods.FirstOrDefault(
- m => m.Name.StartsWith("System.Collections.Generic.IEnumerable", StringComparison.Ordinal)
- && m.Name.EndsWith(".GetEnumerator", StringComparison.Ordinal));
- if (getEnumeratorMethod == null)
+ MethodDefinitionHandle getEnumeratorMethod = metadata.GetTypeDefinition(enumeratorType).GetMethods().FirstOrDefault(
+ m => metadata.GetString(metadata.GetMethodDefinition(m).Name).StartsWith("System.Collections.Generic.IEnumerable", StringComparison.Ordinal)
+ && metadata.GetString(metadata.GetMethodDefinition(m).Name).EndsWith(".GetEnumerator", StringComparison.Ordinal));
+ if (getEnumeratorMethod.IsNil)
return; // no mappings (maybe it's just an IEnumerator implementation?)
var function = CreateILAst(getEnumeratorMethod, context);
foreach (var block in function.Descendants.OfType()) {
@@ -455,12 +461,12 @@ namespace ICSharpCode.Decompiler.IL.ControlFlow
{
if (isCompiledWithMono) {
// On mono, we don't need to analyse Dispose() to reconstruct the try-finally structure.
- disposeMethod = null;
- finallyMethodToStateRange = null;
+ disposeMethod = default;
+ finallyMethodToStateRange = default;
return;
}
- disposeMethod = enumeratorType.Methods.FirstOrDefault(m => m.Name == "System.IDisposable.Dispose");
+ disposeMethod = metadata.GetTypeDefinition(enumeratorType).GetMethods().FirstOrDefault(m => metadata.GetString(metadata.GetMethodDefinition(m).Name) == "System.IDisposable.Dispose");
var function = CreateILAst(disposeMethod, context);
var rangeAnalysis = new StateRangeAnalysis(StateRangeAnalysisMode.IteratorDispose, stateField);
@@ -485,7 +491,7 @@ namespace ICSharpCode.Decompiler.IL.ControlFlow
BlockContainer AnalyzeMoveNext()
{
context.StepStartGroup("AnalyzeMoveNext");
- MethodDefinition moveNextMethod = enumeratorType.Methods.FirstOrDefault(m => m.Name == "MoveNext");
+ MethodDefinitionHandle moveNextMethod = metadata.GetTypeDefinition(enumeratorType).GetMethods().FirstOrDefault(m => metadata.GetString(metadata.GetMethodDefinition(m).Name) == "MoveNext");
ILFunction moveNextFunction = CreateILAst(moveNextMethod, context);
// Copy-propagate temporaries holding a copy of 'this'.
@@ -503,7 +509,7 @@ namespace ICSharpCode.Decompiler.IL.ControlFlow
var faultBlock = faultBlockContainer.Blocks.Single();
if (!(faultBlock.Instructions.Count == 2
&& faultBlock.Instructions[0] is Call call
- && context.TypeSystem.GetCecil(call.Method) == disposeMethod
+ && call.Method.MetadataToken == disposeMethod
&& call.Arguments.Count == 1
&& call.Arguments[0].MatchLdThis()
&& faultBlock.Instructions[1].MatchLeave(faultBlockContainer))) {
@@ -823,7 +829,7 @@ namespace ICSharpCode.Decompiler.IL.ControlFlow
void DecompileFinallyBlocks()
{
foreach (var method in finallyMethodToStateRange.Keys) {
- var function = CreateILAst((MethodDefinition)context.TypeSystem.GetCecil(method), context);
+ var function = CreateILAst((MethodDefinitionHandle)method.MetadataToken, context);
var body = (BlockContainer)function.Body;
var newState = GetNewState(body.EntryPoint);
if (newState != null) {