예제 #1
0
        /// <summary>
        /// Helper API to convert a type to its canonical or universal canonical form.
        /// Note that for now, there is no mixture between specific canonical and universal canonical forms,
        /// meaning that the canonical form or Foo<string, int> can either be Foo<__Canon, int> or
        /// Foo<__UniversalCanon, __UniversalCanon>. It cannot be Foo<__Canon, __UniversalCanon> (yet)
        /// for simplicity. We can always change that rule in the futue and add support for the mixture, but
        /// for now we are keeping it simple.
        /// </summary>
        public static TypeDesc ConvertToCanon(TypeDesc typeToConvert, CanonicalFormKind kind)
        {
            TypeSystemContext context = typeToConvert.Context;

            if (kind == CanonicalFormKind.Universal)
            {
                return(context.UniversalCanonType);
            }
            else if (kind == CanonicalFormKind.Specific)
            {
                if (typeToConvert == context.UniversalCanonType)
                {
                    return(context.UniversalCanonType);
                }
                else if (typeToConvert.IsSignatureVariable)
                {
                    return(typeToConvert);
                }
                else if (typeToConvert.IsDefType)
                {
                    if (!typeToConvert.IsValueType)
                    {
                        return(context.CanonType);
                    }
                    else if (typeToConvert.HasInstantiation)
                    {
                        return(typeToConvert.ConvertToCanonForm(CanonicalFormKind.Specific));
                    }
                    else
                    {
                        return(typeToConvert);
                    }
                }
                else if (typeToConvert.IsArray)
                {
                    return(context.CanonType);
                }
                else
                {
                    return(typeToConvert.ConvertToCanonForm(CanonicalFormKind.Specific));
                }
            }
            else
            {
                Debug.Assert(false);
                return(null);
            }
        }
예제 #2
0
        /// <summary>
        /// Get the NativeLayout for a type from a ReadyToRun image. 
        /// </summary>
        public bool TryGetMetadataNativeLayout(TypeDesc concreteType, out IntPtr nativeLayoutInfoModule, out uint nativeLayoutInfoToken)
        {
            nativeLayoutInfoModule = default(IntPtr);
            nativeLayoutInfoToken = 0;
#if SUPPORTS_NATIVE_METADATA_TYPE_LOADING
            var nativeMetadataType = concreteType.GetTypeDefinition() as TypeSystem.NativeFormat.NativeFormatType;
            if (nativeMetadataType == null)
                return false;

            var canonForm = concreteType.ConvertToCanonForm(CanonicalFormKind.Specific);
            var hashCode = canonForm.GetHashCode();

            var loadedModulesCount = RuntimeAugments.GetLoadedModules(null);
            var loadedModuleHandles = new IntPtr[loadedModulesCount];
            var loadedModules = RuntimeAugments.GetLoadedModules(loadedModuleHandles);
            Debug.Assert(loadedModulesCount == loadedModules);

#if SUPPORTS_R2R_LOADING
            foreach (var moduleHandle in loadedModuleHandles)
            {
                ExternalReferencesTable externalFixupsTable;
                NativeHashtable typeTemplatesHashtable = LoadHashtable(moduleHandle, ReflectionMapBlob.MetadataBasedTypeTemplateMap, out externalFixupsTable);

                if (typeTemplatesHashtable.IsNull)
                    continue;

                var enumerator = typeTemplatesHashtable.Lookup(hashCode);
                var nativeMetadataUnit = nativeMetadataType.Context.ResolveMetadataUnit(moduleHandle);

                NativeParser entryParser;
                while (!(entryParser = enumerator.GetNext()).IsNull)
                {
                    var entryTypeHandle = entryParser.GetUnsigned().AsHandle();
                    TypeDesc typeDesc = nativeMetadataUnit.GetType(entryTypeHandle);
                    Debug.Assert(typeDesc != null);
                    if (typeDesc == canonForm)
                    {
                        TypeLoaderLogger.WriteLine("Found metadata template for type " + concreteType.ToString() + ": " + typeDesc.ToString());
                        nativeLayoutInfoToken = (uint)externalFixupsTable.GetRvaFromIndex(entryParser.GetUnsigned());
                        if (nativeLayoutInfoToken == BadTokenFixupValue)
                        {
                            throw new BadImageFormatException();
                        }

                        nativeLayoutInfoModule = moduleHandle;
                        return true;
                    }
                }
            }
#endif
#endif

            return false;
        }
