diff options
Diffstat (limited to 'src/ILCompiler.Compiler/src/Compiler/UtcNameMangler.cs')
-rw-r--r-- | src/ILCompiler.Compiler/src/Compiler/UtcNameMangler.cs | 84 |
1 files changed, 75 insertions, 9 deletions
diff --git a/src/ILCompiler.Compiler/src/Compiler/UtcNameMangler.cs b/src/ILCompiler.Compiler/src/Compiler/UtcNameMangler.cs index 6eaf70a75..5a0aa6515 100644 --- a/src/ILCompiler.Compiler/src/Compiler/UtcNameMangler.cs +++ b/src/ILCompiler.Compiler/src/Compiler/UtcNameMangler.cs @@ -40,15 +40,19 @@ namespace ILCompiler private ImportExportOrdinals _importOrdinals; private ImportExportOrdinals _exportOrdinals; + private Dictionary<EcmaModule, int> _inputModuleIndices; + private bool HasImport { get; set; } private bool HasExport { get; set; } + private bool BuildingClassLib { get; } - public UTCNameMangler(bool hasImport, bool hasExport, ImportExportOrdinals ordinals) : base(new UtcNodeMangler()) + public UTCNameMangler(bool hasImport, bool hasExport, ImportExportOrdinals ordinals, TypeSystemContext context, List<EcmaModule> inputModules, bool buildingClassLib) : base(new UtcNodeMangler()) { // Do not support both imports and exports for one module Debug.Assert(!hasImport || !hasExport); HasImport = hasImport; HasExport = hasExport; + BuildingClassLib = buildingClassLib; if (hasImport) { @@ -59,11 +63,35 @@ namespace ILCompiler _exportOrdinals = ordinals; } + _inputModuleIndices = new Dictionary<EcmaModule, int>(); + for (int i = 0; i < inputModules.Count; i++) + _inputModuleIndices[inputModules[i]] = i; + // Use SHA256 hash here to provide a high degree of uniqueness to symbol names without requiring them to be long // This hash function provides an exceedingly high likelihood that no two strings will be given equal symbol names // This is not considered used for security purpose; however collisions would be highly unfortunate as they will cause compilation // failure. _sha256 = SHA256.Create(); + + // Special case primitive types and use shortened names. This reduces string sizes in symbol names, and reduces the overall native memory + // usage of the compiler + _mangledTypeNames = _mangledTypeNames.Add(context.GetWellKnownType(WellKnownType.Void), "void"); + _mangledTypeNames = _mangledTypeNames.Add(context.GetWellKnownType(WellKnownType.Boolean), "bool"); + _mangledTypeNames = _mangledTypeNames.Add(context.GetWellKnownType(WellKnownType.Char), "char"); + _mangledTypeNames = _mangledTypeNames.Add(context.GetWellKnownType(WellKnownType.SByte), "sbyte"); + _mangledTypeNames = _mangledTypeNames.Add(context.GetWellKnownType(WellKnownType.Byte), "byte"); + _mangledTypeNames = _mangledTypeNames.Add(context.GetWellKnownType(WellKnownType.Int16), "short"); + _mangledTypeNames = _mangledTypeNames.Add(context.GetWellKnownType(WellKnownType.UInt16), "ushort"); + _mangledTypeNames = _mangledTypeNames.Add(context.GetWellKnownType(WellKnownType.Int32), "int"); + _mangledTypeNames = _mangledTypeNames.Add(context.GetWellKnownType(WellKnownType.UInt32), "uint"); + _mangledTypeNames = _mangledTypeNames.Add(context.GetWellKnownType(WellKnownType.Int64), "long"); + _mangledTypeNames = _mangledTypeNames.Add(context.GetWellKnownType(WellKnownType.UInt64), "ulong"); + _mangledTypeNames = _mangledTypeNames.Add(context.GetWellKnownType(WellKnownType.Single), "float"); + _mangledTypeNames = _mangledTypeNames.Add(context.GetWellKnownType(WellKnownType.Double), "double"); + _mangledTypeNames = _mangledTypeNames.Add(context.GetWellKnownType(WellKnownType.Object), "object"); + _mangledTypeNames = _mangledTypeNames.Add(context.GetWellKnownType(WellKnownType.String), "string"); + _mangledTypeNames = _mangledTypeNames.Add(context.GetWellKnownType(WellKnownType.IntPtr), "IntPtr"); + _mangledTypeNames = _mangledTypeNames.Add(context.GetWellKnownType(WellKnownType.UIntPtr), "UIntPtr"); } private bool GetMethodOrdinal(MethodDesc method, out uint ordinal) @@ -157,6 +185,15 @@ namespace ILCompiler continue; } + if (sb != null) + { + if (c == '[' || c == ']' || c == '&' || c == '*' || c == '$' || c == '<' || c == '>') + { + sb.Append(c); + continue; + } + } + if (sb == null) sb = new StringBuilder(s, 0, i, s.Length); @@ -167,6 +204,13 @@ namespace ILCompiler continue; } + if (c == '$' && i == 0) + { + // '$' is used at the begining of the string as assembly identifiers (ex: $0_, similar to ProjectN) + sb.Append(c); + continue; + } + // Everything else is replaced by underscore. // TODO: We assume that there won't be collisions with our own or C++ built-in identifiers. sb.Append("_"); @@ -254,6 +298,20 @@ namespace ILCompiler return EnterNameScopeSequence + name + ExitNameScopeSequence; } + private string ComputeMangledModuleName(EcmaAssembly module) + { + // Do not prepend the module prefix when building pntestcl because the prefix is unknown + // when building an app against pntestcl. + if (!BuildingClassLib) + { + int index; + if (_inputModuleIndices.TryGetValue(module, out index)) + return "$" + index; + } + + return SanitizeName(module.GetName().Name); + } + /// <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"/>. @@ -268,7 +326,7 @@ namespace ILCompiler { EcmaType ecmaType = (EcmaType)type; - string prependAssemblyName = SanitizeName(((EcmaAssembly)ecmaType.EcmaModule).GetName().Name); + string prependAssemblyName = ComputeMangledModuleName((EcmaAssembly)ecmaType.EcmaModule); var deduplicator = new HashSet<string>(); @@ -280,6 +338,15 @@ namespace ILCompiler { foreach (MetadataType t in ((EcmaType)type).EcmaModule.GetAllTypes()) { + if (_mangledTypeNames.ContainsKey(t)) + { + Debug.Assert( + (t.Category & TypeFlags.CategoryMask) <= TypeFlags.Double || + t == type.Context.GetWellKnownType(WellKnownType.Object) || + t == type.Context.GetWellKnownType(WellKnownType.String)); + continue; + } + string name = t.GetFullName(); // Include encapsulating type @@ -290,8 +357,7 @@ namespace ILCompiler containingType = containingType.ContainingType; } - name = SanitizeName(name, true); - name = prependAssemblyName + "_" + name; + name = SanitizeName(prependAssemblyName + "_" + name, true); // Ensure that name is unique and update our tables accordingly. name = DisambiguateName(name, deduplicator); @@ -310,22 +376,22 @@ namespace ILCompiler { case TypeFlags.Array: case TypeFlags.SzArray: - mangledName = GetMangledTypeName(((ArrayType)type).ElementType) + "__"; + mangledName = GetMangledTypeName(((ArrayType)type).ElementType); if (type.IsMdArray) { - mangledName += NestMangledName("ArrayRank" + ((ArrayType)type).Rank.ToStringInvariant()); + mangledName += "[md" + ((ArrayType)type).Rank.ToString() + "]"; } else { - mangledName += NestMangledName("Array"); + mangledName += "[]"; } break; case TypeFlags.ByRef: - mangledName = GetMangledTypeName(((ByRefType)type).ParameterType) + NestMangledName("ByRef"); + mangledName = GetMangledTypeName(((ByRefType)type).ParameterType) + "&"; break; case TypeFlags.Pointer: - mangledName = GetMangledTypeName(((PointerType)type).ParameterType) + NestMangledName("Pointer"); + mangledName = GetMangledTypeName(((PointerType)type).ParameterType) + "*"; break; default: |