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:
yowl 2019-02-15 09:02:31 +00:00 коммит произвёл Michal Strehovský
Родитель 32d2a20ec5
Коммит c404dd1cbb
3 изменённых файлов: 136 добавлений и 21 удалений

Просмотреть файл

@ -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>