예제 #3
0
 /// <summary>
 /// Helper API to convert a type to its canonical or universal canonical form.
 /// Note that for now, there is no mixture between specific canonical and universal canonical forms,
 /// meaning that the canonical form or Foo<string, int> can either be Foo<__Canon, int> or
 /// Foo<__UniversalCanon, __UniversalCanon>. It cannot be Foo<__Canon, __UniversalCanon> (yet)
 /// for simplicity. We can always change that rule in the futue and add support for the mixture, but
 /// for now we are keeping it simple.
 /// </summary>
 public static TypeDesc ConvertToCanon(TypeDesc typeToConvert, CanonicalFormKind kind)
 {
     TypeSystemContext context = typeToConvert.Context;
     if (kind == CanonicalFormKind.Universal)
     {
         return context.UniversalCanonType;
     }
     else if (kind == CanonicalFormKind.Specific)
     {
         if (typeToConvert == context.UniversalCanonType)
         {
             return context.UniversalCanonType;
         }
         else if (typeToConvert.IsDefType)
         {
             if (!typeToConvert.IsValueType)
                 return context.CanonType;
             else if (typeToConvert.HasInstantiation)
                 return typeToConvert.ConvertToCanonForm(CanonicalFormKind.Specific);
             else
                 return typeToConvert;
         }
         else if (typeToConvert.IsArray)
         {
             return context.CanonType;
         }
         else
         {
             return typeToConvert.ConvertToCanonForm(CanonicalFormKind.Specific);
         }
     }
     else
     {
         Debug.Assert(false);
         return null;
     }
 }
