Wasm: Enable field reflection (#7022)
Fixes #6944 This change enables reflection on fields and in doing so fixes some gaps in the `ExternalReferencesTableNode` which fixes reflecting on some types that were not previously caught in the tests.
This commit is contained in:
Родитель
32d2a20ec5
Коммит
c404dd1cbb
|
@ -6,19 +6,15 @@ using System;
|
|||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Diagnostics;
|
||||
using System.Runtime.InteropServices;
|
||||
|
||||
using ILCompiler.DependencyAnalysisFramework;
|
||||
|
||||
using Internal.Text;
|
||||
using Internal.TypeSystem;
|
||||
using Internal.TypeSystem.TypesDebugInfo;
|
||||
using ObjectData = ILCompiler.DependencyAnalysis.ObjectNode.ObjectData;
|
||||
|
||||
using LLVMSharp;
|
||||
using ILCompiler.CodeGen;
|
||||
using System.Linq;
|
||||
using Internal.IL;
|
||||
|
||||
namespace ILCompiler.DependencyAnalysis
|
||||
{
|
||||
|
@ -36,7 +32,6 @@ namespace ILCompiler.DependencyAnalysis
|
|||
|
||||
if (symbol is ObjectNode)
|
||||
{
|
||||
ObjectNode objNode = (ObjectNode)symbol;
|
||||
ISymbolDefinitionNode symbolDefNode = (ISymbolDefinitionNode)symbol;
|
||||
if (symbolDefNode.Offset == 0)
|
||||
{
|
||||
|
@ -387,16 +382,8 @@ namespace ILCompiler.DependencyAnalysis
|
|||
if (ObjectSymbolRefs.TryGetValue(curOffset, out symbolRef))
|
||||
{
|
||||
LLVMValueRef pointedAtValue = symbolRef.ToLLVMValueRef(module);
|
||||
//TODO: why did this come back null
|
||||
if (pointedAtValue.Pointer != IntPtr.Zero)
|
||||
{
|
||||
var ptrValue = LLVM.ConstBitCast(pointedAtValue, intPtrType);
|
||||
entries.Add(ptrValue);
|
||||
}
|
||||
else
|
||||
{
|
||||
entries.Add(LLVM.ConstPointerNull(intPtrType));
|
||||
}
|
||||
var ptrValue = LLVM.ConstBitCast(pointedAtValue, intPtrType);
|
||||
entries.Add(ptrValue);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -424,7 +411,6 @@ namespace ILCompiler.DependencyAnalysis
|
|||
|
||||
public void DoneObjectNode()
|
||||
{
|
||||
int pointerSize = _nodeFactory.Target.PointerSize;
|
||||
EmitAlignment(_nodeFactory.Target.PointerSize);
|
||||
Debug.Assert(_nodeFactory.Target.PointerSize == 4);
|
||||
int countOfPointerSizedElements = _currentObjectData.Count / _nodeFactory.Target.PointerSize;
|
||||
|
@ -837,7 +823,17 @@ namespace ILCompiler.DependencyAnalysis
|
|||
delta = Relocation.ReadValue(reloc.RelocType, location);
|
||||
}
|
||||
}
|
||||
int size = objectWriter.EmitSymbolReference(reloc.Target, (int)delta, reloc.RelocType);
|
||||
ISymbolNode symbolToWrite = reloc.Target;
|
||||
var eeTypeNode = reloc.Target as EETypeNode;
|
||||
if (eeTypeNode != null)
|
||||
{
|
||||
if (eeTypeNode.ShouldSkipEmittingObjectNode(factory))
|
||||
{
|
||||
symbolToWrite = factory.ConstructedTypeSymbol(eeTypeNode.Type);
|
||||
}
|
||||
}
|
||||
|
||||
int size = objectWriter.EmitSymbolReference(symbolToWrite, (int)delta, reloc.RelocType);
|
||||
|
||||
/*
|
||||
WebAssembly has no thumb
|
||||
|
|
|
@ -21,7 +21,7 @@ namespace ILCompiler
|
|||
|
||||
public override bool IsBlocked(FieldDesc field)
|
||||
{
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -6,6 +6,8 @@ using System;
|
|||
using System.Threading;
|
||||
using System.Runtime.InteropServices;
|
||||
using System.Collections.Generic;
|
||||
using System.Reflection;
|
||||
|
||||
#if PLATFORM_WINDOWS
|
||||
using CpObj;
|
||||
#endif
|
||||
|
@ -734,6 +736,7 @@ internal static class Program
|
|||
|
||||
[System.Runtime.InteropServices.DllImport("*")]
|
||||
private static extern void CallMe(int x);
|
||||
|
||||
private static void TestMetaData()
|
||||
{
|
||||
|
||||
|
@ -754,15 +757,15 @@ internal static class Program
|
|||
var typeofChar = typeof(Char);
|
||||
if (typeofChar == null)
|
||||
{
|
||||
PrintLine("type == null. Simple class metadata test: Failed");
|
||||
PrintLine("type == null. Simple struct metadata test: Failed");
|
||||
}
|
||||
else
|
||||
{
|
||||
if (typeofChar.FullName != "System.Char")
|
||||
{
|
||||
PrintLine("type != System.Char. Simple class metadata test: Failed");
|
||||
PrintLine("type != System.Char. Simple struct metadata test: Failed");
|
||||
}
|
||||
else PrintLine("Simple class metadata test (typeof(Char)): Ok.");
|
||||
else PrintLine("Simple struct metadata test (typeof(Char)): Ok.");
|
||||
}
|
||||
|
||||
var gentT = new Gen<int>();
|
||||
|
@ -801,8 +804,124 @@ internal static class Program
|
|||
{
|
||||
PrintLine("Ok.");
|
||||
}
|
||||
|
||||
PrintString("Type GetFields length: ");
|
||||
var x = new ClassForMetaTests();
|
||||
var s = x.StringField;
|
||||
var i = x.IntField;
|
||||
var fieldClassType = typeof(ClassForMetaTests);
|
||||
FieldInfo[] fields = fieldClassType.GetFields();
|
||||
if (fields.Length == 3)
|
||||
{
|
||||
PrintLine("Ok.");
|
||||
}
|
||||
else
|
||||
{
|
||||
PrintLine(" Failed.");
|
||||
}
|
||||
|
||||
PrintString("Type get string field via reflection: ");
|
||||
var stringFieldInfo = fieldClassType.GetField("StringField");
|
||||
if ((string)stringFieldInfo.GetValue(x) == s)
|
||||
{
|
||||
PrintLine("Ok.");
|
||||
}
|
||||
else
|
||||
{
|
||||
PrintLine("Failed.");
|
||||
}
|
||||
PrintString("Type get int field via reflection: ");
|
||||
var intFieldInfo = fieldClassType.GetField("IntField");
|
||||
if ((int)intFieldInfo.GetValue(x) == i)
|
||||
{
|
||||
PrintLine("Ok.");
|
||||
}
|
||||
else
|
||||
{
|
||||
PrintLine("Failed.");
|
||||
}
|
||||
|
||||
PrintString("Type get static int field via reflection: ");
|
||||
var staticIntFieldInfo = fieldClassType.GetField("StaticIntField");
|
||||
if ((int)staticIntFieldInfo.GetValue(x) == 23)
|
||||
{
|
||||
PrintLine("Ok.");
|
||||
}
|
||||
else
|
||||
{
|
||||
PrintLine("Failed.");
|
||||
}
|
||||
|
||||
PrintString("Type set string field via reflection: ");
|
||||
stringFieldInfo.SetValue(x, "bcd");
|
||||
if (x.StringField == "bcd")
|
||||
{
|
||||
PrintLine("Ok.");
|
||||
}
|
||||
else
|
||||
{
|
||||
PrintLine("Failed.");
|
||||
}
|
||||
|
||||
PrintString("Type set int field via reflection: ");
|
||||
intFieldInfo.SetValue(x, 456);
|
||||
if (x.IntField == 456)
|
||||
{
|
||||
PrintLine("Ok.");
|
||||
}
|
||||
else
|
||||
{
|
||||
PrintLine("Failed.");
|
||||
}
|
||||
|
||||
PrintString("Type set static int field via reflection: ");
|
||||
staticIntFieldInfo.SetValue(x, 987);
|
||||
if (ClassForMetaTests.StaticIntField == 987)
|
||||
{
|
||||
PrintLine("Ok.");
|
||||
}
|
||||
else
|
||||
{
|
||||
PrintLine("Failed.");
|
||||
}
|
||||
var st = new StructForMetaTests();
|
||||
st.StringField = "xyz";
|
||||
var fieldStructType = typeof(StructForMetaTests);
|
||||
var structStringFieldInfo = fieldStructType.GetField("StringField");
|
||||
PrintString("Struct get string field via reflection: ");
|
||||
if ((string)structStringFieldInfo.GetValue(st) == "xyz")
|
||||
{
|
||||
PrintLine("Ok.");
|
||||
}
|
||||
else
|
||||
{
|
||||
PrintLine("Failed.");
|
||||
}
|
||||
}
|
||||
|
||||
public class ClassForMetaTests
|
||||
{
|
||||
// used via reflection
|
||||
#pragma warning disable 0169
|
||||
public int IntField;
|
||||
public string StringField;
|
||||
#pragma warning restore 0169
|
||||
public static int StaticIntField;
|
||||
|
||||
public ClassForMetaTests()
|
||||
{
|
||||
StringField = "ab";
|
||||
IntField = 12;
|
||||
StaticIntField = 23;
|
||||
}
|
||||
}
|
||||
|
||||
public struct StructForMetaTests
|
||||
{
|
||||
public string StringField;
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Ensures all of the blocks of a try/finally function are hit when there aren't exceptions
|
||||
/// </summary>
|
||||
|
|
Загрузка…
Ссылка в новой задаче