Browse Source

SRM WIP basic implementation of DecompilerTypeSystem

pull/1198/head
Siegfried Pammer 8 years ago
parent
commit
b500b24548
  1. 2
      ICSharpCode.Decompiler/CSharp/Resolver/CSharpOperators.cs
  2. 2
      ICSharpCode.Decompiler/Disassembler/DisassemblerHelpers.cs
  3. 2
      ICSharpCode.Decompiler/Disassembler/ILStructure.cs
  4. 2
      ICSharpCode.Decompiler/Disassembler/MethodBodyDisassembler.cs
  5. 16
      ICSharpCode.Decompiler/Disassembler/OpCodeInfo.cs
  6. 6
      ICSharpCode.Decompiler/Disassembler/ReflectionDisassembler.cs
  7. 6
      ICSharpCode.Decompiler/ICSharpCode.Decompiler.csproj
  8. 821
      ICSharpCode.Decompiler/IL/ILReader.cs
  9. 4
      ICSharpCode.Decompiler/IL/Instructions/CallIndirect.cs
  10. 40
      ICSharpCode.Decompiler/Metadata/Dom.cs
  11. 35
      ICSharpCode.Decompiler/Metadata/MetadataExtensions.cs
  12. 24
      ICSharpCode.Decompiler/Metadata/MetadataResolver.cs
  13. 2
      ICSharpCode.Decompiler/Metadata/UniversalAssemblyResolver.cs
  14. 4
      ICSharpCode.Decompiler/SRMExtensions.cs
  15. 30
      ICSharpCode.Decompiler/SRMHacks.cs
  16. 360
      ICSharpCode.Decompiler/TypeSystem/DecompilerTypeSystem.cs
  17. 12
      ICSharpCode.Decompiler/TypeSystem/IDecompilerTypeSystem.cs
  18. 640
      ICSharpCode.Decompiler/TypeSystem/MetadataLoader.cs
  19. 12
      ICSharpCode.Decompiler/TypeSystem/SpecializingDecompilerTypeSystem.cs
  20. 13
      ICSharpCode.Decompiler/Util/CollectionExtensions.cs
  21. 4
      ILSpy/SearchStrategies.cs

2
ICSharpCode.Decompiler/CSharp/Resolver/CSharpOperators.cs