예제 #4
0
        public static TypeDesc ConvertToCanon(TypeDesc typeToConvert, ref CanonicalFormKind kind)
        {
            TypeSystemContext context = typeToConvert.Context;

            if (kind == CanonicalFormKind.Universal)
            {
                return(context.UniversalCanonType);
            }
            else if (kind == CanonicalFormKind.Specific)
            {
                if (typeToConvert == context.UniversalCanonType)
                {
                    kind = CanonicalFormKind.Universal;
                    return(context.UniversalCanonType);
                }
                else if (typeToConvert.IsSignatureVariable)
                {
                    return(typeToConvert);
                }
                else if (typeToConvert.IsDefType)
                {
                    if (!typeToConvert.IsValueType)
                    {
                        return(context.CanonType);
                    }
                    else if (typeToConvert.HasInstantiation)
                    {
                        // This is a generic struct type. If the generic struct is instantiated over universal canon,
                        // the entire struct becomes universally canonical.
                        if (typeToConvert.IsCanonicalSubtype(CanonicalFormKind.Universal))
                        {
                            kind = CanonicalFormKind.Universal;
                            return(context.UniversalCanonType);
                        }

                        TypeDesc canonicalType = typeToConvert.ConvertToCanonForm(CanonicalFormKind.Specific);

                        // We could still have ended up with a universal canonical form here because conversion to
                        // canon form strips runtime determined types from their constituents.
                        // MyStruct<T__UniversalCanon> (which is not universally canonical) becomes MyStruct<__UniversalCanon>.
                        if (canonicalType.IsCanonicalSubtype(CanonicalFormKind.Universal))
                        {
                            kind = CanonicalFormKind.Universal;
                            return(context.UniversalCanonType);
                        }

                        return(canonicalType);
                    }
                    else if (typeToConvert.IsRuntimeDeterminedType)
                    {
                        // For non-universal canon cases, RuntimeDeterminedType's passed into this function are either
                        // reference types (which are turned into normal Canon), or instantiated types (which are handled
                        // by the above case.). But for UniversalCanon, we can have non-instantiated universal canon
                        // which will reach this case.

                        // We should only ever reach this for T__UniversalCanon.
                        Debug.Assert(((RuntimeDeterminedType)typeToConvert).CanonicalType == context.UniversalCanonType);

                        kind = CanonicalFormKind.Universal;
                        return(context.UniversalCanonType);
                    }
                    else
                    {
                        return(typeToConvert);
                    }
                }
                else if (typeToConvert.IsArray)
                {
                    return(context.CanonType);
                }
                else
                {
                    if (typeToConvert.IsCanonicalSubtype(CanonicalFormKind.Universal))
                    {
                        kind = CanonicalFormKind.Universal;
                        return(context.UniversalCanonType);
                    }

                    return(typeToConvert.ConvertToCanonForm(CanonicalFormKind.Specific));
                }
            }
            else
            {
                Debug.Assert(false);
                return(null);
            }
        }
        public static TypeDesc ConvertToCanon(TypeDesc typeToConvert, ref CanonicalFormKind kind)
        {
            TypeSystemContext context = typeToConvert.Context;
            if (kind == CanonicalFormKind.Universal)
            {
                return context.UniversalCanonType;
            }
            else if (kind == CanonicalFormKind.Specific)
            {
                if (typeToConvert == context.UniversalCanonType)
                {
                    kind = CanonicalFormKind.Universal;
                    return context.UniversalCanonType;
                }
                else if (typeToConvert.IsSignatureVariable)
                {
                    return typeToConvert;
                }
                else if (typeToConvert.IsDefType)
                {
                    if (!typeToConvert.IsValueType)
                    {
                        return context.CanonType;
                    }
                    else if (typeToConvert.HasInstantiation)
                    {
                        TypeDesc canonicalType = typeToConvert.ConvertToCanonForm(CanonicalFormKind.Specific);

                        // This is a generic struct type. If the generic struct is instantiated over universal canon,
                        // the entire struct becomes universally canonical.
                        if (canonicalType.IsCanonicalSubtype(CanonicalFormKind.Universal))
                        {
                            kind = CanonicalFormKind.Universal;
                            return context.UniversalCanonType;
                        }

                        return canonicalType;
                    }
                    else if (typeToConvert.IsRuntimeDeterminedType)
                    {
                        // For non-universal canon cases, RuntimeDeterminedType's passed into this function are either
                        // reference types (which are turned into normal Canon), or instantiated types (which are handled 
                        // by the above case.). But for UniversalCanon, we can have non-instantiated universal canon
                        // which will reach this case.

                        // We should only ever reach this for T__UniversalCanon.
                        Debug.Assert(((RuntimeDeterminedType)typeToConvert).CanonicalType == context.UniversalCanonType);

                        kind = CanonicalFormKind.Universal;
                        return context.UniversalCanonType;
                    }
                    else
                    {
                        return typeToConvert;
                    }
                }
                else if (typeToConvert.IsArray)
                {
                    return context.CanonType;
                }
                else
                {
                    if (typeToConvert.IsCanonicalSubtype(CanonicalFormKind.Universal))
                    {
                        kind = CanonicalFormKind.Universal;
                        return context.UniversalCanonType;
                    }

                    return typeToConvert.ConvertToCanonForm(CanonicalFormKind.Specific);
                }
            }
            else
            {
                Debug.Assert(false);
                return null;
            }
        }
