From 6cd66a2182e02f3feebf455c321a5dcc125f09c3 Mon Sep 17 00:00:00 2001 From: Brian Fiete Date: Mon, 6 Jul 2020 09:55:19 -0700 Subject: [PATCH] Reflection fixes for static values --- BeefLibs/corlib/src/Enum.bf | 4 +- BeefLibs/corlib/src/Reflection/FieldInfo.bf | 128 ++++++++++-------- BeefLibs/corlib/src/Reflection/MethodInfo.bf | 8 +- BeefLibs/corlib/src/Type.bf | 3 +- IDE/mintest/minlib/src/System/Object.bf | 2 +- .../minlib/src/System/Reflection/FieldInfo.bf | 14 +- IDE/mintest/minlib/src/System/Type.bf | 54 ++++++-- IDEHelper/Compiler/BfModule.cpp | 26 ++-- IDEHelper/Tests/src/Reflection.bf | 25 +++- 9 files changed, 165 insertions(+), 99 deletions(-) diff --git a/BeefLibs/corlib/src/Enum.bf b/BeefLibs/corlib/src/Enum.bf index 497a9f1c..48712752 100644 --- a/BeefLibs/corlib/src/Enum.bf +++ b/BeefLibs/corlib/src/Enum.bf @@ -8,7 +8,7 @@ namespace System { for (var field in type.GetFields()) { - if (field.[Friend]mFieldData.[Friend]mConstValue == iVal) + if (field.[Friend]mFieldData.[Friend]mData == iVal) { strBuffer.Append(field.Name); return; @@ -24,7 +24,7 @@ namespace System for (var field in typeInst.GetFields()) { if (str.Equals(field.[Friend]mFieldData.mName, ignoreCase)) - return .Ok(*((T*)(&field.[Friend]mFieldData.mConstValue))); + return .Ok(*((T*)(&field.[Friend]mFieldData.mData))); } return .Err; diff --git a/BeefLibs/corlib/src/Reflection/FieldInfo.bf b/BeefLibs/corlib/src/Reflection/FieldInfo.bf index d381a10a..76acb6c9 100644 --- a/BeefLibs/corlib/src/Reflection/FieldInfo.bf +++ b/BeefLibs/corlib/src/Reflection/FieldInfo.bf @@ -24,7 +24,7 @@ namespace System.Reflection { get { - return mFieldData.mDataOffset; + return (int32)mFieldData.mData; } } @@ -64,7 +64,7 @@ namespace System.Reflection } Type fieldType = Type.[Friend]GetType(mFieldData.mFieldTypeId); - void* fieldDataAddr = ((uint8*)Internal.UnsafeCastToPtr(obj)) + mFieldData.mDataOffset + dataOffsetAdjust; + void* fieldDataAddr = ((uint8*)Internal.UnsafeCastToPtr(obj)) + (int)mFieldData.mData + dataOffsetAdjust; if (value == null) { @@ -123,7 +123,7 @@ namespace System.Reflection Type fieldType = Type.[Friend]GetType(mFieldData.mFieldTypeId); - void* dataAddr = ((uint8*)Internal.UnsafeCastToPtr(obj)) + mFieldData.mDataOffset + dataOffsetAdjust; + void* dataAddr = ((uint8*)Internal.UnsafeCastToPtr(obj)) + (int)mFieldData.mData + dataOffsetAdjust; if (value.VariantType != fieldType) return .Err;//("Invalid type"); @@ -158,19 +158,37 @@ namespace System.Reflection { value = default(TMember); - Type tTarget; - void* targetDataAddr = GetDataPtrAndType(target, out tTarget); + void* targetDataAddr; + if (target == null) + { + if (mFieldData.mFlags.HasFlag(FieldFlags.Const)) + { + // Unhandled + return .Err; + } + + if (!mFieldData.mFlags.HasFlag(FieldFlags.Static)) + return .Err; + + targetDataAddr = null; + } + else + { + Type tTarget; + targetDataAddr = GetDataPtrAndType(target, out tTarget); + + if (!tTarget.IsSubtypeOf(mTypeInstance)) + return .Err; //"Invalid type"); + } Type tMember = typeof(TMember); - targetDataAddr = (uint8*)targetDataAddr + mFieldData.mDataOffset; + targetDataAddr = (uint8*)targetDataAddr + (int)mFieldData.mData; Type fieldType = Type.[Friend]GetType(mFieldData.mFieldTypeId); if (tMember.[Friend]mTypeCode == TypeCode.Object) { - if (!tTarget.IsSubtypeOf(mTypeInstance)) - Runtime.FatalError(); value = *(TMember*)targetDataAddr; } else if (fieldType.[Friend]mTypeCode == tMember.[Friend]mTypeCode) @@ -189,13 +207,29 @@ namespace System.Reflection { Variant value = Variant(); - Type tTarget; - void* targetDataAddr = GetDataPtrAndType(target, out tTarget); + void* targetDataAddr; + if (target == null) + { + if (mFieldData.mFlags.HasFlag(FieldFlags.Const)) + { + return Variant.Create(FieldType, &mFieldData.mData); + } - if (!tTarget.IsSubtypeOf(mTypeInstance)) - Runtime.FatalError("Invalid type"); + if (!mFieldData.mFlags.HasFlag(FieldFlags.Static)) + return .Err; - targetDataAddr = (uint8*)targetDataAddr + mFieldData.mDataOffset; + targetDataAddr = null; + } + else + { + Type tTarget; + targetDataAddr = GetDataPtrAndType(target, out tTarget); + + if (!tTarget.IsSubtypeOf(mTypeInstance)) + return .Err; //Invalid type; + } + + targetDataAddr = (uint8*)targetDataAddr + (int)mFieldData.mData; Type fieldType = Type.[Friend]GetType(mFieldData.mFieldTypeId); @@ -220,13 +254,29 @@ namespace System.Reflection { Variant value = Variant(); - Type tTarget; - void* targetDataAddr = GetDataPtrAndType(target, out tTarget); + void* targetDataAddr; + if (target == null) + { + if (mFieldData.mFlags.HasFlag(FieldFlags.Const)) + { + return Variant.Create(FieldType, &mFieldData.mData); + } - if (!tTarget.IsSubtypeOf(mTypeInstance)) - Runtime.FatalError("Invalid type"); + if (!mFieldData.mFlags.HasFlag(FieldFlags.Static)) + return .Err; - targetDataAddr = (uint8*)targetDataAddr + mFieldData.mDataOffset; + targetDataAddr = null; + } + else + { + Type tTarget; + targetDataAddr = GetDataPtrAndType(target, out tTarget); + + if (!tTarget.IsSubtypeOf(mTypeInstance)) + return .Err; //Invalid type; + } + + targetDataAddr = (uint8*)targetDataAddr + (int)mFieldData.mData; Type fieldType = Type.[Friend]GetType(mFieldData.mFieldTypeId); @@ -239,48 +289,6 @@ namespace System.Reflection return value; } - - public Result GetValue() - { - Variant value = Variant(); - - //TODO: Assert static - - if (mFieldData.mFlags.HasFlag(FieldFlags.Const)) - { - return Variant.Create(FieldType, &mFieldData.mConstValue); - } - - ThrowUnimplemented(); - - //Type tTarget; -#unwarn - void* targetDataAddr = (void*)(int)mFieldData.mConstValue; - - Type fieldType = Type.[Friend]GetType(mFieldData.mFieldTypeId); - value.[Friend]mStructType = (int)Internal.UnsafeCastToPtr(fieldType); - - TypeCode typeCode = fieldType.[Friend]mTypeCode; - if (typeCode == TypeCode.Enum) - typeCode = fieldType.UnderlyingType.[Friend]mTypeCode; - - if (typeCode == TypeCode.Int32) - { - *(int32*)&value.[Friend]mData = *(int32*)targetDataAddr; - } - else if (typeCode == TypeCode.Object) - { - value.[Friend]mStructType = 0; - value.[Friend]mData = (int)targetDataAddr; - } - else - { - return .Err; - } - - return value; - } - public struct Enumerator : IEnumerator { BindingFlags mBindingFlags; diff --git a/BeefLibs/corlib/src/Reflection/MethodInfo.bf b/BeefLibs/corlib/src/Reflection/MethodInfo.bf index b78cc69c..8217bc52 100644 --- a/BeefLibs/corlib/src/Reflection/MethodInfo.bf +++ b/BeefLibs/corlib/src/Reflection/MethodInfo.bf @@ -105,12 +105,12 @@ namespace System.Reflection if (fieldType.IsStruct) { - SplatArg((TypeInstance)fieldType, (uint8*)ptr + fieldData.mDataOffset); + SplatArg((TypeInstance)fieldType, (uint8*)ptr + (int)fieldData.mData); } else { ffiParamList.Add(FFIType.Get(fieldType, null, null)); - ffiArgList.Add((uint8*)ptr + fieldData.mDataOffset); + ffiArgList.Add((uint8*)ptr + (int)fieldData.mData); } } } @@ -387,12 +387,12 @@ namespace System.Reflection if (fieldType.IsStruct) { - SplatArg((TypeInstance)fieldType, (uint8*)ptr + fieldData.mDataOffset); + SplatArg((TypeInstance)fieldType, (uint8*)ptr + (int)fieldData.mData); } else { ffiParamList.Add(FFIType.Get(fieldType, null, null)); - ffiArgList.Add((uint8*)ptr + fieldData.mDataOffset); + ffiArgList.Add((uint8*)ptr + (int)fieldData.mData); } } } diff --git a/BeefLibs/corlib/src/Type.bf b/BeefLibs/corlib/src/Type.bf index efb03908..c81d57a8 100644 --- a/BeefLibs/corlib/src/Type.bf +++ b/BeefLibs/corlib/src/Type.bf @@ -607,8 +607,7 @@ namespace System.Reflection public struct FieldData { public String mName; - public int64 mConstValue; - public int32 mDataOffset; + public int64 mData; public TypeId mFieldTypeId; public FieldFlags mFlags; public int32 mCustomAttributesIdx; diff --git a/IDE/mintest/minlib/src/System/Object.bf b/IDE/mintest/minlib/src/System/Object.bf index fbd4ba67..2837b2fa 100644 --- a/IDE/mintest/minlib/src/System/Object.bf +++ b/IDE/mintest/minlib/src/System/Object.bf @@ -478,7 +478,7 @@ namespace System for (var field in typeInst.GetFields()) { if (str == field.[Friend]mFieldData.mName) - return .Ok(*((T*)(&field.[Friend]mFieldData.mConstValue))); + return .Ok(*((T*)(&field.[Friend]mFieldData.mData))); } return .Err; diff --git a/IDE/mintest/minlib/src/System/Reflection/FieldInfo.bf b/IDE/mintest/minlib/src/System/Reflection/FieldInfo.bf index 479e6c05..3478a6dd 100644 --- a/IDE/mintest/minlib/src/System/Reflection/FieldInfo.bf +++ b/IDE/mintest/minlib/src/System/Reflection/FieldInfo.bf @@ -24,7 +24,7 @@ namespace System.Reflection { get { - return mFieldData.mDataOffset; + return (int32)mFieldData.mData; } } @@ -64,7 +64,7 @@ namespace System.Reflection } Type fieldType = Type.[Friend]GetType(mFieldData.mFieldTypeId); - void* fieldDataAddr = ((uint8*)(void*)obj) + mFieldData.mDataOffset + dataOffsetAdjust; + void* fieldDataAddr = ((uint8*)(void*)obj) + mFieldData.mData + dataOffsetAdjust; Type rawValueType = value.[Friend]RawGetType(); void* valueDataAddr = ((uint8*)(void*)value) + rawValueType.[Friend]mMemberDataOffset; @@ -123,7 +123,7 @@ namespace System.Reflection Type fieldType = Type.[Friend]GetType(mFieldData.mFieldTypeId); - void* dataAddr = ((uint8*)(void*)obj) + mFieldData.mDataOffset + dataOffsetAdjust; + void* dataAddr = ((uint8*)(void*)obj) + mFieldData.mData + dataOffsetAdjust; if (value.VariantType != fieldType) return .Err;//("Invalid type"); @@ -175,7 +175,7 @@ namespace System.Reflection Type tMember = typeof(TMember); - targetDataAddr = (uint8*)targetDataAddr + mFieldData.mDataOffset; + targetDataAddr = (uint8*)targetDataAddr + mFieldData.mData; Type fieldType = Type.[Friend]GetType(mFieldData.mFieldTypeId); @@ -207,7 +207,7 @@ namespace System.Reflection if (!tTarget.IsSubtypeOf(mTypeInstance)) Runtime.FatalError("Invalid type"); - targetDataAddr = (uint8*)targetDataAddr + mFieldData.mDataOffset; + targetDataAddr = (uint8*)targetDataAddr + mFieldData.mData; Type fieldType = Type.[Friend]GetType(mFieldData.mFieldTypeId); @@ -236,14 +236,14 @@ namespace System.Reflection if (mFieldData.mFlags.HasFlag(FieldFlags.Const)) { - return Variant.Create(FieldType, &mFieldData.mConstValue); + return Variant.Create(FieldType, &mFieldData.mData); } ThrowUnimplemented(); //Type tTarget; #unwarn - void* targetDataAddr = (void*)(int)mFieldData.mConstValue; + void* targetDataAddr = (void*)(int)mFieldData.mData; Type fieldType = Type.[Friend]GetType(mFieldData.mFieldTypeId); value.[Friend]mStructType = (int)Internal.UnsafeCastToPtr(fieldType); diff --git a/IDE/mintest/minlib/src/System/Type.bf b/IDE/mintest/minlib/src/System/Type.bf index f85f1cda..8ca94208 100644 --- a/IDE/mintest/minlib/src/System/Type.bf +++ b/IDE/mintest/minlib/src/System/Type.bf @@ -246,12 +246,27 @@ namespace System } } - public bool IsBoxedStructPtr + public Type BoxedPtrType { - get - { - return (mTypeFlags & (TypeFlags.Boxed | TypeFlags.Pointer)) == TypeFlags.Boxed | TypeFlags.Pointer; - } + get + { + if (!mTypeFlags.HasFlag(.Boxed)) + return null; + + if (mTypeFlags.HasFlag(.Pointer)) + { + return UnderlyingType; + } + + let underyingType = UnderlyingType; + if (var genericTypeInstance = underyingType as SpecializedGenericType) + { + if (genericTypeInstance.UnspecializedType == typeof(Pointer<>)) + return genericTypeInstance.GetGenericArg(0); + } + + return null; + } } public bool IsEnum @@ -469,7 +484,7 @@ namespace System { return FieldInfo.Enumerator(null, bindingFlags); } - + public override void ToString(String strBuffer) { GetFullName(strBuffer); @@ -531,7 +546,8 @@ namespace System Char16, Char32, Float, - Double, + Double, + Float2, Object, Interface, Struct, @@ -558,8 +574,7 @@ namespace System.Reflection public struct FieldData { public String mName; - public int64 mConstValue; - public int32 mDataOffset; + public int64 mData; public TypeId mFieldTypeId; public FieldFlags mFlags; public int32 mCustomAttributesIdx; @@ -708,6 +723,12 @@ namespace System.Reflection } strBuffer.Append(')'); } + else if (mTypeFlags.HasFlag(.Boxed)) + { + strBuffer.Append("boxed "); + let ut = UnderlyingType; + ut.GetFullName(strBuffer); + } else { if (mOuterType != 0) @@ -720,8 +741,9 @@ namespace System.Reflection if (!String.IsNullOrEmpty(mNamespace)) strBuffer.Append(mNamespace, "."); } - - strBuffer.Append(mName); + + if (mName != null) + strBuffer.Append(mName); } } @@ -744,7 +766,7 @@ namespace System.Reflection public override FieldInfo.Enumerator GetFields(BindingFlags bindingFlags = cDefaultLookup) { return FieldInfo.Enumerator(this, bindingFlags); - } + } } [Ordered, AlwaysInclude(AssumeInstantiated=true)] @@ -853,6 +875,14 @@ namespace System.Reflection TypeId mUnspecializedType; TypeId* mResolvedTypeRefs; + public Type UnspecializedType + { + get + { + return Type.[Friend]GetType(mUnspecializedType); + } + } + public override int32 GenericParamCount { get diff --git a/IDEHelper/Compiler/BfModule.cpp b/IDEHelper/Compiler/BfModule.cpp index 3e45a8d8..0d6cf96d 100644 --- a/IDEHelper/Compiler/BfModule.cpp +++ b/IDEHelper/Compiler/BfModule.cpp @@ -5761,8 +5761,7 @@ BfIRValue BfModule::CreateTypeData(BfType* type, Dictionary& usedStrin { emptyValueType, payloadNameConst, // mName - GetConstValue(0, longType), // mConstValue - GetConstValue(0, intType), // mDataOffset + GetConstValue(0, longType), // mData GetConstValue(payloadType->mTypeId, typeIdType), // mFieldTypeId GetConstValue(FieldFlags_SpecialName | FieldFlags_EnumPayload, shortType), // mFlags GetConstValue(-1, intType), // mCustomAttributesIdx @@ -5776,9 +5775,8 @@ BfIRValue BfModule::CreateTypeData(BfType* type, Dictionary& usedStrin SizedArray dscrFieldVals = { emptyValueType, - dscrNameConst, // mName - GetConstValue(0, longType), // mConstValue - GetConstValue(BF_ALIGN(payloadType->mSize, dscrType->mAlign), intType), // mDataOffset + dscrNameConst, // mName + GetConstValue(BF_ALIGN(payloadType->mSize, dscrType->mAlign), longType), // mData GetConstValue(dscrType->mTypeId, typeIdType), // mFieldTypeId GetConstValue(FieldFlags_SpecialName | FieldFlags_EnumDiscriminator, shortType), // mFlags GetConstValue(-1, intType), // mCustomAttributesIdx @@ -5818,7 +5816,7 @@ BfIRValue BfModule::CreateTypeData(BfType* type, Dictionary& usedStrin fieldFlags = (FieldFlags)(fieldFlags | FieldFlags_Const); int customAttrIdx = _HandleCustomAttrs(fieldInstance->mCustomAttributes); - BfIRValue constValue = GetConstValue(0, longType); + BfIRValue constValue; if (fieldInstance->GetFieldDef()->mIsConst) { if (fieldInstance->mConstIdx != -1) @@ -5826,14 +5824,24 @@ BfIRValue BfModule::CreateTypeData(BfType* type, Dictionary& usedStrin auto constant = typeInstance->mConstHolder->GetConstantById(fieldInstance->mConstIdx); constValue = mBfIRBuilder->CreateConst(BfTypeCode_UInt64, constant->mUInt64); } - } + } + else if (fieldInstance->GetFieldDef()->mIsStatic) + { + auto refVal = ReferenceStaticField(fieldInstance); + if (refVal.IsAddr()) + constValue = mBfIRBuilder->CreatePtrToInt(refVal.mValue, BfTypeCode_Int64); + } + + if (!constValue) + { + constValue = GetConstValue(fieldInstance->mDataOffset, longType); + } SizedArray fieldVals = { emptyValueType, fieldNameConst, // mName - constValue, // mConstValue - GetConstValue(fieldInstance->mDataOffset, intType), // mDataOffset + constValue, // mConstValue GetConstValue(typeId, typeIdType), // mFieldTypeId GetConstValue(fieldFlags, shortType), // mFlags GetConstValue(customAttrIdx, intType), // mCustomAttributesIdx diff --git a/IDEHelper/Tests/src/Reflection.bf b/IDEHelper/Tests/src/Reflection.bf index 07c45f94..3ae35a3c 100644 --- a/IDEHelper/Tests/src/Reflection.bf +++ b/IDEHelper/Tests/src/Reflection.bf @@ -53,8 +53,11 @@ namespace Tests [Reflect] class ClassA { - int32 mA = 123; - String mStr = "A"; + public int32 mA = 123; + public String mStr = "A"; + + public static int32 sA = 234; + public static String sStr = "AA"; [AlwaysInclude, AttrC(71, 72)] static float StaticMethodA(int32 a, int32 b, float c, ref int32 d, ref StructA sa) @@ -237,6 +240,8 @@ namespace Tests Test.Assert(fieldStrV.Get() == "A"); var res = methodInfo.Invoke(.(), fieldAV, fieldStrV).Value; + Test.Assert(ca.mA == 1123); + Test.Assert(ca.mB == "B"); var sa = res.Get(); Test.Assert(sa.mA == 12); Test.Assert(sa.mB == 34); @@ -253,6 +258,22 @@ namespace Tests Test.Assert(fieldStrV.Get() == "B"); fieldAV.Dispose(); fieldStrV.Dispose(); + + var fieldSA = typeInfo.GetField("sA").Value; + var fieldSStr = typeInfo.GetField("sStr").Value; + var fieldSAV = fieldSA.GetValueReference(null).Value; + var fieldSStrV = fieldSStr.GetValueReference(null).Value; + Test.Assert(fieldSAV.Get() == 234); + Test.Assert(fieldSStrV.Get() == "AA"); + res = methodInfo.Invoke(.(), fieldSAV, fieldSStrV).Value; + Test.Assert(fieldSAV.Get() == 1234); + Test.Assert(fieldSStrV.Get() == "B"); + Test.Assert(ClassA.sA == 1234); + Test.Assert(ClassA.sStr == "B"); + res.Dispose(); + fieldSAV.Dispose(); + fieldSStrV.Dispose(); + case 2: Test.Assert(methodInfo.Name == "MemberMethodA"); var result = methodInfo.Invoke(ca, 100, (int32)20, 3.0f).Get();