示例#1
0
        /// <summary>
        /// Constructs a new instance of <see cref="DelegateCreationInfo"/> set up to construct a delegate of type
        /// '<paramref name="delegateType"/>' pointing to '<paramref name="targetMethod"/>'.
        /// </summary>
        public static DelegateCreationInfo Create(TypeDesc delegateType, MethodDesc targetMethod, NodeFactory factory)
        {
            var context = (CompilerTypeSystemContext)delegateType.Context;
            var systemDelegate = targetMethod.Context.GetWellKnownType(WellKnownType.MulticastDelegate).BaseType;

            int paramCountTargetMethod = targetMethod.Signature.Length;
            if (!targetMethod.Signature.IsStatic)
            {
                paramCountTargetMethod++;
            }

            DelegateInfo delegateInfo = context.GetDelegateInfo(delegateType.GetTypeDefinition());
            int paramCountDelegateClosed = delegateInfo.Signature.Length + 1;
            bool closed = false;
            if (paramCountDelegateClosed == paramCountTargetMethod)
            {
                closed = true;
            }
            else
            {
                Debug.Assert(paramCountDelegateClosed == paramCountTargetMethod + 1);
            }

            if (targetMethod.Signature.IsStatic)
            {
                MethodDesc invokeThunk;
                if (!closed)
                {
                    // Open delegate to a static method
                    invokeThunk = delegateInfo.Thunks[DelegateThunkKind.OpenStaticThunk];
                }
                else
                {
                    // Closed delegate to a static method (i.e. delegate to an extension method that locks the first parameter)
                    invokeThunk = delegateInfo.Thunks[DelegateThunkKind.ClosedStaticThunk];
                }

                var instantiatedDelegateType = delegateType as InstantiatedType;
                if (instantiatedDelegateType != null)
                    invokeThunk = context.GetMethodForInstantiatedType(invokeThunk, instantiatedDelegateType);

                // We use InitializeClosedStaticThunk for both because RyuJIT generates same code for both,
                // but passes null as the first parameter for the open one.
                return new DelegateCreationInfo(
                    factory.MethodEntrypoint(systemDelegate.GetKnownMethod("InitializeClosedStaticThunk", null)),
                    factory.MethodEntrypoint(targetMethod),
                    factory.MethodEntrypoint(invokeThunk));
            }
            else
            {
                if (!closed)
                    throw new NotImplementedException("Open instance delegates");

                bool useUnboxingStub = targetMethod.OwningType.IsValueType;

                return new DelegateCreationInfo(
                    factory.MethodEntrypoint(systemDelegate.GetKnownMethod("InitializeClosedInstance", null)),
                    factory.MethodEntrypoint(targetMethod, useUnboxingStub));
            }
        }
示例#2
0
        private bool IsBlocked(Cts.TypeDesc type)
        {
            if (type.IsArray || type.IsByRef || type.IsPointer)
            {
                return(IsBlocked(((Cts.ParameterizedType)type).ParameterType));
            }

            if (type.IsSignatureVariable)
            {
                return(false);
            }

            if (!type.IsTypeDefinition)
            {
                if (IsBlocked(type.GetTypeDefinition()))
                {
                    return(true);
                }

                foreach (var arg in type.Instantiation)
                {
                    if (IsBlocked(arg))
                    {
                        return(true);
                    }
                }

                return(false);
            }

            return(_policy.IsBlocked((Cts.MetadataType)type));
        }
示例#3
0
        private bool IsBlocked(Cts.TypeDesc type)
        {
            switch (type.Category)
            {
            case Cts.TypeFlags.SzArray:
            case Cts.TypeFlags.Array:
            case Cts.TypeFlags.Pointer:
            case Cts.TypeFlags.ByRef:
                return(IsBlocked(((Cts.ParameterizedType)type).ParameterType));

            case Cts.TypeFlags.SignatureMethodVariable:
            case Cts.TypeFlags.SignatureTypeVariable:
                return(false);

            case Cts.TypeFlags.FunctionPointer:
            {
                Cts.MethodSignature pointerSignature = ((Cts.FunctionPointerType)type).Signature;
                if (IsBlocked(pointerSignature.ReturnType))
                {
                    return(true);
                }

                for (int i = 0; i < pointerSignature.Length; i++)
                {
                    if (IsBlocked(pointerSignature[i]))
                    {
                        return(true);
                    }
                }

                return(false);
            }

            default:
                Debug.Assert(type.IsDefType);

                if (!type.IsTypeDefinition)
                {
                    if (IsBlocked(type.GetTypeDefinition()))
                    {
                        return(true);
                    }

                    foreach (var arg in type.Instantiation)
                    {
                        if (IsBlocked(arg))
                        {
                            return(true);
                        }
                    }

                    return(false);
                }

                return(_policy.IsBlocked((Cts.MetadataType)type));
            }
        }
