Skip to content
This repository has been archived by the owner on Nov 1, 2020. It is now read-only.

[CppCodeGen] Enable reflection support #6700

Merged
merged 8 commits into from
Jan 10, 2019
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
Original file line number Diff line number Diff line change
Expand Up @@ -97,18 +97,28 @@ public override ObjectData GetData(NodeFactory factory, bool relocsOnly = false)
objData.RequireInitialPointerAlignment();
objData.AddSymbol(this);

objData.EmitReloc(factory.NecessaryTypeSymbol(_dynamicInvokeMethodContainerType), RelocType.IMAGE_REL_BASED_RELPTR32);
if (factory.Target.SupportsRelativePointers)
objData.EmitReloc(factory.NecessaryTypeSymbol(_dynamicInvokeMethodContainerType), RelocType.IMAGE_REL_BASED_RELPTR32);
else
objData.EmitPointerReloc(factory.NecessaryTypeSymbol(_dynamicInvokeMethodContainerType));

List<KeyValuePair<MethodDesc, int>> sortedList = new List<KeyValuePair<MethodDesc, int>>(_methodToTemplateIndex);
sortedList.Sort((firstEntry, secondEntry) => firstEntry.Value.CompareTo(secondEntry.Value));

for (int i = 0; i < sortedList.Count; i++)
{
Debug.Assert(sortedList[i].Value * 4 == objData.CountBytes);
var nameAndSig = factory.NativeLayout.PlacedSignatureVertex(factory.NativeLayout.MethodNameAndSignatureVertex(sortedList[i].Key));

objData.EmitInt(nameAndSig.SavedVertex.VertexOffset);
objData.EmitReloc(factory.MethodEntrypoint(sortedList[i].Key), RelocType.IMAGE_REL_BASED_RELPTR32);
if (factory.Target.SupportsRelativePointers)
{
objData.EmitInt(nameAndSig.SavedVertex.VertexOffset);
objData.EmitReloc(factory.MethodEntrypoint(sortedList[i].Key), RelocType.IMAGE_REL_BASED_RELPTR32);
}
else
{
objData.EmitNaturalInt(nameAndSig.SavedVertex.VertexOffset);
objData.EmitPointerReloc(factory.MethodEntrypoint(sortedList[i].Key));
}
}

