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; }
/// <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; }
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; }
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; }
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; }
private uint GetGenericArgCountFromSig(NativeParser parser) { MethodCallingConvention callingConvention = (MethodCallingConvention)parser.GetUnsigned(); if ((callingConvention & MethodCallingConvention.Generic) == MethodCallingConvention.Generic) { return parser.GetUnsigned(); } else { return 0; } }
/// <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; }
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; }
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; } }
private static RuntimeTypeHandle[] GetTypeSequence(ref ExternalReferencesTable extRefs, ref NativeParser parser) { uint count = parser.GetUnsigned(); RuntimeTypeHandle[] result = new RuntimeTypeHandle[count]; for (uint i = 0; i < count; i++) result[i] = extRefs.GetRuntimeTypeHandleFromIndex(parser.GetUnsigned()); return result; }
internal MethodDesc GetMethod(ref NativeParser parser, out IntPtr methodNameSigPtr, out IntPtr methodSigPtr) { MethodFlags flags = (MethodFlags)parser.GetUnsigned(); IntPtr functionPointer = IntPtr.Zero; if ((flags & MethodFlags.HasFunctionPointer) != 0) functionPointer = GetExternalReferencePointer(parser.GetUnsigned()); DefType containingType = (DefType)GetType(ref parser); MethodNameAndSignature nameAndSignature = TypeLoaderEnvironment.Instance.GetMethodNameAndSignature(ref parser, out methodNameSigPtr, out methodSigPtr); bool unboxingStub = (flags & MethodFlags.IsUnboxingStub) != 0; MethodDesc retVal = null; if ((flags & MethodFlags.HasInstantiation) != 0) { TypeDesc[] typeArguments = GetTypeSequence(ref parser); Debug.Assert(typeArguments.Length > 0); retVal = this._typeSystemContext.ResolveGenericMethodInstantiation(unboxingStub, containingType, nameAndSignature, new Instantiation(typeArguments), functionPointer, (flags & MethodFlags.FunctionPointerIsUSG) != 0); } else { retVal = this._typeSystemContext.ResolveRuntimeMethod(unboxingStub, containingType, nameAndSignature, functionPointer, (flags & MethodFlags.FunctionPointerIsUSG) != 0); } if ((flags & MethodFlags.FunctionPointerIsUSG) != 0) { // TODO, consider a change such that if a USG function pointer is passed in, but we have // a way to get a non-usg pointer, that may be preferable Debug.Assert(retVal.UsgFunctionPointer != IntPtr.Zero); } return retVal; }
internal TypeDesc GetType(ref NativeParser parser) { uint data; var kind = parser.GetTypeSignatureKind(out data); switch (kind) { case TypeSignatureKind.Lookback: return GetLookbackType(ref parser, data); case TypeSignatureKind.Variable: uint index = data >> 1; return (((data & 0x1) != 0) ? _methodArgumentHandles : _typeArgumentHandles)[checked((int)index)]; case TypeSignatureKind.Instantiation: return GetInstantiationType(ref parser, data); case TypeSignatureKind.Modifier: return GetModifierType(ref parser, (TypeModifierKind)data); case TypeSignatureKind.External: return GetExternalType(data); case TypeSignatureKind.MultiDimArray: { DefType elementType = (DefType)GetType(ref parser); int rank = (int)data; // Skip encoded bounds and lobounds uint boundsCount = parser.GetUnsigned(); while (boundsCount > 0) parser.GetUnsigned(); uint loBoundsCount = parser.GetUnsigned(); while (loBoundsCount > 0) parser.GetUnsigned(); return _typeSystemContext.GetArrayType(elementType, rank); } case TypeSignatureKind.FunctionPointer: Debug.Assert(false, "NYI!"); parser.ThrowBadImageFormatException(); return null; default: parser.ThrowBadImageFormatException(); return null; } }
private static NativeLayoutFieldDesc[] ParseFieldLayout(DefType owningType, NativeLayoutInfoLoadContext nativeLayoutInfoLoadContext, NativeParser fieldLayoutParser) { if (fieldLayoutParser.IsNull) return Empty<NativeLayoutFieldDesc>.Array; uint numFields = fieldLayoutParser.GetUnsigned(); var fields = new NativeLayoutFieldDesc[numFields]; for (int i = 0; i < numFields; i++) { TypeDesc fieldType = nativeLayoutInfoLoadContext.GetType(ref fieldLayoutParser); NativeFormat.FieldStorage storage = (NativeFormat.FieldStorage)fieldLayoutParser.GetUnsigned(); fields[i] = new NativeLayoutFieldDesc(owningType, fieldType, storage); } return fields; }