Skip to content
This repository was archived by the owner on Nov 1, 2020. It is now read-only.
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion src/ILToNative/src/Compiler/AsmWriter.cs
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,7 @@ void OutputMethodCode(RegisteredMethod m)
Out.Write(mangledName);
Out.WriteLine(":");

var methodCode = m.MethodCode;
var methodCode = (MethodCode)m.MethodCode;

Relocation[] relocs = methodCode.Relocs;
int currentRelocIndex = 0;
Expand Down
158 changes: 117 additions & 41 deletions src/ILToNative/src/Compiler/Compilation.cs
Original file line number Diff line number Diff line change
Expand Up @@ -17,18 +17,35 @@

namespace ILToNative
{
public struct CompilationOptions
{
public bool Cpp;
}

public partial class Compilation
{
TypeSystemContext _typeSystemContext;
readonly TypeSystemContext _typeSystemContext;
readonly CompilationOptions _options;

Dictionary<TypeDesc, RegisteredType> _registeredTypes = new Dictionary<TypeDesc, RegisteredType>();
Dictionary<MethodDesc, RegisteredMethod> _registeredMethods = new Dictionary<MethodDesc, RegisteredMethod>();
Dictionary<FieldDesc, RegisteredField> _registeredFields = new Dictionary<FieldDesc, RegisteredField>();
List<MethodDesc> _methodsThatNeedsCompilation = null;

public Compilation(TypeSystemContext typeSystemContext)
ILToNative.CppCodeGen.CppWriter _cppWriter = null;

public Compilation(TypeSystemContext typeSystemContext, CompilationOptions options)
{
_typeSystemContext = typeSystemContext;
_options = options;
}

public TypeSystemContext TypeSystemContext
{
get
{
return _typeSystemContext;
}
}

public TextWriter Log
Expand All @@ -45,8 +62,23 @@ public TextWriter Out

MethodDesc _mainMethod;

internal MethodDesc MainMethod
{
get
{
return _mainMethod;
}
}

RegisteredType GetRegisteredType(TypeDesc type)
internal IEnumerable<RegisteredType> RegisteredTypes
{
get
{
return _registeredTypes.Values;
}
}

internal RegisteredType GetRegisteredType(TypeDesc type)
{
RegisteredType existingRegistration;
if (_registeredTypes.TryGetValue(type, out existingRegistration))
Expand All @@ -63,7 +95,7 @@ RegisteredType GetRegisteredType(TypeDesc type)
return registration;
}

RegisteredMethod GetRegisteredMethod(MethodDesc method)
internal RegisteredMethod GetRegisteredMethod(MethodDesc method)
{
RegisteredMethod existingRegistration;
if (_registeredMethods.TryGetValue(method, out existingRegistration))
Expand All @@ -77,7 +109,7 @@ RegisteredMethod GetRegisteredMethod(MethodDesc method)
return registration;
}

RegisteredField GetRegisteredField(FieldDesc field)
internal RegisteredField GetRegisteredField(FieldDesc field)
{
RegisteredField existingRegistration;
if (_registeredFields.TryGetValue(field, out existingRegistration))
Expand All @@ -96,8 +128,7 @@ enum SpecialMethodKind
Unknown,
PInvoke,
RuntimeImport,
Intrinsic,
BoundsChecking,
Intrinsic
};

SpecialMethodKind DetectSpecialMethodKind(MethodDesc method)
Expand All @@ -118,11 +149,6 @@ SpecialMethodKind DetectSpecialMethodKind(MethodDesc method)
Log.WriteLine("Intrinsic: " + method.ToString());
return SpecialMethodKind.Intrinsic;
}
else if (((EcmaMethod)method).HasCustomAttribute("System.Runtime.CompilerServices.BoundsCheckingAttribute"))
{
Log.WriteLine("BoundsChecking: " + method.ToString());
return SpecialMethodKind.BoundsChecking;
}
else if (((EcmaMethod)method).HasCustomAttribute("System.Runtime.InteropServices.NativeCallableAttribute"))
{
Log.WriteLine("NativeCallable: " + method.ToString());
Expand Down Expand Up @@ -166,17 +192,15 @@ void CompileMethods()

foreach (MethodDesc method in pendingMethods)
{
try
if (_options.Cpp)
{
CompileMethod(method);
_cppWriter.CompileMethod(method);
}
catch (Exception e)
else
{
Log.WriteLine(e.Message + " (" + method + ")");

throw new NotImplementedException();
CompileMethod(method);
}
}
}
}

void ExpandVirtualMethods()
Expand Down Expand Up @@ -210,7 +234,14 @@ void ExpandVirtualMethods()

public void CompileSingleFile(MethodDesc mainMethod)
{
_corInfo = new CorInfoImpl(this);
if (_options.Cpp)
{
_cppWriter = new CppCodeGen.CppWriter(this);
}
else
{
_corInfo = new CorInfoImpl(this);
}

_mainMethod = mainMethod;
AddMethod(mainMethod);
Expand All @@ -222,7 +253,14 @@ public void CompileSingleFile(MethodDesc mainMethod)
ExpandVirtualMethods();
}

OutputCode();
if (_options.Cpp)
{
_cppWriter.OutputCode();
}
else
{
OutputCode();
}
}

public void AddMethod(MethodDesc method)
Expand All @@ -232,13 +270,21 @@ public void AddMethod(MethodDesc method)
return;
reg.IncludedInCompilation = true;

RegisteredType regType = GetRegisteredType(method.OwningType);
reg.Next = regType.Methods;
regType.Methods = reg;

if (_methodsThatNeedsCompilation == null)
_methodsThatNeedsCompilation = new List<MethodDesc>();
_methodsThatNeedsCompilation.Add(method);

GetMangledMethodName(method);

