Browse Source

Decode metadata signatures directly into IType; without going through ITypeReference.

pull/1198/head
Daniel Grunwald 7 years ago
parent
commit
9a74f018b5
  1. 3
      ICSharpCode.Decompiler/CSharp/CSharpDecompiler.cs
  2. 4
      ICSharpCode.Decompiler/CSharp/RequiredNamespaceCollector.cs
  3. 4
      ICSharpCode.Decompiler/Documentation/XmlDocKeyProvider.cs
  4. 3
      ICSharpCode.Decompiler/ICSharpCode.Decompiler.csproj
  5. 43
      ICSharpCode.Decompiler/IL/ILReader.cs
  6. 32
      ICSharpCode.Decompiler/IL/Transforms/TransformArrayInitializers.cs
  7. 19
      ICSharpCode.Decompiler/Metadata/MetadataExtensions.cs
  8. 2
      ICSharpCode.Decompiler/Metadata/MetadataResolver.cs
  9. 41
      ICSharpCode.Decompiler/SRMExtensions.cs
  10. 202
      ICSharpCode.Decompiler/TypeSystem/ApplyAttributeTypeVisitor.cs
  11. 86
      ICSharpCode.Decompiler/TypeSystem/DecompilerTypeSystem.cs
  12. 2
      ICSharpCode.Decompiler/TypeSystem/IAssembly.cs
  13. 5
      ICSharpCode.Decompiler/TypeSystem/IDecompilerTypeSystem.cs
  14. 6
      ICSharpCode.Decompiler/TypeSystem/Implementation/DefaultUnresolvedAssembly.cs
  15. 259
      ICSharpCode.Decompiler/TypeSystem/Implementation/MetadataTypeReference.cs
  16. 168
      ICSharpCode.Decompiler/TypeSystem/Implementation/TypeSpecification.cs
  17. 295
      ICSharpCode.Decompiler/TypeSystem/MetadataLoader.cs
  18. 41
      ICSharpCode.Decompiler/TypeSystem/SpecializingDecompilerTypeSystem.cs
  19. 166
      ICSharpCode.Decompiler/TypeSystem/TypeProvider.cs
  20. 39
      ILSpy/Languages/CSharpLanguage.cs
  21. 2
      ILSpy/TreeNodes/Analyzer/ScopedWhereUsedAnalyzer.cs

3
ICSharpCode.Decompiler/CSharp/CSharpDecompiler.cs

@ -985,7 +985,8 @@ namespace ICSharpCode.Decompiler.CSharp
// Field data as specified in II.16.3.2 of ECMA-335 6th edition: // Field data as specified in II.16.3.2 of ECMA-335 6th edition:
// .data I_X = int32(123) // .data I_X = int32(123)
// .field public static int32 _x at I_X // .field public static int32 _x at I_X
var message = string.Format(" Not supported: data({0}) ", BitConverter.ToString(fieldDefinition.GetInitialValue(typeSystem.ModuleDefinition.Reader)).Replace('-', ' ')); var initVal = fieldDefinition.GetInitialValue(typeSystem.ModuleDefinition.Reader);
var message = string.Format(" Not supported: data({0}) ", BitConverter.ToString(initVal.ReadBytes(initVal.RemainingBytes)).Replace('-', ' '));
((FieldDeclaration)fieldDecl).Variables.Single().AddChild(new Comment(message, CommentType.MultiLine), Roles.Comment); ((FieldDeclaration)fieldDecl).Variables.Single().AddChild(new Comment(message, CommentType.MultiLine), Roles.Comment);
} }
return fieldDecl; return fieldDecl;

4
ICSharpCode.Decompiler/CSharp/RequiredNamespaceCollector.cs