示例#4
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;
        }
示例#5
0
        private void InitializeTypeInstance(Cts.TypeDesc entity, TypeSpecification record)
        {
            var sig = new TypeInstantiationSignature
            {
                GenericType = HandleType(entity.GetTypeDefinition()),
            };

            for (int i = 0; i < entity.Instantiation.Length; i++)
            {
                sig.GenericTypeArguments.Add(HandleType(entity.Instantiation[i]));
            }

            record.Signature = sig;
        }
        public override IEnumerable<MethodDesc> ComputeAllVirtualMethods(TypeDesc type)
        {
            var context = (CompilerTypeSystemContext)type.Context;

            InstantiatedType instantiatedType = type as InstantiatedType;
            if (instantiatedType != null)
            {
                DelegateInfo info = context.GetDelegateInfo(type.GetTypeDefinition());
                yield return context.GetMethodForInstantiatedType(info.GetThunkMethod, instantiatedType);
            }
            else
            {
                DelegateInfo info = context.GetDelegateInfo(type);
                yield return info.GetThunkMethod;
            }
        }
示例#7
0
        protected IEnumerable <MethodDesc> GetAllMethodsForEnum(TypeDesc enumType)
        {
            TypeDesc enumTypeDefinition = enumType.GetTypeDefinition();
            EnumInfo info = _enumInfoHashtable.GetOrCreateValue(enumTypeDefinition);

            if (enumType != enumTypeDefinition)
            {
                yield return(GetMethodForInstantiatedType(info.GetHashCodeMethod, (InstantiatedType)enumType));

                yield return(GetMethodForInstantiatedType(info.EqualsMethod, (InstantiatedType)enumType));
            }
            else
            {
                yield return(info.GetHashCodeMethod);

                yield return(info.EqualsMethod);
            }
        }
示例#8
0
        public static bool CheckConstraints(this TypeDesc type)
        {
            TypeDesc uninstantiatedType = type.GetTypeDefinition();

            // Non-generic types always pass constraints check
            if (uninstantiatedType == type)
            {
                return(true);
            }

            for (int i = 0; i < uninstantiatedType.Instantiation.Length; i++)
            {
                if (!VerifyGenericParamConstraint(type.Instantiation, default(Instantiation), (GenericParameterDesc)uninstantiatedType.Instantiation[i], type.Instantiation[i]))
                {
                    return(false);
                }
            }

            return(true);
        }
        protected virtual IEnumerable <MethodDesc> GetAllMethodsForValueType(TypeDesc valueType)
        {
            TypeDesc valueTypeDefinition = valueType.GetTypeDefinition();

            if (RequiresGetFieldHelperMethod((MetadataType)valueTypeDefinition))
            {
                MethodDesc getFieldHelperMethod = _valueTypeMethodHashtable.GetOrCreateValue((DefType)valueTypeDefinition);

                if (valueType != valueTypeDefinition)
                {
                    yield return(GetMethodForInstantiatedType(getFieldHelperMethod, (InstantiatedType)valueType));
                }
                else
                {
                    yield return(getFieldHelperMethod);
                }
            }

            foreach (MethodDesc method in valueType.GetMethods())
            {
                yield return(method);
            }
        }
        protected virtual IEnumerable<MethodDesc> GetAllMethodsForValueType(TypeDesc valueType)
        {
            TypeDesc valueTypeDefinition = valueType.GetTypeDefinition();

            if (RequiresGetFieldHelperMethod((MetadataType)valueTypeDefinition))
            {
                MethodDesc getFieldHelperMethod = _valueTypeMethodHashtable.GetOrCreateValue((DefType)valueTypeDefinition);

                // Check that System.ValueType has the method we're overriding.
                Debug.Assert(valueTypeDefinition.BaseType.GetMethod(getFieldHelperMethod.Name, null) != null);

                if (valueType != valueTypeDefinition)
                {
                    yield return GetMethodForInstantiatedType(getFieldHelperMethod, (InstantiatedType)valueType);
                }
                else
                {
                    yield return getFieldHelperMethod;
                }
            }

            foreach (MethodDesc method in valueType.GetMethods())
                yield return method;
        }
