Przeglądaj źródła

Reflection fixes for static values

Brian Fiete 5 lat temu
rodzic
commit
6cd66a2182

+ 2 - 2
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;

+ 67 - 59
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 (!mFieldData.mFlags.HasFlag(FieldFlags.Static))
+					return .Err;
 
-			if (!tTarget.IsSubtypeOf(mTypeInstance))
-			    Runtime.FatalError("Invalid type");   
+				targetDataAddr = null;
+			}
+			else
+			{
+				Type tTarget;
+				targetDataAddr = GetDataPtrAndType(target, out tTarget);
 
-			targetDataAddr = (uint8*)targetDataAddr + mFieldData.mDataOffset;
+				if (!tTarget.IsSubtypeOf(mTypeInstance))
+				    return .Err; //Invalid type;
+			}
+
+			targetDataAddr = (uint8*)targetDataAddr + (int)mFieldData.mData;
 
 			Type fieldType = Type.[Friend]GetType(mFieldData.mFieldTypeId);
 
@@ -220,63 +254,37 @@ namespace System.Reflection
 		{
 			Variant value = Variant();
 
-			Type tTarget;
-			void* targetDataAddr = GetDataPtrAndType(target, out tTarget);
-
-			if (!tTarget.IsSubtypeOf(mTypeInstance))
-			    Runtime.FatalError("Invalid type");   
-
-			targetDataAddr = (uint8*)targetDataAddr + mFieldData.mDataOffset;
-
-			Type fieldType = Type.[Friend]GetType(mFieldData.mFieldTypeId);
-
-			TypeCode typeCode = fieldType.[Friend]mTypeCode;
-			if (typeCode == TypeCode.Enum)
-				typeCode = fieldType.UnderlyingType.[Friend]mTypeCode;
-
-			value = Variant.CreateReference(fieldType, targetDataAddr);
-
-			return value;
-		}
-
-
-		public Result<Variant> GetValue()
-		{
-			Variant value = Variant();
+			void* targetDataAddr;
+			if (target == null)
+			{
+				if (mFieldData.mFlags.HasFlag(FieldFlags.Const))
+				{
+					return Variant.Create(FieldType, &mFieldData.mData);
+				}
 
-			//TODO: Assert static
+				if (!mFieldData.mFlags.HasFlag(FieldFlags.Static))
+					return .Err;
 
-			if (mFieldData.mFlags.HasFlag(FieldFlags.Const))
-			{
-				return Variant.Create(FieldType, &mFieldData.mConstValue);
+				targetDataAddr = null;
 			}
+			else
+			{
+				Type tTarget;
+				targetDataAddr = GetDataPtrAndType(target, out tTarget);
 
-			ThrowUnimplemented();
+				if (!tTarget.IsSubtypeOf(mTypeInstance))
+				    return .Err; //Invalid type;
+			}
 
-			//Type tTarget;
-#unwarn
-			void* targetDataAddr = (void*)(int)mFieldData.mConstValue;
+			targetDataAddr = (uint8*)targetDataAddr + (int)mFieldData.mData;
 
 			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;
-		    }
+
+			value = Variant.CreateReference(fieldType, targetDataAddr);
 
 			return value;
 		}

+ 4 - 4
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);
 					}
 				}
 			}

+ 1 - 2
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;

+ 1 - 1
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;

+ 7 - 7
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);

+ 42 - 12
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

+ 17 - 9
IDEHelper/Compiler/BfModule.cpp

@@ -5761,8 +5761,7 @@ BfIRValue BfModule::CreateTypeData(BfType* type, Dictionary<int, int>& 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<int, int>& usedStrin
 		SizedArray<BfIRValue, 8> 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<int, int>& 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<int, int>& 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<BfIRValue, 8> 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

+ 23 - 2
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<String>() == "A");
 
 					var res = methodInfo.Invoke(.(), fieldAV, fieldStrV).Value;
+					Test.Assert(ca.mA == 1123);
+					Test.Assert(ca.mB == "B");
 					var sa = res.Get<StructA>();
 					Test.Assert(sa.mA == 12);
 					Test.Assert(sa.mB == 34);
@@ -253,6 +258,22 @@ namespace Tests
 					Test.Assert(fieldStrV.Get<String>() == "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<int32>() == 234);
+					Test.Assert(fieldSStrV.Get<String>() == "AA");
+					res = methodInfo.Invoke(.(), fieldSAV, fieldSStrV).Value;
+					Test.Assert(fieldSAV.Get<int32>() == 1234);
+					Test.Assert(fieldSStrV.Get<String>() == "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();