public uint GetEnumTypeIndex(TypeDesc type)
        {
            System.Diagnostics.Debug.Assert(type.IsEnum, "GetEnumTypeIndex was called with wrong type");
            DefType defType = type as DefType;

            System.Diagnostics.Debug.Assert(defType != null, "GetEnumTypeIndex was called with non def type");
            EnumTypeDescriptor enumTypeDescriptor = new EnumTypeDescriptor();
            List <FieldDesc>   fieldsDescriptors  = new List <FieldDesc>();

            foreach (var field in defType.GetFields())
            {
                if (field.IsLiteral)
                {
                    fieldsDescriptors.Add(field);
                }
            }
            enumTypeDescriptor.ElementCount = (ulong)fieldsDescriptors.Count;
            enumTypeDescriptor.ElementType  = PrimitiveTypeDescriptor.GetPrimitiveTypeIndex(defType.UnderlyingType);
            enumTypeDescriptor.Name         = defType.Name;
            enumTypeDescriptor.UniqueName   = defType.GetFullName();
            EnumRecordTypeDescriptor[] typeRecords = new EnumRecordTypeDescriptor[enumTypeDescriptor.ElementCount];
            for (int i = 0; i < fieldsDescriptors.Count; ++i)
            {
                FieldDesc field = fieldsDescriptors[i];
                EnumRecordTypeDescriptor recordTypeDescriptor;
                recordTypeDescriptor.Value = GetEnumRecordValue(field);
                recordTypeDescriptor.Name  = field.Name;
                typeRecords[i]             = recordTypeDescriptor;
            }
            uint typeIndex = _objectWriter.GetEnumTypeIndex(enumTypeDescriptor, typeRecords);

            _knownTypes[type]         = typeIndex;
            _completeKnownTypes[type] = typeIndex;
            return(typeIndex);
        }
        public uint GetClassTypeIndex(TypeDesc type, bool needsCompleteType)
        {
            DefType defType = type as DefType;

            System.Diagnostics.Debug.Assert(defType != null, "GetClassTypeIndex was called with non def type");
            ClassTypeDescriptor classTypeDescriptor = new ClassTypeDescriptor();

            classTypeDescriptor.IsStruct    = type.IsValueType ? 1 : 0;
            classTypeDescriptor.Name        = defType.Name;
            classTypeDescriptor.UniqueName  = defType.GetFullName();
            classTypeDescriptor.BaseClassId = 0;
            if (type.HasBaseType && !type.IsValueType)
            {
                classTypeDescriptor.BaseClassId = GetVariableTypeIndex(defType.BaseType, false);
            }
            uint typeIndex = _objectWriter.GetClassTypeIndex(classTypeDescriptor);

            _knownTypes[type] = typeIndex;

            List <DataFieldDescriptor> fieldsDescs = new List <DataFieldDescriptor>();

            foreach (var fieldDesc in defType.GetFields())
            {
                if (fieldDesc.HasRva || fieldDesc.IsLiteral)
                {
                    continue;
                }
                DataFieldDescriptor field = new DataFieldDescriptor();
                field.FieldTypeIndex = GetVariableTypeIndex(fieldDesc.FieldType, false);
                field.Offset         = fieldDesc.Offset.AsInt;
                field.Name           = fieldDesc.Name;
                fieldsDescs.Add(field);
            }

            DataFieldDescriptor[] fields = new DataFieldDescriptor[fieldsDescs.Count];
            for (int i = 0; i < fieldsDescs.Count; ++i)
            {
                fields[i] = fieldsDescs[i];
            }
            ClassFieldsTypeDescriptor fieldsDescriptor = new ClassFieldsTypeDescriptor();

            fieldsDescriptor.FieldsCount = fieldsDescs.Count;
            fieldsDescriptor.Size        = defType.GetElementSize().AsInt;

            uint completeTypeIndex = _objectWriter.GetCompleteClassTypeIndex(classTypeDescriptor, fieldsDescriptor, fields);

            _completeKnownTypes[type] = completeTypeIndex;

            if (needsCompleteType)
            {
                return(completeTypeIndex);
            }
            else
            {
                return(typeIndex);
            }
        }