示例#11
0
        public MethodDesc TryResolveConstrainedEnumMethod(TypeDesc enumType, MethodDesc virtualMethod)
        {
            Debug.Assert(enumType.IsEnum);

            if (!virtualMethod.OwningType.IsObject)
            {
                return(null);
            }

            // Also handle the odd case of generic enums

            TypeDesc enumTypeDefinition = enumType.GetTypeDefinition();
            EnumInfo info = _enumInfoHashtable.GetOrCreateValue(enumTypeDefinition);

            MethodDesc resolvedMethod;

            if (virtualMethod.Name == "Equals")
            {
                resolvedMethod = info.EqualsMethod;
            }
            else if (virtualMethod.Name == "GetHashCode")
            {
                resolvedMethod = info.GetHashCodeMethod;
            }
            else
            {
                return(null);
            }

            if (enumType != enumTypeDefinition)
            {
                return(GetMethodForInstantiatedType(resolvedMethod, (InstantiatedType)enumType));
            }

            return(resolvedMethod);
        }
        protected virtual IEnumerable <MethodDesc> GetAllMethodsForEnum(TypeDesc enumType, bool virtualOnly)
        {
            if (virtualOnly)
            {
                // We devirtualize these, but they're not actually virtual. We don't want standalone method bodies
                // referenced from vtables. The base implementation on System.Enum is perflectly adequate.
                yield break;
            }

            if (_objectEqualsMethod == null)
            {
                _objectEqualsMethod = GetWellKnownType(WellKnownType.Object).GetMethod("Equals", null);
            }

            // If the classlib doesn't have Object.Equals, we don't need this.
            if (_objectEqualsMethod == null)
            {
                yield break;
            }

            TypeDesc enumTypeDefinition = enumType.GetTypeDefinition();
            EnumInfo info = _enumInfoHashtable.GetOrCreateValue(enumTypeDefinition);

            if (enumType != enumTypeDefinition)
            {
                yield return(GetMethodForInstantiatedType(info.GetHashCodeMethod, (InstantiatedType)enumType));

                yield return(GetMethodForInstantiatedType(info.EqualsMethod, (InstantiatedType)enumType));
            }
            else
            {
                yield return(info.GetHashCodeMethod);

                yield return(info.EqualsMethod);
            }
        }
