private static bool IsLayoutDependentOnGenericInstantiation(TypeDesc type, HasVarsInvestigationLevel investigationLevel) { if (type.IsSignatureVariable) { return(true); } else if (type.HasInstantiation && type.IsValueType) { foreach (TypeDesc valueTypeInstantiationParam in type.Instantiation) { if (IsLayoutDependentOnGenericInstantiation(valueTypeInstantiationParam, HasVarsInvestigationLevel.NotParameter)) { if (investigationLevel == HasVarsInvestigationLevel.Parameter) { DefType universalCanonForm = (DefType)type.ConvertToCanonForm(CanonicalFormKind.Universal); return(universalCanonForm.InstanceFieldSize.IsIndeterminate); } else { return(true); } } } return(false); } else { // All other forms of type do not change their shape dependent on signature variables. 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. /// (There is a version of this in UniversalGenericParameterLayout.cs that must be kept in sync with this.) /// /// 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, NativeFormatModuleInfo moduleHandle, 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.BuiltIn: return(false); case TypeSignatureKind.Lookback: { var lookbackParser = parser.GetLookbackParser(data); return(TypeSignatureHasVarsNeedingCallingConventionConverter(ref lookbackParser, moduleHandle, context, investigationLevel)); } case TypeSignatureKind.Instantiation: { RuntimeTypeHandle genericTypeDef; if (!TryGetTypeFromSimpleTypeSignature(ref parser, moduleHandle, 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, moduleHandle, context, HasVarsInvestigationLevel.Ignore); } return(false); } else { bool result = false; for (uint i = 0; i < data; i++) { result = TypeSignatureHasVarsNeedingCallingConventionConverter(ref parser, moduleHandle, 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, moduleHandle, 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, moduleHandle, 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, moduleHandle, context, HasVarsInvestigationLevel.Ignore); } } return(false); default: parser.ThrowBadImageFormatException(); return(true); } }
/// <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; } }
/// <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 static bool TypeHasLayoutDependentOnGenericInstantiation(TypeDesc type, HasVarsInvestigationLevel investigationLevel) { if (type is SignatureVariable) { return true; } else if (type.IsDefType && type.HasInstantiation && type.IsValueType) { foreach (TypeDesc valueTypeInstantiationParam in type.Instantiation) { if (TypeHasLayoutDependentOnGenericInstantiation(valueTypeInstantiationParam, HasVarsInvestigationLevel.NotParameter)) { if (investigationLevel == HasVarsInvestigationLevel.Parameter) { bool needsCallingConventionConverter; if (!TypeLoaderEnvironment.Instance.TryComputeHasInstantiationDeterminedSize((DefType)type, out needsCallingConventionConverter)) Environment.FailFast("Unable to setup calling convention converter correctly"); return needsCallingConventionConverter; } else { return true; } } } return false; } else { // All other forms of type do not change their shape dependent on signature variables. 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> static private bool TypeHasLayoutDependentOnGenericInstantiation(TypeDesc type, HasVarsInvestigationLevel investigationLevel) { if (type is SignatureVariable) { return(true); } else if (type.IsDefType && type.HasInstantiation && type.IsValueType) { foreach (TypeDesc valueTypeInstantiationParam in type.Instantiation) { if (TypeHasLayoutDependentOnGenericInstantiation(valueTypeInstantiationParam, HasVarsInvestigationLevel.NotParameter)) { if (investigationLevel == HasVarsInvestigationLevel.Parameter) { bool needsCallingConventionConverter; if (!TypeLoaderEnvironment.Instance.TryComputeHasInstantiationDeterminedSize((DefType)type, out needsCallingConventionConverter)) { Environment.FailFast("Unable to setup calling convention converter correctly"); } return(needsCallingConventionConverter); } else { return(true); } } } return(false); } else { // All other forms of type do not change their shape dependent on signature variables. return(false); } }