diff --git a/src/ILToNative/reproNative/main.cpp b/src/ILToNative/reproNative/main.cpp
index b7c2750f6f5..c1567c9ea1c 100644
--- a/src/ILToNative/reproNative/main.cpp
+++ b/src/ILToNative/reproNative/main.cpp
@@ -88,28 +88,38 @@ void __register_module(SimpleModuleHeader* pModule)
#endif // USE_MRT
}
-namespace System { class Object {
-public:
- EEType * get_EEType() { return *(EEType **)this; }
-}; };
+namespace mscorlib { namespace System {
+
+ class Object {
+ public:
+ EEType * get_EEType() { return *(EEType **)this; }
+ };
+
+ class Array : public Object {
+ public:
+ int32_t GetArrayLength() {
+ return *(int32_t *)((void **)this + 1);
+ }
+ void * GetArrayData() {
+ return (void **)this + 2;
+ }
+ };
+
+ class String : public Object { public:
+ static MethodTable * __getMethodTable();
+ };
+
+ class String__Array : public Object { public:
+ static MethodTable * __getMethodTable();
+ };
+
+ class EETypePtr { public:
+ intptr_t m_value;
+ };
-namespace System { class Array : public System::Object {
-public:
- int32_t GetArrayLength() {
- return *(int32_t *)((void **)this + 1);
- }
- void * GetArrayData() {
- return (void **)this + 2;
- }
}; };
-namespace System { class String : public System::Object { public:
-static MethodTable * __getMethodTable();
-}; };
-
-namespace System { class EETypePtr { public:
- intptr_t m_value;
-}; }
+using namespace mscorlib;
//
// The fast paths for object allocation and write barriers is performance critical. They are often
@@ -147,6 +157,8 @@ extern "C" Object * __allocate_object(MethodTable * pMT)
Object * __allocate_string(int32_t len)
{
+#ifdef CPPCODEGEN
+
#if !USE_MRT
alloc_context * acontext = GetThread()->GetAllocContext();
Object * pObject;
@@ -178,6 +190,10 @@ Object * __allocate_string(int32_t len)
#else
return RhNewArray(System::String::__getMethodTable(), len);
#endif
+
+#else
+ throw 42;
+#endif
}
extern "C" Object * __allocate_array(MethodTable * pMT, size_t elements)
@@ -291,11 +307,7 @@ void __range_check(void * a, size_t elem)
ThrowRangeOverflowException();
}
-namespace System { class String__Array : public System::Object { public:
-static MethodTable * __getMethodTable();
-}; };
-
-
+#ifdef CPPCODEGEN
Object * __get_commandline_args(int argc, char * argv[])
{
System::Array * p = (System::Array *)__allocate_array(System::String__Array::__getMethodTable(), argc);
@@ -308,6 +320,7 @@ Object * __get_commandline_args(int argc, char * argv[])
return (Object *)p;
}
+#endif
// FCalls
@@ -523,17 +536,17 @@ extern "C" intptr_t RhGetModuleFromEEType(System::EETypePtr)
throw 42;
}
-#if 0
+#ifndef CPPCODEGEN
SimpleModuleHeader __module = { NULL, NULL /* &__gcStatics, &__gcStaticsDescs */ };
-extern "C" int Program__Main();
+extern "C" int repro_Program__Main();
int main(int argc, char * argv[]) {
if (__initialize_runtime() != 0) return -1;
__register_module(&__module);
ReversePInvokeFrame frame; __reverse_pinvoke(&frame);
- Program::Main((System::String__Array*)__get_commandline_args(argc - 1, argv + 1));
+ repro_Program__Main();
__reverse_pinvoke_return(&frame);
__shutdown_runtime();
diff --git a/src/ILToNative/reproNative/reproNativeCpp.vcxproj b/src/ILToNative/reproNative/reproNativeCpp.vcxproj
index eb037a78fd9..537b8ccec2a 100644
--- a/src/ILToNative/reproNative/reproNativeCpp.vcxproj
+++ b/src/ILToNative/reproNative/reproNativeCpp.vcxproj
@@ -53,7 +53,7 @@
Use
Level3
Disabled
- WIN32;_DEBUG;_CONSOLE;_LIB;%(PreprocessorDefinitions)
+ CPPCODEGEN;WIN32;_DEBUG;_CONSOLE;_LIB;%(PreprocessorDefinitions)
true
common.h
..\..\Native\gc;..\..\Native\gc\env
@@ -71,7 +71,7 @@
MaxSpeed
true
true
- WIN32;NDEBUG;_CONSOLE;_LIB;%(PreprocessorDefinitions)
+ CPPCODEGEN;WIN32;NDEBUG;_CONSOLE;_LIB;%(PreprocessorDefinitions)
true
common.h
..\gc;..\..\Native\gc\env
diff --git a/src/ILToNative/reproNative/stubs.cpp b/src/ILToNative/reproNative/stubs.cpp
index 2c1f8caa835..8a405d74468 100644
--- a/src/ILToNative/reproNative/stubs.cpp
+++ b/src/ILToNative/reproNative/stubs.cpp
@@ -1,6 +1,8 @@
// Copyright (c) Microsoft. All rights reserved.
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
+using namespace mscorlib;
+
//
// BoundsChecking
//
diff --git a/src/ILToNative/src/Compiler/AsmWriter.cs b/src/ILToNative/src/Compiler/AsmWriter.cs
index 7205837de24..a00f01f9cdd 100644
--- a/src/ILToNative/src/Compiler/AsmWriter.cs
+++ b/src/ILToNative/src/Compiler/AsmWriter.cs
@@ -16,12 +16,13 @@ void OutputCode()
foreach (var t in _registeredTypes.Values)
{
- RegisteredMethod m = t.Methods;
- while (m != null)
+ if (t.Methods != null)
{
- if (m.MethodCode != null)
- OutputMethodCode(m);
- m = m.Next;
+ foreach (var m in t.Methods)
+ {
+ if (m.MethodCode != null)
+ OutputMethodCode(m);
+ }
}
}
diff --git a/src/ILToNative/src/Compiler/Compilation.cs b/src/ILToNative/src/Compiler/Compilation.cs
index e74a8dad24c..98747715c05 100644
--- a/src/ILToNative/src/Compiler/Compilation.cs
+++ b/src/ILToNative/src/Compiler/Compilation.cs
@@ -290,20 +290,23 @@ public void AddMethod(MethodDesc method)
return;
reg.IncludedInCompilation = true;
+ RegisteredType regType = GetRegisteredType(method.OwningType);
+ if (regType.Methods == null)
+ regType.Methods = new List();
+ regType.Methods.Add(reg);
+
if (_methodsThatNeedsCompilation == null)
_methodsThatNeedsCompilation = new List();
_methodsThatNeedsCompilation.Add(method);
- NameMangler.GetMangledMethodName(method);
-
if (_options.IsCppCodeGen)
{
// Precreate name to ensure that all types referenced by signatures are present
- NameMangler.GetMangledTypeName(method.OwningType);
+ GetRegisteredType(method.OwningType);
var signature = method.Signature;
- NameMangler.GetMangledTypeName(signature.ReturnType);
+ GetRegisteredType(signature.ReturnType);
for (int i = 0; i < signature.Length; i++)
- NameMangler.GetMangledTypeName(signature[i]);
+ GetRegisteredType(signature[i]);
}
}
@@ -352,8 +355,8 @@ public void AddField(FieldDesc field)
if (_options.IsCppCodeGen)
{
// Precreate name to ensure that all types referenced by signatures are present
- NameMangler.GetMangledTypeName(field.OwningType);
- NameMangler.GetMangledTypeName(field.FieldType);
+ GetRegisteredType(field.OwningType);
+ GetRegisteredType(field.FieldType);
}
}
diff --git a/src/ILToNative/src/Compiler/NameMangler.cs b/src/ILToNative/src/Compiler/NameMangler.cs
index 03e5aa4d2aa..e7e36094371 100644
--- a/src/ILToNative/src/Compiler/NameMangler.cs
+++ b/src/ILToNative/src/Compiler/NameMangler.cs
@@ -2,7 +2,11 @@
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
using System;
+using System.Diagnostics;
+using System.Globalization;
using System.Collections.Generic;
+using System.Collections.Immutable;
+using System.Text;
using Internal.TypeSystem;
using Internal.TypeSystem.Ecma;
@@ -10,7 +14,9 @@
namespace ILToNative
{
//
- // NameMangler is reponsible for giving extern C/C++ names to types, methods and fields
+ // NameMangler is reponsible for giving extern C/C++ names to managed types, methods and fields
+ //
+ // The key invariant is that the mangled names are independent on the compilation order.
//
public class NameMangler
{
@@ -21,28 +27,119 @@ public NameMangler(Compilation compilation)
_compilation = compilation;
}
- // Turn a name into a valid identifier
- private static string SanitizeName(string s)
+ //
+ // Turn a name into a valid C/C++ identifier
+ //
+ private string SanitizeName(string s, bool typeName = false)
{
- // TODO: Handle Unicode, etc.
- s = s.Replace("`", "_");
- s = s.Replace("<", "_");
- s = s.Replace(">", "_");
- s = s.Replace("$", "_");
- return s;
+ StringBuilder sb = null;
+ for (int i = 0; i < s.Length; i++)
+ {
+ char c = s[i];
+
+ if (((c >= 'a') && (c <= 'z')) || ((c >= 'A') && (c <= 'Z')))
+ {
+ if (sb != null)
+ sb.Append(c);
+ continue;
+ }
+
+ if ((c >= '0') && (c <= '9'))
+ {
+ // C identifiers cannot start with a digit. Prepend underscores.
+ if (i == 0)
+ {
+ if (sb == null)
+ sb = new StringBuilder(s.Length + 2);
+ sb.Append("_");
+ }
+ if (sb != null)
+ sb.Append(c);
+ continue;
+ }
+
+ if (sb == null)
+ sb = new StringBuilder(s, 0, i, s.Length);
+
+ // For CppCodeGen, replace "." (C# namespace separator) with "::" (C++ namespace separator)
+ if (typeName && c == '.' && _compilation.IsCppCodeGen)
+ {
+ sb.Append("::");
+ 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("_");
+ }
+ return (sb != null) ? sb.ToString() : s;
}
- int _unique = 1;
- HashSet _deduplicator = new HashSet();
+ ImmutableDictionary _mangledTypeNames = ImmutableDictionary.Empty;
- internal string GetMangledTypeName(TypeDesc type)
+ public string GetMangledTypeName(TypeDesc type)
{
- var reg = _compilation.GetRegisteredType(type);
-
- string mangledName = reg.MangledName;
- if (mangledName != null)
+ string mangledName;
+ if (_mangledTypeNames.TryGetValue(type, out mangledName))
return mangledName;
+ return ComputeMangledTypeName(type);
+ }
+
+ private string ComputeMangledTypeName(TypeDesc type)
+ {
+ if (type is EcmaType)
+ {
+ string prependAssemblyName = SanitizeName(((EcmaType)type).Module.GetName().Name);
+
+ var deduplicator = new HashSet();
+
+ // Add consistent names for all types in the module, independent on the order in which
+ // they are compiled
+ lock (this)
+ {
+ foreach (var t in ((EcmaType)type).Module.GetAllTypes())
+ {
+ string name = t.Name;
+
+ // Include encapsulating type
+ TypeDesc containingType = ((EcmaType)t).ContainingType;
+ while (containingType != null)
+ {
+ name = containingType.Name + "_" + name;
+ containingType = ((EcmaType)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:
@@ -57,73 +154,118 @@ internal string GetMangledTypeName(TypeDesc type)
case TypeFlags.Pointer:
mangledName = GetMangledTypeName(((PointerType)type).ParameterType) + "__Pointer";
break;
-
default:
- mangledName = type.Name;
-
- // Include encapsulating type
- TypeDesc def = type.GetTypeDefinition();
- TypeDesc containingType = (def is EcmaType) ? ((EcmaType)def).ContainingType : null;
- while (containingType != null)
+ var typeDefinition = type.GetTypeDefinition();
+ if (typeDefinition != type)
{
- mangledName = containingType.Name + "__" + mangledName;
+ mangledName = GetMangledTypeName(typeDefinition);
- containingType = ((EcmaType)containingType).ContainingType;
+ 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 = type.Name;
}
+ break;
+ }
- mangledName = SanitizeName(mangledName);
+ lock (this)
+ {
+ _mangledTypeNames = _mangledTypeNames.Add(type, mangledName);
+ }
- mangledName = mangledName.Replace(".", _compilation.IsCppCodeGen ? "::" : "_");
+ return mangledName;
+ }
- // TODO: the special handling for "Interop" is needed due to type name / namespace name clashes;
- // find a better solution
- if (type.HasInstantiation || _deduplicator.Contains(mangledName) || mangledName == "Interop")
- mangledName = mangledName + "_" + _unique++;
- _deduplicator.Add(mangledName);
+ ImmutableDictionary _mangledMethodNames = ImmutableDictionary.Empty;
- break;
- }
+ public string GetMangledMethodName(MethodDesc method)
+ {
+ string mangledName;
+ if (_mangledMethodNames.TryGetValue(method, out mangledName))
+ return mangledName;
- reg.MangledName = mangledName;
- return mangledName;
+ return ComputeMangledMethodName(method);
}
- internal string GetMangledMethodName(MethodDesc method)
+ private string ComputeMangledMethodName(MethodDesc method)
{
- var reg = _compilation.GetRegisteredMethod(method);
+ string prependTypeName = null;
+ if (!_compilation.IsCppCodeGen)
+ prependTypeName = GetMangledTypeName(method.OwningType);
- string mangledName = reg.MangledName;
- if (mangledName != null)
- return mangledName;
+ if (method is EcmaMethod)
+ {
+ var deduplicator = new HashSet();
- RegisteredType regType = _compilation.GetRegisteredType(method.OwningType);
+ // Add consistent names for all methods of the type, independent on the order in which
+ // they are compiled
+ lock (this)
+ {
+ foreach (var m in method.OwningType.GetMethods())
+ {
+ string name = SanitizeName(m.Name);
- mangledName = SanitizeName(method.Name);
+ 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);
- mangledName = mangledName.Replace(".", "_"); // To handle names like .ctor
+ if (prependTypeName != null)
+ name = prependTypeName + "__" + name;
+
+ _mangledMethodNames = _mangledMethodNames.Add(m, name);
+ }
+ }
+
+ return _mangledMethodNames[method];
+ }
- if (!_compilation.IsCppCodeGen)
- mangledName = GetMangledTypeName(method.OwningType) + "__" + mangledName;
- RegisteredMethod rm = regType.Methods;
- bool dedup = false;
- while (rm != null)
+ string mangledName;
+
+ var methodDefinition = method.GetTypicalMethodDefinition();
+ if (methodDefinition != method)
{
- if (rm.MangledName != null && rm.MangledName == mangledName)
+ mangledName = GetMangledMethodName(methodDefinition.GetMethodDefinition());
+
+ var inst = method.Instantiation;
+ for (int i = 0; i < inst.Length; i++)
{
- dedup = true;
- break;
+ string instArgName = GetMangledTypeName(inst[i]);
+ if (_compilation.IsCppCodeGen)
+ instArgName = instArgName.Replace("::", "_");
+ mangledName += "__" + instArgName;
}
-
- rm = rm.Next;
}
- if (dedup)
- mangledName = mangledName + "_" + regType.UniqueMethod++;
+ else
+ {
+ // Assume that Name is unique for all other methods
+ mangledName = method.Name;
+ }
- reg.MangledName = mangledName;
+ if (prependTypeName != null)
+ mangledName = prependTypeName + "__" + mangledName;
- reg.Next = regType.Methods;
- regType.Methods = reg;
+ lock (this)
+ {
+ _mangledMethodNames = _mangledMethodNames.Add(method, mangledName);
+ }
return mangledName;
}
diff --git a/src/ILToNative/src/Compiler/RegisteredMethod.cs b/src/ILToNative/src/Compiler/RegisteredMethod.cs
index 41af6bc74ea..cd722d12aa6 100644
--- a/src/ILToNative/src/Compiler/RegisteredMethod.cs
+++ b/src/ILToNative/src/Compiler/RegisteredMethod.cs
@@ -13,10 +13,6 @@ class RegisteredMethod
public bool IncludedInCompilation;
- public string MangledName;
-
public Object MethodCode;
-
- public RegisteredMethod Next;
}
}
diff --git a/src/ILToNative/src/Compiler/RegisteredType.cs b/src/ILToNative/src/Compiler/RegisteredType.cs
index 8d121e9851a..13b590b92c5 100644
--- a/src/ILToNative/src/Compiler/RegisteredType.cs
+++ b/src/ILToNative/src/Compiler/RegisteredType.cs
@@ -15,12 +15,9 @@ class RegisteredType
public bool IncludedInCompilation;
public bool Constructed;
- public int UniqueMethod;
-
- public string MangledName;
public string MangledSignatureName; // CppCodeGen specific
- public RegisteredMethod Methods;
+ public List Methods;
public List VirtualSlots;
}
diff --git a/src/ILToNative/src/CppCodeGen/CppWriter.cs b/src/ILToNative/src/CppCodeGen/CppWriter.cs
index 9d1bbe2bb8a..6ae5f65b595 100644
--- a/src/ILToNative/src/CppCodeGen/CppWriter.cs
+++ b/src/ILToNative/src/CppCodeGen/CppWriter.cs
@@ -613,12 +613,13 @@ void OutputType(RegisteredType t, bool full)
_statics.AppendLine("bool __cctor_" + GetCppTypeName(t.Type).Replace("::", "__") + ";");
}
- RegisteredMethod m = t.Methods;
- while (m != null)
+ if (t.Methods != null)
{
- if (m.IncludedInCompilation)
- OutputMethod(m);
- m = m.Next;
+ foreach (var m in t.Methods)
+ {
+ if (m.IncludedInCompilation)
+ OutputMethod(m);
+ }
}
Out.Write("};");
}
@@ -860,12 +861,14 @@ public void OutputCode()
{
Out.WriteLine(GetCodeForType(t.Type));
}
- RegisteredMethod m = t.Methods;
- while (m != null)
+
+ if (t.Methods != null)
{
- if (m.MethodCode != null)
- Out.WriteLine(m.MethodCode);
- m = m.Next;
+ foreach (var m in t.Methods)
+ {
+ if (m.MethodCode != null)
+ Out.WriteLine(m.MethodCode);
+ }
}
}
diff --git a/src/ILToNative/src/CppCodeGen/ILToCppImporter.cs b/src/ILToNative/src/CppCodeGen/ILToCppImporter.cs
index 8ea842939c6..e9b433d476f 100644
--- a/src/ILToNative/src/CppCodeGen/ILToCppImporter.cs
+++ b/src/ILToNative/src/CppCodeGen/ILToCppImporter.cs
@@ -824,7 +824,7 @@ void ImportCall(ILOpcode opcode, int token)
if (delegateInvoke)
{
_stack[_stackTop - (methodSignature.Length + 1)].Value.Name =
- "((System::Delegate *)" +
+ "((" + _writer.GetCppSignatureTypeName(GetWellKnownType(WellKnownType.MulticastDelegate)) + ")" +
_stack[_stackTop - (methodSignature.Length + 1)].Value.Name + ")->m_firstParameter";
}
}
diff --git a/src/TypeSystem/src/Common/InstantiatedMethod.cs b/src/TypeSystem/src/Common/InstantiatedMethod.cs
index 03d1940d5b8..d96f3fb9bd7 100644
--- a/src/TypeSystem/src/Common/InstantiatedMethod.cs
+++ b/src/TypeSystem/src/Common/InstantiatedMethod.cs
@@ -3,6 +3,7 @@
using System;
using System.Diagnostics;
+using System.Text;
namespace Internal.TypeSystem
{
@@ -91,8 +92,12 @@ public override string Name
public override string ToString()
{
- // TODO: Append instantiation
- return _methodDef.ToString();
+ var sb = new StringBuilder(_methodDef.ToString());
+ sb.Append('<');
+ for (int i = 0; i < _instantiation.Length; i++)
+ sb.Append(_instantiation[i].ToString());
+ sb.Append('>');
+ return sb.ToString();
}
}
}
diff --git a/src/TypeSystem/src/Common/InstantiatedType.cs b/src/TypeSystem/src/Common/InstantiatedType.cs
index 557cb95e0ce..6a5eb88460e 100644
--- a/src/TypeSystem/src/Common/InstantiatedType.cs
+++ b/src/TypeSystem/src/Common/InstantiatedType.cs
@@ -2,6 +2,7 @@
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
using System;
+using System.Text;
using System.Collections.Generic;
using System.Diagnostics;
@@ -203,5 +204,15 @@ public override TypeDesc GetTypeDefinition()
{
return _typeDef;
}
+
+ public override string ToString()
+ {
+ var sb = new StringBuilder(_typeDef.ToString());
+ sb.Append('<');
+ for (int i = 0; i < _instantiation.Length; i++)
+ sb.Append(_instantiation[i].ToString());
+ sb.Append('>');
+ return sb.ToString();
+ }
}
}