示例#13
0
        /// <summary>
        /// If given <param name="type"/> is an <see cref="EcmaType"/> precompute its mangled type name
        /// along with all the other types from the same module as <param name="type"/>.
        /// Otherwise, it is a constructed type and to the EcmaType's mangled name we add a suffix to
        /// show what kind of constructed type it is (e.g. appending __Array for an array type).
        /// </summary>
        /// <param name="type">Type to mangled</param>
        /// <returns>Mangled name for <param name="type"/>.</returns>
        private string ComputeMangledTypeName(TypeDesc type)
        {
            if (type is EcmaType)
            {
                EcmaType ecmaType = (EcmaType)type;

                string prependAssemblyName = SanitizeName(((EcmaAssembly)ecmaType.EcmaModule).GetName().Name);

                var deduplicator = new HashSet<string>();

                // Add consistent names for all types in the module, independent on the order in which
                // they are compiled
                lock (this)
                {
                    foreach (MetadataType t in ((EcmaType)type).EcmaModule.GetAllTypes())
                    {
                        string name = t.GetFullName();

                        // Include encapsulating type
                        DefType containingType = t.ContainingType;
                        while (containingType != null)
                        {
                            name = containingType.GetFullName() + "_" + name;
                            containingType = containingType.ContainingType;
                        }

                        name = SanitizeName(name, true);

                        if (_mangleForCplusPlus)
                        {
                            // Always generate a fully qualified name
                            name = "::" + prependAssemblyName + "::" + name;
                        }
                        else
                        {
                            name = prependAssemblyName + "_" + name;
                        }

                        // Ensure that name is unique and update our tables accordingly.
                        name = DisambiguateName(name, deduplicator);
                        deduplicator.Add(name);
                        _mangledTypeNames = _mangledTypeNames.Add(t, name);
                    }
                }

                return _mangledTypeNames[type];
            }


            string mangledName;

            switch (type.Category)
            {
                case TypeFlags.Array:
                case TypeFlags.SzArray:
                    // mangledName = "Array<" + GetSignatureCPPTypeName(((ArrayType)type).ElementType) + ">";
                    mangledName = GetMangledTypeName(((ArrayType)type).ElementType) + "__Array";
                    if (!type.IsSzArray)
                        mangledName += "Rank" + ((ArrayType)type).Rank.ToStringInvariant();
                    break;
                case TypeFlags.ByRef:
                    mangledName = GetMangledTypeName(((ByRefType)type).ParameterType) + "__ByRef";
                    break;
                case TypeFlags.Pointer:
                    mangledName = GetMangledTypeName(((PointerType)type).ParameterType) + "__Pointer";
                    break;
                default:
                    // Case of a generic type. If `type' is a type definition we use the type name
                    // for mangling, otherwise we use the mangling of the type and its generic type
                    // parameters, e.g. A <B> becomes A__B.
                    var typeDefinition = type.GetTypeDefinition();
                    if (typeDefinition != type)
                    {
                        mangledName = GetMangledTypeName(typeDefinition);

                        var inst = type.Instantiation;
                        for (int i = 0; i < inst.Length; i++)
                        {
                            string instArgName = GetMangledTypeName(inst[i]);
                            if (_mangleForCplusPlus)
                                instArgName = instArgName.Replace("::", "_");
                            mangledName += "__" + instArgName;
                        }
                    }
                    else
                    {
                        mangledName = SanitizeName(((DefType)type).GetFullName(), true);
                    }
                    break;
            }

            lock (this)
            {
                // Ensure that name is unique and update our tables accordingly.
                _mangledTypeNames = _mangledTypeNames.Add(type, mangledName);
            }

            return mangledName;
        }
示例#14
0
 /// <summary>
 /// Determine if two types share the same type definition
 /// </summary>
 public bool HasSameTypeDefinition(TypeDesc otherType)
 {
     return(GetTypeDefinition() == otherType.GetTypeDefinition());
 }
示例#15
0
        private static bool CanCastByVarianceToInterfaceOrDelegate(this TypeDesc thisType, TypeDesc otherType, StackOverflowProtect protectInput)
        {
            if (!thisType.HasSameTypeDefinition(otherType))
            {
                return(false);
            }

            var stackOverflowProtectKey = new CastingPair(thisType, otherType);

            if (protectInput != null)
            {
                if (protectInput.Contains(stackOverflowProtectKey))
                {
                    return(false);
                }
            }

            StackOverflowProtect protect = new StackOverflowProtect(stackOverflowProtectKey, protectInput);

            Instantiation instantiationThis   = thisType.Instantiation;
            Instantiation instantiationTarget = otherType.Instantiation;
            Instantiation instantiationOpen   = thisType.GetTypeDefinition().Instantiation;

            Debug.Assert(instantiationThis.Length == instantiationTarget.Length &&
                         instantiationThis.Length == instantiationOpen.Length);

            for (int i = 0; i < instantiationThis.Length; i++)
            {
                TypeDesc arg       = instantiationThis[i];
                TypeDesc targetArg = instantiationTarget[i];

                if (arg != targetArg)
                {
                    GenericParameterDesc openArgType = (GenericParameterDesc)instantiationOpen[i];

                    switch (openArgType.Variance)
                    {
                    case GenericVariance.Covariant:
                        if (!arg.IsBoxedAndCanCastTo(targetArg, protect))
                        {
                            return(false);
                        }
                        break;

                    case GenericVariance.Contravariant:
                        if (!targetArg.IsBoxedAndCanCastTo(arg, protect))
                        {
                            return(false);
                        }
                        break;

                    default:
                        // non-variant
                        Debug.Assert(openArgType.Variance == GenericVariance.None);
                        return(false);
                    }
                }
            }

            return(true);
        }