예제 #6
0
        private TypeDesc TryGetTypeTemplate_Internal(TypeDesc concreteType, CanonicalFormKind kind, out IntPtr nativeLayoutInfoModule, out uint nativeLayoutInfoToken)
        {
            nativeLayoutInfoModule = default(IntPtr);
            nativeLayoutInfoToken = 0;
            var canonForm = concreteType.ConvertToCanonForm(kind);
            var hashCode = canonForm.GetHashCode();

            var loadedModulesCount = RuntimeAugments.GetLoadedModules(null);
            var loadedModuleHandles = new IntPtr[loadedModulesCount];
            var loadedModules = RuntimeAugments.GetLoadedModules(loadedModuleHandles);
            Debug.Assert(loadedModulesCount == loadedModules);

            foreach (var moduleHandle in loadedModuleHandles)
            {
                ExternalReferencesTable externalFixupsTable;
                NativeHashtable typeTemplatesHashtable = LoadHashtable(moduleHandle, ReflectionMapBlob.TypeTemplateMap, out externalFixupsTable);

                if (typeTemplatesHashtable.IsNull)
                    continue;

                var enumerator = typeTemplatesHashtable.Lookup(hashCode);

                NativeParser entryParser;
                while (!(entryParser = enumerator.GetNext()).IsNull)
                {
                    RuntimeTypeHandle candidateTemplateTypeHandle = externalFixupsTable.GetRuntimeTypeHandleFromIndex(entryParser.GetUnsigned());
                    TypeDesc candidateTemplate = concreteType.Context.ResolveRuntimeTypeHandle(candidateTemplateTypeHandle);

                    if (canonForm == candidateTemplate.ConvertToCanonForm(kind))
                    {
                        TypeLoaderLogger.WriteLine("Found template for type " + concreteType.ToString() + ": " + candidateTemplate.ToString());
                        nativeLayoutInfoToken = (uint)externalFixupsTable.GetRvaFromIndex(entryParser.GetUnsigned());
                        if (nativeLayoutInfoToken == BadTokenFixupValue)
                        {
                            // TODO: once multifile gets fixed up, make this throw a BadImageFormatException
                            TypeLoaderLogger.WriteLine("ERROR: template not fixed up, skipping");
                            continue;
                        }

                        Debug.Assert(
                            (kind != CanonicalFormKind.Universal && candidateTemplate != candidateTemplate.ConvertToCanonForm(kind)) ||
                            (kind == CanonicalFormKind.Universal && candidateTemplate == candidateTemplate.ConvertToCanonForm(kind)));

                        nativeLayoutInfoModule = moduleHandle;
                        return candidateTemplate;
                    }
                }
            }

            TypeLoaderLogger.WriteLine("ERROR: Cannot find a suitable template for type " + concreteType.ToString());
            return null;
        }
 private static TypeDesc ConvertToCanon(TypeDesc typeToConvert, ref CanonicalFormKind kind)
 {
     TypeSystemContext context = typeToConvert.Context;
     if (kind == CanonicalFormKind.Universal)
     {
         return context.UniversalCanonType;
     }
     else if (kind == CanonicalFormKind.Specific)
     {
         if (typeToConvert == context.UniversalCanonType)
         {
             kind = CanonicalFormKind.Universal;
             return context.UniversalCanonType;
         }
         else if (typeToConvert.IsSignatureVariable)
         {
             return typeToConvert;
         }
         else if (typeToConvert.IsDefType)
         {
             if (!typeToConvert.IsValueType)
                 return context.CanonType;
             else if (typeToConvert.HasInstantiation)
             {
                 TypeDesc convertedType = typeToConvert.ConvertToCanonForm(CanonicalFormKind.Specific);
                 if (convertedType.IsCanonicalSubtype(CanonicalFormKind.Universal))
                 {
                     kind = CanonicalFormKind.Universal;
                     return context.UniversalCanonType;
                 }
                 return convertedType;
             }
             else
                 return typeToConvert;
         }
         else if (typeToConvert.IsArray)
         {
             return context.CanonType;
         }
         else
         {
             TypeDesc convertedType = typeToConvert.ConvertToCanonForm(CanonicalFormKind.Specific);
             if (convertedType.IsCanonicalSubtype(CanonicalFormKind.Universal))
             {
                 kind = CanonicalFormKind.Universal;
                 return context.UniversalCanonType;
             }
             return convertedType;
         }
     }
     else
     {
         Debug.Assert(false);
         return null;
     }
 }