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; } }
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; }
/// <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; } }
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; } }