示例#16
0
文件: TypeDesc.cs 项目: mjp41/corert
 /// <summary>
 /// Determine if two types share the same type definition
 /// </summary>
 public bool HasSameTypeDefinition(TypeDesc otherType)
 {
     return GetTypeDefinition() == otherType.GetTypeDefinition();
 }
        /// <summary>
        /// Locate field on native format type and fill in the field access flags and offset.
        /// </summary>
        /// <param name="type">Metadata reader for the declaring type</param>
        /// <param name="fieldName">Field name</param>
        /// <param name="fieldAccessMetadata">Output - metadata information for field accessor construction</param>
        /// <returns>true when found, false otherwise</returns>
        private static bool TryGetFieldAccessMetadataForNativeFormatType(
            TypeDesc type,
            string fieldName,
            ref FieldAccessMetadata fieldAccessMetadata)
        {
#if SUPPORTS_NATIVE_METADATA_TYPE_LOADING
            FieldDesc fieldDesc = type.GetField(fieldName);
            if (fieldDesc == null)
            {
                return false;
            }

            fieldAccessMetadata.MappingTableModule = IntPtr.Zero;

#if SUPPORTS_R2R_LOADING
            fieldAccessMetadata.MappingTableModule = ModuleList.Instance.GetModuleForMetadataReader(((NativeFormatType)type.GetTypeDefinition()).MetadataReader);
#endif
            fieldAccessMetadata.Offset = fieldDesc.Offset;
            fieldAccessMetadata.Flags = FieldTableFlags.HasMetadataHandle;

            if (fieldDesc.IsThreadStatic)
            {
                // Specify that the data is thread local
                fieldAccessMetadata.Flags |= FieldTableFlags.ThreadStatic;

                // Specify that the general purpose field access routine that only relies on offset should be used.
                fieldAccessMetadata.Flags |= FieldTableFlags.IsUniversalCanonicalEntry;
            }
            else if (fieldDesc.IsStatic)
            {
                uint nonGcStaticsRVA = 0;
                uint gcStaticsRVA = 0;
                bool nonGenericCase = false;

                if (type is MetadataType)
                {
                    // Static fields on Non-Generic types are contained within the module, and their offsets
                    // are adjusted by their static rva base.
                    nonGenericCase = true;

#if SUPPORTS_R2R_LOADING
                    if (!TryGetStaticsTableEntry((MetadataType)type, nonGcStaticsRVA: out nonGcStaticsRVA, gcStaticsRVA: out gcStaticsRVA))
#endif
                    {
                        Environment.FailFast(
                            "Failed to locate statics table entry for for field '" +
                            fieldName +
                            "' on type " +
                            type.ToString());
                    }
                }

                if (fieldDesc.HasGCStaticBase)
                {
                    if ((gcStaticsRVA == 0) && nonGenericCase)
                    {
                        Environment.FailFast(
                            "GC statics region was not found for field '" +
                            fieldName +
                            "' on type " +
                            type.ToString());
                    }
                    fieldAccessMetadata.Offset += (int)gcStaticsRVA;
                    fieldAccessMetadata.Flags |= FieldTableFlags.IsGcSection;
                }
                else
                {
                    if ((nonGcStaticsRVA == 0) && nonGenericCase)
                    {
                        Environment.FailFast(
                            "Non-GC statics region was not found for field '" +
                            fieldName +
                            "' on type " +
                            type.ToString());
                    }
                    fieldAccessMetadata.Offset += (int)nonGcStaticsRVA;
                }
                fieldAccessMetadata.Flags |= FieldTableFlags.Static;
                return true;
            }
            else
            {
                // Instance field
                fieldAccessMetadata.Flags |= FieldTableFlags.Instance;
            }

            return true;
#else
            return false;
#endif
        }
