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);
     }
 }
Esempio n. 2
0
        /// <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);
     }
 }