_endSymbol.SetSymbolOffset(objData.CountBytes);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ namespace ILCompiler.DependencyAnalysis
/// types. It only fills out enough pieces of the EEType structure so that the GC can operate on it. Runtime should
/// never see these.
/// </summary>
internal class GCStaticEETypeNode : ObjectNode, ISymbolDefinitionNode
public class GCStaticEETypeNode : ObjectNode, ISymbolDefinitionNode
{
private GCPointerMap _gcMap;
private TargetDetails _target;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -89,7 +89,7 @@ protected override DependencyList ComputeNonRelocationBasedDependencies(NodeFact

public override ObjectData GetData(NodeFactory factory, bool relocsOnly = false)
{
if (factory.Target.Abi == TargetAbi.CoreRT)
if (factory.Target.Abi == TargetAbi.CoreRT || factory.Target.Abi == TargetAbi.CppCodegen)
{
ObjectDataBuilder builder = new ObjectDataBuilder(factory, relocsOnly);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -157,9 +157,9 @@ public override ObjectData GetData(NodeFactory factory, bool relocsOnly = false)
uint index = _externalReferences.GetIndex(staticsNode, field.Offset.AsInt);
vertex = writer.GetTuple(vertex, writer.GetUnsignedConstant(index));
}
else
else if (factory.Target.Abi == TargetAbi.CoreRT || factory.Target.Abi == TargetAbi.CppCodegen)
{
Debug.Assert(field.HasGCStaticBase && factory.Target.Abi == TargetAbi.CoreRT);
Debug.Assert(field.HasGCStaticBase);

uint index = _externalReferences.GetIndex(staticsNode);
vertex = writer.GetTuple(vertex, writer.GetUnsignedConstant(index));
Expand Down
326 changes: 165 additions & 161 deletions src/ILCompiler.CppCodeGen/src/CppCodeGen/CppWriter.cs

Large diffs are not rendered by default.

19 changes: 9 additions & 10 deletions src/ILCompiler.CppCodeGen/src/CppCodeGen/ILToCppImporter.cs
Original file line number Diff line number Diff line change
Expand Up @@ -1867,8 +1867,9 @@ private void ImportCall(ILOpcode opcode, int token)
{
if (canonMethod.RequiresInstMethodDescArg())
{
Append("&");
Append("(char*)&");
AppendMethodGenericDictionary(method);
Append(" + sizeof(void*)");
}
else
{
Expand Down Expand Up @@ -2655,7 +2656,7 @@ private void ImportLoadField(int token, bool isStatic)

if (field.IsStatic)
{
Append(_writer.GetCppStaticsName(owningType, field.HasGCStaticBase, field.IsThreadStatic));
Append(_writer.GetCppStaticsName(owningType, field.HasGCStaticBase, field.IsThreadStatic, true));
Append(".");
Append(_writer.GetCppFieldName(field));
}
Expand Down Expand Up @@ -2733,7 +2734,7 @@ private void ImportAddressOfField(int token, bool isStatic)

if (field.IsStatic)
{
Append(_writer.GetCppStaticsName(owningType, field.HasGCStaticBase, field.IsThreadStatic));
Append(_writer.GetCppStaticsName(owningType, field.HasGCStaticBase, field.IsThreadStatic, true));
Append(".");
Append(_writer.GetCppFieldName(field));
}
Expand Down Expand Up @@ -2800,7 +2801,7 @@ private void ImportStoreField(int token, bool isStatic)
AppendLine();
if (field.IsStatic)
{
Append(_writer.GetCppStaticsName(owningType, field.HasGCStaticBase, field.IsThreadStatic));
Append(_writer.GetCppStaticsName(owningType, field.HasGCStaticBase, field.IsThreadStatic, true));
Append(".");
Append(_writer.GetCppFieldName(field));
}
Expand Down Expand Up @@ -2992,11 +2993,9 @@ private ExpressionEntry BoxValue(TypeDesc type, StackEntry value)

AppendSemicolon();

string typeName = GetStackValueKindCPPTypeName(GetStackValueKind(type), type);

// TODO: Write barrier as necessary
AppendLine();
Append("*(" + typeName + " *)((void **)");
Append("*(" + _writer.GetCppSignatureTypeName(type) + " *)((void **)");
Append(tempName);
Append(" + 1) = ");
Append(value);
Expand Down Expand Up @@ -3310,9 +3309,9 @@ private void ImportUnbox(int token, ILOpcode opCode)
if (opCode == ILOpcode.unbox_any)
{
string typeName = GetStackValueKindCPPTypeName(GetStackValueKind(type), type);
Append("*(");
Append("(");
Append(typeName);
Append("*)");
Append(")*");
}

Append("(");
Expand Down Expand Up @@ -3378,7 +3377,7 @@ private void ImportLdToken(int token)
}
else
{
AddTypeReference(type, false);
AddTypeReference(type, true);

name = String.Concat(
name,
Expand Down
7 changes: 7 additions & 0 deletions src/Native/Bootstrap/CppCodeGen.h
Original file line number Diff line number Diff line change
Expand Up @@ -61,4 +61,11 @@ struct PInvokeTransitionFrame
// can be an invalid pointer in universal transition cases (which never need to call GetThread)
uint32_t m_Flags; // PInvokeTransitionFrameFlags
};

// Should be synchronized with System.Private.CoreLib/src/System/Runtime/CompilerServices/StaticClassConstructionContext.cs
struct StaticClassConstructionContext
{
void* m_cctorMethodAddress;
uint32_t m_initialized;
};
#endif
Original file line number Diff line number Diff line change
Expand Up @@ -1151,6 +1151,14 @@ public static void RhYield()
{
RuntimeImports.RhYield();
}

public static bool SupportsRelativePointers
{
get
{
return Internal.Runtime.EEType.SupportsRelativePointers;
}
}
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -414,7 +414,6 @@ private unsafe void GetDynamicMethodInvokeMethodInfo(NativeFormatModuleInfo modu
byte* pBlobAsBytes;
uint cbBlob;
bool success = module.TryFindBlob((int)ReflectionMapBlob.DynamicInvokeTemplateData, out pBlobAsBytes, out cbBlob);
uint* pBlob = (uint*)pBlobAsBytes;
Debug.Assert(success && cbBlob > 4);

byte* pNativeLayoutInfoBlob;
Expand All @@ -426,21 +425,38 @@ private unsafe void GetDynamicMethodInvokeMethodInfo(NativeFormatModuleInfo modu
// All methods referred from this blob are contained in the same type. The first UINT in the blob is a reloc to that EEType
if (module.Handle.IsTypeManager)
{
// CoreRT uses 32bit relative relocs
declaringTypeHandle = RuntimeAugments.CreateRuntimeTypeHandle((IntPtr)(pBlobAsBytes + *(int*)pBlobAsBytes));
if (RuntimeAugments.SupportsRelativePointers)
{
// CoreRT uses 32bit relative relocs
declaringTypeHandle = RuntimeAugments.CreateRuntimeTypeHandle((IntPtr)(pBlobAsBytes + *(int*)pBlobAsBytes));
}
else
{
declaringTypeHandle = RuntimeAugments.CreateRuntimeTypeHandle(*(IntPtr*)pBlobAsBytes);
}
}
else
{
// .NET Native uses RVAs
declaringTypeHandle = TypeLoaderEnvironment.RvaToRuntimeTypeHandle(module.Handle, pBlob[0]);
declaringTypeHandle = TypeLoaderEnvironment.RvaToRuntimeTypeHandle(module.Handle, *(uint*)pBlobAsBytes);
}

// The index points to two entries: the token of the dynamic invoke method and the function pointer to the canonical method
// Now have the type loader build or locate a dictionary for this method
uint index = cookie >> 1;

MethodNameAndSignature nameAndSignature;
RuntimeSignature nameAndSigSignature = RuntimeSignature.CreateFromNativeLayoutSignature(module.Handle, pBlob[index]);
RuntimeSignature nameAndSigSignature;

if (RuntimeAugments.SupportsRelativePointers)
{
nameAndSigSignature = RuntimeSignature.CreateFromNativeLayoutSignature(module.Handle, ((uint*)pBlobAsBytes)[index]);
}
else
{
nameAndSigSignature = RuntimeSignature.CreateFromNativeLayoutSignature(module.Handle, (uint)((IntPtr*)pBlobAsBytes)[index]);
}

success = TypeLoaderEnvironment.Instance.TryGetMethodNameAndSignatureFromNativeLayoutSignature(nameAndSigSignature, out nameAndSignature);
Debug.Assert(success);

Expand All @@ -449,14 +465,21 @@ private unsafe void GetDynamicMethodInvokeMethodInfo(NativeFormatModuleInfo modu

if (module.Handle.IsTypeManager)
{
// CoreRT uses 32bit relative relocs
int* pRelPtr32 = &((int*)pBlob)[index + 1];
dynamicInvokeMethod = (IntPtr)((byte*)pRelPtr32 + *pRelPtr32);
if (RuntimeAugments.SupportsRelativePointers)
{
// CoreRT uses 32bit relative relocs
int* pRelPtr32 = &((int*)pBlobAsBytes)[index + 1];
dynamicInvokeMethod = (IntPtr)((byte*)pRelPtr32 + *pRelPtr32);
}
else
{
dynamicInvokeMethod = ((IntPtr*)pBlobAsBytes)[index + 1];
}
}
else
{
// .NET Native uses RVAs
dynamicInvokeMethod = TypeLoaderEnvironment.RvaToFunctionPointer(module.Handle, pBlob[index + 1]);
dynamicInvokeMethod = TypeLoaderEnvironment.RvaToFunctionPointer(module.Handle, ((uint*)pBlobAsBytes)[index + 1]);
}
}
else
Expand Down
4 changes: 2 additions & 2 deletions tests/src/Simple/Generics/Generics.cs
Original file line number Diff line number Diff line change
Expand Up @@ -29,11 +29,11 @@ static int Main()
TestGvmDependencies.Run();
TestInterfaceVTableTracking.Run();
TestClassVTableTracking.Run();
TestReflectionInvoke.Run();
TestFieldAccess.Run();
#if !CODEGEN_CPP
TestNullableCasting.Run();
TestReflectionInvoke.Run();
TestMDArrayAddressMethod.Run();
TestFieldAccess.Run();
TestNativeLayoutGeneration.Run();
#endif
return 100;
Expand Down
10 changes: 9 additions & 1 deletion tests/src/Simple/Reflection/Reflection.cs
Original file line number Diff line number Diff line change
Expand Up @@ -30,8 +30,12 @@ private static int Main()
#if !OPTIMIZED_MODE_WITHOUT_SCANNER
TestContainment.Run();
TestInterfaceMethod.Run();
// Need to implement RhGetCodeTarget for CppCodeGen
#if !CODEGEN_CPP
TestByRefLikeTypeMethod.Run();
#endif
#endif

TestAttributeInheritance.Run();
TestStringConstructor.Run();
TestAssemblyAndModuleAttributes.Run();
Expand All @@ -46,8 +50,9 @@ private static int Main()
TestCreateDelegate.Run();
TestInstanceFields.Run();
TestReflectionInvoke.Run();
#if !CODEGEN_CPP
TestByRefReturnInvoke.Run();

#endif
return 100;
}

Expand Down Expand Up @@ -687,9 +692,12 @@ public static void Run()
if (!HasTypeHandle(usedNestedType))
throw new Exception($"{nameof(NeverUsedContainerType.UsedNestedType)} should have an EEType");

// Need to implement exceptions for CppCodeGen
#if !CODEGEN_CPP
// But the containing type doesn't need an EEType
if (HasTypeHandle(neverUsedContainerType))
throw new Exception($"{nameof(NeverUsedContainerType)} should not have an EEType");
#endif
}
}

Expand Down
1 change: 0 additions & 1 deletion tests/src/Simple/Reflection/no_cpp

This file was deleted.