示例#18
0
        /// <summary>
        /// Replace some of the types in a type's construction with a new set of types. This function does not
        /// support any situation where there is an instantiated generic that is not represented by an
        /// InstantiatedType. Does not replace the open generics that may be instantiated over in this type.
        ///
        /// For instance, Given MyType&lt;object, int[]&gt;,
        ///  an array of types to replace such as {int,object}, and
        ///  an array of replacement types such as {string,__Canon}.
        ///  The result shall be MyType&lt;__Canon, string[]&gt;
        ///
        /// This function cannot be used to replace MyType in the above example.
        /// </summary>
        public static TypeDesc ReplaceTypesInConstructionOfType(this TypeDesc type, TypeDesc[] typesToReplace, TypeDesc[] replacementTypes)
        {
            int directReplacementIndex = Array.IndexOf(typesToReplace, type);

            if (directReplacementIndex != -1)
            {
                return(replacementTypes[directReplacementIndex]);
            }

            if (type.HasInstantiation)
            {
                TypeDesc[] newInstantiation = null;
                Debug.Assert(type is InstantiatedType);
                int instantiationIndex = 0;
                for (; instantiationIndex < type.Instantiation.Length; instantiationIndex++)
                {
                    TypeDesc oldType = type.Instantiation[instantiationIndex];
                    TypeDesc newType = oldType.ReplaceTypesInConstructionOfType(typesToReplace, replacementTypes);
                    if ((oldType != newType) || (newInstantiation != null))
                    {
                        if (newInstantiation == null)
                        {
                            newInstantiation = new TypeDesc[type.Instantiation.Length];
                            for (int i = 0; i < instantiationIndex; i++)
                            {
                                newInstantiation[i] = type.Instantiation[i];
                            }
                        }
                        newInstantiation[instantiationIndex] = newType;
                    }
                }
                if (newInstantiation != null)
                {
                    return(type.Context.GetInstantiatedType((MetadataType)type.GetTypeDefinition(), new Instantiation(newInstantiation)));
                }
            }
            else if (type.IsParameterizedType)
            {
                ParameterizedType parameterizedType = (ParameterizedType)type;
                TypeDesc          oldParameter      = parameterizedType.ParameterType;
                TypeDesc          newParameter      = oldParameter.ReplaceTypesInConstructionOfType(typesToReplace, replacementTypes);
                if (oldParameter != newParameter)
                {
                    if (type.IsArray)
                    {
                        ArrayType arrayType = (ArrayType)type;
                        if (arrayType.IsSzArray)
                        {
                            return(type.Context.GetArrayType(newParameter));
                        }
                        else
                        {
                            return(type.Context.GetArrayType(newParameter, arrayType.Rank));
                        }
                    }
                    else if (type.IsPointer)
                    {
                        return(type.Context.GetPointerType(newParameter));
                    }
                    else if (type.IsByRef)
                    {
                        return(type.Context.GetByRefType(newParameter));
                    }
                    Debug.Fail("Unknown form of type");
                }
            }
            else if (type.IsFunctionPointer)
            {
                MethodSignature        oldSig     = ((FunctionPointerType)type).Signature;
                MethodSignatureBuilder sigBuilder = new MethodSignatureBuilder(oldSig);
                sigBuilder.ReturnType = oldSig.ReturnType.ReplaceTypesInConstructionOfType(typesToReplace, replacementTypes);
                for (int paramIndex = 0; paramIndex < oldSig.Length; paramIndex++)
                {
                    sigBuilder[paramIndex] = oldSig[paramIndex].ReplaceTypesInConstructionOfType(typesToReplace, replacementTypes);
                }

                MethodSignature newSig = sigBuilder.ToSignature();
                if (newSig != oldSig)
                {
                    return(type.Context.GetFunctionPointerType(newSig));
                }
            }

            return(type);
        }
