private bool FindMatchingInterfaceSlot(IntPtr moduleHandle, NativeReader nativeLayoutReader, ref NativeParser entryParser, ref ExternalReferencesTable extRefs, ref RuntimeTypeHandle declaringType, ref MethodNameAndSignature methodNameAndSignature, RuntimeTypeHandle openTargetTypeHandle, RuntimeTypeHandle[] targetTypeInstantiation, bool variantDispatch) { uint numTargetImplementations = entryParser.GetUnsigned(); for (uint j = 0; j < numTargetImplementations; j++) { uint nameAndSigToken = extRefs.GetRvaFromIndex(entryParser.GetUnsigned()); MethodNameAndSignature targetMethodNameAndSignature = GetMethodNameAndSignatureFromNativeReader(nativeLayoutReader, nameAndSigToken); RuntimeTypeHandle targetTypeHandle = extRefs.GetRuntimeTypeHandleFromIndex(entryParser.GetUnsigned()); #if REFLECTION_EXECUTION_TRACE ReflectionExecutionLogger.WriteLine(" Searching for GVM implementation on targe type = " + GetTypeNameDebug(targetTypeHandle)); #endif uint numIfaceImpls = entryParser.GetUnsigned(); for (uint k = 0; k < numIfaceImpls; k++) { RuntimeTypeHandle implementingTypeHandle = extRefs.GetRuntimeTypeHandleFromIndex(entryParser.GetUnsigned()); uint numIfaceSigs = entryParser.GetUnsigned(); if (!openTargetTypeHandle.Equals(implementingTypeHandle)) { // Skip over signatures data for (uint l = 0; l < numIfaceSigs; l++) entryParser.GetUnsigned(); continue; } for (uint l = 0; l < numIfaceSigs; l++) { RuntimeTypeHandle currentIfaceTypeHandle = default(RuntimeTypeHandle); NativeParser ifaceSigParser = new NativeParser(nativeLayoutReader, extRefs.GetRvaFromIndex(entryParser.GetUnsigned())); IntPtr currentIfaceSigPtr = ifaceSigParser.Reader.OffsetToAddress(ifaceSigParser.Offset); if (TypeLoaderEnvironment.Instance.GetTypeFromSignatureAndContext(currentIfaceSigPtr, targetTypeInstantiation, null, out currentIfaceTypeHandle, out currentIfaceSigPtr)) { Debug.Assert(!currentIfaceTypeHandle.IsNull()); if ((!variantDispatch && declaringType.Equals(currentIfaceTypeHandle)) || (variantDispatch && RuntimeAugments.IsAssignableFrom(declaringType, currentIfaceTypeHandle))) { #if REFLECTION_EXECUTION_TRACE ReflectionExecutionLogger.WriteLine(" " + (declaringType.Equals(currentIfaceTypeHandle) ? "Exact" : "Variant-compatible") + " match found on this target type!"); #endif // We found the GVM slot target for the input interface GVM call, so let's update the interface GVM slot and return success to the caller declaringType = targetTypeHandle; methodNameAndSignature = targetMethodNameAndSignature; return true; } } } } } return false; }
private TypeDesc GetInstantiationType(ref NativeParser parser, uint arity) { DefType typeDefinition = (DefType)GetType(ref parser); TypeDesc[] typeArguments = new TypeDesc[arity]; for (uint i = 0; i < arity; i++) typeArguments[i] = GetType(ref parser); return _typeSystemContext.ResolveGenericInstantiation(typeDefinition, new Instantiation(typeArguments)); }
private MethodNameAndSignature GetMethodNameAndSignatureFromNativeReader(NativeReader nativeLayoutReader, uint nativeLayoutOffset) { NativeParser parser = new NativeParser(nativeLayoutReader, nativeLayoutOffset); string methodName = parser.GetString(); // Signatures are indirected to through a relative offset so that we don't have to parse them // when not comparing signatures (parsing them requires resolving types and is tremendously // expensive). NativeParser sigParser = parser.GetParserFromRelativeOffset(); IntPtr methodSigPtr = sigParser.Reader.OffsetToAddress(sigParser.Offset); return new MethodNameAndSignature(methodName, RuntimeMethodSignature.CreateFromNativeLayoutSignature(methodSigPtr)); }
public bool CompareMethodSignatures(RuntimeMethodSignature signature1, RuntimeMethodSignature signature2) { IntPtr nativeLayoutSignature1 = signature1.NativeLayoutSignature; IntPtr nativeLayoutSignature2 = signature2.NativeLayoutSignature; if ((nativeLayoutSignature1 != IntPtr.Zero) && (nativeLayoutSignature2 != IntPtr.Zero)) { if (nativeLayoutSignature1 == nativeLayoutSignature2) return true; NativeReader reader1 = GetNativeLayoutInfoReader(RuntimeAugments.GetModuleFromPointer(nativeLayoutSignature1)); NativeParser parser1 = new NativeParser(reader1, reader1.AddressToOffset(nativeLayoutSignature1)); NativeReader reader2 = GetNativeLayoutInfoReader(RuntimeAugments.GetModuleFromPointer(nativeLayoutSignature2)); NativeParser parser2 = new NativeParser(reader2, reader2.AddressToOffset(nativeLayoutSignature2)); return CompareMethodSigs(parser1, parser2); } else if (nativeLayoutSignature1 != IntPtr.Zero) { int token = signature2.Token; MetadataReader metadataReader = ModuleList.Instance.GetMetadataReaderForModule(signature2.ModuleHandle); MethodSignatureComparer comparer = new MethodSignatureComparer(metadataReader, token.AsHandle().ToMethodHandle(metadataReader)); return comparer.IsMatchingNativeLayoutMethodSignature(nativeLayoutSignature1); } else if (nativeLayoutSignature2 != IntPtr.Zero) { int token = signature1.Token; MetadataReader metadataReader = ModuleList.Instance.GetMetadataReaderForModule(signature1.ModuleHandle); MethodSignatureComparer comparer = new MethodSignatureComparer(metadataReader, token.AsHandle().ToMethodHandle(metadataReader)); return comparer.IsMatchingNativeLayoutMethodSignature(nativeLayoutSignature2); } else { // For now, RuntimeMethodSignatures are only used to compare for method signature equality (along with their Name) // So we can implement this with the simple equals check if (signature1.Token != signature2.Token) return false; if (signature1.ModuleHandle != signature2.ModuleHandle) return false; return true; } }
private TypeDesc GetModifierType(ref NativeParser parser, TypeModifierKind modifier) { TypeDesc typeParameter = GetType(ref parser); switch (modifier) { case TypeModifierKind.Array: return _typeSystemContext.GetArrayType(typeParameter); case TypeModifierKind.ByRef: return _typeSystemContext.GetByRefType(typeParameter); case TypeModifierKind.Pointer: return _typeSystemContext.GetPointerType(typeParameter); default: parser.ThrowBadImageFormatException(); return null; } }
public uint GetGenericArgumentCountFromMethodNameAndSignature(MethodNameAndSignature signature) { if (signature.Signature.IsNativeLayoutSignature) { IntPtr sigPtr = signature.Signature.NativeLayoutSignature; NativeReader reader = GetNativeLayoutInfoReader(RuntimeAugments.GetModuleFromPointer(sigPtr)); NativeParser parser = new NativeParser(reader, reader.AddressToOffset(sigPtr)); return GetGenericArgCountFromSig(parser); } else { var metadataReader = ModuleList.Instance.GetMetadataReaderForModule(signature.Signature.ModuleHandle); var methodHandle = signature.Signature.Token.AsHandle().ToMethodHandle(metadataReader); var method = methodHandle.GetMethod(metadataReader); var methodSignature = method.Signature.GetMethodSignature(metadataReader); return checked((uint)methodSignature.GenericParameterCount); } }
public unsafe bool TryGetMetadataForNamedType(RuntimeTypeHandle runtimeTypeHandle, out MetadataReader metadataReader, out TypeDefinitionHandle typeDefHandle) { // Iterate over all modules, starting with the module that defines the EEType foreach (IntPtr moduleHandle in ModuleList.Enumerate(RuntimeAugments.GetModuleFromTypeHandle(runtimeTypeHandle))) { NativeReader typeMapReader; if (TryGetNativeReaderForBlob(moduleHandle, ReflectionMapBlob.TypeMap, out typeMapReader)) { NativeParser typeMapParser = new NativeParser(typeMapReader, 0); NativeHashtable typeHashtable = new NativeHashtable(typeMapParser); ExternalReferencesTable externalReferences = default(ExternalReferencesTable); externalReferences.InitializeCommonFixupsTable(moduleHandle); var lookup = typeHashtable.Lookup(runtimeTypeHandle.GetHashCode()); NativeParser entryParser; while (!(entryParser = lookup.GetNext()).IsNull) { RuntimeTypeHandle foundType = externalReferences.GetRuntimeTypeHandleFromIndex(entryParser.GetUnsigned()); if (foundType.Equals(runtimeTypeHandle)) { Handle entryMetadataHandle = entryParser.GetUnsigned().AsHandle(); if (entryMetadataHandle.HandleType == HandleType.TypeDefinition) { metadataReader = ModuleList.Instance.GetMetadataReaderForModule(moduleHandle); typeDefHandle = entryMetadataHandle.ToTypeDefinitionHandle(metadataReader); return true; } } } } } metadataReader = null; typeDefHandle = default(TypeDefinitionHandle); return false; }
/// <summary> /// IF THESE SEMANTICS EVER CHANGE UPDATE THE LOGIC WHICH DEFINES THIS BEHAVIOR IN /// THE DYNAMIC TYPE LOADER AS WELL AS THE COMPILER. /// /// Parameter's are considered to have type layout dependent on their generic instantiation /// if the type of the parameter in its signature is a type variable, or if the type is a generic /// structure which meets 2 characteristics: /// 1. Structure size/layout is affected by the size/layout of one or more of its generic parameters /// 2. One or more of the generic parameters is a type variable, or a generic structure which also recursively /// would satisfy constraint 2. (Note, that in the recursion case, whether or not the structure is affected /// by the size/layout of its generic parameters is not investigated.) /// /// Examples parameter types, and behavior. /// /// T -> true /// List<T> -> false /// StructNotDependentOnArgsForSize<T> -> false /// GenStructDependencyOnArgsForSize<T> -> true /// StructNotDependentOnArgsForSize<GenStructDependencyOnArgsForSize<T>> -> true /// StructNotDependentOnArgsForSize<GenStructDependencyOnArgsForSize<List<T>>>> -> false /// /// Example non-parameter type behavior /// T -> true /// List<T> -> false /// StructNotDependentOnArgsForSize<T> -> *true* /// GenStructDependencyOnArgsForSize<T> -> true /// StructNotDependentOnArgsForSize<GenStructDependencyOnArgsForSize<T>> -> true /// StructNotDependentOnArgsForSize<GenStructDependencyOnArgsForSize<List<T>>>> -> false /// </summary> private bool TypeSignatureHasVarsNeedingCallingConventionConverter(ref NativeParser parser, TypeSystemContext context, HasVarsInvestigationLevel investigationLevel) { uint data; var kind = parser.GetTypeSignatureKind(out data); switch (kind) { case TypeSignatureKind.External: return false; case TypeSignatureKind.Variable: return true; case TypeSignatureKind.Lookback: { var lookbackParser = parser.GetLookbackParser(data); return TypeSignatureHasVarsNeedingCallingConventionConverter(ref lookbackParser, context, investigationLevel); } case TypeSignatureKind.Instantiation: { RuntimeTypeHandle genericTypeDef; if (!TryGetTypeFromSimpleTypeSignature(ref parser, out genericTypeDef)) { Debug.Assert(false); return true; // Returning true will prevent further reading from the native parser } if (!RuntimeAugments.IsValueType(genericTypeDef)) { // Reference types are treated like pointers. No calling convention conversion needed. Just consume the rest of the signature. for (uint i = 0; i < data; i++) TypeSignatureHasVarsNeedingCallingConventionConverter(ref parser, context, HasVarsInvestigationLevel.Ignore); return false; } else { bool result = false; for (uint i = 0; i < data; i++) result = TypeSignatureHasVarsNeedingCallingConventionConverter(ref parser, context, HasVarsInvestigationLevel.NotParameter) || result; if ((result == true) && (investigationLevel == HasVarsInvestigationLevel.Parameter)) { if (!TryComputeHasInstantiationDeterminedSize(genericTypeDef, context, out result)) Environment.FailFast("Unable to setup calling convention converter correctly"); return result; } return result; } } case TypeSignatureKind.Modifier: { // Arrays, pointers and byref types signatures are treated as pointers, not requiring calling convention conversion. // Just consume the parameter type from the stream and return false; TypeSignatureHasVarsNeedingCallingConventionConverter(ref parser, context, HasVarsInvestigationLevel.Ignore); return false; } case TypeSignatureKind.MultiDimArray: { // No need for a calling convention converter for this case. Just consume the signature from the stream. TypeSignatureHasVarsNeedingCallingConventionConverter(ref parser, context, HasVarsInvestigationLevel.Ignore); uint boundCount = parser.GetUnsigned(); for (uint i = 0; i < boundCount; i++) parser.GetUnsigned(); uint lowerBoundCount = parser.GetUnsigned(); for (uint i = 0; i < lowerBoundCount; i++) parser.GetUnsigned(); } return false; case TypeSignatureKind.FunctionPointer: { // No need for a calling convention converter for this case. Just consume the signature from the stream. uint argCount = parser.GetUnsigned(); for (uint i = 0; i < argCount; i++) TypeSignatureHasVarsNeedingCallingConventionConverter(ref parser, context, HasVarsInvestigationLevel.Ignore); } return false; default: parser.ThrowBadImageFormatException(); return true; } }
private bool MethodSignatureHasVarsNeedingCallingConventionConverter_NativeLayout(TypeSystemContext context, IntPtr methodSig) { IntPtr moduleHandle = RuntimeAugments.GetModuleFromPointer(methodSig); NativeReader reader = GetNativeLayoutInfoReader(moduleHandle); NativeParser parser = new NativeParser(reader, reader.AddressToOffset(methodSig)); MethodCallingConvention callingConvention = (MethodCallingConvention)parser.GetUnsigned(); uint numGenArgs = callingConvention.HasFlag(MethodCallingConvention.Generic) ? parser.GetUnsigned() : 0; uint parameterCount = parser.GetUnsigned(); // Check the return type of the method if (TypeSignatureHasVarsNeedingCallingConventionConverter(ref parser, context, HasVarsInvestigationLevel.Parameter)) return true; // Check the parameters of the method for (uint i = 0; i < parameterCount; i++) { if (TypeSignatureHasVarsNeedingCallingConventionConverter(ref parser, context, HasVarsInvestigationLevel.Parameter)) return true; } return false; }
public NativeHashtable(NativeParser parser) { uint header = parser.GetUInt8(); _reader = parser.Reader; _baseOffset = parser.Offset; int numberOfBucketsShift = (int)(header >> 2); if (numberOfBucketsShift > 31) _reader.ThrowBadImageFormatException(); _bucketMask = (uint)((1 << numberOfBucketsShift) - 1); byte entryIndexSize = (byte)(header & 3); if (entryIndexSize > 2) _reader.ThrowBadImageFormatException(); _entryIndexSize = entryIndexSize; }
internal bool GetCallingConverterDataFromMethodSignature_NativeLayout(TypeSystemContext context, IntPtr methodSig, NativeLayoutInfoLoadContext nativeLayoutContext, out bool hasThis, out TypeDesc[] parameters, out bool[] parametersWithGenericDependentLayout) { hasThis = false; parameters = null; IntPtr moduleHandle = RuntimeAugments.GetModuleFromPointer(methodSig); NativeReader reader = GetNativeLayoutInfoReader(moduleHandle); NativeParser parser = new NativeParser(reader, reader.AddressToOffset(methodSig)); MethodCallingConvention callingConvention = (MethodCallingConvention)parser.GetUnsigned(); hasThis = !callingConvention.HasFlag(MethodCallingConvention.Static); uint numGenArgs = callingConvention.HasFlag(MethodCallingConvention.Generic) ? parser.GetUnsigned() : 0; uint parameterCount = parser.GetUnsigned(); parameters = new TypeDesc[parameterCount + 1]; parametersWithGenericDependentLayout = new bool[parameterCount + 1]; // One extra parameter to account for the return type for (uint i = 0; i <= parameterCount; i++) { // NativeParser is a struct, so it can be copied. NativeParser parserCopy = parser; // Parse the signature twice. The first time to find out the exact type of the signature // The second time to identify if the parameter loaded via the signature should be forced to be // passed byref as part of the universal generic calling convention. parameters[i] = GetConstructedTypeFromParserAndNativeLayoutContext(ref parser, nativeLayoutContext); parametersWithGenericDependentLayout[i] = TypeSignatureHasVarsNeedingCallingConventionConverter(ref parserCopy, context, HasVarsInvestigationLevel.Parameter); if (parameters[i] == null) return false; } return true; }
private uint GetGenericArgCountFromSig(NativeParser parser) { MethodCallingConvention callingConvention = (MethodCallingConvention)parser.GetUnsigned(); if ((callingConvention & MethodCallingConvention.Generic) == MethodCallingConvention.Generic) { return parser.GetUnsigned(); } else { return 0; } }
private bool CompareTypeSigs(ref NativeParser parser1, ref NativeParser parser2) { // startOffset lets us backtrack to the TypeSignatureKind for external types since the TypeLoader // expects to read it in. uint data1; uint startOffset1 = parser1.Offset; var typeSignatureKind1 = parser1.GetTypeSignatureKind(out data1); // If the parser is at a lookback type, get a new parser for it and recurse. // Since we haven't read the element type of parser2 yet, we just pass it in unchanged if (typeSignatureKind1 == TypeSignatureKind.Lookback) { NativeParser lookbackParser1 = parser1.GetLookbackParser(data1); return CompareTypeSigs(ref lookbackParser1, ref parser2); } uint data2; uint startOffset2 = parser2.Offset; var typeSignatureKind2 = parser2.GetTypeSignatureKind(out data2); // If parser2 is a lookback type, we need to rewind parser1 to its startOffset1 // before recursing. if (typeSignatureKind2 == TypeSignatureKind.Lookback) { NativeParser lookbackParser2 = parser2.GetLookbackParser(data2); parser1 = new NativeParser(parser1.Reader, startOffset1); return CompareTypeSigs(ref parser1, ref lookbackParser2); } if (typeSignatureKind1 != typeSignatureKind2) return false; switch (typeSignatureKind1) { case TypeSignatureKind.Lookback: { // Recursion above better have removed all lookbacks Debug.Assert(false, "Unexpected lookback type"); return false; } case TypeSignatureKind.Modifier: { // Ensure the modifier kind (vector, pointer, byref) is the same if (data1 != data2) return false; return CompareTypeSigs(ref parser1, ref parser2); } case TypeSignatureKind.Variable: { // variable index is in data if (data1 != data2) return false; break; } case TypeSignatureKind.MultiDimArray: { // rank is in data if (data1 != data2) return false; if (!CompareTypeSigs(ref parser1, ref parser2)) return false; uint boundCount1 = parser1.GetUnsigned(); uint boundCount2 = parser2.GetUnsigned(); if (boundCount1 != boundCount2) return false; for (uint i = 0; i < boundCount1; i++) { if (parser1.GetUnsigned() != parser2.GetUnsigned()) return false; } uint lowerBoundCount1 = parser1.GetUnsigned(); uint lowerBoundCount2 = parser2.GetUnsigned(); if (lowerBoundCount1 != lowerBoundCount2) return false; for (uint i = 0; i < lowerBoundCount1; i++) { if (parser1.GetUnsigned() != parser2.GetUnsigned()) return false; } break; } case TypeSignatureKind.FunctionPointer: { // callingConvention is in data if (data1 != data2) return false; uint argCount1 = parser1.GetUnsigned(); uint argCount2 = parser2.GetUnsigned(); if (argCount1 != argCount2) return false; for (uint i = 0; i < argCount1; i++) { if (!CompareTypeSigs(ref parser1, ref parser2)) return false; } break; } case TypeSignatureKind.Instantiation: { // Type parameter count is in data if (data1 != data2) return false; if (!CompareTypeSigs(ref parser1, ref parser2)) return false; for (uint i = 0; i < data1; i++) { if (!CompareTypeSigs(ref parser1, ref parser2)) return false; } break; } case TypeSignatureKind.External: { RuntimeTypeHandle typeHandle1 = GetExternalTypeHandle(ref parser1, data1); RuntimeTypeHandle typeHandle2 = GetExternalTypeHandle(ref parser2, data2); if (!typeHandle1.Equals(typeHandle2)) return false; break; } default: return false; } return true; }
public unsafe bool TryGetNamedTypeForMetadata(MetadataReader metadataReader, TypeDefinitionHandle typeDefHandle, out RuntimeTypeHandle runtimeTypeHandle) { int hashCode = typeDefHandle.ComputeHashCode(metadataReader); IntPtr moduleHandle = ModuleList.Instance.GetModuleForMetadataReader(metadataReader); NativeReader typeMapReader; if (TryGetNativeReaderForBlob(moduleHandle, ReflectionMapBlob.TypeMap, out typeMapReader)) { NativeParser typeMapParser = new NativeParser(typeMapReader, 0); NativeHashtable typeHashtable = new NativeHashtable(typeMapParser); ExternalReferencesTable externalReferences = default(ExternalReferencesTable); externalReferences.InitializeCommonFixupsTable(moduleHandle); var lookup = typeHashtable.Lookup(hashCode); NativeParser entryParser; while (!(entryParser = lookup.GetNext()).IsNull) { var foundTypeIndex = entryParser.GetUnsigned(); if (entryParser.GetUnsigned().AsHandle().Equals(typeDefHandle)) { runtimeTypeHandle = externalReferences.GetRuntimeTypeHandleFromIndex(foundTypeIndex); return true; } } } runtimeTypeHandle = default(RuntimeTypeHandle); return false; }
public bool TryGetMethodNameAndSignatureFromNativeLayoutSignature(ref IntPtr signature, out MethodNameAndSignature nameAndSignature) { nameAndSignature = null; NativeReader reader = GetNativeLayoutInfoReader(RuntimeAugments.GetModuleFromPointer(signature)); uint offset = reader.AddressToOffset(signature); NativeParser parser = new NativeParser(reader, offset); if (parser.IsNull) return false; IntPtr methodSigPtr; IntPtr methodNameSigPtr; nameAndSignature = GetMethodNameAndSignature(ref parser, out methodNameSigPtr, out methodSigPtr); signature = (IntPtr)((long)signature + (parser.Offset - offset)); return true; }
private bool ResolveInterfaceGenericVirtualMethodSlot_Static(RuntimeTypeHandle targetTypeHandle, ref RuntimeTypeHandle declaringType, ref MethodNameAndSignature methodNameAndSignature) { // Get the open type definition of the containing type of the generic virtual method being resolved RuntimeTypeHandle openCallingTypeHandle = GetTypeDefinition(declaringType); // Get the open type definition of the current type of the object instance on which the GVM is being resolved RuntimeTypeHandle openTargetTypeHandle; RuntimeTypeHandle[] targetTypeInstantiation; openTargetTypeHandle = GetOpenTypeDefinition(targetTypeHandle, out targetTypeInstantiation); #if REFLECTION_EXECUTION_TRACE ReflectionExecutionLogger.WriteLine("INTERFACE GVM call = " + GetTypeNameDebug(declaringType) + "." + methodNameAndSignature.Name); #endif foreach (IntPtr moduleHandle in ModuleList.Enumerate(RuntimeAugments.GetModuleFromTypeHandle(openTargetTypeHandle))) { NativeReader gvmTableReader; if (!TryGetNativeReaderForBlob(moduleHandle, ReflectionMapBlob.InterfaceGenericVirtualMethodTable, out gvmTableReader)) continue; NativeReader nativeLayoutReader; if (!TryGetNativeReaderForBlob(moduleHandle, ReflectionMapBlob.NativeLayoutInfo, out nativeLayoutReader)) continue; NativeParser gvmTableParser = new NativeParser(gvmTableReader, 0); NativeHashtable gvmHashtable = new NativeHashtable(gvmTableParser); ExternalReferencesTable extRefs = default(ExternalReferencesTable); extRefs.InitializeCommonFixupsTable(moduleHandle); var lookup = gvmHashtable.Lookup(openCallingTypeHandle.GetHashCode()); NativeParser entryParser; while (!(entryParser = lookup.GetNext()).IsNull) { RuntimeTypeHandle interfaceTypeHandle = extRefs.GetRuntimeTypeHandleFromIndex(entryParser.GetUnsigned()); if (!openCallingTypeHandle.Equals(interfaceTypeHandle)) continue; uint nameAndSigToken = extRefs.GetRvaFromIndex(entryParser.GetUnsigned()); MethodNameAndSignature interfaceMethodNameAndSignature = GetMethodNameAndSignatureFromNativeReader(nativeLayoutReader, nameAndSigToken); if (!interfaceMethodNameAndSignature.Equals(methodNameAndSignature)) continue; // For each of the possible GVM slot targets for the current interface call, we will do the following: // // Step 1: Scan the types that currently provide implementations for the current GVM slot target, and look // for ones that match the target object's type. // // Step 2: For each type that we find in step #1, get a list of all the interfaces that the current GVM target // provides an implementation for // // Step 3: For each interface in the list in step #2, parse the signature of that interface, do the generic argument // substitution (in case of a generic interface), and check if this interface signature is assignable from the // calling interface signature (from the name and sig input). if there is an exact match based on // interface type, then we've found the right slot. Otherwise, re-scan the entry again and see if some interface // type is compatible with the initial slots interface by means of variance. // This is done by calling the TypeLoaderEnvironment helper function. // // Example: // public interface IFoo<out T, out U> // { // string M1<V>(); // } // public class Foo1<T, U> : IFoo<T, U>, IFoo<Kvp<T, string>, U> // { // string IFoo<T, U>.M1<V>() { ... } // public virtual string M1<V>() { ... } // } // public class Foo2<T, U> : Foo1<object, U>, IFoo<U, T> // { // string IFoo<U, T>.M1<V>() { ... } // } // // GVM Table layout for IFoo<T, U>.M1<V>: // { // InterfaceTypeHandle = IFoo<T, U> // InterfaceMethodNameAndSignature = { "M1", SigOf(string M1) } // GVMTargetSlots[] = // { // { // TargetMethodNameAndSignature = { "M1", SigOf(M1) } // TargetTypeHandle = Foo1<T, U> // ImplementingTypes[] = { // ImplementingTypeHandle = Foo1<T, U> // ImplementedInterfacesSignatures[] = { SigOf(IFoo<!0, !1>) } // } // }, // // { // TargetMethodNameAndSignature = { "M1", SigOf(M1) } // TargetTypeHandle = Foo1<T, U> // ImplementingTypes[] = { // ImplementingTypeHandle = Foo1<T, U> // ImplementedInterfacesSignatures[] = { SigOf(IFoo<Kvp<!0, string>, !1>) } // } // }, // // { // TargetMethodNameAndSignature = { "M1", SigOf(M1) } // TargetTypeHandle = Foo2<T, U> // ImplementingTypes = { // ImplementingTypeHandle = Foo2<T, U> // ImplementedInterfacesSignatures[] = { SigOf(IFoo<!1, !0>) } // } // }, // } // } // uint currentOffset = entryParser.Offset; // Non-variant dispatch of a variant generic interface generic virtual method. if (FindMatchingInterfaceSlot(moduleHandle, nativeLayoutReader, ref entryParser, ref extRefs, ref declaringType, ref methodNameAndSignature, openTargetTypeHandle, targetTypeInstantiation, false)) { return true; } entryParser.Offset = currentOffset; // Variant dispatch of a variant generic interface generic virtual method. if (FindMatchingInterfaceSlot(moduleHandle, nativeLayoutReader, ref entryParser, ref extRefs, ref declaringType, ref methodNameAndSignature, openTargetTypeHandle, targetTypeInstantiation, true)) { return true; } } } return false; }
private unsafe bool ResolveGenericVirtualMethodTarget_Static(RuntimeTypeHandle targetTypeHandle, RuntimeTypeHandle declaringType, RuntimeTypeHandle[] genericArguments, MethodNameAndSignature callingMethodNameAndSignature, out IntPtr methodPointer, out IntPtr dictionaryPointer) { methodPointer = dictionaryPointer = IntPtr.Zero; // Get the open type definition of the containing type of the generic virtual method being resolved RuntimeTypeHandle openCallingTypeHandle = GetTypeDefinition(declaringType); // Get the open type definition of the current type of the object instance on which the GVM is being resolved RuntimeTypeHandle openTargetTypeHandle = GetTypeDefinition(targetTypeHandle); int hashCode = openCallingTypeHandle.GetHashCode(); hashCode = ((hashCode << 13) ^ hashCode) ^ openTargetTypeHandle.GetHashCode(); #if REFLECTION_EXECUTION_TRACE ReflectionExecutionLogger.WriteLine("GVM Target Resolution = " + GetTypeNameDebug(targetTypeHandle) + "." + callingMethodNameAndSignature.Name); #endif foreach (IntPtr moduleHandle in ModuleList.Enumerate(RuntimeAugments.GetModuleFromTypeHandle(openTargetTypeHandle))) { NativeReader gvmTableReader; if (!TryGetNativeReaderForBlob(moduleHandle, ReflectionMapBlob.GenericVirtualMethodTable, out gvmTableReader)) continue; NativeReader nativeLayoutReader; if (!TryGetNativeReaderForBlob(moduleHandle, ReflectionMapBlob.NativeLayoutInfo, out nativeLayoutReader)) continue; NativeParser gvmTableParser = new NativeParser(gvmTableReader, 0); NativeHashtable gvmHashtable = new NativeHashtable(gvmTableParser); ExternalReferencesTable extRefs = default(ExternalReferencesTable); extRefs.InitializeCommonFixupsTable(moduleHandle); var lookup = gvmHashtable.Lookup(hashCode); NativeParser entryParser; while (!(entryParser = lookup.GetNext()).IsNull) { RuntimeTypeHandle parsedCallingTypeHandle = extRefs.GetRuntimeTypeHandleFromIndex(entryParser.GetUnsigned()); if (!parsedCallingTypeHandle.Equals(openCallingTypeHandle)) continue; RuntimeTypeHandle parsedTargetTypeHandle = extRefs.GetRuntimeTypeHandleFromIndex(entryParser.GetUnsigned()); if (!parsedTargetTypeHandle.Equals(openTargetTypeHandle)) continue; uint parsedCallingNameAndSigToken = extRefs.GetRvaFromIndex(entryParser.GetUnsigned()); MethodNameAndSignature parsedCallingNameAndSignature = GetMethodNameAndSignatureFromNativeReader(nativeLayoutReader, parsedCallingNameAndSigToken); if (!parsedCallingNameAndSignature.Equals(callingMethodNameAndSignature)) continue; uint parsedTargetMethodNameAndSigToken = extRefs.GetRvaFromIndex(entryParser.GetUnsigned()); MethodNameAndSignature targetMethodNameAndSignature = GetMethodNameAndSignatureFromNativeReader(nativeLayoutReader, parsedTargetMethodNameAndSigToken); Debug.Assert(targetMethodNameAndSignature != null); return TryGetGenericVirtualMethodPointer(targetTypeHandle, targetMethodNameAndSignature, genericArguments, out methodPointer, out dictionaryPointer); } } return false; }
public NativeParser GetNext() { for (;;) { while (_parser.Offset < _endOffset) { byte lowHashcode = _parser.GetUInt8(); return _parser.GetParserFromRelativeOffset(); } if (_currentBucket >= _table._bucketMask) return new NativeParser(); _currentBucket++; _parser = _table.GetParserForBucket(_currentBucket, out _endOffset); } }
internal AllEntriesEnumerator(NativeHashtable table) { _table = table; _currentBucket = 0; _parser = _table.GetParserForBucket(_currentBucket, out _endOffset); }
internal Enumerator(NativeParser parser, uint endOffset, byte lowHashcode) { _parser = parser; _endOffset = endOffset; _lowHashcode = lowHashcode; }
private bool TryGetTypeFromSimpleTypeSignature(ref NativeParser parser, out RuntimeTypeHandle typeHandle) { uint data; TypeSignatureKind kind = parser.GetTypeSignatureKind(out data); if (kind == TypeSignatureKind.Lookback) { var lookbackParser = parser.GetLookbackParser(data); return TryGetTypeFromSimpleTypeSignature(ref lookbackParser, out typeHandle); } else if (kind == TypeSignatureKind.External) { typeHandle = GetExternalTypeHandle(ref parser, data); return true; } // Not a simple type signature... requires more work to skip typeHandle = default(RuntimeTypeHandle); return false; }
internal unsafe static GenericDictionaryCell[] BuildDictionary(TypeBuilder typeBuilder, NativeLayoutInfoLoadContext nativeLayoutInfoLoadContext, NativeParser parser) { uint parserStartOffset = parser.Offset; uint count = parser.GetSequenceCount(); Debug.Assert(count > 0); TypeLoaderLogger.WriteLine("Parsing dictionary layout @ " + parserStartOffset.LowLevelToString() + " (" + count.LowLevelToString() + " entries)"); GenericDictionaryCell[] dictionary = new GenericDictionaryCell[count]; for (uint i = 0; i < count; i++) { GenericDictionaryCell cell = ParseAndCreateCell(nativeLayoutInfoLoadContext, ref parser); cell.Prepare(typeBuilder); dictionary[i] = cell; } return dictionary; }
private RuntimeTypeHandle GetExternalTypeHandle(ref NativeParser parser, uint typeIndex) { IntPtr moduleHandle = RuntimeAugments.GetModuleFromPointer(parser.Reader.OffsetToAddress(parser.Offset)); Debug.Assert(moduleHandle != IntPtr.Zero); RuntimeTypeHandle result; TypeSystemContext context = TypeSystemContextFactory.Create(); { NativeLayoutInfoLoadContext nativeLayoutContext = new NativeLayoutInfoLoadContext(); nativeLayoutContext._moduleHandle = moduleHandle; nativeLayoutContext._typeSystemContext = context; TypeDesc type = nativeLayoutContext.GetExternalType(typeIndex); result = type.RuntimeTypeHandle; } TypeSystemContextFactory.Recycle(context); Debug.Assert(!result.IsNull()); return result; }
private bool CompareMethodSigs(NativeParser parser1, NativeParser parser2) { MethodCallingConvention callingConvention1 = (MethodCallingConvention)parser1.GetUnsigned(); MethodCallingConvention callingConvention2 = (MethodCallingConvention)parser2.GetUnsigned(); if (callingConvention1 != callingConvention2) return false; if ((callingConvention1 & MethodCallingConvention.Generic) == MethodCallingConvention.Generic) { if (parser1.GetUnsigned() != parser2.GetUnsigned()) return false; } uint parameterCount1 = parser1.GetUnsigned(); uint parameterCount2 = parser2.GetUnsigned(); if (parameterCount1 != parameterCount2) return false; // Compare one extra parameter to account for the return type for (uint i = 0; i <= parameterCount1; i++) { if (!CompareTypeSigs(ref parser1, ref parser2)) return false; } return true; }
internal bool IsStaticMethodSignature(RuntimeMethodSignature methodSig) { if (methodSig.IsNativeLayoutSignature) { IntPtr moduleHandle = RuntimeAugments.GetModuleFromPointer(methodSig.NativeLayoutSignature); NativeReader reader = GetNativeLayoutInfoReader(moduleHandle); NativeParser parser = new NativeParser(reader, reader.AddressToOffset(methodSig.NativeLayoutSignature)); MethodCallingConvention callingConvention = (MethodCallingConvention)parser.GetUnsigned(); return callingConvention.HasFlag(MethodCallingConvention.Static); } else { var metadataReader = ModuleList.Instance.GetMetadataReaderForModule(methodSig.ModuleHandle); var methodHandle = methodSig.Token.AsHandle().ToMethodHandle(metadataReader); var method = methodHandle.GetMethod(metadataReader); return (method.Flags & MethodAttributes.Static) != 0; } }
public bool TryGetMethodNameAndSignaturePointersFromNativeLayoutSignature(IntPtr module, uint methodNameAndSigToken, out IntPtr methodNameSigPtr, out IntPtr methodSigPtr) { methodNameSigPtr = default(IntPtr); methodSigPtr = default(IntPtr); NativeReader reader = GetNativeLayoutInfoReader(module); uint offset = methodNameAndSigToken; NativeParser parser = new NativeParser(reader, offset); if (parser.IsNull) return false; methodNameSigPtr = parser.Reader.OffsetToAddress(parser.Offset); string methodName = parser.GetString(); // Signatures are indirected to through a relative offset so that we don't have to parse them // when not comparing signatures (parsing them requires resolving types and is tremendously // expensive). NativeParser sigParser = parser.GetParserFromRelativeOffset(); methodSigPtr = sigParser.Reader.OffsetToAddress(sigParser.Offset); return true; }
internal override void ParseBaseType(NativeLayoutInfoLoadContext nativeLayoutInfoLoadContext, NativeParser baseTypeParser) { if (!baseTypeParser.IsNull) { // If the base type is available from the native layout info use it if the type we have is a NoMetadataType SetBaseType((DefType)nativeLayoutInfoLoadContext.GetType(ref baseTypeParser)); } else { // Set the base type for no metadata types, if we reach this point, and there isn't a parser, then we simply use the value from the template SetBaseType(ComputeTemplate().BaseType); } }
internal static GenericDictionaryCell ParseAndCreateCell(NativeLayoutInfoLoadContext nativeLayoutInfoLoadContext, ref NativeParser parser) { GenericDictionaryCell cell; var kind = parser.GetFixupSignatureKind(); switch (kind) { case FixupSignatureKind.TypeHandle: { var type = nativeLayoutInfoLoadContext.GetType(ref parser); TypeLoaderLogger.WriteLine("TypeHandle: " + type.ToString()); cell = new TypeHandleCell() { Type = type }; } break; case FixupSignatureKind.InterfaceCall: { var interfaceType = nativeLayoutInfoLoadContext.GetType(ref parser); var slot = parser.GetUnsigned(); TypeLoaderLogger.WriteLine("InterfaceCall: " + interfaceType.ToString() + ", slot #" + slot.LowLevelToString()); cell = new InterfaceCallCell() { InterfaceType = interfaceType, Slot = (int)slot }; } break; case FixupSignatureKind.MethodDictionary: { var genericMethod = nativeLayoutInfoLoadContext.GetMethod(ref parser); Debug.Assert(genericMethod.Instantiation.Length > 0); TypeLoaderLogger.WriteLine("MethodDictionary: " + genericMethod.ToString()); cell = new MethodDictionaryCell { GenericMethod = (InstantiatedMethod)genericMethod }; } break; case FixupSignatureKind.StaticData: { var type = nativeLayoutInfoLoadContext.GetType(ref parser); StaticDataKind staticDataKind = (StaticDataKind)parser.GetUnsigned(); TypeLoaderLogger.WriteLine("StaticData (" + (staticDataKind == StaticDataKind.Gc ? "Gc" : "NonGc") + ": " + type.ToString()); cell = new StaticDataCell() { DataKind = staticDataKind, Type = type }; } break; case FixupSignatureKind.UnwrapNullableType: { var type = nativeLayoutInfoLoadContext.GetType(ref parser); TypeLoaderLogger.WriteLine("UnwrapNullableType of: " + type.ToString()); cell = new UnwrapNullableTypeCell() { Type = (DefType)type }; } break; case FixupSignatureKind.FieldLdToken: { NativeParser ldtokenSigParser = parser.GetParserFromRelativeOffset(); var type = nativeLayoutInfoLoadContext.GetType(ref ldtokenSigParser); IntPtr fieldNameSig = ldtokenSigParser.Reader.OffsetToAddress(ldtokenSigParser.Offset); TypeLoaderLogger.WriteLine("LdToken on: " + type.ToString() + "." + ldtokenSigParser.GetString()); cell = new FieldLdTokenCell() { FieldName = fieldNameSig, ContainingType = type }; } break; case FixupSignatureKind.MethodLdToken: { NativeParser ldtokenSigParser = parser.GetParserFromRelativeOffset(); IntPtr methodNameSigPtr; IntPtr methodSigPtr; var method = nativeLayoutInfoLoadContext.GetMethod(ref ldtokenSigParser, out methodNameSigPtr, out methodSigPtr); TypeLoaderLogger.WriteLine("LdToken on: " + method.OwningType.ToString() + "::" + method.NameAndSignature.Name); cell = new MethodLdTokenCell { Method = method, MethodName = methodNameSigPtr, MethodSignature = RuntimeMethodSignature.CreateFromNativeLayoutSignature(methodSigPtr) }; } break; case FixupSignatureKind.TypeSize: { var type = nativeLayoutInfoLoadContext.GetType(ref parser); TypeLoaderLogger.WriteLine("TypeSize: " + type.ToString()); cell = new TypeSizeCell() { Type = type }; } break; case FixupSignatureKind.FieldOffset: { var type = (DefType)nativeLayoutInfoLoadContext.GetType(ref parser); uint ordinal = parser.GetUnsigned(); TypeLoaderLogger.WriteLine("FieldOffset on: " + type.ToString()); cell = new FieldOffsetCell() { Ordinal = ordinal, ContainingType = type }; } break; case FixupSignatureKind.VTableOffset: { var type = nativeLayoutInfoLoadContext.GetType(ref parser); var vtableSlot = parser.GetUnsigned(); TypeLoaderLogger.WriteLine("VTableOffset on: " + type.ToString() + ", slot: " + vtableSlot.LowLevelToString()); cell = new VTableOffsetCell() { ContainingType = type, VTableSlot = vtableSlot }; } break; case FixupSignatureKind.AllocateObject: { var type = nativeLayoutInfoLoadContext.GetType(ref parser); TypeLoaderLogger.WriteLine("AllocateObject on: " + type.ToString()); cell = new AllocateObjectCell { Type = type }; } break; case FixupSignatureKind.DefaultConstructor: { var type = nativeLayoutInfoLoadContext.GetType(ref parser); TypeLoaderLogger.WriteLine("DefaultConstructor on: " + type.ToString()); cell = new DefaultConstructorCell { Type = type }; } break; case FixupSignatureKind.TlsIndex: { var type = nativeLayoutInfoLoadContext.GetType(ref parser); TypeLoaderLogger.WriteLine("TlsIndex on: " + type.ToString()); cell = new TlsIndexCell { Type = type }; } break; case FixupSignatureKind.TlsOffset: { var type = nativeLayoutInfoLoadContext.GetType(ref parser); TypeLoaderLogger.WriteLine("TlsOffset on: " + type.ToString()); cell = new TlsOffsetCell { Type = type }; } break; case FixupSignatureKind.Method: { IntPtr methodSigPtr; IntPtr methodNameSigPtr; var method = nativeLayoutInfoLoadContext.GetMethod(ref parser, out methodNameSigPtr, out methodSigPtr); TypeLoaderLogger.WriteLine("Method: " + method.ToString()); cell = new MethodCell { Method = method, MethodSignature = RuntimeMethodSignature.CreateFromNativeLayoutSignature(methodSigPtr) }; } break; case FixupSignatureKind.NonGenericDirectConstrainedMethod: { var constraintType = nativeLayoutInfoLoadContext.GetType(ref parser); var constrainedMethodType = nativeLayoutInfoLoadContext.GetType(ref parser); var constrainedMethodSlot = parser.GetUnsigned(); TypeLoaderLogger.WriteLine("NonGenericDirectConstrainedMethod: " + constraintType.ToString() + " Method " + constrainedMethodType.ToString() + ", slot #" + constrainedMethodSlot.LowLevelToString()); cell = new NonGenericDirectConstrainedMethodCell() { ConstraintType = constraintType, ConstrainedMethodType = constrainedMethodType, ConstrainedMethodSlot = (int)constrainedMethodSlot }; } break; case FixupSignatureKind.NonGenericConstrainedMethod: { var constraintType = nativeLayoutInfoLoadContext.GetType(ref parser); var constrainedMethodType = nativeLayoutInfoLoadContext.GetType(ref parser); var constrainedMethodSlot = parser.GetUnsigned(); TypeLoaderLogger.WriteLine("NonGenericConstrainedMethod: " + constraintType.ToString() + " Method " + constrainedMethodType.ToString() + ", slot #" + constrainedMethodSlot.LowLevelToString()); cell = new NonGenericConstrainedMethodCell() { ConstraintType = constraintType, ConstrainedMethodType = constrainedMethodType, ConstrainedMethodSlot = (int)constrainedMethodSlot }; } break; case FixupSignatureKind.GenericConstrainedMethod: { var constraintType = nativeLayoutInfoLoadContext.GetType(ref parser); NativeParser ldtokenSigParser = parser.GetParserFromRelativeOffset(); IntPtr methodNameSigPtr; IntPtr methodSigPtr; var method = nativeLayoutInfoLoadContext.GetMethod(ref ldtokenSigParser, out methodNameSigPtr, out methodSigPtr); TypeLoaderLogger.WriteLine("GenericConstrainedMethod: " + constraintType.ToString() + " Method " + method.OwningType.ToString() + "::" + method.NameAndSignature.Name); cell = new GenericConstrainedMethodCell() { ConstraintType = constraintType, ConstrainedMethod = method, MethodName = methodNameSigPtr, MethodSignature = RuntimeMethodSignature.CreateFromNativeLayoutSignature(methodSigPtr) }; } break; case FixupSignatureKind.IsInst: case FixupSignatureKind.CastClass: { var type = nativeLayoutInfoLoadContext.GetType(ref parser); TypeLoaderLogger.WriteLine("Casting on: " + type.ToString()); cell = new CastingCell { Type = type, Throwing = (kind == FixupSignatureKind.CastClass) }; } break; case FixupSignatureKind.AllocateArray: { var type = nativeLayoutInfoLoadContext.GetType(ref parser); TypeLoaderLogger.WriteLine("AllocateArray on: " + type.ToString()); cell = new AllocateArrayCell { Type = type }; } break; case FixupSignatureKind.CheckArrayElementType: { var type = nativeLayoutInfoLoadContext.GetType(ref parser); TypeLoaderLogger.WriteLine("CheckArrayElementType on: " + type.ToString()); cell = new CheckArrayElementTypeCell { Type = type }; } break; case FixupSignatureKind.CallingConventionConverter: { NativeFormat.CallingConventionConverterKind flags = (NativeFormat.CallingConventionConverterKind)parser.GetUnsigned(); NativeParser sigParser = parser.GetParserFromRelativeOffset(); IntPtr signature = sigParser.Reader.OffsetToAddress(sigParser.Offset); #if TYPE_LOADER_TRACE TypeLoaderLogger.WriteLine("CallingConventionConverter on: "); TypeLoaderLogger.WriteLine(" -> Flags: " + ((int)flags).LowLevelToString()); TypeLoaderLogger.WriteLine(" -> Signature: " + signature.LowLevelToString()); for (int i = 0; !nativeLayoutInfoLoadContext._typeArgumentHandles.IsNull && i < nativeLayoutInfoLoadContext._typeArgumentHandles.Length; i++) TypeLoaderLogger.WriteLine(" -> TypeArg[" + i.LowLevelToString() + "]: " + nativeLayoutInfoLoadContext._typeArgumentHandles[i]); for (int i = 0; !nativeLayoutInfoLoadContext._methodArgumentHandles.IsNull && i < nativeLayoutInfoLoadContext._methodArgumentHandles.Length; i++) TypeLoaderLogger.WriteLine(" -> MethodArg[" + i.LowLevelToString() + "]: " + nativeLayoutInfoLoadContext._methodArgumentHandles[i]); #endif cell = new CallingConventionConverterCell { Flags = flags, Signature = RuntimeMethodSignature.CreateFromNativeLayoutSignature(signature), MethodArgs = nativeLayoutInfoLoadContext._methodArgumentHandles, TypeArgs = nativeLayoutInfoLoadContext._typeArgumentHandles }; } break; case FixupSignatureKind.NotYetSupported: TypeLoaderLogger.WriteLine("Valid dictionary entry, but not yet supported by the TypeLoader!"); throw new TypeBuilder.MissingTemplateException(); default: parser.ThrowBadImageFormatException(); cell = null; break; } return cell; }
public bool TryGetMethodNameAndSignatureFromNativeLayoutOffset(IntPtr moduleHandle, uint nativeLayoutOffset, out MethodNameAndSignature nameAndSignature) { nameAndSignature = null; NativeReader reader = GetNativeLayoutInfoReader(moduleHandle); NativeParser parser = new NativeParser(reader, nativeLayoutOffset); if (parser.IsNull) return false; IntPtr methodSigPtr; IntPtr methodNameSigPtr; nameAndSignature = GetMethodNameAndSignature(ref parser, out methodNameSigPtr, out methodSigPtr); return true; }
/// <summary> /// Build an array of GenericDictionaryCell from a NativeParser stream that has the appropriate metadata /// Return null if there are no cells to describe /// </summary> internal unsafe static GenericDictionaryCell[] BuildDictionaryFromMetadataTokensAndContext(TypeBuilder typeBuilder, NativeParser parser, NativeFormatMetadataUnit nativeMetadataUnit, FixupCellMetadataResolver resolver) { uint parserStartOffset = parser.Offset; uint count = parser.GetSequenceCount(); // An empty dictionary isn't interesting if (count == 0) return null; Debug.Assert(count > 0); TypeLoaderLogger.WriteLine("Parsing dictionary layout @ " + parserStartOffset.LowLevelToString() + " (" + count.LowLevelToString() + " entries)"); GenericDictionaryCell[] dictionary = new GenericDictionaryCell[count]; for (uint i = 0; i < count; i++) { MetadataFixupKind fixupKind = (MetadataFixupKind)parser.GetUInt8(); Internal.Metadata.NativeFormat.Handle token = parser.GetUnsigned().AsHandle(); Internal.Metadata.NativeFormat.Handle token2 = new Internal.Metadata.NativeFormat.Handle(); switch (fixupKind) { case MetadataFixupKind.GenericConstrainedMethod: case MetadataFixupKind.NonGenericConstrainedMethod: case MetadataFixupKind.NonGenericDirectConstrainedMethod: token2 = parser.GetUnsigned().AsHandle(); break; } GenericDictionaryCell cell = CreateCellFromFixupKindAndToken(fixupKind, resolver, token, token2); cell.Prepare(typeBuilder); dictionary[i] = cell; } return dictionary; }