@ -116,7 +116,7 @@ namespace ICSharpCode.Decompiler.CSharp.Resolver @@ -116,7 +116,7 @@ namespace ICSharpCode.Decompiler.CSharp.Resolver
return null;
}
public System.Reflection.Metadata.EntityHandle MetadataToken => default(System.Reflection.Metadata.EntityHandle);
public System.Reflection.Metadata.EntityHandle MetadataToken => default;
ITypeDefinition IEntity.DeclaringTypeDefinition {
get { return null; }

2
ICSharpCode.Decompiler/Disassembler/DisassemblerHelpers.cs

@ -133,7 +133,7 @@ namespace ICSharpCode.Decompiler.Disassembler @@ -133,7 +133,7 @@ namespace ICSharpCode.Decompiler.Disassembler
{
var metadata = method.Module.GetMetadataReader();
var methodDefinition = metadata.GetMethodDefinition(method.Handle);
var signature = methodDefinition.DecodeSignature(new FullTypeNameSignatureDecoder(metadata), default(Unit));
var signature = methodDefinition.DecodeSignature(new FullTypeNameSignatureDecoder(metadata), default);
var parameters = methodDefinition.GetParameters().Select(p => metadata.GetParameter(p)).ToArray();
var signatureHeader = signature.Header;
int index = sequence;

2
ICSharpCode.Decompiler/Disassembler/ILStructure.cs

@ -132,7 +132,7 @@ namespace ICSharpCode.Decompiler.Disassembler @@ -132,7 +132,7 @@ namespace ICSharpCode.Decompiler.Disassembler
SortChildren();
}
public ILStructure(Metadata.MethodDefinition method, ILStructureType type, int startOffset, int endOffset, ExceptionRegion handler = default(ExceptionRegion))
public ILStructure(Metadata.MethodDefinition method, ILStructureType type, int startOffset, int endOffset, ExceptionRegion handler = default)
{
Debug.Assert(startOffset < endOffset);
this.Method = method;

2
ICSharpCode.Decompiler/Disassembler/MethodBodyDisassembler.cs

@ -299,7 +299,7 @@ namespace ICSharpCode.Decompiler.Disassembler @@ -299,7 +299,7 @@ namespace ICSharpCode.Decompiler.Disassembler
handle = MetadataTokens.EntityHandle(blob.ReadInt32());
switch (handle.Kind) {
case HandleKind.MemberReference:
switch (method.Module.GetMetadataReader().GetMemberReference((MemberReferenceHandle)handle).GetKind()) {
switch (metadata.GetMemberReference((MemberReferenceHandle)handle).GetKind()) {
case MemberReferenceKind.Method:
output.Write("method ");
break;

16
ICSharpCode.Decompiler/Disassembler/OpCodeInfo.cs

@ -163,9 +163,21 @@ namespace ICSharpCode.Decompiler.Disassembler @@ -163,9 +163,21 @@ namespace ICSharpCode.Decompiler.Disassembler
return targets;
}
public static string DecodeUserString(ref BlobReader blob, Metadata.PEFile module)
public static string DecodeUserString(ref BlobReader blob, MetadataReader metadata)
{
return module.GetMetadataReader().GetUserString(MetadataTokens.UserStringHandle(blob.ReadInt32()));
return metadata.GetUserString(MetadataTokens.UserStringHandle(blob.ReadInt32()));
}
public static int DecodeIndex(ref BlobReader blob, ILOpCode opCode)
{
switch (opCode.GetOperandType()) {
case OperandType.ShortVariable:
return blob.ReadByte();
case OperandType.Variable:
return blob.ReadUInt16();
default:
throw new ArgumentException($"{opCode} not supported!");
}
}
public static bool IsReturn(this ILOpCode opCode)

6
ICSharpCode.Decompiler/Disassembler/ReflectionDisassembler.cs

@ -457,13 +457,13 @@ namespace ICSharpCode.Decompiler.Disassembler @@ -457,13 +457,13 @@ namespace ICSharpCode.Decompiler.Disassembler
PrimitiveSerializationTypeCode ResolveEnumUnderlyingType(string typeName, PEFile module, out Metadata.TypeDefinition typeDefinition)
{
typeDefinition = default(Metadata.TypeDefinition);
typeDefinition = default;
TypeDefinitionHandle FindType(PEFile currentModule, string[] name)
{
var metadata = currentModule.GetMetadataReader();
var currentNamespace = metadata.GetNamespaceDefinitionRoot();
ImmutableArray<TypeDefinitionHandle> typeDefinitions = default(ImmutableArray<TypeDefinitionHandle>);
ImmutableArray<TypeDefinitionHandle> typeDefinitions = default;
for (int i = 0; i < name.Length; i++) {
string identifier = name[i];
@ -489,7 +489,7 @@ namespace ICSharpCode.Decompiler.Disassembler @@ -489,7 +489,7 @@ namespace ICSharpCode.Decompiler.Disassembler
}
}
}
return default(TypeDefinitionHandle);
return default;
}
string[] nameParts = typeName.Split(new[] { ", " }, 2, StringSplitOptions.None);
string[] typeNameParts = nameParts[0].Split('.');

6
ICSharpCode.Decompiler/ICSharpCode.Decompiler.csproj

@ -51,6 +51,10 @@ @@ -51,6 +51,10 @@
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|AnyCPU'">
<LangVersion>7.2</LangVersion>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Humanizer.Core" Version="2.2.0" />
<PackageReference Include="Mono.Cecil" Version="0.10.0-beta7" />
@ -450,7 +454,7 @@ @@ -450,7 +454,7 @@
<Compile Include="TypeSystem\ArrayType.cs" />
<Compile Include="TypeSystem\AssemblyQualifiedTypeName.cs" />
<Compile Include="TypeSystem\ByReferenceType.cs" />
<Compile Include="TypeSystem\CecilLoader.cs" />
<Compile Include="TypeSystem\MetadataLoader.cs" />
<Compile Include="TypeSystem\ComHelper.cs" />
<Compile Include="TypeSystem\DecompilerTypeSystem.cs" />
<Compile Include="TypeSystem\DefaultSolutionSnapshot.cs" />

821
ICSharpCode.Decompiler/IL/ILReader.cs

File diff suppressed because it is too large Load Diff

4
ICSharpCode.Decompiler/IL/Instructions/CallIndirect.cs

@ -33,7 +33,7 @@ namespace ICSharpCode.Decompiler.IL @@ -33,7 +33,7 @@ namespace ICSharpCode.Decompiler.IL
public readonly InstructionCollection<ILInstruction> Arguments;
ILInstruction functionPointer;
public Mono.Cecil.MethodCallingConvention CallingConvention { get; }
public System.Reflection.Metadata.SignatureCallingConvention CallingConvention { get; }
public IType ReturnType { get; }
public ImmutableArray<IType> ParameterTypes { get; }
@ -61,7 +61,7 @@ namespace ICSharpCode.Decompiler.IL @@ -61,7 +61,7 @@ namespace ICSharpCode.Decompiler.IL
functionPointer.ChildIndex = Arguments.Count;
}
public CallIndirect(Mono.Cecil.MethodCallingConvention callingConvention, IType returnType, ImmutableArray<IType> parameterTypes,
public CallIndirect(System.Reflection.Metadata.SignatureCallingConvention callingConvention, IType returnType, ImmutableArray<IType> parameterTypes,
IEnumerable<ILInstruction> arguments, ILInstruction functionPointer) : base(OpCode.CallIndirect)
{
this.CallingConvention = callingConvention;

40
ICSharpCode.Decompiler/Metadata/Dom.cs

@ -76,6 +76,7 @@ namespace ICSharpCode.Decompiler.Metadata @@ -76,6 +76,7 @@ namespace ICSharpCode.Decompiler.Metadata
{
IList<SequencePoint> GetSequencePoints(MethodDefinition method);
IList<Variable> GetVariables(MethodDefinition method);
bool TryGetName(MethodDefinition method, int index, out string name);
}
public class PEFile
@ -301,7 +302,7 @@ namespace ICSharpCode.Decompiler.Metadata @@ -301,7 +302,7 @@ namespace ICSharpCode.Decompiler.Metadata
}
}
public struct AssemblyReference : IAssemblyReference
public struct AssemblyReference : IAssemblyReference, IEquatable<AssemblyReference>
{
static readonly SHA1 sha1 = SHA1.Create();
@ -332,6 +333,26 @@ namespace ICSharpCode.Decompiler.Metadata @@ -332,6 +333,26 @@ namespace ICSharpCode.Decompiler.Metadata
return bytes;
}
public bool Equals(AssemblyReference other)
{
return Module == other.Module && Handle == other.Handle;
}
public override bool Equals(object obj)
{
if (obj is AssemblyReference reference)
return Equals(reference);
return false;
}
public override int GetHashCode()
{
return unchecked(982451629 * Module.GetHashCode() + 982451653 * MetadataTokens.GetToken(Handle));
}
public static bool operator ==(AssemblyReference lhs, AssemblyReference rhs) => lhs.Equals(rhs);
public static bool operator !=(AssemblyReference lhs, AssemblyReference rhs) => !lhs.Equals(rhs);
public AssemblyReference(PEFile module, AssemblyReferenceHandle handle)
{
Module = module;
@ -358,9 +379,14 @@ namespace ICSharpCode.Decompiler.Metadata @@ -358,9 +379,14 @@ namespace ICSharpCode.Decompiler.Metadata
return MetadataResolver.ResolveType(Handle, new SimpleMetadataResolveContext(Module));
}
public FieldDefinition ResolveAsField()
{
return MetadataResolver.ResolveAsField(Handle, new SimpleMetadataResolveContext(Module));
}
public MethodDefinition ResolveAsMethod()
{
return MetadataResolver.ResolveMember(Handle, new SimpleMetadataResolveContext(Module));
return MetadataResolver.ResolveAsMethod(Handle, new SimpleMetadataResolveContext(Module));
}
public bool Equals(Entity other)
@ -717,7 +743,7 @@ namespace ICSharpCode.Decompiler.Metadata @@ -717,7 +743,7 @@ namespace ICSharpCode.Decompiler.Metadata
public FullTypeName FullName {
get {
return DecodeSignature(new FullTypeNameSignatureDecoder(Module.GetMetadataReader()), default(Unit));
return DecodeSignature(new FullTypeNameSignatureDecoder(Module.GetMetadataReader()), default);
}
}
@ -785,7 +811,7 @@ namespace ICSharpCode.Decompiler.Metadata @@ -785,7 +811,7 @@ namespace ICSharpCode.Decompiler.Metadata
public FullTypeName GetFunctionPointerType(MethodSignature<FullTypeName> signature)
{
return default(FullTypeName);
return default;
}
public FullTypeName GetGenericInstantiation(FullTypeName genericType, ImmutableArray<FullTypeName> typeArguments)
@ -795,12 +821,12 @@ namespace ICSharpCode.Decompiler.Metadata @@ -795,12 +821,12 @@ namespace ICSharpCode.Decompiler.Metadata
public FullTypeName GetGenericMethodParameter(Unit genericContext, int index)
{
return default(FullTypeName);
return default;
}
public FullTypeName GetGenericTypeParameter(Unit genericContext, int index)
{
return default(FullTypeName);
return default;
}
public FullTypeName GetModifiedType(FullTypeName modifier, FullTypeName unmodifiedType, bool isRequired)
@ -840,7 +866,7 @@ namespace ICSharpCode.Decompiler.Metadata @@ -840,7 +866,7 @@ namespace ICSharpCode.Decompiler.Metadata
public FullTypeName GetTypeFromSpecification(MetadataReader reader, Unit genericContext, TypeSpecificationHandle handle, byte rawTypeKind)
{
return reader.GetTypeSpecification(handle).DecodeSignature(new FullTypeNameSignatureDecoder(metadata), default(Unit));
return reader.GetTypeSpecification(handle).DecodeSignature(new FullTypeNameSignatureDecoder(metadata), default);
}
}

35
ICSharpCode.Decompiler/Metadata/MetadataExtensions.cs

@ -23,8 +23,27 @@ namespace ICSharpCode.Decompiler.Metadata @@ -23,8 +23,27 @@ namespace ICSharpCode.Decompiler.Metadata
{
return new Entity(module, entity).ResolveAsType();
}
public static FieldDefinition ResolveAsField(this EntityHandle entity, PEFile module)
{
return new Entity(module, entity).ResolveAsField();
}
public static MethodDefinition ResolveAsMethod(this EntityHandle entity, PEFile module)
{
return new Entity(module, entity).ResolveAsMethod();
}
#endregion
public static MethodDefinition AsMethod(this IMetadataEntity entity)
{
if (entity is MethodDefinition method)
return method;
if (entity is Entity e)
return e;
throw new NotSupportedException();
}
public static bool IsNil(this IAssemblyReference reference)
{
return reference == null || (reference is Metadata.AssemblyReference ar && ar.IsNil);
@ -121,7 +140,7 @@ namespace ICSharpCode.Decompiler.Metadata @@ -121,7 +140,7 @@ namespace ICSharpCode.Decompiler.Metadata
case HandleKind.AssemblyReference:
return (AssemblyReferenceHandle)tr.ResolutionScope;
default:
return default(AssemblyReferenceHandle);
return default;
}
}
@ -374,5 +393,19 @@ namespace ICSharpCode.Decompiler.Metadata @@ -374,5 +393,19 @@ namespace ICSharpCode.Decompiler.Metadata
return metadata.GetAssemblyDefinition();
return null;
}
public unsafe static ParameterHandle At(this ParameterHandleCollection collection, MetadataReader metadata, int index)
{
if (metadata.GetTableRowCount(TableIndex.ParamPtr) > 0) {
int rowSize = metadata.GetTableRowSize(TableIndex.ParamPtr);
int paramRefSize = (metadata.GetReferenceSize(TableIndex.ParamPtr) > 2) ? 4 : metadata.GetReferenceSize(TableIndex.Param);
int offset = metadata.GetTableMetadataOffset(TableIndex.ParamPtr) + index * rowSize;
byte* ptr = metadata.MetadataPointer + offset;
if (paramRefSize == 2)
return MetadataTokens.ParameterHandle(*(ushort*)ptr);
return MetadataTokens.ParameterHandle((int)*(uint*)ptr);
}
return MetadataTokens.ParameterHandle((index + 1) & 0xFFFFFF);
}
}
}