if (_options.Cpp)
{
// Precreate name to ensure that all types referenced by signatures are present
GetMangledTypeName(method.OwningType);
var signature = method.Signature;
GetMangledTypeName(signature.ReturnType);
for (int i = 0; i < signature.Length; i++)
GetMangledTypeName(signature[i]);
}
}

public void AddVirtualSlot(MethodDesc method)
Expand Down Expand Up @@ -282,9 +328,16 @@ public void AddField(FieldDesc field)
if (reg.IncludedInCompilation)
return;
reg.IncludedInCompilation = true;

if (_options.Cpp)
{
// Precreate name to ensure that all types referenced by signatures are present
GetMangledTypeName(field.OwningType);
GetMangledTypeName(field.FieldType);
}
}

MethodDesc ResolveVirtualMethod(TypeDesc implType, MethodDesc declMethod)
internal MethodDesc ResolveVirtualMethod(TypeDesc implType, MethodDesc declMethod)
{
// TODO: Proper virtual method resolution
string name = declMethod.Name;
Expand All @@ -301,11 +354,6 @@ MethodDesc ResolveVirtualMethod(TypeDesc implType, MethodDesc declMethod)
}
}

internal TypeDesc GetWellKnownType(WellKnownType wellKnownType)
{
return _typeSystemContext.GetWellKnownType(wellKnownType);
}

// Turn a name into a valid identifier
private static string SanitizeName(string s)
{
Expand All @@ -331,21 +379,44 @@ internal string GetMangledTypeName(TypeDesc type)
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";
if (_options.Cpp)
mangledName = _cppWriter.GetCppSignatureTypeName(((ByRefType)type).ParameterType) + "*";
else
mangledName = GetMangledTypeName(((ByRefType)type).ParameterType) + "__ByRef";
break;
case TypeFlags.Pointer:
mangledName = GetMangledTypeName(((PointerType)type).ParameterType) + "__Pointer";
if (_options.Cpp)
mangledName = _cppWriter.GetCppSignatureTypeName(((PointerType)type).ParameterType) + "*";
else
mangledName = GetMangledTypeName(((PointerType)type).ParameterType) + "__Pointer";
break;

default:
// TODO: Include encapsulating type
mangledName = SanitizeName(type.Name);
mangledName = type.Name;

// Include encapsulating type
TypeDesc def = type.GetTypeDefinition();
TypeDesc containingType = (def is EcmaType) ? ((EcmaType)def).ContainingType : null;
while (containingType != null)
{
mangledName = containingType.Name + "__" + mangledName;

containingType = ((EcmaType)containingType).ContainingType;
}

mangledName = SanitizeName(mangledName);

mangledName = mangledName.Replace(".", "_");
mangledName = mangledName.Replace(".", _options.Cpp ? "::" : "_");

if (type.HasInstantiation || _deduplicator.Contains(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);

Expand All @@ -364,15 +435,16 @@ internal string GetMangledMethodName(MethodDesc method)
if (mangledName != null)
return mangledName;

RegisteredType owner = GetRegisteredType(method.OwningType);
RegisteredType regType = GetRegisteredType(method.OwningType);

mangledName = SanitizeName(method.Name);

mangledName = mangledName.Replace(".", "_"); // To handle names like .ctor

mangledName = GetMangledTypeName(method.OwningType) + "__" + mangledName;
if (!_options.Cpp)
mangledName = GetMangledTypeName(method.OwningType) + "__" + mangledName;

RegisteredMethod rm = owner.Methods;
RegisteredMethod rm = regType.Methods;
bool dedup = false;
while (rm != null)
{
Expand All @@ -385,9 +457,13 @@ internal string GetMangledMethodName(MethodDesc method)
rm = rm.Next;
}
if (dedup)
mangledName = mangledName + "_" + owner.UniqueMethod++;
mangledName = mangledName + "_" + regType.UniqueMethod++;

reg.MangledName = mangledName;

reg.Next = regType.Methods;
regType.Methods = reg;

return mangledName;
}

Expand Down
56 changes: 56 additions & 0 deletions src/ILToNative/src/Compiler/MethodExtensions.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
// Copyright (c) Microsoft. All rights reserved.
// Licensed under the MIT license. See LICENSE file in the project root for full license information.

using System;

using Internal.TypeSystem;
using Internal.TypeSystem.Ecma;

namespace ILToNative
{
static class MethodExtensions
{
const string RuntimeImportAttributeName = "System.Runtime.RuntimeImportAttribute";

public static bool IsRuntimeImport(this EcmaMethod This)
{
return This.HasCustomAttribute(RuntimeImportAttributeName);
}

public static string GetRuntimeImportEntryPointName(this EcmaMethod This)
{
var metadataReader = This.MetadataReader;
foreach (var attributeHandle in metadataReader.GetMethodDefinition(This.Handle).GetCustomAttributes())
{
var customAttribute = metadataReader.GetCustomAttribute(attributeHandle);
var constructorHandle = customAttribute.Constructor;

var constructor = This.Module.GetMethod(constructorHandle);
var type = constructor.OwningType;

if (type.Name == RuntimeImportAttributeName)
{
if (constructor.Signature.Length != 1 && constructor.Signature.Length != 2)
throw new BadImageFormatException();

for (int i = 0; i < constructor.Signature.Length; i++)
if (constructor.Signature[i] != This.Context.GetWellKnownType(WellKnownType.String))
throw new BadImageFormatException();

var attributeBlob = metadataReader.GetBlobReader(customAttribute.Value);
if (attributeBlob.ReadInt16() != 1)
throw new BadImageFormatException();

// Skip module name if present
if (constructor.Signature.Length == 2)
attributeBlob.ReadSerializedString();

return attributeBlob.ReadSerializedString();
}
}

return null;
}

}
}
Loading