示例#19
0
        private string ComputeMangledTypeName(TypeDesc type)
        {
            if (type is EcmaType)
            {
                string prependAssemblyName = SanitizeName(((EcmaType)type).EcmaModule.GetName().Name);

                var deduplicator = new HashSet<string>();

                // Add consistent names for all types in the module, independent on the order in which 
                // they are compiled
                lock (this)
                {
                    foreach (MetadataType t in ((EcmaType)type).EcmaModule.GetAllTypes())
                    {
                        string name = t.GetFullName();

                        // Include encapsulating type
                        MetadataType containingType = t.ContainingType;
                        while (containingType != null)
                        {
                            name = containingType.GetFullName() + "_" + name;
                            containingType = containingType.ContainingType;
                        }

                        name = SanitizeName(name, true);

                        if (deduplicator.Contains(name))
                        {
                            string nameWithIndex;
                            for (int index = 1; ; index++)
                            {
                                nameWithIndex = name + "_" + index.ToString(CultureInfo.InvariantCulture);
                                if (!deduplicator.Contains(nameWithIndex))
                                    break;
                            }
                            name = nameWithIndex;
                        }
                        deduplicator.Add(name);

                        if (_compilation.IsCppCodeGen)
                            name = prependAssemblyName + "::" + name;
                        else
                            name = prependAssemblyName + "_" + name;

                        _mangledTypeNames = _mangledTypeNames.Add(t, name);
                    }
                }

                return _mangledTypeNames[type];
            }


            string mangledName;

            switch (type.Category)
            {
                case TypeFlags.Array:
                    // mangledName = "Array<" + GetSignatureCPPTypeName(((ArrayType)type).ElementType) + ">";
                    mangledName = GetMangledTypeName(((ArrayType)type).ElementType) + "__Array";
                    if (((ArrayType)type).Rank != 1)
                        mangledName += "Rank" + ((ArrayType)type).Rank.ToString();
                    break;
                case TypeFlags.ByRef:
                    mangledName = GetMangledTypeName(((ByRefType)type).ParameterType) + "__ByRef";
                    break;
                case TypeFlags.Pointer:
                    mangledName = GetMangledTypeName(((PointerType)type).ParameterType) + "__Pointer";
                    break;
                default:
                    var typeDefinition = type.GetTypeDefinition();
                    if (typeDefinition != type)
                    {
                        mangledName = GetMangledTypeName(typeDefinition);

                        var inst = type.Instantiation;
                        for (int i = 0; i < inst.Length; i++)
                        {
                            string instArgName = GetMangledTypeName(inst[i]);
                            if (_compilation.IsCppCodeGen)
                                instArgName = instArgName.Replace("::", "_");
                            mangledName += "__" + instArgName;
                        }
                    }
                    else
                    {
                        mangledName = SanitizeName(((MetadataType)type).GetFullName(), true);
                    }
                    break;
            }

            lock (this)
            {
                _mangledTypeNames = _mangledTypeNames.Add(type, mangledName);
            }

            return mangledName;
        }
        private void EncodeType(BlobBuilder blobBuilder, TypeDesc type, EmbeddedSignatureDataEmitter signatureDataEmitter)
        {
            signatureDataEmitter.Push();
            signatureDataEmitter.Push();
            signatureDataEmitter.EmitAtCurrentIndexStack(blobBuilder);
            signatureDataEmitter.Pop();

            signatureDataEmitter.Push();
            if (type.IsPrimitive)
            {
                SignatureTypeCode primitiveCode;
                switch (type.Category)
                {
                case TypeFlags.Void:
                    primitiveCode = SignatureTypeCode.Void;
                    break;

                case TypeFlags.Boolean:
                    primitiveCode = SignatureTypeCode.Boolean;
                    break;

                case TypeFlags.Char:
                    primitiveCode = SignatureTypeCode.Char;
                    break;

                case TypeFlags.SByte:
                    primitiveCode = SignatureTypeCode.SByte;
                    break;

                case TypeFlags.Byte:
                    primitiveCode = SignatureTypeCode.Byte;
                    break;

                case TypeFlags.Int16:
                    primitiveCode = SignatureTypeCode.Int16;
                    break;

                case TypeFlags.UInt16:
                    primitiveCode = SignatureTypeCode.UInt16;
                    break;

                case TypeFlags.Int32:
                    primitiveCode = SignatureTypeCode.Int32;
                    break;

                case TypeFlags.UInt32:
                    primitiveCode = SignatureTypeCode.UInt32;
                    break;

                case TypeFlags.Int64:
                    primitiveCode = SignatureTypeCode.Int64;
                    break;

                case TypeFlags.UInt64:
                    primitiveCode = SignatureTypeCode.UInt64;
                    break;

                case TypeFlags.IntPtr:
                    primitiveCode = SignatureTypeCode.IntPtr;
                    break;

                case TypeFlags.UIntPtr:
                    primitiveCode = SignatureTypeCode.UIntPtr;
                    break;

                case TypeFlags.Single:
                    primitiveCode = SignatureTypeCode.Single;
                    break;

                case TypeFlags.Double:
                    primitiveCode = SignatureTypeCode.Double;
                    break;

                default:
                    throw new Exception("Unknown primitive type");
                }

                blobBuilder.WriteByte((byte)primitiveCode);
            }
            else if (type.IsSzArray)
            {
                blobBuilder.WriteByte((byte)SignatureTypeCode.SZArray);
                EncodeType(blobBuilder, type.GetParameterType(), signatureDataEmitter);
            }
            else if (type.IsArray)
            {
                var arrayType = (ArrayType)type;
                blobBuilder.WriteByte((byte)SignatureTypeCode.Array);
                EncodeType(blobBuilder, type.GetParameterType(), signatureDataEmitter);

                signatureDataEmitter.EmitArrayShapeAtCurrentIndexStack(blobBuilder, arrayType.Rank);
            }
            else if (type.IsPointer)
            {
                blobBuilder.WriteByte((byte)SignatureTypeCode.Pointer);
                EncodeType(blobBuilder, type.GetParameterType(), signatureDataEmitter);
            }
            else if (type.IsFunctionPointer)
            {
                FunctionPointerType fnptrType = (FunctionPointerType)type;
                blobBuilder.WriteByte((byte)SignatureTypeCode.FunctionPointer);
                EncodeMethodSignature(blobBuilder, fnptrType.Signature, signatureDataEmitter);
            }
            else if (type.IsByRef)
            {
                blobBuilder.WriteByte((byte)SignatureTypeCode.ByReference);
                EncodeType(blobBuilder, type.GetParameterType(), signatureDataEmitter);
            }
            else if (type.IsObject)
            {
                blobBuilder.WriteByte((byte)SignatureTypeCode.Object);
            }
            else if (type.IsString)
            {
                blobBuilder.WriteByte((byte)SignatureTypeCode.String);
            }
            else if (type.IsWellKnownType(WellKnownType.TypedReference))
            {
                blobBuilder.WriteByte((byte)SignatureTypeCode.TypedReference);
            }
            else if (type.IsWellKnownType(WellKnownType.Void))
            {
                blobBuilder.WriteByte((byte)SignatureTypeCode.Void);
            }
            else if (type is SignatureVariable)
            {
                SignatureVariable sigVar = (SignatureVariable)type;
                SignatureTypeCode code   = sigVar.IsMethodSignatureVariable ? SignatureTypeCode.GenericMethodParameter : SignatureTypeCode.GenericTypeParameter;
                blobBuilder.WriteByte((byte)code);
                blobBuilder.WriteCompressedInteger(sigVar.Index);
            }
            else if (type is InstantiatedType)
            {
                blobBuilder.WriteByte((byte)SignatureTypeCode.GenericTypeInstance);
                EncodeType(blobBuilder, type.GetTypeDefinition(), signatureDataEmitter);
                blobBuilder.WriteCompressedInteger(type.Instantiation.Length);
                foreach (var instantiationArg in type.Instantiation)
                {
                    EncodeType(blobBuilder, instantiationArg, signatureDataEmitter);
                }
            }
            else if (type is MetadataType)
            {
                var metadataType = (MetadataType)type;
                // Must be class or valuetype
                blobBuilder.WriteByte(type.IsValueType ? (byte)SignatureTypeKind.ValueType : (byte)SignatureTypeKind.Class);
                int codedIndex = CodedIndex.TypeDefOrRef(GetTypeRef(metadataType));
                blobBuilder.WriteCompressedInteger(codedIndex);
            }
            else
            {
                throw new Exception("Unexpected type");
            }
            signatureDataEmitter.Pop();
            signatureDataEmitter.Pop();
        }