@ -156,9 +156,9 @@ namespace ICSharpCode.Decompiler.CSharp
var metadata = reader.GetMetadataReader(); var metadata = reader.GetMetadataReader();
if (!method.LocalSignature.IsNil) { if (!method.LocalSignature.IsNil) {
var localSignature = metadata.GetStandaloneSignature(method.LocalSignature).DecodeLocalSignature(TypeReferenceSignatureDecoder.Instance, default); var localSignature = typeSystem.DecodeLocalSignature(method.LocalSignature);
foreach (var type in localSignature) foreach (var type in localSignature)
CollectNamespacesForTypeReference(typeSystem.ResolveFromSignature(type), namespaces); CollectNamespacesForTypeReference(type, namespaces);
} }
foreach (var region in method.ExceptionRegions) { foreach (var region in method.ExceptionRegions) {

4
ICSharpCode.Decompiler/Documentation/XmlDocKeyProvider.cs

@ -198,12 +198,12 @@ namespace ICSharpCode.Decompiler.Documentation
public string GetModifiedType(string modifier, string unmodifiedType, bool isRequired) public string GetModifiedType(string modifier, string unmodifiedType, bool isRequired)
{ {
throw new NotImplementedException(); return unmodifiedType;
} }
public string GetPinnedType(string elementType) public string GetPinnedType(string elementType)
{ {
throw new NotImplementedException(); return elementType;
} }
public string GetPointerType(string elementType) public string GetPointerType(string elementType)

3
ICSharpCode.Decompiler/ICSharpCode.Decompiler.csproj

@ -338,11 +338,14 @@
<Compile Include="Pdb\PortablePdbWriter.cs" /> <Compile Include="Pdb\PortablePdbWriter.cs" />
<Compile Include="SRMExtensions.cs" /> <Compile Include="SRMExtensions.cs" />
<Compile Include="SRMHacks.cs" /> <Compile Include="SRMHacks.cs" />
<Compile Include="TypeSystem\ApplyAttributeTypeVisitor.cs" />
<Compile Include="TypeSystem\Implementation\MetadataTypeReference.cs" />
<Compile Include="TypeSystem\Implementation\TypeSpecification.cs" /> <Compile Include="TypeSystem\Implementation\TypeSpecification.cs" />
<Compile Include="Metadata\MetadataExtensions.cs" /> <Compile Include="Metadata\MetadataExtensions.cs" />
<Compile Include="Semantics\TupleResolveResult.cs" /> <Compile Include="Semantics\TupleResolveResult.cs" />
<Compile Include="TypeSystem\NormalizeTypeVisitor.cs" /> <Compile Include="TypeSystem\NormalizeTypeVisitor.cs" />
<Compile Include="TypeSystem\TupleType.cs" /> <Compile Include="TypeSystem\TupleType.cs" />
<Compile Include="TypeSystem\TypeProvider.cs" />
<Compile Include="Util\GraphVizGraph.cs" /> <Compile Include="Util\GraphVizGraph.cs" />
<Compile Include="Util\KeyComparer.cs" /> <Compile Include="Util\KeyComparer.cs" />
<Compile Include="Util\LongDict.cs" /> <Compile Include="Util\LongDict.cs" />

43
ICSharpCode.Decompiler/IL/ILReader.cs

@ -54,7 +54,6 @@ namespace ICSharpCode.Decompiler.IL
IMethod method; IMethod method;
MethodBodyBlock body; MethodBodyBlock body;
Metadata.IDebugInfoProvider debugInfo; Metadata.IDebugInfoProvider debugInfo;
MethodSignature<ITypeReference> methodSignature;
StackType methodReturnStackType; StackType methodReturnStackType;
BlobReader reader; BlobReader reader;
ImmutableStack<ILVariable> currentStack; ImmutableStack<ILVariable> currentStack;
@ -78,14 +77,13 @@ namespace ICSharpCode.Decompiler.IL
this.metadata = module.Metadata; this.metadata = module.Metadata;
this.method = typeSystem.ResolveAsMethod(methodDefinitionHandle); this.method = typeSystem.ResolveAsMethod(methodDefinitionHandle);
var methodDefinition = metadata.GetMethodDefinition(methodDefinitionHandle); var methodDefinition = metadata.GetMethodDefinition(methodDefinitionHandle);
this.methodSignature = methodDefinition.DecodeSignature(TypeSystem.Implementation.TypeReferenceSignatureDecoder.Instance, default);
this.body = body; this.body = body;
this.reader = body.GetILReader(); this.reader = body.GetILReader();
this.debugInfo = module.DebugInfo; this.debugInfo = module.DebugInfo;
this.currentStack = ImmutableStack<ILVariable>.Empty; this.currentStack = ImmutableStack<ILVariable>.Empty;
this.unionFind = new UnionFind<ILVariable>(); this.unionFind = new UnionFind<ILVariable>();
this.stackMismatchPairs = new List<(ILVariable, ILVariable)>(); this.stackMismatchPairs = new List<(ILVariable, ILVariable)>();
this.methodReturnStackType = typeSystem.ResolveFromSignature(TypeSystem.Implementation.DynamicTypeReference.Create(methodSignature.ReturnType, methodDefinition.GetCustomAttributes(), metadata)).GetStackType(); this.methodReturnStackType = method.ReturnType.GetStackType();
InitParameterVariables(); InitParameterVariables();
localVariables = InitLocalVariables(); localVariables = InitLocalVariables();
if (body.LocalVariablesInitialized) { if (body.LocalVariablesInitialized) {
@ -126,12 +124,10 @@ namespace ICSharpCode.Decompiler.IL
ILVariable[] InitLocalVariables() ILVariable[] InitLocalVariables()
{ {
if (body.LocalSignature.IsNil) return Empty<ILVariable>.Array; if (body.LocalSignature.IsNil) return Empty<ILVariable>.Array;
var standaloneSignature = metadata.GetStandaloneSignature(body.LocalSignature); var variableTypes = typeSystem.DecodeLocalSignature(body.LocalSignature);
Debug.Assert(standaloneSignature.GetKind() == StandaloneSignatureKind.LocalVariables);
var variableTypes = standaloneSignature.DecodeLocalSignature(TypeSystem.Implementation.TypeReferenceSignatureDecoder.Instance, default);
var localVariables = new ILVariable[variableTypes.Length]; var localVariables = new ILVariable[variableTypes.Length];
foreach (var (index, type) in variableTypes.WithIndex()) { foreach (var (index, type) in variableTypes.WithIndex()) {
localVariables[index] = CreateILVariable(index, typeSystem.ResolveFromSignature(type)); localVariables[index] = CreateILVariable(index, type);
} }
return localVariables; return localVariables;
} }
@ -144,14 +140,16 @@ namespace ICSharpCode.Decompiler.IL
if (method.Parameters.LastOrDefault()?.Type == SpecialType.ArgList) if (method.Parameters.LastOrDefault()?.Type == SpecialType.ArgList)
popCount--; popCount--;
parameterVariables = new ILVariable[popCount]; parameterVariables = new ILVariable[popCount];
int paramIndex = 0; int offset = 0; int paramIndex = 0;
if (methodSignature.Header.IsInstance) { int offset = 0;
if (!method.IsStatic) {
offset = 1; offset = 1;
parameterVariables[paramIndex++] = CreateILVariable(-1, method.DeclaringType, "this"); parameterVariables[paramIndex++] = CreateILVariable(-1, method.DeclaringType, "this");
} }
while (paramIndex < parameterVariables.Length) { while (paramIndex < parameterVariables.Length) {
var type = typeSystem.ResolveFromSignature(methodSignature.ParameterTypes[paramIndex - offset]); IType type = method.Parameters[paramIndex - offset].Type;
parameterVariables[paramIndex] = CreateILVariable(paramIndex - offset, type, method.Parameters[paramIndex - offset].Name); string name = method.Parameters[paramIndex - offset].Name;
parameterVariables[paramIndex] = CreateILVariable(paramIndex - offset, type, name);
paramIndex++; paramIndex++;
} }
Debug.Assert(paramIndex == parameterVariables.Length); Debug.Assert(paramIndex == parameterVariables.Length);
@ -181,16 +179,16 @@ namespace ICSharpCode.Decompiler.IL
ILVariable CreateILVariable(int index, IType parameterType, string name) ILVariable CreateILVariable(int index, IType parameterType, string name)
{ {
ITypeDefinition def = parameterType.GetDefinition();
if (def != null && index < 0 && def.IsReferenceType == false) {
parameterType = new ByReferenceType(parameterType);
}
Debug.Assert(!parameterType.IsUnbound()); Debug.Assert(!parameterType.IsUnbound());
if (parameterType.IsUnbound()) { if (parameterType.IsUnbound()) {
// parameter types should not be unbound, the only known cause for these is a Cecil bug: // parameter types should not be unbound, the only known cause for these is a Cecil bug:
Debug.Assert(index < 0); // cecil bug occurs only for "this" Debug.Assert(index < 0); // cecil bug occurs only for "this"
parameterType = new ParameterizedType(parameterType.GetDefinition(), parameterType.TypeArguments); parameterType = new ParameterizedType(parameterType.GetDefinition(), parameterType.TypeArguments);
} }
ITypeDefinition def = parameterType.GetDefinition();
if (def != null && index < 0 && def.IsReferenceType == false) {
parameterType = new ByReferenceType(parameterType);
}
var ilVar = new ILVariable(VariableKind.Parameter, parameterType, index); var ilVar = new ILVariable(VariableKind.Parameter, parameterType, index);
Debug.Assert(ilVar.StoreCount == 1); // count the initial store when the method is called with an argument Debug.Assert(ilVar.StoreCount == 1); // count the initial store when the method is called with an argument
if (index < 0) if (index < 0)
@ -1289,21 +1287,18 @@ namespace ICSharpCode.Decompiler.IL
ILInstruction DecodeCallIndirect() ILInstruction DecodeCallIndirect()
{ {
var standaloneSignature = metadata.GetStandaloneSignature((StandaloneSignatureHandle)ReadAndDecodeMetadataToken()); var signatureHandle = (StandaloneSignatureHandle)ReadAndDecodeMetadataToken();
Debug.Assert(standaloneSignature.GetKind() == StandaloneSignatureKind.Method); var signature = typeSystem.DecodeMethodSignature(signatureHandle);
var signature = standaloneSignature.DecodeMethodSignature(TypeSystem.Implementation.TypeReferenceSignatureDecoder.Instance, default);
var functionPointer = Pop(StackType.I); var functionPointer = Pop(StackType.I);
Debug.Assert(!signature.Header.IsInstance); Debug.Assert(!signature.Header.IsInstance);
var parameterTypes = new IType[signature.ParameterTypes.Length]; var arguments = new ILInstruction[signature.ParameterTypes.Length];
var arguments = new ILInstruction[parameterTypes.Length];
for (int i = signature.ParameterTypes.Length - 1; i >= 0; i--) { for (int i = signature.ParameterTypes.Length - 1; i >= 0; i--) {
parameterTypes[i] = typeSystem.ResolveFromSignature(signature.ParameterTypes[i]); arguments[i] = Pop(signature.ParameterTypes[i].GetStackType());
arguments[i] = Pop(parameterTypes[i].GetStackType());
} }
var call = new CallIndirect( var call = new CallIndirect(
signature.Header.CallingConvention, signature.Header.CallingConvention,
typeSystem.ResolveFromSignature(signature.ReturnType), signature.ReturnType,
parameterTypes.ToImmutableArray(), signature.ParameterTypes,
arguments, arguments,
functionPointer functionPointer
); );

32
ICSharpCode.Decompiler/IL/Transforms/TransformArrayInitializers.cs

@ -19,8 +19,8 @@
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq; using System.Linq;
using System.Reflection.Metadata;
using ICSharpCode.Decompiler.TypeSystem; using ICSharpCode.Decompiler.TypeSystem;
using ICSharpCode.Decompiler.TypeSystem.Implementation;
using ICSharpCode.Decompiler.Util; using ICSharpCode.Decompiler.Util;
namespace ICSharpCode.Decompiler.IL.Transforms namespace ICSharpCode.Decompiler.IL.Transforms
@ -337,7 +337,8 @@ namespace ICSharpCode.Decompiler.IL.Transforms
if (MatchInitializeArrayCall(body.Instructions[pos], out var method, out var v2, out var field) && array == v2) { if (MatchInitializeArrayCall(body.Instructions[pos], out var method, out var v2, out var field) && array == v2) {
if (field.HasFlag(System.Reflection.FieldAttributes.HasFieldRVA)) { if (field.HasFlag(System.Reflection.FieldAttributes.HasFieldRVA)) {
var valuesList = new List<ILInstruction>(); var valuesList = new List<ILInstruction>();
if (DecodeArrayInitializer(arrayType, array, field.GetInitialValue(context.TypeSystem.ModuleDefinition.Reader), arrayLength, valuesList)) { var initialValue = field.GetInitialValue(context.TypeSystem.ModuleDefinition.Reader);
if (DecodeArrayInitializer(arrayType, array, initialValue, arrayLength, valuesList)) {
values = valuesList.ToArray(); values = valuesList.ToArray();
foundPos = pos; foundPos = pos;
return true; return true;
@ -349,30 +350,30 @@ namespace ICSharpCode.Decompiler.IL.Transforms
return false; return false;
} }
static bool DecodeArrayInitializer(IType type, ILVariable array, byte[] initialValue, int[] arrayLength, List<ILInstruction> output) static bool DecodeArrayInitializer(IType type, ILVariable array, BlobReader initialValue, int[] arrayLength, List<ILInstruction> output)
{ {
TypeCode typeCode = ReflectionHelper.GetTypeCode(type); TypeCode typeCode = ReflectionHelper.GetTypeCode(type);
switch (typeCode) { switch (typeCode) {
case TypeCode.Boolean: case TypeCode.Boolean:
case TypeCode.Byte: case TypeCode.Byte:
return DecodeArrayInitializer(initialValue, array, arrayLength, output, typeCode, type, (d, i) => new LdcI4((int)d[i])); return DecodeArrayInitializer(initialValue, array, arrayLength, output, typeCode, type, (ref BlobReader r) => new LdcI4(r.ReadByte()));
case TypeCode.SByte: case TypeCode.SByte:
return DecodeArrayInitializer(initialValue, array, arrayLength, output, typeCode, type, (d, i) => new LdcI4((int)unchecked((sbyte)d[i]))); return DecodeArrayInitializer(initialValue, array, arrayLength, output, typeCode, type, (ref BlobReader r) => new LdcI4(r.ReadSByte()));
case TypeCode.Int16: case TypeCode.Int16:
return DecodeArrayInitializer(initialValue, array, arrayLength, output, typeCode, type, (d, i) => new LdcI4((int)BitConverter.ToInt16(d, i))); return DecodeArrayInitializer(initialValue, array, arrayLength, output, typeCode, type, (ref BlobReader r) => new LdcI4(r.ReadInt16()));
case TypeCode.Char: case TypeCode.Char:
case TypeCode.UInt16: case TypeCode.UInt16:
return DecodeArrayInitializer(initialValue, array, arrayLength, output, typeCode, type, (d, i) => new LdcI4((int)BitConverter.ToUInt16(d, i))); return DecodeArrayInitializer(initialValue, array, arrayLength, output, typeCode, type, (ref BlobReader r) => new LdcI4(r.ReadUInt16()));
case TypeCode.Int32: case TypeCode.Int32:
case TypeCode.UInt32: case TypeCode.UInt32:
return DecodeArrayInitializer(initialValue, array, arrayLength, output, typeCode, type, (d, i) => new LdcI4(BitConverter.ToInt32(d, i))); return DecodeArrayInitializer(initialValue, array, arrayLength, output, typeCode, type, (ref BlobReader r) => new LdcI4(r.ReadInt32()));
case TypeCode.Int64: case TypeCode.Int64:
case TypeCode.UInt64: case TypeCode.UInt64:
return DecodeArrayInitializer(initialValue, array, arrayLength, output, typeCode, type, (d, i) => new LdcI8(BitConverter.ToInt64(d, i))); return DecodeArrayInitializer(initialValue, array, arrayLength, output, typeCode, type, (ref BlobReader r) => new LdcI8(r.ReadInt64()));
case TypeCode.Single: case TypeCode.Single:
return DecodeArrayInitializer(initialValue, array, arrayLength, output, typeCode, type, (d, i) => new LdcF4(BitConverter.ToSingle(d, i))); return DecodeArrayInitializer(initialValue, array, arrayLength, output, typeCode, type, (ref BlobReader r) => new LdcF4(r.ReadSingle()));
case TypeCode.Double: case TypeCode.Double:
return DecodeArrayInitializer(initialValue, array, arrayLength, output, typeCode, type, (d, i) => new LdcF8(BitConverter.ToDouble(d, i))); return DecodeArrayInitializer(initialValue, array, arrayLength, output, typeCode, type, (ref BlobReader r) => new LdcF8(r.ReadDouble()));
case TypeCode.Object: case TypeCode.Object:
case TypeCode.Empty: case TypeCode.Empty:
var typeDef = type.GetDefinition(); var typeDef = type.GetDefinition();
@ -384,15 +385,18 @@ namespace ICSharpCode.Decompiler.IL.Transforms
} }
} }
static bool DecodeArrayInitializer(byte[] initialValue, ILVariable array, int[] arrayLength, List<ILInstruction> output, TypeCode elementType, IType type, Func<byte[], int, ILInstruction> decoder) delegate ILInstruction ValueDecoder(ref BlobReader reader);
static bool DecodeArrayInitializer(BlobReader initialValue, ILVariable array, int[] arrayLength,
List<ILInstruction> output, TypeCode elementType, IType type, ValueDecoder decoder)
{ {
int elementSize = ElementSizeOf(elementType); int elementSize = ElementSizeOf(elementType);
var totalLength = arrayLength.Aggregate(1, (t, l) => t * l); var totalLength = arrayLength.Aggregate(1, (t, l) => t * l);
if (initialValue.Length < (totalLength * elementSize)) if (initialValue.RemainingBytes < (totalLength * elementSize))
return false; return false;
for (int i = 0; i < totalLength; i++) { for (int i = 0; i < totalLength; i++) {
output.Add(decoder(initialValue, i * elementSize)); output.Add(decoder(ref initialValue));
int next = i; int next = i;
for (int j = arrayLength.Length - 1; j >= 0; j--) { for (int j = arrayLength.Length - 1; j >= 0; j--) {
output.Add(new LdcI4(next % arrayLength[j])); output.Add(new LdcI4(next % arrayLength[j]));

19
ICSharpCode.Decompiler/Metadata/MetadataExtensions.cs

@ -170,7 +170,16 @@ namespace ICSharpCode.Decompiler.Metadata
return type.GetDefaultMemberName(reader, out var attr); return type.GetDefaultMemberName(reader, out var attr);
} }
static readonly ITypeResolveContext minimalCorlibContext = new SimpleTypeResolveContext(MinimalCorlib.Instance.CreateCompilation()); internal static readonly TypeProvider minimalCorlibTypeProvider =
new TypeProvider(MinimalCorlib.Instance.CreateCompilation().MainAssembly);
/// <summary>
/// An attribute type provider that can be used to decode attribute signatures
/// that only mention built-in types.
/// </summary>
public static ICustomAttributeTypeProvider<IType> MinimalAttributeTypeProvider {
get => minimalCorlibTypeProvider;
}
public static string GetDefaultMemberName(this TypeDefinitionHandle type, MetadataReader reader, out CustomAttributeHandle defaultMemberAttribute) public static string GetDefaultMemberName(this TypeDefinitionHandle type, MetadataReader reader, out CustomAttributeHandle defaultMemberAttribute)
{ {
@ -178,8 +187,8 @@ namespace ICSharpCode.Decompiler.Metadata
foreach (var h in td.GetCustomAttributes()) { foreach (var h in td.GetCustomAttributes()) {
var ca = reader.GetCustomAttribute(h); var ca = reader.GetCustomAttribute(h);
if (ca.GetAttributeType(reader).ToString() == "System.Reflection.DefaultMemberAttribute") { if (ca.GetAttributeType(reader).IsTopLevelType(reader, "System.Reflection", "DefaultMemberAttribute")) {
var decodedValues = ca.DecodeValue(new TypeSystemAttributeTypeProvider(minimalCorlibContext)); var decodedValues = ca.DecodeValue(minimalCorlibTypeProvider);
if (decodedValues.FixedArguments.Length == 1 && decodedValues.FixedArguments[0].Value is string value) { if (decodedValues.FixedArguments.Length == 1 && decodedValues.FixedArguments[0].Value is string value) {
defaultMemberAttribute = h; defaultMemberAttribute = h;
return value; return value;
@ -190,7 +199,7 @@ namespace ICSharpCode.Decompiler.Metadata
defaultMemberAttribute = default(CustomAttributeHandle); defaultMemberAttribute = default(CustomAttributeHandle);
return null; return null;
} }
public static bool HasOverrides(this MethodDefinitionHandle handle, MetadataReader reader) public static bool HasOverrides(this MethodDefinitionHandle handle, MetadataReader reader)
{ {
for (int row = 1; row <= reader.GetTableRowCount(TableIndex.MethodImpl); row++) { for (int row = 1; row <= reader.GetTableRowCount(TableIndex.MethodImpl); row++) {
@ -214,7 +223,7 @@ namespace ICSharpCode.Decompiler.Metadata
return false; return false;
} }
public static PrimitiveTypeCode ToPrimtiveTypeCode(this KnownTypeCode typeCode) public static PrimitiveTypeCode ToPrimitiveTypeCode(this KnownTypeCode typeCode)
{ {
switch (typeCode) { switch (typeCode) {
case KnownTypeCode.Object: case KnownTypeCode.Object:

2
ICSharpCode.Decompiler/Metadata/MetadataResolver.cs

@ -360,7 +360,7 @@ namespace ICSharpCode.Decompiler.Metadata
for (; i < totalParameterCount; i++) { for (; i < totalParameterCount; i++) {
if (!IsSameCompressedInteger(ref a, ref b, out typeCode)) if (!IsSameCompressedInteger(ref a, ref b, out typeCode))
return false; return false;
// // varargs sentinel
if (typeCode == 65) if (typeCode == 65)
break; break;
if (!TypesAreEqual(ref a, ref b, contextForA, contextForB, typeCode)) if (!TypesAreEqual(ref a, ref b, contextForA, contextForB, typeCode))

41
ICSharpCode.Decompiler/SRMExtensions.cs

@ -183,6 +183,16 @@ namespace ICSharpCode.Decompiler
} }
} }
public static bool IsTopLevelType(this EntityHandle handle, MetadataReader reader, string namespaceName, string name, int typeParameterCount = 0)
{
return GetFullTypeName(handle, reader) == new TopLevelTypeName(namespaceName, name, typeParameterCount);
}
public static bool IsAttributeType(this CustomAttribute attr, MetadataReader reader, string namespaceName, string name)
{
return attr.GetAttributeType(reader).IsTopLevelType(reader, namespaceName, name);
}
public static FullTypeName GetFullTypeName(this TypeSpecificationHandle handle, MetadataReader reader) public static FullTypeName GetFullTypeName(this TypeSpecificationHandle handle, MetadataReader reader)
{ {
if (handle.IsNil) if (handle.IsNil)
@ -362,24 +372,13 @@ namespace ICSharpCode.Decompiler
} }
#endregion #endregion
public static byte[] GetInitialValue(this FieldDefinition field, PEReader pefile) public static unsafe BlobReader GetInitialValue(this FieldDefinition field, PEReader pefile)
{ {
if (!field.HasFlag(FieldAttributes.HasFieldRVA) || field.GetRelativeVirtualAddress() == 0) if (!field.HasFlag(FieldAttributes.HasFieldRVA) || field.GetRelativeVirtualAddress() == 0)
return Empty<byte>.Array; return default;
int rva = field.GetRelativeVirtualAddress(); int rva = field.GetRelativeVirtualAddress();
int size = field.DecodeSignature(new FieldValueSizeDecoder(), default); int size = field.DecodeSignature(new FieldValueSizeDecoder(), default);
var headers = pefile.PEHeaders; return pefile.GetSectionData(rva).GetReader(0, size);
int index = headers.GetContainingSectionIndex(rva);
var sectionHeader = headers.SectionHeaders[index];
var sectionData = pefile.GetEntireImage();
int totalOffset = rva + sectionHeader.PointerToRawData - sectionHeader.VirtualAddress;
var reader = sectionData.GetReader();
reader.Offset += totalOffset;
int offset = field.GetOffset();
if (offset > 0)
reader.Offset += offset;
return reader.ReadBytes(size);
} }
class FieldValueSizeDecoder : ISignatureTypeProvider<int, Unit> class FieldValueSizeDecoder : ISignatureTypeProvider<int, Unit>
@ -387,14 +386,14 @@ namespace ICSharpCode.Decompiler
public int GetArrayType(int elementType, ArrayShape shape) => elementType; public int GetArrayType(int elementType, ArrayShape shape) => elementType;
public int GetByReferenceType(int elementType) => elementType; public int GetByReferenceType(int elementType) => elementType;
public int GetFunctionPointerType(MethodSignature<int> signature) => IntPtr.Size; public int GetFunctionPointerType(MethodSignature<int> signature) => IntPtr.Size;
public int GetGenericInstantiation(int genericType, ImmutableArray<int> typeArguments) => throw new NotSupportedException(); public int GetGenericInstantiation(int genericType, ImmutableArray<int> typeArguments) => genericType;
public int GetGenericMethodParameter(Unit genericContext, int index) => throw new NotSupportedException(); public int GetGenericMethodParameter(Unit genericContext, int index) => 0;
public int GetGenericTypeParameter(Unit genericContext, int index) => throw new NotSupportedException(); public int GetGenericTypeParameter(Unit genericContext, int index) => 0;
public int GetModifiedType(int modifier, int unmodifiedType, bool isRequired) => unmodifiedType; public int GetModifiedType(int modifier, int unmodifiedType, bool isRequired) => unmodifiedType;
public int GetPinnedType(int elementType) => elementType; public int GetPinnedType(int elementType) => elementType;
public int GetPointerType(int elementType) => elementType; public int GetPointerType(int elementType) => elementType;
public int GetPrimitiveType(PrimitiveTypeCode typeCode) public int GetPrimitiveType(PrimitiveTypeCode typeCode)
{ {
switch (typeCode) { switch (typeCode) {
case PrimitiveTypeCode.Boolean: case PrimitiveTypeCode.Boolean:
@ -421,7 +420,7 @@ namespace ICSharpCode.Decompiler
} }
} }
public int GetSZArrayType(int elementType) => throw new NotSupportedException(); public int GetSZArrayType(int elementType) => 0;
public int GetTypeFromDefinition(MetadataReader reader, TypeDefinitionHandle handle, byte rawTypeKind) public int GetTypeFromDefinition(MetadataReader reader, TypeDefinitionHandle handle, byte rawTypeKind)
{ {
@ -431,12 +430,12 @@ namespace ICSharpCode.Decompiler
public int GetTypeFromReference(MetadataReader reader, TypeReferenceHandle handle, byte rawTypeKind) public int GetTypeFromReference(MetadataReader reader, TypeReferenceHandle handle, byte rawTypeKind)
{ {
throw new NotImplementedException(); return 0;
} }
public int GetTypeFromSpecification(MetadataReader reader, Unit genericContext, TypeSpecificationHandle handle, byte rawTypeKind) public int GetTypeFromSpecification(MetadataReader reader, Unit genericContext, TypeSpecificationHandle handle, byte rawTypeKind)
{ {
throw new NotImplementedException(); return 0;
} }
} }
} }

202
ICSharpCode.Decompiler/TypeSystem/ApplyAttributeTypeVisitor.cs

@ -0,0 +1,202 @@
// Copyright (c) 2018 Daniel Grunwald
//
// 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.Immutable;
using System.Diagnostics;
using System.Linq;
using ICSharpCode.Decompiler.Util;
using SRM = System.Reflection.Metadata;
namespace ICSharpCode.Decompiler.TypeSystem
{
/// <summary>
/// Options for converting builtin
/// </summary>
[Flags]
enum TypeAttributeOptions
{
None = 0,
Dynamic = 1,
Tuple = 2,
Default = Dynamic | Tuple
}
/// <summary>
/// Introduces 'dynamic' and tuple types based on attribute values.
/// </summary>
class ApplyAttributeTypeVisitor : TypeVisitor
{
public static IType ApplyAttributesToType(
IType inputType,
ICompilation compilation,
SRM.CustomAttributeHandleCollection? attributes,
SRM.MetadataReader metadata,
TypeAttributeOptions options)
{
if (options == TypeAttributeOptions.None) {
return inputType;
}
bool hasDynamicAttribute = false;
bool[] dynamicAttributeData = null;
bool useTupleTypes = (options & TypeAttributeOptions.Tuple) != 0;
string[] tupleElementNames = null;
if (attributes != null) {
foreach (var attrHandle in attributes.Value) {
var attr = metadata.GetCustomAttribute(attrHandle);
var attrType = attr.GetAttributeType(metadata);
if ((options & TypeAttributeOptions.Dynamic) != 0
&& attrType.IsTopLevelType(metadata, "System.Runtime.CompilerServices", "DynamicAttribute")) {
hasDynamicAttribute = true;
var ctor = attr.DecodeValue(Metadata.MetadataExtensions.minimalCorlibTypeProvider);
if (ctor.FixedArguments.Length == 1) {
var arg = ctor.FixedArguments[0];
if (arg.Value is ImmutableArray<SRM.CustomAttributeTypedArgument<IType>> values
&& values.All(v => v.Value is bool)) {
dynamicAttributeData = values.SelectArray(v => (bool)v.Value);
}
}
} else if (useTupleTypes && attrType.IsTopLevelType(metadata, "System.Runtime.CompilerServices", "TupleElementNamesAttribute")) {
var ctor = attr.DecodeValue(Metadata.MetadataExtensions.minimalCorlibTypeProvider);
if (ctor.FixedArguments.Length == 1) {
var arg = ctor.FixedArguments[0];
if (arg.Value is ImmutableArray<SRM.CustomAttributeTypedArgument<IType>> values
&& values.All(v => v.Value is string || v.Value == null)) {
tupleElementNames = values.SelectArray(v => (string)v.Value);
}
}
}
}
}
if (hasDynamicAttribute || useTupleTypes) {
return inputType.AcceptVisitor(new ApplyAttributeTypeVisitor(
compilation, hasDynamicAttribute, dynamicAttributeData, useTupleTypes, tupleElementNames
));
} else {
return inputType;
}
}
readonly ICompilation compilation;
readonly bool hasDynamicAttribute;
readonly bool[] dynamicAttributeData;
readonly bool useTupleTypes;
readonly string[] tupleElementNames;
int dynamicTypeIndex = 0;
int tupleTypeIndex = 0;
public ApplyAttributeTypeVisitor(ICompilation compilation, bool hasDynamicAttribute, bool[] dynamicAttributeData, bool useTupleTypes, string[] tupleElementNames)
{
this.compilation = compilation ?? throw new ArgumentNullException(nameof(compilation));
this.hasDynamicAttribute = hasDynamicAttribute;
this.dynamicAttributeData = dynamicAttributeData;
this.useTupleTypes = useTupleTypes;
this.tupleElementNames = tupleElementNames;
}
public override IType VisitPointerType(PointerType type)
{
dynamicTypeIndex++;
return base.VisitPointerType(type);
}
public override IType VisitArrayType(ArrayType type)
{
dynamicTypeIndex++;
return base.VisitArrayType(type);
}
public override IType VisitByReferenceType(ByReferenceType type)
{
dynamicTypeIndex++;
return base.VisitByReferenceType(type);
}
public override IType VisitParameterizedType(ParameterizedType type)
{
if (useTupleTypes && TupleType.IsTupleCompatible(type, out int tupleCardinality)) {
if (tupleCardinality > 1) {
var valueTupleAssembly = type.GetDefinition()?.ParentAssembly;
ImmutableArray<string> elementNames = default;
if (tupleElementNames != null && tupleTypeIndex < tupleElementNames.Length) {
string[] extractedValues = new string[tupleCardinality];
Array.Copy(tupleElementNames, tupleTypeIndex, extractedValues, 0,
Math.Min(tupleCardinality, tupleElementNames.Length - tupleTypeIndex));
elementNames = ImmutableArray.CreateRange(extractedValues);
}
tupleTypeIndex += tupleCardinality;
var elementTypes = ImmutableArray.CreateBuilder<IType>(tupleCardinality);
do {
int normalArgCount = Math.Min(type.TypeArguments.Count, TupleType.RestPosition - 1);
for (int i = 0; i < normalArgCount; i++) {
dynamicTypeIndex++;
elementTypes.Add(type.TypeArguments[i].AcceptVisitor(this));
}
if (type.TypeArguments.Count == TupleType.RestPosition) {
type = type.TypeArguments.Last() as ParameterizedType;
dynamicTypeIndex++;
if (type != null && TupleType.IsTupleCompatible(type, out int nestedCardinality)) {
tupleTypeIndex += nestedCardinality;
} else {
Debug.Fail("TRest should be another value tuple");
type = null;
}
} else {
type = null;
}
} while (type != null);
Debug.Assert(elementTypes.Count == tupleCardinality);
return new TupleType(
compilation,
elementTypes.ToImmutable(),
elementNames,
valueTupleAssembly
);
} else {
// C# doesn't have syntax for tuples of cardinality <= 1
tupleTypeIndex += tupleCardinality;
}
}
// Visit generic type and type arguments.
// Like base implementation, except that it increments typeIndex.
var genericType = type.GenericType.AcceptVisitor(this);
bool changed = type.GenericType != genericType;
var arguments = new IType[type.TypeArguments.Count];
for (int i = 0; i < type.TypeArguments.Count; i++) {
dynamicTypeIndex++;
arguments[i] = type.TypeArguments[i].AcceptVisitor(this);
changed = changed || arguments[i] != type.TypeArguments[i];
}
if (!changed)
return type;
return new ParameterizedType(genericType, arguments);
}
public override IType VisitTypeDefinition(ITypeDefinition type)
{
if (type.KnownTypeCode == KnownTypeCode.Object && hasDynamicAttribute) {
if (dynamicAttributeData == null || dynamicTypeIndex >= dynamicAttributeData.Length)
return SpecialType.Dynamic;
if (dynamicAttributeData[dynamicTypeIndex])
return SpecialType.Dynamic;
return type;
}
return type;
}
}
}

86
ICSharpCode.Decompiler/TypeSystem/DecompilerTypeSystem.cs

@ -7,6 +7,7 @@ using ICSharpCode.Decompiler.Util;
using static ICSharpCode.Decompiler.Metadata.MetadataExtensions; using static ICSharpCode.Decompiler.Metadata.MetadataExtensions;
using System.Diagnostics; using System.Diagnostics;
using System.Collections.Immutable;
namespace ICSharpCode.Decompiler.TypeSystem namespace ICSharpCode.Decompiler.TypeSystem
{ {
@ -21,12 +22,7 @@ namespace ICSharpCode.Decompiler.TypeSystem
readonly Metadata.PEFile moduleDefinition; readonly Metadata.PEFile moduleDefinition;
readonly ICompilation compilation; readonly ICompilation compilation;
readonly ITypeResolveContext context; readonly ITypeResolveContext context;
readonly TypeAttributeOptions typeAttributeOptions;
/// <summary>
/// CecilLoader used for converting cecil type references to ITypeReference.
/// May only be accessed within lock(typeReferenceCecilLoader).
/// </summary>
readonly MetadataLoader typeReferenceCecilLoader;
Dictionary<SRM.EntityHandle, IField> fieldLookupCache = new Dictionary<SRM.EntityHandle, IField>(); Dictionary<SRM.EntityHandle, IField> fieldLookupCache = new Dictionary<SRM.EntityHandle, IField>();
Dictionary<SRM.EntityHandle, IProperty> propertyLookupCache = new Dictionary<SRM.EntityHandle, IProperty>(); Dictionary<SRM.EntityHandle, IProperty> propertyLookupCache = new Dictionary<SRM.EntityHandle, IProperty>();
@ -44,19 +40,18 @@ namespace ICSharpCode.Decompiler.TypeSystem
if (settings == null) if (settings == null)
throw new ArgumentNullException(nameof(settings)); throw new ArgumentNullException(nameof(settings));
this.moduleDefinition = moduleDefinition; this.moduleDefinition = moduleDefinition;
typeReferenceCecilLoader = new MetadataLoader { typeAttributeOptions = TypeAttributeOptions.None;
UseDynamicType = settings.Dynamic, if (settings.Dynamic)
UseTupleTypes = settings.TupleTypes, typeAttributeOptions |= TypeAttributeOptions.Dynamic;
}; if (settings.TupleTypes)
MetadataLoader cecilLoader = new MetadataLoader { typeAttributeOptions |= TypeAttributeOptions.Tuple;
MetadataLoader loader = new MetadataLoader {
IncludeInternalMembers = true, IncludeInternalMembers = true,
LazyLoad = true,
ShortenInterfaceImplNames = false, ShortenInterfaceImplNames = false,
UseDynamicType = settings.Dynamic, UseDynamicType = settings.Dynamic,
UseTupleTypes = settings.TupleTypes, UseTupleTypes = settings.TupleTypes,
}; };
typeReferenceCecilLoader.SetCurrentModule(moduleDefinition); IUnresolvedAssembly mainAssembly = loader.LoadModule(moduleDefinition);
IUnresolvedAssembly mainAssembly = cecilLoader.LoadModule(moduleDefinition);
// Load referenced assemblies and type-forwarder references. // Load referenced assemblies and type-forwarder references.
// This is necessary to make .NET Core/PCL binaries work better. // This is necessary to make .NET Core/PCL binaries work better.
var referencedAssemblies = new List<IUnresolvedAssembly>(); var referencedAssemblies = new List<IUnresolvedAssembly>();
@ -68,7 +63,7 @@ namespace ICSharpCode.Decompiler.TypeSystem
continue; continue;
var asm = moduleDefinition.AssemblyResolver.Resolve(asmRef); var asm = moduleDefinition.AssemblyResolver.Resolve(asmRef);
if (asm != null) { if (asm != null) {
IUnresolvedAssembly unresolvedAsm = cecilLoader.LoadModule(asm); IUnresolvedAssembly unresolvedAsm = loader.LoadModule(asm);
referencedAssemblies.Add(unresolvedAsm); referencedAssemblies.Add(unresolvedAsm);
moduleLookup.Add(unresolvedAsm, asm); moduleLookup.Add(unresolvedAsm, asm);
var metadata = asm.Metadata; var metadata = asm.Metadata;
@ -111,12 +106,7 @@ namespace ICSharpCode.Decompiler.TypeSystem
return null; return null;
return file; return file;
} }
public IType ResolveFromSignature(ITypeReference typeReference)
{
return typeReference.Resolve(context);
}
public IMember ResolveAsMember(SRM.EntityHandle memberReference) public IMember ResolveAsMember(SRM.EntityHandle memberReference)
{ {
switch (memberReference.Kind) { switch (memberReference.Kind) {
@ -147,14 +137,37 @@ namespace ICSharpCode.Decompiler.TypeSystem
#region Resolve Type #region Resolve Type
public IType ResolveAsType(SRM.EntityHandle typeReference) public IType ResolveAsType(SRM.EntityHandle typeReference)
{ {
if (typeReference.IsNil) return MetadataTypeReference.Resolve(
return SpecialType.UnknownType; typeReference,
ITypeReference typeRef; moduleDefinition.Metadata,
lock (typeReferenceCecilLoader) context,
typeRef = typeReferenceCecilLoader.ReadTypeReference(typeReference); typeAttributes: null,
return typeRef.Resolve(context); typeAttributeOptions
);
} }
#endregion #endregion
public SRM.MethodSignature<IType> DecodeMethodSignature(SRM.StandaloneSignatureHandle handle)
{
var standaloneSignature = moduleDefinition.Metadata.GetStandaloneSignature(handle);
if (standaloneSignature.GetKind() != SRM.StandaloneSignatureKind.Method)
throw new InvalidOperationException("Expected Method signature");
return standaloneSignature.DecodeMethodSignature(
new TypeProvider(compilation.MainAssembly),
context
);
}
public ImmutableArray<IType> DecodeLocalSignature(SRM.StandaloneSignatureHandle handle)
{
var standaloneSignature = moduleDefinition.Metadata.GetStandaloneSignature(handle);
if (standaloneSignature.GetKind() != SRM.StandaloneSignatureKind.LocalVariables)
throw new InvalidOperationException("Expected Local signature");
return standaloneSignature.DecodeLocalSignature(
new TypeProvider(compilation.MainAssembly),
context
);
}
#region Resolve Field #region Resolve Field
public IField ResolveAsField(SRM.EntityHandle fieldReference) public IField ResolveAsField(SRM.EntityHandle fieldReference)
@ -171,9 +184,10 @@ namespace ICSharpCode.Decompiler.TypeSystem
ITypeReference returnType; ITypeReference returnType;
switch (fieldReference.Kind) { switch (fieldReference.Kind) {
case SRM.HandleKind.FieldDefinition: case SRM.HandleKind.FieldDefinition:
var fieldDef = metadata.GetFieldDefinition((SRM.FieldDefinitionHandle)fieldReference); var fieldDefHandle = (SRM.FieldDefinitionHandle)fieldReference;
var fieldDef = metadata.GetFieldDefinition(fieldDefHandle);
declaringType = ResolveAsType(fieldDef.GetDeclaringType()); declaringType = ResolveAsType(fieldDef.GetDeclaringType());
returnType = DynamicTypeReference.Create(fieldDef.DecodeSignature(TypeReferenceSignatureDecoder.Instance, default), fieldDef.GetCustomAttributes(), metadata); returnType = new FieldTypeReference(fieldDefHandle, metadata, typeAttributeOptions);
var declaringTypeDefinition = declaringType.GetDefinition(); var declaringTypeDefinition = declaringType.GetDefinition();
if (declaringTypeDefinition == null) if (declaringTypeDefinition == null)
field = CreateFakeField(declaringType, metadata.GetString(fieldDef.Name), returnType); field = CreateFakeField(declaringType, metadata.GetString(fieldDef.Name), returnType);
@ -412,14 +426,12 @@ namespace ICSharpCode.Decompiler.TypeSystem
m.ReturnType = signature.ReturnType; m.ReturnType = signature.ReturnType;
m.IsStatic = !signature.Header.IsInstance; m.IsStatic = !signature.Header.IsInstance;
lock (typeReferenceCecilLoader) { var metadata = moduleDefinition.Metadata;
var metadata = moduleDefinition.Metadata; for (int i = 0; i < signature.GenericParameterCount; i++) {
for (int i = 0; i < signature.GenericParameterCount; i++) { m.TypeParameters.Add(new DefaultUnresolvedTypeParameter(SymbolKind.Method, i, ""));
m.TypeParameters.Add(new DefaultUnresolvedTypeParameter(SymbolKind.Method, i, "")); }
} for (int i = 0; i < signature.ParameterTypes.Length; i++) {
for (int i = 0; i < signature.ParameterTypes.Length; i++) { m.Parameters.Add(new DefaultUnresolvedParameter(signature.ParameterTypes[i], ""));
m.Parameters.Add(new DefaultUnresolvedParameter(signature.ParameterTypes[i], ""));
}
} }
return new ResolvedFakeMethod(m, context.WithCurrentTypeDefinition(declaringType.GetDefinition()), declaringType); return new ResolvedFakeMethod(m, context.WithCurrentTypeDefinition(declaringType.GetDefinition()), declaringType);
} }

2
ICSharpCode.Decompiler/TypeSystem/IAssembly.cs

@ -122,6 +122,6 @@ namespace ICSharpCode.Decompiler.TypeSystem
/// <summary> /// <summary>
/// Gets the type definition from the metadata token, or null if not found. /// Gets the type definition from the metadata token, or null if not found.
/// </summary> /// </summary>
ITypeDefinition ResolveTypeDefToken(EntityHandle token); ITypeDefinition ResolveTypeDefToken(TypeDefinitionHandle token);
} }
} }

5
ICSharpCode.Decompiler/TypeSystem/IDecompilerTypeSystem.cs

@ -16,6 +16,7 @@
// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER // OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
// DEALINGS IN THE SOFTWARE. // DEALINGS IN THE SOFTWARE.
using System.Collections.Immutable;
using System.Reflection.Metadata; using System.Reflection.Metadata;
using ICSharpCode.Decompiler.Metadata; using ICSharpCode.Decompiler.Metadata;
@ -28,7 +29,9 @@ namespace ICSharpCode.Decompiler.TypeSystem
{ {
ICompilation Compilation { get; } ICompilation Compilation { get; }
IType ResolveFromSignature(ITypeReference typeReference); MethodSignature<IType> DecodeMethodSignature(StandaloneSignatureHandle standaloneSignatureHandle);
ImmutableArray<IType> DecodeLocalSignature(StandaloneSignatureHandle standaloneSignatureHandle);
IType ResolveAsType(EntityHandle typeReference); IType ResolveAsType(EntityHandle typeReference);
IField ResolveAsField(EntityHandle fieldReference); IField ResolveAsField(EntityHandle fieldReference);
IMethod ResolveAsMethod(EntityHandle methodReference); IMethod ResolveAsMethod(EntityHandle methodReference);

6
ICSharpCode.Decompiler/TypeSystem/Implementation/DefaultUnresolvedAssembly.cs

@ -297,10 +297,8 @@ namespace ICSharpCode.Decompiler.TypeSystem.Implementation
return lookup; return lookup;
} }
internal IUnresolvedTypeDefinition GetTypeDefByToken(System.Reflection.Metadata.EntityHandle token) internal IUnresolvedTypeDefinition GetTypeDefByToken(System.Reflection.Metadata.TypeDefinitionHandle token)
{ {
if (token.Kind != System.Reflection.Metadata.HandleKind.TypeDefinition)
throw new ArgumentException("Token must be typedef-token.");
var lookup = LazyInit.VolatileRead(ref allTypesByMetadata); var lookup = LazyInit.VolatileRead(ref allTypesByMetadata);
if (lookup == null) { if (lookup == null) {
lookup = LazyInit.GetOrSet(ref allTypesByMetadata, BuildMetadataLookup()); lookup = LazyInit.GetOrSet(ref allTypesByMetadata, BuildMetadataLookup());
@ -445,7 +443,7 @@ namespace ICSharpCode.Decompiler.TypeSystem.Implementation
} }
} }
public ITypeDefinition ResolveTypeDefToken(System.Reflection.Metadata.EntityHandle token) public ITypeDefinition ResolveTypeDefToken(System.Reflection.Metadata.TypeDefinitionHandle token)
{ {
var td = unresolvedAssembly.GetTypeDefByToken(token); var td = unresolvedAssembly.GetTypeDefByToken(token);
if (td != null) if (td != null)

259
ICSharpCode.Decompiler/TypeSystem/Implementation/MetadataTypeReference.cs

@ -0,0 +1,259 @@
// Copyright (c) 2018 Daniel Grunwald
//
// 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 SRM = System.Reflection.Metadata;
using System.Diagnostics;
using System;
using ICSharpCode.Decompiler.Util;
using System.Linq;
using System.Collections.Immutable;
namespace ICSharpCode.Decompiler.TypeSystem.Implementation
{
sealed class MetadataTypeReference : ITypeReference
{
readonly SRM.EntityHandle type;
readonly SRM.MetadataReader metadata;
readonly SRM.CustomAttributeHandleCollection? typeAttributes;
readonly TypeAttributeOptions attributeOptions;
public MetadataTypeReference(SRM.EntityHandle type,
SRM.MetadataReader metadata,
SRM.CustomAttributeHandleCollection? typeAttributes = null,
TypeAttributeOptions attributeOptions = TypeAttributeOptions.Default)
{
this.type = type;
this.metadata = metadata;
this.typeAttributes = typeAttributes;
this.attributeOptions = attributeOptions;
}
public IType Resolve(ITypeResolveContext context)
{
return Resolve(type, metadata, context,
typeAttributes, attributeOptions);
}
public static IType Resolve(SRM.EntityHandle type,
SRM.MetadataReader metadata,
ITypeResolveContext context,
SRM.CustomAttributeHandleCollection? typeAttributes = null,
TypeAttributeOptions attributeOptions = TypeAttributeOptions.Default)
{
if (type.IsNil)
return SpecialType.UnknownType;
var tp = new TypeProvider(context.CurrentAssembly);
IType ty;
switch (type.Kind) {
case SRM.HandleKind.TypeDefinition:
ty = tp.GetTypeFromDefinition(metadata, (SRM.TypeDefinitionHandle)type, 0);
break;
case SRM.HandleKind.TypeReference:
ty = tp.GetTypeFromReference(metadata, (SRM.TypeReferenceHandle)type, 0);
break;
case SRM.HandleKind.TypeSpecification:
var typeSpec = metadata.GetTypeSpecification((SRM.TypeSpecificationHandle)type);
ty = typeSpec.DecodeSignature(tp, context);
break;
default:
Debug.Fail("Not a type handle");
ty = SpecialType.UnknownType;
break;
}
ty = ApplyAttributeTypeVisitor.ApplyAttributesToType(ty, context.Compilation,
typeAttributes, metadata, attributeOptions);
return ty;
}
}
sealed class FieldTypeReference : ITypeReference
{
readonly SRM.FieldDefinitionHandle fieldHandle;
readonly SRM.MetadataReader metadata;
readonly TypeAttributeOptions attributeOptions;
public FieldTypeReference(SRM.FieldDefinitionHandle fieldHandle,
SRM.MetadataReader metadata,
TypeAttributeOptions attributeOptions = TypeAttributeOptions.Default)
{
this.fieldHandle = fieldHandle;
this.metadata = metadata;
this.attributeOptions = attributeOptions;
}
IType ITypeReference.Resolve(ITypeResolveContext context)
{
return Resolve(fieldHandle, metadata, context, attributeOptions);
}
public static IType Resolve(SRM.FieldDefinitionHandle fieldHandle,
SRM.MetadataReader metadata,
ITypeResolveContext context,
TypeAttributeOptions attributeOptions = TypeAttributeOptions.Default)
{
var fieldDef = metadata.GetFieldDefinition(fieldHandle);
IType ty = fieldDef.DecodeSignature(new TypeProvider(context.CurrentAssembly), context);
ty = ApplyAttributeTypeVisitor.ApplyAttributesToType(ty, context.Compilation,
fieldDef.GetCustomAttributes(), metadata, attributeOptions);
return ty;
}
}
/// <summary>
/// Represents an unresolved method signature.
/// </summary>
sealed class UnresolvedMethodSignature
{
readonly SRM.EntityHandle handle;
readonly SRM.MetadataReader metadata;
readonly TypeAttributeOptions attributeOptions;
public UnresolvedMethodSignature(SRM.MethodDefinitionHandle handle, SRM.MetadataReader metadata,
TypeAttributeOptions attributeOptions = TypeAttributeOptions.Default)
{
this.handle = handle;
this.metadata = metadata;
this.attributeOptions = attributeOptions;
}
public UnresolvedMethodSignature(SRM.PropertyDefinitionHandle handle, SRM.MetadataReader metadata,
TypeAttributeOptions attributeOptions = TypeAttributeOptions.Default)
{
this.handle = handle;
this.metadata = metadata;
this.attributeOptions = attributeOptions;
}
public SRM.MethodSignature<IType> Resolve(ITypeResolveContext context)
{
return (SRM.MethodSignature<IType>)context.Compilation.CacheManager.GetOrAddShared(
this, key => {
Debug.Assert(key == this);
switch (handle.Kind) {
case SRM.HandleKind.MethodDefinition:
return GetSignature(
metadata.GetMethodDefinition((SRM.MethodDefinitionHandle)handle),
metadata, context
);
case SRM.HandleKind.PropertyDefinition:
return GetSignature(
metadata.GetPropertyDefinition((SRM.PropertyDefinitionHandle)handle),
metadata, context
);
default:
throw new InvalidOperationException();
}
}
);
}
public static SRM.MethodSignature<IType> GetSignature(SRM.MethodDefinition methodDef,
SRM.MetadataReader metadata, ITypeResolveContext context,
TypeAttributeOptions attributeOptions = TypeAttributeOptions.Default)
{
var typeProvider = new TypeProvider(context.CurrentAssembly);
var signature = methodDef.DecodeSignature(typeProvider, context);
return ApplyAttributes(signature, methodDef.GetParameters(), context.Compilation, metadata, attributeOptions);
}
public static SRM.MethodSignature<IType> GetSignature(SRM.PropertyDefinition propertyDef,
SRM.MetadataReader metadata, ITypeResolveContext context,
TypeAttributeOptions attributeOptions = TypeAttributeOptions.Default)
{
var typeProvider = new TypeProvider(context.CurrentAssembly);
var signature = propertyDef.DecodeSignature(typeProvider, context);
var accessors = propertyDef.GetAccessors();
SRM.ParameterHandleCollection? parameterHandles = null;
if (!accessors.Getter.IsNil) {
var getter = metadata.GetMethodDefinition(accessors.Getter);
parameterHandles = getter.GetParameters();
} else {
if (!accessors.Setter.IsNil) {
var setter = metadata.GetMethodDefinition(accessors.Setter);
parameterHandles = setter.GetParameters();
}
}
return ApplyAttributes(signature, parameterHandles, context.Compilation, metadata, attributeOptions);
}
static SRM.MethodSignature<IType> ApplyAttributes(SRM.MethodSignature<IType> signature, SRM.ParameterHandleCollection? parameterHandles, ICompilation compilation, SRM.MetadataReader metadata, TypeAttributeOptions attributeOptions)
{
SRM.CustomAttributeHandleCollection? returnTypeAttributes = null;
var parameterAttributes = new SRM.CustomAttributeHandleCollection?[signature.ParameterTypes.Length];
if (parameterHandles != null) {
foreach (var parameterHandle in parameterHandles) {
var par = metadata.GetParameter(parameterHandle);
if (par.SequenceNumber == 0) {
returnTypeAttributes = par.GetCustomAttributes();
} else if (par.SequenceNumber <= parameterAttributes.Length) {
parameterAttributes[par.SequenceNumber - 1] = par.GetCustomAttributes();
}
}
}
IType returnType = ApplyAttributeTypeVisitor.ApplyAttributesToType(
signature.ReturnType, compilation, returnTypeAttributes, metadata, attributeOptions
);
var parameterTypes = signature.ParameterTypes.SelectWithIndex(
(i, p) => ApplyAttributeTypeVisitor.ApplyAttributesToType(
p, compilation, parameterAttributes[i], metadata, attributeOptions
)
).ToImmutableArray();
return new SRM.MethodSignature<IType>(
signature.Header, returnType,
signature.RequiredParameterCount, signature.GenericParameterCount,
parameterTypes
);
}
}
sealed class SignatureParameterTypeReference : ITypeReference
{
readonly UnresolvedMethodSignature unresolvedSig;
readonly int index;
public SignatureParameterTypeReference(UnresolvedMethodSignature unresolvedSig, int index)
{
this.unresolvedSig = unresolvedSig;
this.index = index;
}
public IType Resolve(ITypeResolveContext context)
{
var sig = unresolvedSig.Resolve(context);
if (index < sig.ParameterTypes.Length)
return sig.ParameterTypes[index];
else
return SpecialType.UnknownType;
}
}
sealed class SignatureReturnTypeReference : ITypeReference
{
readonly UnresolvedMethodSignature unresolvedSig;
public SignatureReturnTypeReference(UnresolvedMethodSignature unresolvedSig)
{
this.unresolvedSig = unresolvedSig;
}
public IType Resolve(ITypeResolveContext context)
{
return unresolvedSig.Resolve(context).ReturnType;
}
}
}

168
ICSharpCode.Decompiler/TypeSystem/Implementation/TypeSpecification.cs

@ -23,6 +23,7 @@ using SRM = System.Reflection.Metadata;
using ICSharpCode.Decompiler.Metadata; using ICSharpCode.Decompiler.Metadata;
using ICSharpCode.Decompiler.Util; using ICSharpCode.Decompiler.Util;
using System.Collections.Generic; using System.Collections.Generic;
using System.Diagnostics;
namespace ICSharpCode.Decompiler.TypeSystem.Implementation namespace ICSharpCode.Decompiler.TypeSystem.Implementation
{ {
@ -81,120 +82,37 @@ namespace ICSharpCode.Decompiler.TypeSystem.Implementation
return ElementType.Resolve(context); return ElementType.Resolve(context);
} }
} }
public sealed class DynamicTypeReference : TypeVisitor, ITypeReference sealed class TypeDefTokenTypeReference : ITypeReference
{ {
readonly ITypeReference reference; readonly SRM.TypeDefinitionHandle token;
readonly bool[] dynamicInfo;
int typeIndex;
static readonly ITypeResolveContext minimalCorlibContext = new SimpleTypeResolveContext(MinimalCorlib.Instance.CreateCompilation());
public static ITypeReference Create(ITypeReference reference, SRM.CustomAttributeHandleCollection? customAttributes, SRM.MetadataReader metadata)
{
if (HasDynamicAttribute(customAttributes, metadata, out var dynamicInfo))
return new DynamicTypeReference(reference, dynamicInfo);
return reference;
}
public static bool HasDynamicAttribute(SRM.CustomAttributeHandleCollection? attributes, SRM.MetadataReader metadata, out bool[] mapping)
{
mapping = null;
if (attributes == null)
return false;
foreach (var handle in attributes) {
var a = metadata.GetCustomAttribute(handle);
var type = a.GetAttributeType(metadata);
if (type.GetFullTypeName(metadata).ToString() == "System.Runtime.CompilerServices.DynamicAttribute") {
var ctor = a.DecodeValue(new TypeSystemAttributeTypeProvider(minimalCorlibContext));
if (ctor.FixedArguments.Length == 1) {
var arg = ctor.FixedArguments[0];
if (arg.Type.ReflectionName == "System.Boolean[]" && arg.Value is ImmutableArray<SRM.CustomAttributeTypedArgument<IType>> values) {
mapping = values.SelectArray(v => (bool)v.Value);
return true;
}
}
return true;
}
}
return false;
}
DynamicTypeReference(ITypeReference reference, bool[] dynamicInfo) public TypeDefTokenTypeReference(SRM.TypeDefinitionHandle token)
{ {
this.reference = reference; this.token = token;
this.dynamicInfo = dynamicInfo;
} }
public IType Resolve(ITypeResolveContext context) public IType Resolve(ITypeResolveContext context)
{ {
return reference.Resolve(context).AcceptVisitor(this); ITypeDefinition td = context.CurrentAssembly.ResolveTypeDefToken(token);
} if (td != null)
return td;
public override IType VisitPointerType(PointerType type) return SpecialType.UnknownType;
{
typeIndex++;
return base.VisitPointerType(type);
}
public override IType VisitArrayType(ArrayType type)
{
typeIndex++;
return base.VisitArrayType(type);
}
public override IType VisitByReferenceType(ByReferenceType type)
{
typeIndex++;
return base.VisitByReferenceType(type);
}
public override IType VisitParameterizedType(ParameterizedType type)
{
var genericType = type.GenericType.AcceptVisitor(this);
bool changed = type.GenericType != genericType;
var arguments = new IType[type.TypeArguments.Count];
for (int i = 0; i < type.TypeArguments.Count; i++) {
typeIndex++;
arguments[i] = type.TypeArguments[i].AcceptVisitor(this);
changed = changed || arguments[i] != type.TypeArguments[i];
}
if (!changed)
return type;
return new ParameterizedType(genericType, arguments);
}
public override IType VisitTypeDefinition(ITypeDefinition type)
{
if (type.KnownTypeCode == KnownTypeCode.Object) {
if (dynamicInfo == null || typeIndex >= dynamicInfo.Length)
return SpecialType.Dynamic;
if (dynamicInfo[typeIndex])
return SpecialType.Dynamic;
return type;
}
return type;
} }
} }
sealed class TypeDefTokenTypeReference : ITypeReference sealed class TypeSpecTypeReference : ITypeReference
{ {
readonly SRM.EntityHandle token; readonly SRM.TypeSpecification typeSpec;
public TypeDefTokenTypeReference(SRM.EntityHandle token) public TypeSpecTypeReference(SRM.TypeSpecification typeSpec)
{ {
if (token.Kind != SRM.HandleKind.TypeDefinition) this.typeSpec = typeSpec;
throw new ArgumentException(nameof(token), "must be TypeDef token");
this.token = token;
} }
public IType Resolve(ITypeResolveContext context) public IType Resolve(ITypeResolveContext context)
{ {
ITypeDefinition td = context.CurrentAssembly.ResolveTypeDefToken(token); return typeSpec.DecodeSignature(new TypeProvider(context.CurrentAssembly), context);
if (td != null)
return td;
return SpecialType.UnknownType;
} }
} }
@ -279,60 +197,4 @@ namespace ICSharpCode.Decompiler.TypeSystem.Implementation
.DecodeSignature(this, default); .DecodeSignature(this, default);
} }
} }
public class TypeSystemAttributeTypeProvider : SRM.ICustomAttributeTypeProvider<IType>
{
readonly ITypeResolveContext context;
public static TypeSystemAttributeTypeProvider CreateDefault() => new TypeSystemAttributeTypeProvider(new SimpleTypeResolveContext(MinimalCorlib.Instance.CreateCompilation()));
public TypeSystemAttributeTypeProvider(ITypeResolveContext context)
{
this.context = context;
}
public IType GetPrimitiveType(SRM.PrimitiveTypeCode typeCode)
{
return context.Compilation.FindType(typeCode.ToKnownTypeCode());
}
public IType GetSystemType()
{
return context.Compilation.FindType(KnownTypeCode.Type);
}
public IType GetSZArrayType(IType elementType)
{
return new ArrayType(context.Compilation, elementType);
}
public IType GetTypeFromDefinition(SRM.MetadataReader reader, SRM.TypeDefinitionHandle handle, byte rawTypeKind)
{
var type = reader.GetTypeDefinition(handle);
return new DefaultUnresolvedTypeDefinition(type.GetFullTypeName(reader).ToString()).Resolve(context);
}
public IType GetTypeFromReference(SRM.MetadataReader reader, SRM.TypeReferenceHandle handle, byte rawTypeKind)
{
return new DefaultUnresolvedTypeDefinition(handle.GetFullTypeName(reader).ToString()).Resolve(context);
}
public IType GetTypeFromSerializedName(string name)
{
return new GetClassTypeReference(new FullTypeName(name)).Resolve(context);
}
public SRM.PrimitiveTypeCode GetUnderlyingEnumType(IType type)
{
var def = type.GetEnumUnderlyingType().GetDefinition();
if (def == null)
throw new InvalidOperationException();
return def.KnownTypeCode.ToPrimtiveTypeCode();
}
public bool IsSystemType(IType type)
{
return type.IsKnownType(KnownTypeCode.Type);
}
}
} }

295
ICSharpCode.Decompiler/TypeSystem/MetadataLoader.cs

@ -18,6 +18,7 @@
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Collections.Immutable;
using System.Diagnostics; using System.Diagnostics;
using System.IO; using System.IO;
using System.Linq; using System.Linq;
@ -91,19 +92,8 @@ namespace ICSharpCode.Decompiler.TypeSystem
/// for every delay-loading operation. /// for every delay-loading operation.
/// If you access the Cecil objects directly in your application, you may need to take the same lock. /// If you access the Cecil objects directly in your application, you may need to take the same lock.
/// </remarks> /// </remarks>
public bool LazyLoad { get; set; } public bool LazyLoad { get; private set; } = true;
/// <summary>
/// This delegate gets executed whenever an entity was loaded.
/// </summary>
/// <remarks>
/// This callback may be to build a dictionary that maps between
/// entities and cecil objects.
/// Warning: if delay-loading is used and the type system is accessed by multiple threads,
/// the callback may be invoked concurrently on multiple threads.
/// </remarks>
public Action<IUnresolvedEntity> OnEntityLoaded { get; set; }
bool shortenInterfaceImplNames = true; bool shortenInterfaceImplNames = true;
/// <summary> /// <summary>
@ -140,8 +130,9 @@ namespace ICSharpCode.Decompiler.TypeSystem
// use a shared typeSystemTranslationTable // use a shared typeSystemTranslationTable
this.IncludeInternalMembers = loader.IncludeInternalMembers; this.IncludeInternalMembers = loader.IncludeInternalMembers;
this.LazyLoad = loader.LazyLoad; this.LazyLoad = loader.LazyLoad;
this.OnEntityLoaded = loader.OnEntityLoaded;
this.ShortenInterfaceImplNames = loader.ShortenInterfaceImplNames; this.ShortenInterfaceImplNames = loader.ShortenInterfaceImplNames;
this.UseDynamicType = loader.UseDynamicType;
this.UseTupleTypes = loader.UseTupleTypes;
this.currentModule = loader.currentModule; this.currentModule = loader.currentModule;
this.currentMetadata = loader.currentMetadata; this.currentMetadata = loader.currentMetadata;
this.currentAssembly = loader.currentAssembly; this.currentAssembly = loader.currentAssembly;
@ -222,7 +213,6 @@ namespace ICSharpCode.Decompiler.TypeSystem
if (this.LazyLoad) { if (this.LazyLoad) {
var t = new LazySRMTypeDefinition(cecilLoaderCloneForLazyLoading, module, h); var t = new LazySRMTypeDefinition(cecilLoaderCloneForLazyLoading, module, h);
currentAssembly.AddTypeDefinition(t); currentAssembly.AddTypeDefinition(t);
RegisterCecilObject(t);
} else { } else {
var t = CreateTopLevelTypeDefinition(h, td); var t = CreateTopLevelTypeDefinition(h, td);
cecilTypeDefs.Add(h); cecilTypeDefs.Add(h);
@ -295,32 +285,24 @@ namespace ICSharpCode.Decompiler.TypeSystem
/// <summary> /// <summary>
/// Reads a type reference. /// Reads a type reference.
/// </summary> /// </summary>
/// <param name="type">The Cecil type reference that should be converted into /// <param name="type">The metadata type token that should be converted into
/// a type system type reference.</param> /// a type system type reference.</param>
/// <param name="typeAttributes">Attributes associated with the Cecil type reference. /// <param name="typeAttributes">Attributes associated with the type.
/// This is used to support the 'dynamic' type.</param> /// This is used to support the 'dynamic' type, and for tuple element names.
/// </param>
public ITypeReference ReadTypeReference(EntityHandle type, CustomAttributeHandleCollection? typeAttributes = null) public ITypeReference ReadTypeReference(EntityHandle type, CustomAttributeHandleCollection? typeAttributes = null)
{ {
ITypeReference CreateTypeReference(TypeReferenceHandle handle) return new MetadataTypeReference(type, currentMetadata, typeAttributes, TypeAttributeOptions);
{ }
var t = currentMetadata.GetTypeReference(handle);
var asmref = handle.GetDeclaringAssembly(currentMetadata); private TypeAttributeOptions TypeAttributeOptions {
if (asmref.IsNil) get {
return new GetClassTypeReference(handle.GetFullTypeName(currentMetadata), DefaultAssemblyReference.CurrentAssembly); TypeAttributeOptions options = TypeAttributeOptions.None;
var asm = currentMetadata.GetAssemblyReference(asmref); if (UseDynamicType)
return new GetClassTypeReference(handle.GetFullTypeName(currentMetadata), new DefaultAssemblyReference(currentMetadata.GetString(asm.Name))); options |= TypeAttributeOptions.Dynamic;
} if (UseTupleTypes)
options |= TypeAttributeOptions.Tuple;
switch (type.Kind) { return options;
case HandleKind.TypeSpecification:
return DynamicTypeReference.Create(currentMetadata.GetTypeSpecification((TypeSpecificationHandle)type)
.DecodeSignature(TypeReferenceSignatureDecoder.Instance, default), typeAttributes, currentMetadata);
case HandleKind.TypeReference:
return CreateTypeReference((TypeReferenceHandle)type);
case HandleKind.TypeDefinition:
return new TypeDefTokenTypeReference(type);
default:
throw new NotSupportedException();
} }
} }
#endregion #endregion
@ -808,7 +790,6 @@ namespace ICSharpCode.Decompiler.TypeSystem
InitMembers(typeDefinition, td, td.Members); InitMembers(typeDefinition, td, td.Members);
td.ApplyInterningProvider(interningProvider); td.ApplyInterningProvider(interningProvider);
td.Freeze(); td.Freeze();
RegisterCecilObject(td);
} }
void InitBaseTypes(TypeDefinitionHandle handle, IList<ITypeReference> baseTypes) void InitBaseTypes(TypeDefinitionHandle handle, IList<ITypeReference> baseTypes)
@ -986,10 +967,10 @@ namespace ICSharpCode.Decompiler.TypeSystem
{ {
foreach (var h in typeDefinition.GetCustomAttributes()) { foreach (var h in typeDefinition.GetCustomAttributes()) {
var a = reader.GetCustomAttribute(h); var a = reader.GetCustomAttribute(h);
var type = a.GetAttributeType(reader).GetFullTypeName(reader); var type = a.GetAttributeType(reader);
if (type.ToString() != typeof(System.Reflection.DefaultMemberAttribute).FullName) if (!type.IsTopLevelType(reader, "System.Reflection", "DefaultMemberAttribute"))
continue; continue;
var value = a.DecodeValue(new TypeSystemAttributeTypeProvider(minimalCorlibContext)); var value = a.DecodeValue(Metadata.MetadataExtensions.minimalCorlibTypeProvider);
if (value.FixedArguments.Length == 1 && value.FixedArguments[0].Value is string name) if (value.FixedArguments.Length == 1 && value.FixedArguments[0].Value is string name)
return name; return name;
} }
@ -998,14 +979,14 @@ namespace ICSharpCode.Decompiler.TypeSystem
static bool IsAccessor(MethodSemanticsAttributes semantics) static bool IsAccessor(MethodSemanticsAttributes semantics)
{ {
return semantics > (MethodSemanticsAttributes)0 && semantics != MethodSemanticsAttributes.Other; return semantics != 0 && semantics != MethodSemanticsAttributes.Other;
} }
#endregion #endregion
#region Lazy-Loaded Type Definition #region Lazy-Loaded Type Definition
sealed class LazySRMTypeDefinition : AbstractUnresolvedEntity, IUnresolvedTypeDefinition sealed class LazySRMTypeDefinition : AbstractUnresolvedEntity, IUnresolvedTypeDefinition
{ {
// loader + cecilTypeDef, used for lazy-loading; and set to null after lazy loading is complete // loader + cecilTypeDef, used for lazy-loading
readonly MetadataLoader loader; readonly MetadataLoader loader;
readonly Metadata.PEFile module; readonly Metadata.PEFile module;
readonly MetadataReader metadata; readonly MetadataReader metadata;
@ -1224,31 +1205,11 @@ namespace ICSharpCode.Decompiler.TypeSystem
AddAttributes(method, m.Attributes, m.ReturnTypeAttributes); AddAttributes(method, m.Attributes, m.ReturnTypeAttributes);
TranslateModifiers(handle, m); TranslateModifiers(handle, m);
var declaringType = currentMetadata.GetTypeDefinition(method.GetDeclaringType()); var signature = method.DecodeSignature(TypeCodeProvider.Instance, default);
var reader = currentMetadata.GetBlobReader(method.Signature); var unresolvedSig = new UnresolvedMethodSignature(handle, currentMetadata, TypeAttributeOptions);
var signature = method.DecodeSignature(TypeReferenceSignatureDecoder.Instance, default); var (retType, parameters) = TranslateSignature(signature, unresolvedSig, method.GetParameters());
m.ReturnType = retType;
var parameters = method.GetParameters().ToArray(); m.Parameters.AddRange(parameters);
m.ReturnType = HandleReturnType(parameters.FirstOrDefault(), signature.ReturnType);
int j = 0;
if (signature.RequiredParameterCount > parameters.Length) {
foreach (var parameterType in signature.ParameterTypes) {
m.Parameters.Add(new DefaultUnresolvedParameter(DynamicTypeReference.Create(parameterType, null, currentMetadata), string.Empty));
}
} else {
foreach (var p in parameters) {
var par = currentMetadata.GetParameter(p);
if (par.SequenceNumber > 0) {
m.Parameters.Add(ReadParameter(par, signature.ParameterTypes[j]));
j++;
}
}
}
if (signature.Header.CallingConvention == SignatureCallingConvention.VarArgs) {
m.Parameters.Add(new DefaultUnresolvedParameter(SpecialType.ArgList, string.Empty));
}
// mark as extension method if the attribute is set // mark as extension method if the attribute is set
if ((method.Attributes & MethodAttributes.Static) == MethodAttributes.Static && HasExtensionAttribute(currentMetadata, method.GetCustomAttributes())) { if ((method.Attributes & MethodAttributes.Static) == MethodAttributes.Static && HasExtensionAttribute(currentMetadata, method.GetCustomAttributes())) {
@ -1297,24 +1258,79 @@ namespace ICSharpCode.Decompiler.TypeSystem
return m; return m;
} }
ITypeReference HandleReturnType(ParameterHandle parameterHandle, ITypeReference returnType) private (ITypeReference, List<IUnresolvedParameter>) TranslateSignature(
MethodSignature<SignatureTypeCode> signature,
UnresolvedMethodSignature unresolvedSig, ParameterHandleCollection? parameterHandleCollection)
{ {
CustomAttributeHandleCollection? attributes = null; var returnType = new SignatureReturnTypeReference(unresolvedSig);
if (!parameterHandle.IsNil) { var parameters = new List<IUnresolvedParameter>();
var par = currentMetadata.GetParameter(parameterHandle); int i = 0;
if (par.SequenceNumber == 0) { if (parameterHandleCollection != null) {
attributes = par.GetCustomAttributes(); foreach (var p in parameterHandleCollection) {
var par = currentMetadata.GetParameter(p);
if (par.SequenceNumber > 0 && i < signature.RequiredParameterCount) {
Debug.Assert(par.SequenceNumber - 1 == i);
var paramTypeRef = new SignatureParameterTypeReference(unresolvedSig, i);
parameters.Add(ReadParameter(par, paramTypeRef, signature.ParameterTypes[i]));
i++;
}
} }
} }
return DynamicTypeReference.Create(returnType, attributes, currentMetadata); Debug.Assert(i == parameters.Count);
while (i < signature.RequiredParameterCount) {
parameters.Add(new DefaultUnresolvedParameter(
new SignatureParameterTypeReference(unresolvedSig, i),
name: string.Empty
));
i++;
}
if (signature.Header.CallingConvention == SignatureCallingConvention.VarArgs) {
parameters.Add(new DefaultUnresolvedParameter(SpecialType.ArgList, string.Empty));
}
return (returnType, parameters);
} }
static bool HasExtensionAttribute(MetadataReader currentModule, CustomAttributeHandleCollection attributes) /// <summary>
/// Allows decoding a signature without decoding the types,
/// e.g. for counting the number of parameters in a method signature.
/// </summary>
sealed class TypeCodeProvider : ISignatureTypeProvider<SignatureTypeCode, Unit>
{
public static readonly TypeCodeProvider Instance = new TypeCodeProvider();
public SignatureTypeCode GetArrayType(SignatureTypeCode elementType, ArrayShape shape) => SignatureTypeCode.Array;
public SignatureTypeCode GetByReferenceType(SignatureTypeCode elementType) => SignatureTypeCode.ByReference;
public SignatureTypeCode GetFunctionPointerType(MethodSignature<SignatureTypeCode> signature) => SignatureTypeCode.FunctionPointer;
public SignatureTypeCode GetGenericInstantiation(SignatureTypeCode genericType, ImmutableArray<SignatureTypeCode> typeArguments) => SignatureTypeCode.GenericTypeInstance;
public SignatureTypeCode GetGenericMethodParameter(Unit genericContext, int index) => SignatureTypeCode.GenericMethodParameter;
public SignatureTypeCode GetGenericTypeParameter(Unit genericContext, int index) => SignatureTypeCode.GenericTypeParameter;
public SignatureTypeCode GetModifiedType(SignatureTypeCode modifier, SignatureTypeCode unmodifiedType, bool isRequired)
{
// skip modifiers
return unmodifiedType;
}
public SignatureTypeCode GetPinnedType(SignatureTypeCode elementType) => SignatureTypeCode.Pinned;
public SignatureTypeCode GetPointerType(SignatureTypeCode elementType) => SignatureTypeCode.Pointer;
public SignatureTypeCode GetPrimitiveType(PrimitiveTypeCode typeCode) => (SignatureTypeCode)typeCode;
public SignatureTypeCode GetSZArrayType(SignatureTypeCode elementType) => SignatureTypeCode.SZArray;
public SignatureTypeCode GetTypeFromDefinition(MetadataReader reader, TypeDefinitionHandle handle, byte rawTypeKind)
=> SignatureTypeCode.TypeHandle;
public SignatureTypeCode GetTypeFromReference(MetadataReader reader, TypeReferenceHandle handle, byte rawTypeKind)
=> SignatureTypeCode.TypeHandle;
public SignatureTypeCode GetTypeFromSpecification(MetadataReader reader, Unit genericContext, TypeSpecificationHandle handle, byte rawTypeKind)
=> SignatureTypeCode.TypeHandle;
}
static bool HasExtensionAttribute(MetadataReader metadata, CustomAttributeHandleCollection attributes)
{ {
foreach (var h in attributes) { foreach (var h in attributes) {
var attr = currentModule.GetCustomAttribute(h); var attr = metadata.GetCustomAttribute(h);
var type = attr.GetAttributeType(currentModule); var type = attr.GetAttributeType(metadata);
if (type.GetFullTypeName(currentModule).ToString() == "System.Runtime.CompilerServices.ExtensionAttribute") if (type.IsTopLevelType(metadata, "System.Runtime.CompilerServices", "ExtensionAttribute"))
return true; return true;
} }
return false; return false;
@ -1376,11 +1392,11 @@ namespace ICSharpCode.Decompiler.TypeSystem
#endregion #endregion
#region Read Parameter #region Read Parameter
public IUnresolvedParameter ReadParameter(Parameter parameter, ITypeReference type) public IUnresolvedParameter ReadParameter(Parameter parameter, ITypeReference typeRef, SignatureTypeCode type)
{ {
var p = new DefaultUnresolvedParameter(DynamicTypeReference.Create(type, parameter.GetCustomAttributes(), currentMetadata), interningProvider.Intern(currentMetadata.GetString(parameter.Name))); var p = new DefaultUnresolvedParameter(typeRef, interningProvider.Intern(currentMetadata.GetString(parameter.Name)));
if (type is ByReferenceTypeReference) { if (type == SignatureTypeCode.ByReference) {
if ((parameter.Attributes & ParameterAttributes.In) == 0 && (parameter.Attributes & ParameterAttributes.Out) != 0) if ((parameter.Attributes & ParameterAttributes.In) == 0 && (parameter.Attributes & ParameterAttributes.Out) != 0)
p.IsOut = true; p.IsOut = true;
else else
@ -1393,16 +1409,16 @@ namespace ICSharpCode.Decompiler.TypeSystem
if (!constantHandle.IsNil) { if (!constantHandle.IsNil) {
var constant = currentMetadata.GetConstant(constantHandle); var constant = currentMetadata.GetConstant(constantHandle);
var blobReader = currentMetadata.GetBlobReader(constant.Value); var blobReader = currentMetadata.GetBlobReader(constant.Value);
p.DefaultValue = CreateSimpleConstantValue(type, blobReader.ReadConstant(constant.TypeCode)); p.DefaultValue = CreateSimpleConstantValue(typeRef, blobReader.ReadConstant(constant.TypeCode));
} else { } else {
p.DefaultValue = CreateSimpleConstantValue(type, null); p.DefaultValue = CreateSimpleConstantValue(typeRef, null);
} }
} }
if (type is ArrayTypeReference) { if (type == SignatureTypeCode.SZArray) {
foreach (CustomAttributeHandle h in parameter.GetCustomAttributes()) { foreach (CustomAttributeHandle h in parameter.GetCustomAttributes()) {
var att = currentMetadata.GetCustomAttribute(h); var att = currentMetadata.GetCustomAttribute(h);
if (att.GetAttributeType(currentMetadata).GetFullTypeName(currentMetadata).ToString() == typeof(ParamArrayAttribute).FullName) { if (att.IsAttributeType(currentMetadata, "System", "ParamArrayAttribute")) {
p.IsParams = true; p.IsParams = true;
break; break;
} }
@ -1426,55 +1442,28 @@ namespace ICSharpCode.Decompiler.TypeSystem
decimal? TryDecodeDecimalConstantAttribute(CustomAttributeHandle handle) decimal? TryDecodeDecimalConstantAttribute(CustomAttributeHandle handle)
{ {
var attribute = currentMetadata.GetCustomAttribute(handle); var attribute = currentMetadata.GetCustomAttribute(handle);
var attrValue = attribute.DecodeValue(minimalCorlibTypeProvider);
ITypeReference attributeType = ReadTypeReference(attribute.GetAttributeType(currentMetadata)); if (attrValue.FixedArguments.Length != 5)
MethodSignature<ITypeReference> signature;
switch (attribute.Constructor.Kind) {
case HandleKind.MethodDefinition:
var md = currentMetadata.GetMethodDefinition((MethodDefinitionHandle)attribute.Constructor);
signature = md.DecodeSignature(TypeReferenceSignatureDecoder.Instance, default);
break;
case HandleKind.MemberReference:
var mr = currentMetadata.GetMemberReference((MemberReferenceHandle)attribute.Constructor);
Debug.Assert(mr.GetKind() == MemberReferenceKind.Method);
signature = mr.DecodeMethodSignature(TypeReferenceSignatureDecoder.Instance, default);
break;
default:
throw new NotSupportedException();
}
if (signature.RequiredParameterCount != 5)
return null; return null;
var reader = new Implementation.BlobReader(currentMetadata.GetBlobBytes(attribute.Value), null);
if (reader.ReadUInt16() != 0x0001) {
Debug.WriteLine("Unknown blob prolog");
return null;
}
// DecimalConstantAttribute has the arguments (byte scale, byte sign, uint hi, uint mid, uint low) or (byte scale, byte sign, int hi, int mid, int low) // DecimalConstantAttribute has the arguments (byte scale, byte sign, uint hi, uint mid, uint low) or (byte scale, byte sign, int hi, int mid, int low)
// Both of these invoke the Decimal constructor (int lo, int mid, int hi, bool isNegative, byte scale) with explicit argument conversions if required. // Both of these invoke the Decimal constructor (int lo, int mid, int hi, bool isNegative, byte scale) with explicit argument conversions if required.
var ctorArgs = new object[signature.RequiredParameterCount]; if (!(attrValue.FixedArguments[0].Value is byte scale && attrValue.FixedArguments[1].Value is byte sign))
for (int i = 0; i < ctorArgs.Length; i++) { return null;
switch (signature.ParameterTypes[i].Resolve(minimalCorlibContext).FullName) { unchecked {
case "System.Byte": if (attrValue.FixedArguments[2].Value is uint hi
ctorArgs[i] = reader.ReadByte(); && attrValue.FixedArguments[3].Value is uint mid
break; && attrValue.FixedArguments[4].Value is uint lo) {
case "System.Int32": return new decimal((int)lo, (int)mid, (int)hi, sign != 0, scale);
ctorArgs[i] = reader.ReadInt32();
break;
case "System.UInt32":
ctorArgs[i] = unchecked((int)reader.ReadUInt32());
break;
default:
return null;
} }
} }
{
if (!ctorArgs.Select(a => a.GetType()).SequenceEqual(new[] { typeof(byte), typeof(byte), typeof(int), typeof(int), typeof(int) })) if (attrValue.FixedArguments[2].Value is int hi
return null; && attrValue.FixedArguments[3].Value is int mid
&& attrValue.FixedArguments[4].Value is int lo) {
return new decimal((int)ctorArgs[4], (int)ctorArgs[3], (int)ctorArgs[2], (byte)ctorArgs[1] != 0, (byte)ctorArgs[0]); return new decimal(lo, mid, hi, sign != 0, scale);
}
}
return null;
} }
public IUnresolvedField ReadField(FieldDefinitionHandle handle, IUnresolvedTypeDefinition parentType) public IUnresolvedField ReadField(FieldDefinitionHandle handle, IUnresolvedTypeDefinition parentType)
@ -1489,7 +1478,7 @@ namespace ICSharpCode.Decompiler.TypeSystem
f.Accessibility = GetAccessibility(field.Attributes); f.Accessibility = GetAccessibility(field.Attributes);
f.IsReadOnly = (field.Attributes & FieldAttributes.InitOnly) == FieldAttributes.InitOnly; f.IsReadOnly = (field.Attributes & FieldAttributes.InitOnly) == FieldAttributes.InitOnly;
f.IsStatic = (field.Attributes & FieldAttributes.Static) == FieldAttributes.Static; f.IsStatic = (field.Attributes & FieldAttributes.Static) == FieldAttributes.Static;
f.ReturnType = DynamicTypeReference.Create(field.DecodeSignature(TypeReferenceSignatureDecoder.Instance, default), field.GetCustomAttributes(), currentMetadata); f.ReturnType = new FieldTypeReference(handle, currentMetadata, TypeAttributeOptions);
var constantHandle = field.GetDefaultValue(); var constantHandle = field.GetDefaultValue();
if (!constantHandle.IsNil) { if (!constantHandle.IsNil) {
var constant = currentMetadata.GetConstant(constantHandle); var constant = currentMetadata.GetConstant(constantHandle);
@ -1599,37 +1588,23 @@ namespace ICSharpCode.Decompiler.TypeSystem
if (!accessors.Getter.IsNil && !accessors.Setter.IsNil) if (!accessors.Getter.IsNil && !accessors.Setter.IsNil)
p.Accessibility = MergePropertyAccessibility(GetAccessibility(currentMetadata.GetMethodDefinition(accessors.Getter).Attributes), GetAccessibility(currentMetadata.GetMethodDefinition(accessors.Setter).Attributes)); p.Accessibility = MergePropertyAccessibility(GetAccessibility(currentMetadata.GetMethodDefinition(accessors.Getter).Attributes), GetAccessibility(currentMetadata.GetMethodDefinition(accessors.Setter).Attributes));
var signature = property.DecodeSignature(TypeReferenceSignatureDecoder.Instance, default);
p.Getter = ReadMethod(accessors.Getter, parentType, SymbolKind.Accessor, p); p.Getter = ReadMethod(accessors.Getter, parentType, SymbolKind.Accessor, p);
p.Setter = ReadMethod(accessors.Setter, parentType, SymbolKind.Accessor, p); p.Setter = ReadMethod(accessors.Setter, parentType, SymbolKind.Accessor, p);
var parameterHandles = Empty<ParameterHandle>.Array; ParameterHandleCollection? parameterHandles = null;
if (!accessors.Getter.IsNil) { if (!accessors.Getter.IsNil) {
var getter = currentMetadata.GetMethodDefinition(accessors.Getter); var getter = currentMetadata.GetMethodDefinition(accessors.Getter);
parameterHandles = getter.GetParameters().ToArray(); parameterHandles = getter.GetParameters();
} else { } else if (!accessors.Setter.IsNil) {
if (!accessors.Setter.IsNil) { var setter = currentMetadata.GetMethodDefinition(accessors.Setter);
var setter = currentMetadata.GetMethodDefinition(accessors.Setter); parameterHandles = setter.GetParameters();
parameterHandles = setter.GetParameters().ToArray();
}
} }
p.ReturnType = HandleReturnType(parameterHandles.FirstOrDefault(), signature.ReturnType); var signature = property.DecodeSignature(TypeCodeProvider.Instance, default);
var unresolvedSig = new UnresolvedMethodSignature(handle, currentMetadata, TypeAttributeOptions);
int i = 0; var (retType, parameters) = TranslateSignature(signature, unresolvedSig, parameterHandles);
if (signature.RequiredParameterCount > parameterHandles.Length) { p.ReturnType = retType;
foreach (var parameterType in signature.ParameterTypes) { p.Parameters.AddRange(parameters);
p.Parameters.Add(new DefaultUnresolvedParameter(DynamicTypeReference.Create(parameterType, null, currentMetadata), string.Empty));
}
} else {
foreach (var h in parameterHandles) {
var par = currentMetadata.GetParameter(h);
if (par.SequenceNumber > 0 && i < signature.ParameterTypes.Length) {
p.Parameters.Add(ReadParameter(par, signature.ParameterTypes[i]));
i++;
}
}
}
AddAttributes(property, p); AddAttributes(property, p);
var accessor = p.Getter ?? p.Setter; var accessor = p.Getter ?? p.Setter;
@ -1691,14 +1666,6 @@ namespace ICSharpCode.Decompiler.TypeSystem
member.MetadataToken = cecilDefinition; member.MetadataToken = cecilDefinition;
member.ApplyInterningProvider(interningProvider); member.ApplyInterningProvider(interningProvider);
member.Freeze(); member.Freeze();
RegisterCecilObject(member);
}
#endregion
#region Type system translation table
void RegisterCecilObject(IUnresolvedEntity typeSystemObject)
{
OnEntityLoaded?.Invoke(typeSystemObject);
} }
#endregion #endregion
} }

41
ICSharpCode.Decompiler/TypeSystem/SpecializingDecompilerTypeSystem.cs

@ -17,6 +17,8 @@
// DEALINGS IN THE SOFTWARE. // DEALINGS IN THE SOFTWARE.
using System; using System;
using System.Collections.Immutable;
using System.Reflection.Metadata;
using ICSharpCode.Decompiler.Metadata; using ICSharpCode.Decompiler.Metadata;
namespace ICSharpCode.Decompiler.TypeSystem namespace ICSharpCode.Decompiler.TypeSystem
@ -53,18 +55,13 @@ namespace ICSharpCode.Decompiler.TypeSystem
public TypeParameterSubstitution Substitution { public TypeParameterSubstitution Substitution {
get { return substitution; } get { return substitution; }
} }
public IType ResolveFromSignature(ITypeReference typeReference) public IType ResolveAsType(EntityHandle typeReference)
{
return context.ResolveFromSignature(typeReference).AcceptVisitor(substitution);
}
public IType ResolveAsType(System.Reflection.Metadata.EntityHandle typeReference)
{ {
return context.ResolveAsType(typeReference).AcceptVisitor(substitution); return context.ResolveAsType(typeReference).AcceptVisitor(substitution);
} }
public IField ResolveAsField(System.Reflection.Metadata.EntityHandle fieldReference) public IField ResolveAsField(EntityHandle fieldReference)
{ {
IField field = context.ResolveAsField(fieldReference); IField field = context.ResolveAsField(fieldReference);
if (field != null) if (field != null)
@ -72,7 +69,7 @@ namespace ICSharpCode.Decompiler.TypeSystem
return field; return field;
} }
public IMethod ResolveAsMethod(System.Reflection.Metadata.EntityHandle methodReference) public IMethod ResolveAsMethod(EntityHandle methodReference)
{ {
IMethod method = context.ResolveAsMethod(methodReference); IMethod method = context.ResolveAsMethod(methodReference);
if (method != null) if (method != null)
@ -88,12 +85,12 @@ namespace ICSharpCode.Decompiler.TypeSystem
return context.GetSpecializingTypeSystem(newSubstitution); return context.GetSpecializingTypeSystem(newSubstitution);
} }
public System.Reflection.Metadata.MetadataReader GetMetadata() public MetadataReader GetMetadata()
{ {
return context.GetMetadata(); return context.GetMetadata();
} }
public IMember ResolveAsMember(System.Reflection.Metadata.EntityHandle memberReference) public IMember ResolveAsMember(EntityHandle memberReference)
{ {
IMember member = context.ResolveAsMember(memberReference); IMember member = context.ResolveAsMember(memberReference);
if (member != null) if (member != null)
@ -105,5 +102,27 @@ namespace ICSharpCode.Decompiler.TypeSystem
{ {
return context.GetModuleDefinition(assembly); return context.GetModuleDefinition(assembly);
} }
MethodSignature<IType> IDecompilerTypeSystem.DecodeMethodSignature(StandaloneSignatureHandle standaloneSignatureHandle)
{
var sig = context.DecodeMethodSignature(standaloneSignatureHandle);
return new MethodSignature<IType>(
sig.Header,
sig.ReturnType.AcceptVisitor(substitution),
sig.RequiredParameterCount,
sig.GenericParameterCount,
ImmutableArray.CreateRange(
sig.ParameterTypes, t => t.AcceptVisitor(substitution)
)
);
}
ImmutableArray<IType> IDecompilerTypeSystem.DecodeLocalSignature(StandaloneSignatureHandle standaloneSignatureHandle)
{
var sig = context.DecodeLocalSignature(standaloneSignatureHandle);
return ImmutableArray.CreateRange(
sig, t => t.AcceptVisitor(substitution)
);
}
} }
} }

166
ICSharpCode.Decompiler/TypeSystem/TypeProvider.cs

@ -0,0 +1,166 @@
// Copyright (c) 2018 Daniel Grunwald
//
// 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.Immutable;
using System.Reflection.Metadata.Ecma335;
using ICSharpCode.Decompiler.Metadata;
using ICSharpCode.Decompiler.TypeSystem.Implementation;
using SRM = System.Reflection.Metadata;
namespace ICSharpCode.Decompiler.TypeSystem
{
/// <summary>
/// Allows decoding signatures using decompiler types.
/// </summary>
class TypeProvider : SRM.ISignatureTypeProvider<IType, ITypeResolveContext>, SRM.ICustomAttributeTypeProvider<IType>
{
readonly IAssembly assembly;
readonly ICompilation compilation;
public TypeProvider(IAssembly assembly)
{
this.assembly = assembly;
this.compilation = assembly.Compilation;
}
public IType GetArrayType(IType elementType, SRM.ArrayShape shape)
{
return new ArrayType(compilation, elementType, shape.Rank);
}
public IType GetByReferenceType(IType elementType)
{
return new ByReferenceType(elementType);
}
public IType GetFunctionPointerType(SRM.MethodSignature<IType> signature)
{
return compilation.FindType(KnownTypeCode.IntPtr);
}
public IType GetGenericInstantiation(IType genericType, ImmutableArray<IType> typeArguments)
{
return new ParameterizedType(genericType, typeArguments);
}
public IType GetGenericMethodParameter(ITypeResolveContext genericContext, int index)
{
// Note: returning type parameter, never type argument.
// Otherwise we risk screwing up the counting for dynamicTypeIndex.
IMethod method = genericContext.CurrentMember as IMethod;
if (method != null && index < method.TypeParameters.Count) {
return method.TypeParameters[index];
}
return DummyTypeParameter.GetMethodTypeParameter(index);
}
public IType GetGenericTypeParameter(ITypeResolveContext genericContext, int index)
{
ITypeDefinition typeDef = genericContext.CurrentTypeDefinition;
if (typeDef != null && index < typeDef.TypeParameters.Count) {
return typeDef.TypeParameters[index];
}
return DummyTypeParameter.GetClassTypeParameter(index);
}
public IType GetModifiedType(IType modifier, IType unmodifiedType, bool isRequired)
{
return unmodifiedType;
}
public IType GetPinnedType(IType elementType)
{
return new PinnedType(elementType);
}
public IType GetPointerType(IType elementType)
{
return new PointerType(elementType);
}
public IType GetPrimitiveType(SRM.PrimitiveTypeCode typeCode)
{
return compilation.FindType(typeCode.ToKnownTypeCode());
}
public IType GetSystemType()
{
return compilation.FindType(KnownTypeCode.Type);
}
public IType GetSZArrayType(IType elementType)
{
return new ArrayType(compilation, elementType);
}
public IType GetTypeFromDefinition(SRM.MetadataReader reader, SRM.TypeDefinitionHandle handle, byte rawTypeKind)
{
ITypeDefinition td = assembly.ResolveTypeDefToken(handle);
if (td != null)
return td;
return SpecialType.UnknownType;
}
public IType GetTypeFromReference(SRM.MetadataReader reader, SRM.TypeReferenceHandle handle, byte rawTypeKind)
{
var asmref = handle.GetDeclaringAssembly(reader);
IAssemblyReference nrAsmRef;
if (asmref.IsNil)
nrAsmRef = DefaultAssemblyReference.CurrentAssembly;
else
nrAsmRef = new DefaultAssemblyReference(reader.GetString(reader.GetAssemblyReference(asmref).Name));
bool? isReferenceType = null;
switch (reader.ResolveSignatureTypeKind(handle, rawTypeKind)) {
case SRM.SignatureTypeKind.ValueType:
isReferenceType = false;
break;
case SRM.SignatureTypeKind.Class:
isReferenceType = true;
break;
}
var gctr = new GetClassTypeReference(handle.GetFullTypeName(reader), nrAsmRef, isReferenceType);
return gctr.Resolve(new SimpleTypeResolveContext(assembly));
}
public IType GetTypeFromSerializedName(string name)
{
// TODO: aren't we missing support for assembly-qualified names?
return new GetClassTypeReference(new FullTypeName(name))
.Resolve(new SimpleTypeResolveContext(assembly));
}
public IType GetTypeFromSpecification(SRM.MetadataReader reader, ITypeResolveContext genericContext, SRM.TypeSpecificationHandle handle, byte rawTypeKind)
{
return reader.GetTypeSpecification(handle).DecodeSignature(this, genericContext);
}
public SRM.PrimitiveTypeCode GetUnderlyingEnumType(IType type)
{
var def = type.GetEnumUnderlyingType().GetDefinition();
if (def == null)
throw new InvalidOperationException();
return def.KnownTypeCode.ToPrimitiveTypeCode();
}
public bool IsSystemType(IType type)
{
return type.IsKnownType(KnownTypeCode.Type);
}
}
}

39
ILSpy/Languages/CSharpLanguage.cs

@ -586,7 +586,7 @@ namespace ICSharpCode.ILSpy
var st = new SyntaxTree(); var st = new SyntaxTree();
st.AddChild(astType, Roles.Type); st.AddChild(astType, Roles.Type);
st.AcceptVisitor(new InsertDynamicTypeVisitor(metadata, customAttributes)); //st.AcceptVisitor(new InsertDynamicTypeVisitor(metadata, customAttributes));
st.FirstChild.AcceptVisitor(new CSharpOutputVisitor(w, TypeToStringFormattingOptions)); st.FirstChild.AcceptVisitor(new CSharpOutputVisitor(w, TypeToStringFormattingOptions));
return w.ToString(); return w.ToString();
} }
@ -788,41 +788,4 @@ namespace ICSharpCode.ILSpy
return info; return info;
} }
} }
class InsertDynamicTypeVisitor : DepthFirstAstVisitor
{
bool isDynamic;
bool[] mapping;
int typeIndex;
public InsertDynamicTypeVisitor(MetadataReader metadata, CustomAttributeHandleCollection? customAttributes)
{
isDynamic = DynamicTypeReference.HasDynamicAttribute(customAttributes, metadata, out mapping);
}
public override void VisitComposedType(ComposedType composedType)
{
typeIndex++;
base.VisitComposedType(composedType);
}
public override void VisitPrimitiveType(PrimitiveType primitiveType)
{
if (isDynamic && primitiveType.KnownTypeCode == KnownTypeCode.Object && (mapping == null || typeIndex >= mapping.Length || mapping[typeIndex])) {
primitiveType.ReplaceWith(new SimpleType("dynamic"));
} else {
base.VisitPrimitiveType(primitiveType);
}
}
public override void VisitMemberType(MemberType memberType)
{
base.VisitMemberType(memberType);
}
public override void VisitSimpleType(SimpleType simpleType)
{
base.VisitSimpleType(simpleType);
}
}
} }

2
ILSpy/TreeNodes/Analyzer/ScopedWhereUsedAnalyzer.cs

@ -38,7 +38,6 @@ namespace ICSharpCode.ILSpy.TreeNodes.Analyzer
readonly bool provideTypeSystem; readonly bool provideTypeSystem;
TypeDefinitionHandle typeScopeHandle; TypeDefinitionHandle typeScopeHandle;
TypeDefinition typeScope; TypeDefinition typeScope;
static readonly TypeSystemAttributeTypeProvider typeProvider = TypeSystemAttributeTypeProvider.CreateDefault();
readonly Accessibility memberAccessibility = Accessibility.Public; readonly Accessibility memberAccessibility = Accessibility.Public;
Accessibility typeAccessibility = Accessibility.Public; Accessibility typeAccessibility = Accessibility.Public;
@ -305,6 +304,7 @@ namespace ICSharpCode.ILSpy.TreeNodes.Analyzer
string typeScopeNamespace = metadata.GetString(typeScope.Namespace); string typeScopeNamespace = metadata.GetString(typeScope.Namespace);
string typeScopeName = metadata.GetString(typeScope.Name); string typeScopeName = metadata.GetString(typeScope.Name);
var typeProvider = Decompiler.Metadata.MetadataExtensions.MinimalAttributeTypeProvider;
var attributes = metadata.CustomAttributes.Select(h => metadata.GetCustomAttribute(h)).Where(ca => ca.GetAttributeType(metadata).GetFullTypeName(metadata).ToString() == "System.Runtime.CompilerServices.InternalsVisibleToAttribute"); var attributes = metadata.CustomAttributes.Select(h => metadata.GetCustomAttribute(h)).Where(ca => ca.GetAttributeType(metadata).GetFullTypeName(metadata).ToString() == "System.Runtime.CompilerServices.InternalsVisibleToAttribute");
var friendAssemblies = new HashSet<string>(); var friendAssemblies = new HashSet<string>();
foreach (var attribute in attributes) { foreach (var attribute in attributes) {

Loading…
Cancel
Save