Beispiel #3
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)
                {
                    if (!_mangledTypeNames.ContainsKey(type))
                    {
                        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);
                            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 = GetMangledTypeName(((ArrayType)type).ElementType) + "__";

                if (type.IsMdArray)
                {
                    mangledName += NestMangledName("ArrayRank" + ((ArrayType)type).Rank.ToStringInvariant());
                }
                else
                {
                    mangledName += NestMangledName("Array");
                }
                break;

            case TypeFlags.ByRef:
                mangledName = GetMangledTypeName(((ByRefType)type).ParameterType) + NestMangledName("ByRef");
                break;

            case TypeFlags.Pointer:
                mangledName = GetMangledTypeName(((PointerType)type).ParameterType) + NestMangledName("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_>_ in RyuJIT compilation, or A_A___B_V_
                // in C++ compilation.
                var typeDefinition = type.GetTypeDefinition();
                if (typeDefinition != type)
                {
                    mangledName = GetMangledTypeName(typeDefinition);

                    var    inst = type.Instantiation;
                    string mangledInstantiation = "";
                    for (int i = 0; i < inst.Length; i++)
                    {
                        string instArgName = GetMangledTypeName(inst[i]);
                        if (i > 0)
                        {
                            mangledInstantiation += "__";
                        }

                        mangledInstantiation += instArgName;
                    }
                    mangledName += NestMangledName(mangledInstantiation);
                }
                else
                {
                    mangledName = SanitizeName(((DefType)type).GetFullName(), true);
                }
                break;
            }

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

            return(mangledName);
        }
        /// <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 assemblyName    = ((EcmaAssembly)ecmaType.EcmaModule).GetName().Name;
                bool   isSystemPrivate = assemblyName.StartsWith("System.Private.");

                // Abbreviate System.Private to S.P. This might conflict with user defined assembly names,
                // but we already have a problem due to running SanitizeName without disambiguating the result
                // This problem needs a better fix.
                if (isSystemPrivate && !_mangleForCplusPlus)
                {
                    assemblyName = "S.P." + assemblyName.Substring(15);
                }
                string prependAssemblyName = SanitizeName(assemblyName);

                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)
                {
                    bool isSystemModule = ecmaType.Module == ecmaType.Context.SystemModule;

                    if (!_mangledTypeNames.ContainsKey(type))
                    {
                        foreach (MetadataType t in ecmaType.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;

                                // If this is one of the well known types, use a shorter name
                                // We know this won't conflict because all the other types are
                                // prefixed by the assembly name.
                                if (isSystemModule)
                                {
                                    switch (t.Category)
                                    {
                                    case TypeFlags.Boolean: name = "Bool"; break;

                                    case TypeFlags.Byte: name = "UInt8"; break;

                                    case TypeFlags.SByte: name = "Int8"; break;

                                    case TypeFlags.UInt16: name = "UInt16"; break;

                                    case TypeFlags.Int16: name = "Int16"; break;

                                    case TypeFlags.UInt32: name = "UInt32"; break;

                                    case TypeFlags.Int32: name = "Int32"; break;

                                    case TypeFlags.UInt64: name = "UInt64"; break;

                                    case TypeFlags.Int64: name = "Int64"; break;

                                    case TypeFlags.Char: name = "Char"; break;

                                    case TypeFlags.Double: name = "Double"; break;

                                    case TypeFlags.Single: name = "Single"; break;

                                    case TypeFlags.IntPtr: name = "IntPtr"; break;

                                    case TypeFlags.UIntPtr: name = "UIntPtr"; break;

                                    default:
                                        if (t.IsObject)
                                        {
                                            name = "Object";
                                        }
                                        else if (t.IsString)
                                        {
                                            name = "String";
                                        }
                                        break;
                                    }
                                }
                            }

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

            string mangledName;

            switch (type.Category)
            {
            case TypeFlags.Array:
                mangledName = "__MDArray" +
                              EnterNameScopeSequence +
                              GetMangledTypeName(((ArrayType)type).ElementType) +
                              DelimitNameScopeSequence +
                              ((ArrayType)type).Rank.ToStringInvariant() +
                              ExitNameScopeSequence;
                break;

            case TypeFlags.SzArray:
                mangledName = "__Array" + NestMangledName(GetMangledTypeName(((ArrayType)type).ElementType));
                break;

            case TypeFlags.ByRef:
                mangledName = GetMangledTypeName(((ByRefType)type).ParameterType) + NestMangledName("ByRef");
                break;

            case TypeFlags.Pointer:
                mangledName = GetMangledTypeName(((PointerType)type).ParameterType) + NestMangledName("Pointer");
                break;

            case TypeFlags.FunctionPointer:
                // TODO: need to also encode calling convention (or all modopts?)
                var fnPtrType = (FunctionPointerType)type;
                mangledName  = "__FnPtr" + EnterNameScopeSequence;
                mangledName += GetMangledTypeName(fnPtrType.Signature.ReturnType);

                mangledName += EnterNameScopeSequence;
                for (int i = 0; i < fnPtrType.Signature.Length; i++)
                {
                    if (i != 0)
                    {
                        mangledName += DelimitNameScopeSequence;
                    }
                    mangledName += GetMangledTypeName(fnPtrType.Signature[i]);
                }
                mangledName += ExitNameScopeSequence;

                mangledName += ExitNameScopeSequence;
                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_>_ in RyuJIT compilation, or A_A___B_V_
                // in C++ compilation.
                var typeDefinition = type.GetTypeDefinition();
                if (typeDefinition != type)
                {
                    mangledName = GetMangledTypeName(typeDefinition);

                    var    inst = type.Instantiation;
                    string mangledInstantiation = "";
                    for (int i = 0; i < inst.Length; i++)
                    {
                        string instArgName = GetMangledTypeName(inst[i]);
                        if (_mangleForCplusPlus)
                        {
                            instArgName = instArgName.Replace("::", "_");
                        }
                        if (i > 0)
                        {
                            mangledInstantiation += "__";
                        }

                        mangledInstantiation += instArgName;
                    }
                    mangledName += NestMangledName(mangledInstantiation);
                }
                else if (type is IPrefixMangledMethod)
                {
                    mangledName = GetPrefixMangledMethodName((IPrefixMangledMethod)type).ToString();
                }
                else if (type is IPrefixMangledType)
                {
                    mangledName = GetPrefixMangledTypeName((IPrefixMangledType)type).ToString();
                }
                else
                {
                    // This is a type definition. Since we didn't fall in the `is EcmaType` case above,
                    // it's likely a compiler-generated type.
                    mangledName = SanitizeName(((DefType)type).GetFullName(), true);

                    // Always generate a fully qualified name
                    if (_mangleForCplusPlus)
                    {
                        mangledName = "::" + mangledName;
                    }
                }
                break;
            }

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

            return(mangledName);
        }
Beispiel #5
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.IsMdArray)
                {
                    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);
        }