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); } }
/// <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); }
/// <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); }