24
ICSharpCode.Decompiler/Metadata/MetadataResolver.cs

@ -57,12 +57,34 @@ namespace ICSharpCode.Decompiler.Metadata @@ -57,12 +57,34 @@ namespace ICSharpCode.Decompiler.Metadata
}
}
public static MethodDefinition ResolveMember(EntityHandle handle, IMetadataResolveContext context)
public static MethodDefinition ResolveAsMethod(EntityHandle handle, IMetadataResolveContext context)
{
switch (handle.Kind) {
case HandleKind.MethodDefinition:
return new MethodDefinition(context.CurrentModule, (MethodDefinitionHandle)handle);
case HandleKind.MemberReference:
var memberRefHandle = (MemberReferenceHandle)handle;
var metadata = context.CurrentModule.GetMetadataReader();
var memberRef = metadata.GetMemberReference(memberRefHandle);
if (memberRef.GetKind() != MemberReferenceKind.Method)
return default;
break;
}
throw new NotImplementedException();
}
public static FieldDefinition ResolveAsField(EntityHandle handle, IMetadataResolveContext context)
{
switch (handle.Kind) {
case HandleKind.FieldDefinition:
return new FieldDefinition(context.CurrentModule, (FieldDefinitionHandle)handle);
case HandleKind.MemberReference:
var memberRefHandle = (MemberReferenceHandle)handle;
var metadata = context.CurrentModule.GetMetadataReader();
var memberRef = metadata.GetMemberReference(memberRefHandle);
if (memberRef.GetKind() != MemberReferenceKind.Field)
throw new ArgumentException("MemberReferenceKind must be Field!", nameof(handle));
break;
}
throw new NotImplementedException();

2
ICSharpCode.Decompiler/Metadata/UniversalAssemblyResolver.cs

@ -61,7 +61,7 @@ namespace ICSharpCode.Decompiler.Metadata @@ -61,7 +61,7 @@ namespace ICSharpCode.Decompiler.Metadata
{
var resolver = new UniversalAssemblyResolver(mainAssemblyFileName, throwOnError);
var module = new PEReader(new FileStream(mainAssemblyFileName, FileMode.Open));
var module = new PEReader(new FileStream(mainAssemblyFileName, FileMode.Open), inMemory ? PEStreamOptions.PrefetchEntireImage : PEStreamOptions.Default);
resolver.TargetFramework = module.DetectTargetFrameworkId();

4
ICSharpCode.Decompiler/SRMExtensions.cs

@ -16,6 +16,10 @@ namespace ICSharpCode.Decompiler @@ -16,6 +16,10 @@ namespace ICSharpCode.Decompiler
public static bool HasFlag(this PropertyDefinition propertyDefinition, PropertyAttributes attribute) => (propertyDefinition.Attributes & attribute) == attribute;
public static bool HasFlag(this EventDefinition eventDefinition, EventAttributes attribute) => (eventDefinition.Attributes & attribute) == attribute;
public static bool IsTypeKind(this HandleKind kind) => kind == HandleKind.TypeDefinition || kind == HandleKind.TypeReference || kind == HandleKind.TypeSpecification;
public static bool IsMemberKind(this HandleKind kind) => kind == HandleKind.MethodDefinition || kind == HandleKind.PropertyDefinition || kind == HandleKind.FieldDefinition
|| kind == HandleKind.EventDefinition || kind == HandleKind.MemberReference || kind == HandleKind.MethodSpecification;
public static bool IsValueType(this TypeDefinitionHandle handle, MetadataReader reader)
{
return reader.GetTypeDefinition(handle).IsValueType(reader);

30
ICSharpCode.Decompiler/SRMHacks.cs

@ -32,31 +32,19 @@ namespace ICSharpCode.Decompiler @@ -32,31 +32,19 @@ namespace ICSharpCode.Decompiler
return 0;
}
public static unsafe ImmutableArray<MethodImplementationHandle> GetMethodImplementations(this MethodDefinitionHandle handle, MetadataReader reader)
public static ImmutableArray<MethodImplementationHandle> GetMethodImplementations(this MethodDefinitionHandle handle, MetadataReader reader)
{
byte* startPointer = reader.MetadataPointer;
int offset = reader.GetTableMetadataOffset(TableIndex.MethodImpl);
int rowSize = reader.GetTableRowSize(TableIndex.MethodImpl);
int rowCount = reader.GetTableRowCount(TableIndex.MethodImpl);
var methodDefSize = reader.GetReferenceSize(TableIndex.MethodDef);
var typeDefSize = reader.GetReferenceSize(TableIndex.TypeDef);
var containingTypeRow = reader.GetRowNumber(reader.GetMethodDefinition(handle).GetDeclaringType());
var methodDefRow = reader.GetRowNumber(handle);
var list = new List<MethodImplementationHandle>();
var resultBuilder = ImmutableArray.CreateBuilder<MethodImplementationHandle>();
var typeDefinition = reader.GetTypeDefinition(reader.GetMethodDefinition(handle).GetDeclaringType());
// TODO : if sorted -> binary search?
for (int row = 0; row < reader.GetTableRowCount(TableIndex.MethodImpl); row++) {
byte* ptr = startPointer + offset + rowSize * row;
uint currentTypeRow = typeDefSize == 2 ? *(ushort*)ptr : *(uint*)ptr;
if (currentTypeRow != containingTypeRow) continue;
uint currentMethodRowCoded = methodDefSize == 2 ? *(ushort*)(ptr + typeDefSize) : *(uint*)(ptr + typeDefSize);
if ((currentMethodRowCoded >> 1) != methodDefRow) continue;
list.Add(MetadataTokens.MethodImplementationHandle(row + 1));
foreach (var methodImplementationHandle in typeDefinition.GetMethodImplementations()) {
var methodImplementation = reader.GetMethodImplementation(methodImplementationHandle);
if (methodImplementation.MethodBody == handle) {
resultBuilder.Add(methodImplementationHandle);
}
}
return list.ToImmutableArray();
return resultBuilder.ToImmutable();
}
/*

360
ICSharpCode.Decompiler/TypeSystem/DecompilerTypeSystem.cs

@ -1,9 +1,12 @@ @@ -1,9 +1,12 @@
using System;
using System.Collections.Generic;
using System.Linq;
using SRM = System.Reflection.Metadata;
using ICSharpCode.Decompiler.TypeSystem.Implementation;
using ICSharpCode.Decompiler.Util;
using Mono.Cecil;
using static ICSharpCode.Decompiler.Metadata.MetadataExtensions;
using System.Diagnostics;
namespace ICSharpCode.Decompiler.TypeSystem
{
@ -15,7 +18,7 @@ namespace ICSharpCode.Decompiler.TypeSystem @@ -15,7 +18,7 @@ namespace ICSharpCode.Decompiler.TypeSystem
/// </remarks>
public class DecompilerTypeSystem : IDecompilerTypeSystem
{
readonly ModuleDefinition moduleDefinition;
readonly Metadata.PEFile moduleDefinition;
readonly ICompilation compilation;
readonly ITypeResolveContext context;
@ -29,36 +32,38 @@ namespace ICSharpCode.Decompiler.TypeSystem @@ -29,36 +32,38 @@ namespace ICSharpCode.Decompiler.TypeSystem
/// Dictionary for NRefactory->Cecil lookup.
/// May only be accessed within lock(entityDict)
/// </summary>
Dictionary<IUnresolvedEntity, MemberReference> entityDict = new Dictionary<IUnresolvedEntity, MemberReference>();
Dictionary<IUnresolvedEntity, SRM.EntityHandle> entityDict = new Dictionary<IUnresolvedEntity, SRM.EntityHandle>();
Dictionary<FieldReference, IField> fieldLookupCache = new Dictionary<FieldReference, IField>();
Dictionary<PropertyReference, IProperty> propertyLookupCache = new Dictionary<PropertyReference, IProperty>();
Dictionary<MethodReference, IMethod> methodLookupCache = new Dictionary<MethodReference, IMethod>();
Dictionary<EventReference, IEvent> eventLookupCache = new Dictionary<EventReference, IEvent>();
Dictionary<SRM.EntityHandle, IField> fieldLookupCache = new Dictionary<SRM.EntityHandle, IField>();
Dictionary<SRM.EntityHandle, IProperty> propertyLookupCache = new Dictionary<SRM.EntityHandle, IProperty>();
Dictionary<SRM.EntityHandle, IMethod> methodLookupCache = new Dictionary<SRM.EntityHandle, IMethod>();
Dictionary<SRM.EntityHandle, IEvent> eventLookupCache = new Dictionary<SRM.EntityHandle, IEvent>();
public DecompilerTypeSystem(ModuleDefinition moduleDefinition)
public DecompilerTypeSystem(Metadata.PEFile moduleDefinition)
{
if (moduleDefinition == null)
throw new ArgumentNullException(nameof(moduleDefinition));
this.moduleDefinition = moduleDefinition;
/*MetadataLoader cecilLoader = new MetadataLoader { IncludeInternalMembers = true, LazyLoad = true, OnEntityLoaded = StoreMemberReference, ShortenInterfaceImplNames = false };
typeReferenceCecilLoader.SetCurrentModule(moduleDefinition);
IUnresolvedAssembly mainAssembly = cecilLoader.LoadModule(moduleDefinition);
MetadataLoader cecilLoader = new MetadataLoader { IncludeInternalMembers = true, LazyLoad = true, OnEntityLoaded = StoreMemberReference, ShortenInterfaceImplNames = false };
typeReferenceCecilLoader.SetCurrentModule(moduleDefinition.GetMetadataReader());
IUnresolvedAssembly mainAssembly = cecilLoader.LoadModule(moduleDefinition.GetMetadataReader());
// Load referenced assemblies and type-forwarder references.
// This is necessary to make .NET Core/PCL binaries work better.
var referencedAssemblies = new List<IUnresolvedAssembly>();
var assemblyReferenceQueue = new Queue<AssemblyNameReference>(moduleDefinition.AssemblyReferences);
var processedAssemblyReferences = new HashSet<AssemblyNameReference>(KeyComparer.Create((AssemblyNameReference reference) => reference.FullName));
var assemblyReferenceQueue = new Queue<Metadata.AssemblyReference>(moduleDefinition.AssemblyReferences);
var processedAssemblyReferences = new HashSet<Metadata.AssemblyReference>(KeyComparer.Create((Metadata.AssemblyReference reference) => reference.FullName));
while (assemblyReferenceQueue.Count > 0) {
var asmRef = assemblyReferenceQueue.Dequeue();
if (!processedAssemblyReferences.Add(asmRef))
continue;
var asm = moduleDefinition.AssemblyResolver.Resolve(asmRef);
if (asm != null) {
referencedAssemblies.Add(cecilLoader.LoadAssembly(asm));
foreach (var forwarder in asm.MainModule.ExportedTypes) {
if (!forwarder.IsForwarder || !(forwarder.Scope is AssemblyNameReference forwarderRef)) continue;
assemblyReferenceQueue.Enqueue(forwarderRef);
referencedAssemblies.Add(cecilLoader.LoadModule(asm.GetMetadataReader()));
var metadata = asm.GetMetadataReader();
foreach (var h in metadata.ExportedTypes) {
var forwarder = metadata.GetExportedType(h);
if (!forwarder.IsForwarder || forwarder.Implementation.Kind != SRM.HandleKind.AssemblyReference) continue;
assemblyReferenceQueue.Enqueue(new Metadata.AssemblyReference(asm, (SRM.AssemblyReferenceHandle)forwarder.Implementation));
}
}
}
@ -69,7 +74,7 @@ namespace ICSharpCode.Decompiler.TypeSystem @@ -69,7 +74,7 @@ namespace ICSharpCode.Decompiler.TypeSystem
referencedAssemblies.Add(MinimalCorlib.Instance);
compilation = new SimpleCompilation(mainAssembly, referencedAssemblies);
}
context = new SimpleTypeResolveContext(compilation.MainAssembly);*/
context = new SimpleTypeResolveContext(compilation.MainAssembly);
}
public ICompilation Compilation {
@ -80,30 +85,24 @@ namespace ICSharpCode.Decompiler.TypeSystem @@ -80,30 +85,24 @@ namespace ICSharpCode.Decompiler.TypeSystem
get { return compilation.MainAssembly; }
}
public ModuleDefinition ModuleDefinition {
public Metadata.PEFile ModuleDefinition {
get { return moduleDefinition; }
}
void StoreMemberReference(IUnresolvedEntity entity, MemberReference mr)
void StoreMemberReference(IUnresolvedEntity entity, SRM.EntityHandle mr)
{
// This is a callback from the type system, which is multi-threaded and may be accessed externally
lock (entityDict)
entityDict[entity] = mr;
}
/// <summary>
/// Retrieves the Cecil member definition for the specified member.
/// </summary>
/// <remarks>
/// Returns null if the member is not defined in the module being decompiled.
/// </remarks>
public MemberReference GetCecil(IUnresolvedEntity member)
/*
Metadata.IMetadataEntity GetMetadata(IUnresolvedEntity member)
{
if (member == null)
return null;
lock (entityDict) {
MemberReference mr;
if (entityDict.TryGetValue(member, out mr))
if (entityDict.TryGetValue(member, out var mr))
return mr;
return null;
}
@ -115,62 +114,90 @@ namespace ICSharpCode.Decompiler.TypeSystem @@ -115,62 +114,90 @@ namespace ICSharpCode.Decompiler.TypeSystem
/// <remarks>
/// Returns null if the member is not defined in the module being decompiled.
/// </remarks>
public MemberReference GetCecil(IMember member)
public Metadata.IMetadataEntity GetMetadata(IMember member)
{
if (member == null)
return null;
return GetCecil(member.UnresolvedMember);
return GetMetadata(member.UnresolvedMember);
}
/// <summary>
/// Retrieves the Cecil type definition.
/// </summary>
/// <remarks>
/// Returns null if the type is not defined in the module being decompiled.
/// </remarks>
public TypeDefinition GetCecil(ITypeDefinition typeDefinition)
public Metadata.TypeDefinition GetMetadata(ITypeDefinition typeDefinition)
{
if (typeDefinition == null)
return null;
return GetCecil(typeDefinition.Parts[0]) as TypeDefinition;
return default;
return (Metadata.TypeDefinition)GetMetadata(typeDefinition.Parts[0]);
}
*/
#region Resolve Type
public IType Resolve(TypeReference typeReference)
public IMember ResolveAsMember(SRM.EntityHandle memberReference)
{
throw new NotImplementedException();
#if false
if (typeReference == null)
}
#region Resolve Type
public IType ResolveAsType(SRM.EntityHandle typeReference)
{
if (typeReference.IsNil)
return SpecialType.UnknownType;
// We need to skip SentinelType and PinnedType.
// But PinnedType can be nested within modopt, so we'll also skip those.
while (typeReference is OptionalModifierType || typeReference is RequiredModifierType) {
typeReference = ((TypeSpecification)typeReference).ElementType;
}
if (typeReference is SentinelType || typeReference is Mono.Cecil.PinnedType) {
typeReference = ((TypeSpecification)typeReference).ElementType;
}
ITypeReference typeRef;
lock (typeReferenceCecilLoader)
typeRef = typeReferenceCecilLoader.ReadTypeReference(typeReference);
return typeRef.Resolve(context);
#endif
}
#endregion
#endregion
#region Resolve Field
public IField Resolve(FieldReference fieldReference)
public IField ResolveAsField(SRM.EntityHandle fieldReference)
{
if (fieldReference == null)
if (fieldReference.IsNil)
throw new ArgumentNullException(nameof(fieldReference));
if (fieldReference.Kind != SRM.HandleKind.FieldDefinition && fieldReference.Kind != SRM.HandleKind.MemberReference)
throw new ArgumentException("HandleKind must be either FieldDefinition or MemberReference", nameof(fieldReference));
lock (fieldLookupCache) {
IField field;
if (!fieldLookupCache.TryGetValue(fieldReference, out field)) {
field = FindNonGenericField(fieldReference);
if (fieldReference.DeclaringType.IsGenericInstance) {
var git = (GenericInstanceType)fieldReference.DeclaringType;
var typeArguments = git.GenericArguments.SelectArray(Resolve);
field = (IField)field.Specialize(new TypeParameterSubstitution(typeArguments, null));
var metadata = moduleDefinition.GetMetadataReader();
IType declaringType;
ITypeReference returnType;
switch (fieldReference.Kind) {
case SRM.HandleKind.FieldDefinition:
var fieldDef = metadata.GetFieldDefinition((SRM.FieldDefinitionHandle)fieldReference);
declaringType = ResolveAsType(fieldDef.GetDeclaringType());
returnType = fieldDef.DecodeSignature(new TypeReferenceSignatureDecoder(), default);
var declaringTypeDefinition = declaringType.GetDefinition();
if (declaringTypeDefinition == null)
field = CreateFakeField(declaringType, metadata.GetString(fieldDef.Name), returnType);
else {
field = declaringTypeDefinition.GetFields(f => f.MetadataToken == fieldReference, GetMemberOptions.IgnoreInheritedMembers).FirstOrDefault()
?? CreateFakeField(declaringType, metadata.GetString(fieldDef.Name), returnType);
}
break;
case SRM.HandleKind.MemberReference:
var memberRef = metadata.GetMemberReference((SRM.MemberReferenceHandle)fieldReference);
switch (memberRef.Parent.Kind) {
case SRM.HandleKind.TypeReference:
declaringType = ResolveAsType(memberRef.Parent);
field = FindNonGenericField(metadata, memberRef, declaringType);
break;
case SRM.HandleKind.TypeSpecification:
throw new NotImplementedException();
/*if (fieldReference.DeclaringType.IsGenericInstance) {
var git = (GenericInstanceType)fieldReference.DeclaringType;
var typeArguments = git.GenericArguments.SelectArray(Resolve);
field = (IField)field.Specialize(new TypeParameterSubstitution(typeArguments, null));
}*/
default:
throw new NotSupportedException();
}
break;
}
fieldLookupCache.Add(fieldReference, field);
}
@ -178,29 +205,26 @@ namespace ICSharpCode.Decompiler.TypeSystem @@ -178,29 +205,26 @@ namespace ICSharpCode.Decompiler.TypeSystem
}
}
IField FindNonGenericField(FieldReference fieldReference)
IField FindNonGenericField(SRM.MetadataReader metadata, SRM.MemberReference memberRef, IType declaringType)
{
ITypeDefinition typeDef = Resolve(fieldReference.DeclaringType).GetDefinition();
string name = metadata.GetString(memberRef.Name);
ITypeDefinition typeDef = declaringType.GetDefinition();
ITypeReference returnType = memberRef.DecodeFieldSignature(new TypeReferenceSignatureDecoder(), default);
if (typeDef == null)
return CreateFakeField(fieldReference);
return CreateFakeField(declaringType, name, returnType);
foreach (IField field in typeDef.Fields)
if (field.Name == fieldReference.Name)
if (field.Name == name)
return field;
return CreateFakeField(fieldReference);
return CreateFakeField(declaringType, name, returnType);
}
IField CreateFakeField(FieldReference fieldReference)
IField CreateFakeField(IType declaringType, string name, ITypeReference returnType)
{
throw new NotImplementedException();
#if false
var declaringType = Resolve(fieldReference.DeclaringType);
var f = new DefaultUnresolvedField();
f.Name = fieldReference.Name;
lock (typeReferenceCecilLoader) {
f.ReturnType = typeReferenceCecilLoader.ReadTypeReference(fieldReference.FieldType);
}
f.Name = name;
f.ReturnType = returnType;
return new ResolvedFakeField(f, context.WithCurrentTypeDefinition(declaringType.GetDefinition()), declaringType);
#endif
}
class ResolvedFakeField : DefaultResolvedField
@ -218,79 +242,114 @@ namespace ICSharpCode.Decompiler.TypeSystem @@ -218,79 +242,114 @@ namespace ICSharpCode.Decompiler.TypeSystem
get { return declaringType; }
}
}
#endregion
#endregion
#region Resolve Method
public IMethod Resolve(MethodReference methodReference)
public IMethod ResolveAsMethod(SRM.EntityHandle methodReference)
{
if (methodReference == null)
if (methodReference.IsNil)
throw new ArgumentNullException(nameof(methodReference));
if (methodReference.Kind != SRM.HandleKind.MethodDefinition && methodReference.Kind != SRM.HandleKind.MemberReference && methodReference.Kind != SRM.HandleKind.MethodSpecification)
throw new ArgumentException("HandleKind must be either a MethodDefinition, MemberReference or MethodSpecification", nameof(methodReference));
lock (methodLookupCache) {
IMethod method;
if (!methodLookupCache.TryGetValue(methodReference, out method)) {
method = FindNonGenericMethod(methodReference.GetElementMethod());
if (methodReference.CallingConvention == MethodCallingConvention.VarArg) {
var metadata = moduleDefinition.GetMetadataReader();
IType declaringType;
switch (methodReference.Kind) {
case SRM.HandleKind.MethodDefinition:
var methodDef = metadata.GetMethodDefinition((SRM.MethodDefinitionHandle)methodReference);
declaringType = ResolveAsType(methodDef.GetDeclaringType());
var declaringTypeDefinition = declaringType.GetDefinition();
if (declaringTypeDefinition == null)
method = CreateFakeMethod(declaringType, metadata.GetString(methodDef.Name), methodDef.DecodeSignature(new TypeReferenceSignatureDecoder(), default));
else {
method = (IMethod)declaringTypeDefinition.GetMembers(m => m.MetadataToken == methodReference, GetMemberOptions.IgnoreInheritedMembers).FirstOrDefault()
?? CreateFakeMethod(declaringType, metadata.GetString(methodDef.Name), methodDef.DecodeSignature(new TypeReferenceSignatureDecoder(), default));
}
break;
case SRM.HandleKind.MemberReference:
var memberRef = metadata.GetMemberReference((SRM.MemberReferenceHandle)methodReference);
break;
case SRM.HandleKind.MethodSpecification:
break;
}
/*method = FindNonGenericMethod(metadata, new Metadata.Entity(moduleDefinition, methodReference).ResolveAsMethod(), signature);
switch (methodReference.Kind) {
case SRM.HandleKind.StandaloneSignature:
var standaloneSignature = metadata.GetStandaloneSignature((SRM.StandaloneSignatureHandle)methodReference);
Debug.Assert(standaloneSignature.GetKind() == SRM.StandaloneSignatureKind.Method);
var signature = standaloneSignature.DecodeMethodSignature(new TypeReferenceSignatureDecoder(), default);
method = new VarArgInstanceMethod(
method,
methodReference.Parameters.SkipWhile(p => !p.ParameterType.IsSentinel).Select(p => Resolve(p.ParameterType))
signature.ParameterTypes.Skip(signature.RequiredParameterCount).Select(p => p.Resolve(context))
);
} else if (methodReference.IsGenericInstance || methodReference.DeclaringType.IsGenericInstance) {
break;
case SRM.HandleKind.MethodSpecification:
IReadOnlyList<IType> classTypeArguments = null;
IReadOnlyList<IType> methodTypeArguments = null;
if (methodReference.IsGenericInstance) {
var gim = ((GenericInstanceMethod)methodReference);
methodTypeArguments = gim.GenericArguments.SelectArray(Resolve);
var methodSpec = metadata.GetMethodSpecification((SRM.MethodSpecificationHandle)methodReference);
var typeArguments = methodSpec.DecodeSignature(new TypeReferenceSignatureDecoder(), default);
if (typeArguments.Length > 0) {
methodTypeArguments = typeArguments.SelectArray(arg => arg.Resolve(context));
}
var methodmethodSpec.Method.ResolveAsMethod(moduleDefinition);
if (methodReference.DeclaringType.IsGenericInstance) {
var git = (GenericInstanceType)methodReference.DeclaringType;
classTypeArguments = git.GenericArguments.SelectArray(Resolve);
}
method = method.Specialize(new TypeParameterSubstitution(classTypeArguments, methodTypeArguments));
}
break;
}*/
methodLookupCache.Add(methodReference, method);
}
return method;
}
}
IMethod FindNonGenericMethod(MethodReference methodReference)
/*IMethod FindNonGenericMethod(SRM.MetadataReader metadata, Metadata.MethodDefinition method)
{
ITypeDefinition typeDef = Resolve(methodReference.DeclaringType).GetDefinition();
var methodDefinition = metadata.GetMethodDefinition(method.Handle);
ITypeDefinition typeDef = ResolveAsType(methodDefinition.GetDeclaringType()).GetDefinition();
if (typeDef == null)
return CreateFakeMethod(methodReference);
return CreateFakeMethod(methodDefinition);
IEnumerable<IMethod> methods;
if (methodReference.Name == ".ctor") {
var name = metadata.GetString(methodDefinition.Name);
if (name == ".ctor") {
methods = typeDef.GetConstructors();
} else if (methodReference.Name == ".cctor") {
} else if (name == ".cctor") {
return typeDef.Methods.FirstOrDefault(m => m.IsConstructor && m.IsStatic);
} else {
methods = typeDef.GetMethods(m => m.Name == methodReference.Name, GetMemberOptions.IgnoreInheritedMembers)
.Concat(typeDef.GetAccessors(m => m.Name == methodReference.Name, GetMemberOptions.IgnoreInheritedMembers));
methods = typeDef.GetMethods(m => m.Name == name, GetMemberOptions.IgnoreInheritedMembers)
.Concat(typeDef.GetAccessors(m => m.Name == name, GetMemberOptions.IgnoreInheritedMembers));
}
foreach (var method in methods) {
if (GetCecil(method) == methodReference)
return method;
foreach (var m in methods) {
if (GetMetadata(m).AsMethod() == method)
return m;
}
IType[] parameterTypes;
if (methodReference.CallingConvention == MethodCallingConvention.VarArg) {
parameterTypes = methodReference.Parameters
.TakeWhile(p => !p.ParameterType.IsSentinel)
.Select(p => Resolve(p.ParameterType))
var signature = methodDefinition.DecodeSignature(new TypeReferenceSignatureDecoder(), default);
if (signature.Header.CallingConvention == SRM.SignatureCallingConvention.VarArgs) {
parameterTypes = signature.ParameterTypes
.Take(signature.RequiredParameterCount)
.Select(p => p.Resolve(context))
.Concat(new[] { SpecialType.ArgList })
.ToArray();
} else {
parameterTypes = methodReference.Parameters.SelectArray(p => Resolve(p.ParameterType));
parameterTypes = signature.ParameterTypes.SelectArray(p => p.Resolve(context));
}
var returnType = Resolve(methodReference.ReturnType);
foreach (var method in methods) {
if (method.TypeParameters.Count != methodReference.GenericParameters.Count)
var returnType = signature.ReturnType.Resolve(context);
foreach (var m in methods) {
if (m.TypeParameters.Count != signature.GenericParameterCount)
continue;
if (!CompareSignatures(method.Parameters, parameterTypes) || !CompareTypes(method.ReturnType, returnType))
if (!CompareSignatures(m.Parameters, parameterTypes) || !CompareTypes(m.ReturnType, returnType))
continue;
return method;
return m;
}
return CreateFakeMethod(methodReference);
}
return CreateFakeMethod(methodDefinition);
}*/
static bool CompareTypes(IType a, IType b)
{
@ -318,29 +377,33 @@ namespace ICSharpCode.Decompiler.TypeSystem @@ -318,29 +377,33 @@ namespace ICSharpCode.Decompiler.TypeSystem
/// <summary>
/// Create a dummy IMethod from the specified MethodReference
/// </summary>
IMethod CreateFakeMethod(MethodReference methodReference)
IMethod CreateFakeMethod(IType declaringType, string name, SRM.MethodSignature<ITypeReference> signature)
{
throw new NotImplementedException();
#if false
var m = new DefaultUnresolvedMethod();
ITypeReference declaringTypeReference;
if (name == ".ctor" || name == ".cctor")
m.SymbolKind = SymbolKind.Constructor;
m.Name = name;
m.ReturnType = signature.ReturnType;
m.IsStatic = !signature.Header.IsInstance;
/*ITypeReference declaringTypeReference;
lock (typeReferenceCecilLoader) {
declaringTypeReference = typeReferenceCecilLoader.ReadTypeReference(methodReference.DeclaringType);
if (methodReference.Name == ".ctor" || methodReference.Name == ".cctor")
m.SymbolKind = SymbolKind.Constructor;
m.Name = methodReference.Name;
m.ReturnType = typeReferenceCecilLoader.ReadTypeReference(methodReference.ReturnType);
m.IsStatic = !methodReference.HasThis;
for (int i = 0; i < methodReference.GenericParameters.Count; i++) {
m.TypeParameters.Add(new DefaultUnresolvedTypeParameter(SymbolKind.Method, i, methodReference.GenericParameters[i].Name));
var metadata = moduleDefinition.GetMetadataReader();
declaringTypeReference = typeReferenceCecilLoader.ReadTypeReference(methodDefinition.GetDeclaringType());
string name = metadata.GetString(methodDefinition.Name);
var gps = methodDefinition.GetGenericParameters();
for (int i = 0; i < signature.GenericParameterCount; i++) {
var gp = metadata.GetGenericParameter(gps[i]);
m.TypeParameters.Add(new DefaultUnresolvedTypeParameter(SymbolKind.Method, i, metadata.GetString(gp.Name)));
}
foreach (var p in methodReference.Parameters) {
m.Parameters.Add(new DefaultUnresolvedParameter(typeReferenceCecilLoader.ReadTypeReference(p.ParameterType), p.Name));
var ps = methodDefinition.GetParameters();
for (int i = 0; i < ps.Count; i++) {
var p = metadata.GetParameter(ps.At(metadata, i));
m.Parameters.Add(new DefaultUnresolvedParameter(signature.ParameterTypes[i], metadata.GetString(p.Name)));
}
}
var type = declaringTypeReference.Resolve(context);
return new ResolvedFakeMethod(m, context.WithCurrentTypeDefinition(type.GetDefinition()), type);
#endif
var type = declaringTypeReference.Resolve(context);*/
return new ResolvedFakeMethod(m, context.WithCurrentTypeDefinition(declaringType.GetDefinition()), declaringType);
}
class ResolvedFakeMethod : DefaultResolvedMethod
@ -360,76 +423,83 @@ namespace ICSharpCode.Decompiler.TypeSystem @@ -360,76 +423,83 @@ namespace ICSharpCode.Decompiler.TypeSystem
}
#endregion
#region Resolve Property
public IProperty Resolve(PropertyReference propertyReference)
#region Resolve Property
public IProperty ResolveAsProperty(SRM.EntityHandle propertyReference)
{
if (propertyReference == null)
if (propertyReference.IsNil)
throw new ArgumentNullException(nameof(propertyReference));
if (propertyReference.Kind != SRM.HandleKind.PropertyDefinition)
throw new ArgumentException("HandleKind must be PropertyDefinition", nameof(propertyReference));
lock (propertyLookupCache) {
IProperty property;
if (!propertyLookupCache.TryGetValue(propertyReference, out property)) {
property = FindNonGenericProperty(propertyReference);
if (propertyReference.DeclaringType.IsGenericInstance) {
var metadata = moduleDefinition.GetMetadataReader();
property = FindNonGenericProperty(metadata, (SRM.PropertyDefinitionHandle)propertyReference);
/*if (propertyReference.DeclaringType.IsGenericInstance) {
var git = (GenericInstanceType)propertyReference.DeclaringType;
var typeArguments = git.GenericArguments.SelectArray(Resolve);
property = (IProperty)property.Specialize(new TypeParameterSubstitution(typeArguments, null));
}
}*/
propertyLookupCache.Add(propertyReference, property);
}
return property;
}
}
IProperty FindNonGenericProperty(PropertyReference propertyReference)
IProperty FindNonGenericProperty(SRM.MetadataReader metadata, SRM.PropertyDefinitionHandle handle)
{
ITypeDefinition typeDef = Resolve(propertyReference.DeclaringType).GetDefinition();
var propertyDefinition = metadata.GetPropertyDefinition(handle);
var declaringType = metadata.GetMethodDefinition(propertyDefinition.GetAccessors().GetAny()).GetDeclaringType();
ITypeDefinition typeDef = ResolveAsType(declaringType).GetDefinition();
if (typeDef == null)
return null;
var parameterTypes = propertyReference.Parameters.SelectArray(p => Resolve(p.ParameterType));
var returnType = Resolve(propertyReference.PropertyType);
foreach (IProperty property in typeDef.Properties) {
if (property.Name == propertyReference.Name
&& CompareTypes(property.ReturnType, returnType)
&& CompareSignatures(property.Parameters, parameterTypes))
if (property.MetadataToken == handle)
return property;
}
return null;
}
#endregion
#endregion
#region Resolve Event
public IEvent Resolve(EventReference eventReference)
#region Resolve Event
public IEvent ResolveAsEvent(SRM.EntityHandle eventReference)
{
if (eventReference == null)
throw new ArgumentNullException("propertyReference");
if (eventReference.IsNil)
throw new ArgumentNullException(nameof(eventReference));
if (eventReference.Kind != SRM.HandleKind.EventDefinition)
throw new ArgumentException("HandleKind must be EventDefinition", nameof(eventReference));
lock (eventLookupCache) {
IEvent ev;
if (!eventLookupCache.TryGetValue(eventReference, out ev)) {
ev = FindNonGenericEvent(eventReference);
if (eventReference.DeclaringType.IsGenericInstance) {
var metadata = moduleDefinition.GetMetadataReader();
ev = FindNonGenericEvent(metadata, (SRM.EventDefinitionHandle)eventReference);
/*if (eventReference.DeclaringType.IsGenericInstance) {
var git = (GenericInstanceType)eventReference.DeclaringType;
var typeArguments = git.GenericArguments.SelectArray(Resolve);
ev = (IEvent)ev.Specialize(new TypeParameterSubstitution(typeArguments, null));
}
}*/
eventLookupCache.Add(eventReference, ev);
}
return ev;
}
}
IEvent FindNonGenericEvent(EventReference eventReference)
IEvent FindNonGenericEvent(SRM.MetadataReader metadata, SRM.EventDefinitionHandle handle)
{
ITypeDefinition typeDef = Resolve(eventReference.DeclaringType).GetDefinition();
var eventDefinition = metadata.GetEventDefinition(handle);
var declaringType = metadata.GetMethodDefinition(eventDefinition.GetAccessors().GetAny()).GetDeclaringType();
ITypeDefinition typeDef = ResolveAsType(declaringType).GetDefinition();
if (typeDef == null)
return null;
var returnType = Resolve(eventReference.EventType);
var returnType = ResolveAsType(eventDefinition.Type);
string name = metadata.GetString(eventDefinition.Name);
foreach (IEvent ev in typeDef.Events) {
if (ev.Name == eventReference.Name && CompareTypes(ev.ReturnType, returnType))
if (ev.MetadataToken == handle)
return ev;
}
return null;
}
#endregion
#endregion
public IDecompilerTypeSystem GetSpecializingTypeSystem(TypeParameterSubstitution substitution)
{

12
ICSharpCode.Decompiler/TypeSystem/IDecompilerTypeSystem.cs

@ -16,7 +16,7 @@ @@ -16,7 +16,7 @@
// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
// DEALINGS IN THE SOFTWARE.
using Mono.Cecil;
using System.Reflection.Metadata;
namespace ICSharpCode.Decompiler.TypeSystem
{
@ -27,12 +27,10 @@ namespace ICSharpCode.Decompiler.TypeSystem @@ -27,12 +27,10 @@ namespace ICSharpCode.Decompiler.TypeSystem
{
ICompilation Compilation { get; }
TypeDefinition GetCecil(ITypeDefinition typeDefinition);
MemberReference GetCecil(IMember member);
IType Resolve(TypeReference typeReference);
IField Resolve(FieldReference fieldReference);
IMethod Resolve(MethodReference methodReference);
IType ResolveAsType(EntityHandle typeReference);
IField ResolveAsField(EntityHandle fieldReference);
IMethod ResolveAsMethod(EntityHandle methodReference);
IMember ResolveAsMember(EntityHandle memberReference);
/// <summary>
/// Gets a type system instance that automatically specializes the results

640
ICSharpCode.Decompiler/TypeSystem/MetadataLoader.cs

File diff suppressed because it is too large Load Diff

12
ICSharpCode.Decompiler/TypeSystem/SpecializingDecompilerTypeSystem.cs

@ -51,22 +51,22 @@ namespace ICSharpCode.Decompiler.TypeSystem @@ -51,22 +51,22 @@ namespace ICSharpCode.Decompiler.TypeSystem
get { return substitution; }
}
public IType Resolve(Mono.Cecil.TypeReference typeReference)
public IType ResolveAsType(System.Reflection.Metadata.EntityHandle typeReference)
{
return context.Resolve(typeReference).AcceptVisitor(substitution);
return context.ResolveAsType(typeReference).AcceptVisitor(substitution);
}
public IField Resolve(Mono.Cecil.FieldReference fieldReference)
public IField ResolveAsField(System.Reflection.Metadata.EntityHandle fieldReference)
{
IField field = context.Resolve(fieldReference);
IField field = context.ResolveAsField(fieldReference);
if (field != null)
field = (IField)field.Specialize(substitution);
return field;
}
public IMethod Resolve(Mono.Cecil.MethodReference methodReference)
public IMethod ResolveAsMethod(System.Reflection.Metadata.EntityHandle methodReference)
{
IMethod method = context.Resolve(methodReference);
IMethod method = context.ResolveAsMethod(methodReference);
if (method != null)
method = (IMethod)method.Specialize(substitution);
return method;

13
ICSharpCode.Decompiler/Util/CollectionExtensions.cs

@ -138,10 +138,19 @@ namespace ICSharpCode.Decompiler.Util @@ -138,10 +138,19 @@ namespace ICSharpCode.Decompiler.Util
public static IEnumerable<U> SelectWithIndex<T, U>(this IEnumerable<T> source, Func<int, T, U> func)
{
int index = 0;
foreach (var element in source)
foreach (var element in source)
yield return func(index++, element);
}
public static IEnumerable<(int, T)> WithIndex<T>(this ICollection<T> source)
{
int index = 0;
foreach (var item in source) {
yield return (index, item);
index++;
}
}
/// <summary>
/// The merge step of merge sort.
/// </summary>

4
ILSpy/SearchStrategies.cs

@ -422,7 +422,7 @@ namespace ICSharpCode.ILSpy @@ -422,7 +422,7 @@ namespace ICSharpCode.ILSpy
return true;
break;
case ILOpCode.Ldstr:
if ((string)searchTermLiteralValue == ILParser.DecodeUserString(ref blob, module))
if ((string)searchTermLiteralValue == ILParser.DecodeUserString(ref blob, metadata))
return true;
break;
}
@ -434,7 +434,7 @@ namespace ICSharpCode.ILSpy @@ -434,7 +434,7 @@ namespace ICSharpCode.ILSpy
ILParser.SkipOperand(ref blob, code);
continue;
}
if (IsMatch(t => ILParser.DecodeUserString(ref blob, module)))
if (IsMatch(t => ILParser.DecodeUserString(ref blob, metadata)))
return true;
}
}

Loading…
Cancel
Save