From da5b81f4195965cc3f3b4ba467823724b2e0f7b4 Mon Sep 17 00:00:00 2001 From: Brian Fiete Date: Mon, 14 Sep 2020 11:18:24 -0700 Subject: [PATCH] Dynamic boxing --- BeefLibs/corlib/src/Attribute.bf | 6 +- .../corlib/src/Reflection/TypeInstance.bf | 36 +-- BeefLibs/corlib/src/Type.bf | 8 + BeefLibs/corlib/src/Variant.bf | 16 ++ IDE/src/BuildOptions.bf | 6 + IDE/src/Compiler/BfSystem.bf | 16 +- IDE/src/ui/BuildPropertiesDialog.bf | 4 + IDEHelper/Compiler/BfCompiler.cpp | 49 +++- IDEHelper/Compiler/BfCompiler.h | 1 + IDEHelper/Compiler/BfModule.cpp | 224 +++++++++--------- IDEHelper/Compiler/BfModule.h | 2 + IDEHelper/Compiler/BfModuleTypeUtils.cpp | 19 +- IDEHelper/Compiler/BfResolvedTypeUtils.h | 2 + IDEHelper/Compiler/BfSystem.h | 28 ++- 14 files changed, 266 insertions(+), 151 deletions(-) diff --git a/BeefLibs/corlib/src/Attribute.bf b/BeefLibs/corlib/src/Attribute.bf index b18c9437..c65401a3 100644 --- a/BeefLibs/corlib/src/Attribute.bf +++ b/BeefLibs/corlib/src/Attribute.bf @@ -46,9 +46,11 @@ namespace System Constructors = 0x10, StaticMethods = 0x20, Methods = 0x40, - All = 0x7F, + DynamicBoxing = 0x80, + //User = 0x100, // Internal Use + All = 0xFF, - ApplyToInnerTypes = 0x80, + ApplyToInnerTypes = 0x200, } public enum AttributeFlags diff --git a/BeefLibs/corlib/src/Reflection/TypeInstance.bf b/BeefLibs/corlib/src/Reflection/TypeInstance.bf index 4ca25e70..cf7ebd3e 100644 --- a/BeefLibs/corlib/src/Reflection/TypeInstance.bf +++ b/BeefLibs/corlib/src/Reflection/TypeInstance.bf @@ -83,20 +83,23 @@ namespace System.Reflection return .Err; MethodInfo methodInfo = default; - for (int methodId < mMethodDataCount) + if (!IsBoxed) { - let methodData = &mMethodDataPtr[methodId]; - if ((!methodData.mFlags.HasFlag(.Constructor)) || (methodData.mFlags.HasFlag(.Static))) - continue; - if (methodData.mParamCount != 0) - continue; - - methodInfo = .(this, methodData); - break; - } + for (int methodId < mMethodDataCount) + { + let methodData = &mMethodDataPtr[methodId]; + if ((!methodData.mFlags.HasFlag(.Constructor)) || (methodData.mFlags.HasFlag(.Static))) + continue; + if (methodData.mParamCount != 0) + continue; + + methodInfo = .(this, methodData); + break; + } - if (!methodInfo.IsInitialized) - return .Err; + if (!methodInfo.IsInitialized) + return .Err; + } Object obj; let objType = typeof(Object) as TypeInstance; @@ -109,10 +112,13 @@ namespace System.Reflection obj.[Friend]mClassVData = (.)(void*)mTypeClassVData; #endif Internal.MemSet((uint8*)Internal.UnsafeCastToPtr(obj) + objType.mInstSize, 0, mInstSize - objType.mInstSize); - if (methodInfo.Invoke(obj) case .Err) + if (methodInfo.IsInitialized) { - delete obj; - return .Err; + if (methodInfo.Invoke(obj) case .Err) + { + delete obj; + return .Err; + } } return obj; diff --git a/BeefLibs/corlib/src/Type.bf b/BeefLibs/corlib/src/Type.bf index 25b53d7e..ef228a58 100644 --- a/BeefLibs/corlib/src/Type.bf +++ b/BeefLibs/corlib/src/Type.bf @@ -304,6 +304,14 @@ namespace System } } + public TypeInstance BoxedType + { + get + { + return (TypeInstance)GetType(mBoxedType); + } + } + public bool IsEnum { get diff --git a/BeefLibs/corlib/src/Variant.bf b/BeefLibs/corlib/src/Variant.bf index f4459233..e397c804 100644 --- a/BeefLibs/corlib/src/Variant.bf +++ b/BeefLibs/corlib/src/Variant.bf @@ -296,6 +296,22 @@ namespace System return *(T*)(void*)mData; } + public Result GetBoxed() + { + if (IsObject) + return .Err; + + var type = VariantType; + var boxedType = type.BoxedType; + if (boxedType == null) + return .Err; + + var self = this; + var object = Try!(boxedType.CreateObject()); + Internal.MemCpy((uint8*)Internal.UnsafeCastToPtr(object) + boxedType.[Friend]mMemberDataOffset, self.DataPtr, type.Size); + return object; + } + /*public void Get(ref T val) { if (VariantType != typeof(T)) diff --git a/IDE/src/BuildOptions.bf b/IDE/src/BuildOptions.bf index 32f23d6a..cfe01806 100644 --- a/IDE/src/BuildOptions.bf +++ b/IDE/src/BuildOptions.bf @@ -106,6 +106,8 @@ namespace IDE [Reflect] public BuildOptions.AlwaysIncludeKind mReflectAlwaysInclude; [Reflect] + public bool? mReflectBoxing; + [Reflect] public bool? mReflectStaticFields; [Reflect] public bool? mReflectNonStaticFields; @@ -135,6 +137,7 @@ namespace IDE newVal.mEmitObjectAccessCheck = mEmitObjectAccessCheck; newVal.mAllocStackTraceDepth = mAllocStackTraceDepth; newVal.mReflectAlwaysInclude = mReflectAlwaysInclude; + newVal.mReflectBoxing = mReflectBoxing; newVal.mReflectStaticFields = mReflectStaticFields; newVal.mReflectNonStaticFields = mReflectNonStaticFields; newVal.mReflectStaticMethods = mReflectStaticMethods; @@ -166,6 +169,8 @@ namespace IDE if (data.Contains("ReflectAlwaysInclude")) mReflectAlwaysInclude = data.GetEnum("ReflectAlwaysInclude"); + if (data.Contains("ReflectBoxing")) + mReflectStaticFields = data.GetBool("ReflectBoxing"); if (data.Contains("ReflectStaticFields")) mReflectStaticFields = data.GetBool("ReflectStaticFields"); if (data.Contains("ReflectNonStaticFields")) @@ -191,6 +196,7 @@ namespace IDE data.ConditionalAdd("EmitObjectAccessCheck", mEmitObjectAccessCheck); data.ConditionalAdd("AllocStackTraceDepth", mAllocStackTraceDepth); data.ConditionalAdd("ReflectAlwaysInclude", mReflectAlwaysInclude); + data.ConditionalAdd("ReflectBoxing", mReflectBoxing); data.ConditionalAdd("ReflectStaticFields", mReflectStaticFields); data.ConditionalAdd("ReflectNonStaticFields", mReflectNonStaticFields); data.ConditionalAdd("ReflectStaticMethods", mReflectStaticMethods); diff --git a/IDE/src/Compiler/BfSystem.bf b/IDE/src/Compiler/BfSystem.bf index f48bec3e..0d7b93ee 100644 --- a/IDE/src/Compiler/BfSystem.bf +++ b/IDE/src/Compiler/BfSystem.bf @@ -18,14 +18,15 @@ namespace IDE.Compiler ReflectAlwaysIncludeType = 0x10, ReflectAlwaysIncludeAll = 0x20, - ReflectAssumeInstantiated = 0x40, - ReflectStaticFields = 0x80, - ReflectNonStaticFields = 0x100, - ReflectStaticMethods = 0x200, - ReflectNonStaticMethods = 0x400, - ReflectConstructors = 0x800, + ReflectAssumeInstantiated = 0x40, + ReflectBoxing = 0x80, + ReflectStaticFields = 0x100, + ReflectNonStaticFields = 0x200, + ReflectStaticMethods = 0x400, + ReflectNonStaticMethods = 0x800, + ReflectConstructors = 0x1000, - All = 0xFFF + All = 0x1FFF }; [CallingConvention(.Stdcall), CLink] @@ -401,6 +402,7 @@ namespace IDE.Compiler orFlags |= .ReflectAlwaysIncludeType | .ReflectAlwaysIncludeAll | .ReflectAssumeInstantiated; } + SetFlag(typeOption.mReflectBoxing, .ReflectBoxing); SetFlag(typeOption.mReflectStaticFields, .ReflectStaticFields); SetFlag(typeOption.mReflectNonStaticFields, .ReflectNonStaticFields); SetFlag(typeOption.mReflectStaticMethods, .ReflectStaticMethods); diff --git a/IDE/src/ui/BuildPropertiesDialog.bf b/IDE/src/ui/BuildPropertiesDialog.bf index 0136dcf8..58310662 100644 --- a/IDE/src/ui/BuildPropertiesDialog.bf +++ b/IDE/src/ui/BuildPropertiesDialog.bf @@ -151,6 +151,10 @@ namespace IDE.ui typeName.Clear(); typeName.Append(optionsName, "mReflectAlwaysInclude"); AddPropertiesItem(reflectItem, "Always Include", typeName); + typeName.Clear(); typeName.Append(optionsName, "mReflectBoxing"); + AddPropertiesItem(reflectItem, "Dynamic Boxing", typeName, + scope String[] ( "No", "Yes" )); + typeName.Clear(); typeName.Append(optionsName, "mReflectStaticFields"); AddPropertiesItem(reflectItem, "Static Fields", typeName, scope String[] ( "No", "Yes" )); diff --git a/IDEHelper/Compiler/BfCompiler.cpp b/IDEHelper/Compiler/BfCompiler.cpp index 7e5f635d..84de1116 100644 --- a/IDEHelper/Compiler/BfCompiler.cpp +++ b/IDEHelper/Compiler/BfCompiler.cpp @@ -438,6 +438,7 @@ BfCompiler::BfCompiler(BfSystem* bfSystem, bool isResolveOnly) mErrorAttributeTypeDef = NULL; mWarnAttributeTypeDef = NULL; mIgnoreErrorsAttributeTypeDef = NULL; + mReflectAttributeTypeDef = NULL; mLastAutocompleteModule = NULL; } @@ -4247,7 +4248,7 @@ void BfCompiler::ProcessAutocompleteTempType() BP_ZONE("ProcessAutocompleteTempType.CheckMethod"); BfMethodInstanceGroup methodInstanceGroup; - methodInstanceGroup.mOwner = typeInst; + methodInstanceGroup.mOwner = typeInst; methodInstanceGroup.mOnDemandKind = BfMethodOnDemandKind_AlwaysInclude; BfMethodInstance* methodInstance = new BfMethodInstance(); @@ -5111,9 +5112,37 @@ void BfCompiler::PopulateReified() if (!unspecializedType->mIsReified) unspecializedType->mIsReified = true; } + + if ((typeInst != NULL) && (typeInst->mTypeDef->mName->ToString() == "StructA")) + { + NOP; + } + + if ((type->IsValueType()) && (!type->IsUnspecializedType())) + { + bool dynamicBoxing = false; + if ((typeInst != NULL) && (typeInst->mTypeOptionsIdx != -2)) + { + auto typeOptions = mSystem->GetTypeOptions(typeInst->mTypeOptionsIdx); + if (typeOptions != NULL) + { + if (typeOptions->Apply(false, BfOptionFlags_ReflectBoxing)) + dynamicBoxing = true; + } + } + auto reflectKind = module->GetReflectKind(BfReflectKind_None, typeInst); + if ((reflectKind & BfReflectKind_DynamicBoxing) != 0) + dynamicBoxing = true; + if (dynamicBoxing) + { + auto boxedType = module->CreateBoxedType(typeInst); + module->AddDependency(boxedType, typeInst, BfDependencyMap::DependencyFlag_Allocates); + boxedType->mHasBeenInstantiated = true; + } + } // Check reifications forced by virtuals or interfaces - if ((!mIsResolveOnly) && (typeInst != NULL) && (typeInst->mIsReified) && (typeInst->IsObject()) && (!typeInst->IsUnspecializedType()) + if ((!mIsResolveOnly) && (typeInst != NULL) && (typeInst->mIsReified) && (!typeInst->IsUnspecializedType()) && (typeInst->mHasBeenInstantiated) && (!typeInst->IsIncomplete())) { // If we have chained methods, make sure we implement the chain members if the chain head is implemented and reified @@ -5228,7 +5257,20 @@ void BfCompiler::PopulateReified() for (int iMethodIdx = 0; iMethodIdx < iMethodCount; iMethodIdx++) { - auto ifaceMethodInst = ifaceInst->mMethodInstanceGroups[iMethodIdx].mDefault; + auto& ifaceMethodInstGroup = ifaceInst->mMethodInstanceGroups[iMethodIdx]; + auto ifaceMethodInst = ifaceMethodInstGroup.mDefault; + + if (typeInst->IsObject()) + { + // If the implementor is an object then this can be dynamically dispatched + } + else + { + // If this method is explicitly reflected then a struct's implementation may be invoked with reflection + if (!ifaceMethodInstGroup.mExplicitlyReflected) + continue; + } + if ((ifaceMethodInst == NULL) || (!ifaceMethodInst->IsReifiedAndImplemented())) continue; @@ -6348,6 +6390,7 @@ bool BfCompiler::DoCompile(const StringImpl& outputDirectory) mErrorAttributeTypeDef = _GetRequiredType("System.ErrorAttribute"); mWarnAttributeTypeDef = _GetRequiredType("System.WarnAttribute"); mIgnoreErrorsAttributeTypeDef = _GetRequiredType("System.IgnoreErrorsAttribute"); + mReflectAttributeTypeDef = _GetRequiredType("System.ReflectAttribute"); for (int i = 0; i < BfTypeCode_Length; i++) mContext->mPrimitiveStructTypes[i] = NULL; diff --git a/IDEHelper/Compiler/BfCompiler.h b/IDEHelper/Compiler/BfCompiler.h index 0ec7a1d3..9f054caa 100644 --- a/IDEHelper/Compiler/BfCompiler.h +++ b/IDEHelper/Compiler/BfCompiler.h @@ -404,6 +404,7 @@ public: BfTypeDef* mErrorAttributeTypeDef; BfTypeDef* mWarnAttributeTypeDef; BfTypeDef* mIgnoreErrorsAttributeTypeDef; + BfTypeDef* mReflectAttributeTypeDef; int mCurTypeId; diff --git a/IDEHelper/Compiler/BfModule.cpp b/IDEHelper/Compiler/BfModule.cpp index 1c04281a..e1912cce 100644 --- a/IDEHelper/Compiler/BfModule.cpp +++ b/IDEHelper/Compiler/BfModule.cpp @@ -5530,120 +5530,24 @@ BfIRValue BfModule::CreateTypeData(BfType* type, Dictionary& usedStrin reflectIncludeAllMethods = true; } - enum ReflectKind - { - ReflectKind_None = 0, - ReflectKind_Type = 1, - ReflectKind_NonStaticFields = 2, - ReflectKind_StaticFields = 4, - ReflectKind_DefaultConstructor = 8, - ReflectKind_Constructors = 0x10, - ReflectKind_StaticMethods = 0x20, - ReflectKind_Methods = 0x40, - ReflectKind_User = 0x80, - ReflectKind_All = 0x7F, - - ReflectKind_ApplyToInnerTypes = 0x80 - }; - - ReflectKind reflectKind = ReflectKind_Type; - - auto _GetReflectUser = [&](BfTypeInstance* attrType) - { - ReflectKind reflectKind = ReflectKind_None; - - if (attrType->mCustomAttributes != NULL) - { - for (auto& customAttr : attrType->mCustomAttributes->mAttributes) - { - if (customAttr.mType->mTypeDef->mName->ToString() == "AttributeUsageAttribute") - { - for (auto& prop : customAttr.mSetProperties) - { - auto propDef = prop.mPropertyRef.mTypeInstance->mTypeDef->mProperties[prop.mPropertyRef.mPropIdx]; - if (propDef->mName == "ReflectUser") - { - if (prop.mParam.mValue.IsConst()) - { - auto constant = attrType->mConstHolder->GetConstant(prop.mParam.mValue); - reflectKind = (ReflectKind)(reflectKind | (ReflectKind)constant->mInt32); - } - } - } - - // Check for Flags arg - if (customAttr.mCtorArgs.size() < 2) - continue; - auto constant = attrType->mConstHolder->GetConstant(customAttr.mCtorArgs[1]); - if (constant == NULL) - continue; - if (constant->mTypeCode == BfTypeCode_Boolean) - continue; - if ((constant->mInt8 & BfCustomAttributeFlags_ReflectAttribute) != 0) - reflectKind = (ReflectKind)(reflectKind | ReflectKind_User); - } - } - } - - return reflectKind; - }; + BfReflectKind reflectKind = BfReflectKind_Type; auto _GetReflectUserFromDirective = [&](BfAttributeDirective* attributesDirective, BfAttributeTargets attrTarget) { - ReflectKind reflectKind = ReflectKind_None; + BfReflectKind reflectKind = BfReflectKind_None; auto customAttrs = GetCustomAttributes(attributesDirective, attrTarget); if (customAttrs != NULL) { for (auto& attr : customAttrs->mAttributes) { - reflectKind = (ReflectKind)(reflectKind | _GetReflectUser(attr.mType)); + reflectKind = (BfReflectKind)(reflectKind | GetUserReflectKind(attr.mType)); } } return reflectKind; }; - // - { - - auto checkTypeInstance = typeInstance; - while (checkTypeInstance != NULL) - { - if (checkTypeInstance->mCustomAttributes != NULL) - { - auto checkReflectKind = ReflectKind_None; - - for (auto& customAttr : checkTypeInstance->mCustomAttributes->mAttributes) - { - if (customAttr.mType->mTypeDef->mName->ToString() == "ReflectAttribute") - { - if (customAttr.mCtorArgs.size() > 0) - { - auto constant = checkTypeInstance->mConstHolder->GetConstant(customAttr.mCtorArgs[0]); - checkReflectKind = (ReflectKind)((int)checkReflectKind | constant->mInt32); - } - else - { - checkReflectKind = ReflectKind_All; - } - } - else - { - auto userReflectKind = _GetReflectUser(customAttr.mType); - checkReflectKind = (ReflectKind)(checkReflectKind | userReflectKind); - } - } - - if ((checkTypeInstance == typeInstance) || - ((checkReflectKind & ReflectKind_ApplyToInnerTypes) != 0)) - { - reflectKind = (ReflectKind)(reflectKind | checkReflectKind); - } - } - - checkTypeInstance = mContext->mUnreifiedModule->GetOuterType(checkTypeInstance); - } - } - + reflectKind = GetReflectKind(reflectKind, typeInstance); + // Fields BfType* reflectFieldDataType = ResolveTypeDef(mCompiler->mReflectFieldDataDef); BfIRValue emptyValueType = mBfIRBuilder->CreateConstStruct(mBfIRBuilder->MapTypeInst(reflectFieldDataType->ToTypeInstance()->mBaseType), SizedArray()); @@ -5836,7 +5740,7 @@ BfIRValue BfModule::CreateTypeData(BfType* type, Dictionary& usedStrin if (fieldDef == NULL) continue; - auto fieldReflectKind = (ReflectKind)(reflectKind & ~ReflectKind_User); + auto fieldReflectKind = (BfReflectKind)(reflectKind & ~BfReflectKind_User); bool includeField = reflectIncludeAllFields; @@ -5850,17 +5754,17 @@ BfIRValue BfModule::CreateTypeData(BfType* type, Dictionary& usedStrin } else { - auto userReflectKind = _GetReflectUser(customAttr.mType); - fieldReflectKind = (ReflectKind)(fieldReflectKind | userReflectKind); + auto userReflectKind = GetUserReflectKind(customAttr.mType); + fieldReflectKind = (BfReflectKind)(fieldReflectKind | userReflectKind); } } } - if ((fieldReflectKind & ReflectKind_User) != 0) + if ((fieldReflectKind & BfReflectKind_User) != 0) includeField = true; - if ((!fieldDef->mIsStatic) && ((fieldReflectKind & ReflectKind_NonStaticFields) != 0)) + if ((!fieldDef->mIsStatic) && ((fieldReflectKind & BfReflectKind_NonStaticFields) != 0)) includeField = true; - if ((fieldDef->mIsStatic) && ((fieldReflectKind & ReflectKind_StaticFields) != 0)) + if ((fieldDef->mIsStatic) && ((fieldReflectKind & BfReflectKind_StaticFields) != 0)) includeField = true; if ((!fieldDef->mIsStatic) && (typeOptions != NULL)) @@ -6142,7 +6046,7 @@ BfIRValue BfModule::CreateTypeData(BfType* type, Dictionary& usedStrin if (defaultMethod->mMethodDef->mMethodType == BfMethodType_CtorNoBody) continue; - auto methodReflectKind = (ReflectKind)(reflectKind & ~ReflectKind_User); + auto methodReflectKind = (BfReflectKind)(reflectKind & ~BfReflectKind_User); bool includeMethod = reflectIncludeAllMethods; @@ -6158,8 +6062,8 @@ BfIRValue BfModule::CreateTypeData(BfType* type, Dictionary& usedStrin } else { - auto userReflectKind = _GetReflectUser(customAttr.mType); - methodReflectKind = (ReflectKind)(methodReflectKind | userReflectKind); + auto userReflectKind = GetUserReflectKind(customAttr.mType); + methodReflectKind = (BfReflectKind)(methodReflectKind | userReflectKind); } } } @@ -6172,15 +6076,15 @@ BfIRValue BfModule::CreateTypeData(BfType* type, Dictionary& usedStrin for (BfParameterDeclaration* paramDecl : methodDeclaration->mParams) { if (paramDecl->mAttributes != NULL) - methodReflectKind = (ReflectKind)(methodReflectKind | _GetReflectUserFromDirective(paramDecl->mAttributes, BfAttributeTargets_Parameter)); + methodReflectKind = (BfReflectKind)(methodReflectKind | _GetReflectUserFromDirective(paramDecl->mAttributes, BfAttributeTargets_Parameter)); } if (methodDeclaration->mReturnAttributes != NULL) - methodReflectKind = (ReflectKind)(methodReflectKind | _GetReflectUserFromDirective(methodDeclaration->mReturnAttributes, BfAttributeTargets_ReturnValue)); + methodReflectKind = (BfReflectKind)(methodReflectKind | _GetReflectUserFromDirective(methodDeclaration->mReturnAttributes, BfAttributeTargets_ReturnValue)); } - if ((methodReflectKind & (ReflectKind_Methods | ReflectKind_User)) != 0) + if ((methodReflectKind & (BfReflectKind_Methods | BfReflectKind_User)) != 0) includeMethod = true; - if ((methodDef->mIsStatic) && ((methodReflectKind & ReflectKind_StaticMethods) != 0)) + if ((methodDef->mIsStatic) && ((methodReflectKind & BfReflectKind_StaticMethods) != 0)) includeMethod = true; if ((!includeMethod) && (typeOptions != NULL)) @@ -6395,6 +6299,11 @@ BfIRValue BfModule::CreateTypeData(BfType* type, Dictionary& usedStrin if ((!typeInstance->IsInterface()) && (typeInstance->mIsReified) && (!typeInstance->IsUnspecializedType()) && (!typeInstance->mInterfaceMethodTable.IsEmpty())) { + if (typeDef->mName->ToString() == "StructA") + { + NOP; + } + SizedArray methods; for (auto& methodEntry : typeInstance->mInterfaceMethodTable) { @@ -6412,8 +6321,8 @@ BfIRValue BfModule::CreateTypeData(BfType* type, Dictionary& usedStrin methods.Add(funcVal); } - while ((!methods.IsEmpty()) && (methods.back() == voidPtrNull)) - methods.pop_back(); +// while ((!methods.IsEmpty()) && (methods.back() == voidPtrNull)) +// methods.pop_back(); BfIRType methodDataArrayType = mBfIRBuilder->GetSizedArrayType(mBfIRBuilder->MapType(voidPtrType, BfIRPopulateType_Full), (int)methods.size()); BfIRValue methodDataConst = mBfIRBuilder->CreateConstArray(methodDataArrayType, methods); @@ -13461,6 +13370,89 @@ BfTypeOptions* BfModule::GetTypeOptions() return mSystem->GetTypeOptions(mCurTypeInstance->mTypeOptionsIdx); } +BfReflectKind BfModule::GetUserReflectKind(BfTypeInstance* attrType) +{ + BfReflectKind reflectKind = BfReflectKind_None; + + if (attrType->mCustomAttributes != NULL) + { + for (auto& customAttr : attrType->mCustomAttributes->mAttributes) + { + if (customAttr.mType->mTypeDef->mName->ToString() == "AttributeUsageAttribute") + { + for (auto& prop : customAttr.mSetProperties) + { + auto propDef = prop.mPropertyRef.mTypeInstance->mTypeDef->mProperties[prop.mPropertyRef.mPropIdx]; + if (propDef->mName == "ReflectUser") + { + if (prop.mParam.mValue.IsConst()) + { + auto constant = attrType->mConstHolder->GetConstant(prop.mParam.mValue); + reflectKind = (BfReflectKind)(reflectKind | (BfReflectKind)constant->mInt32); + } + } + } + + // Check for Flags arg + if (customAttr.mCtorArgs.size() < 2) + continue; + auto constant = attrType->mConstHolder->GetConstant(customAttr.mCtorArgs[1]); + if (constant == NULL) + continue; + if (constant->mTypeCode == BfTypeCode_Boolean) + continue; + if ((constant->mInt8 & BfCustomAttributeFlags_ReflectAttribute) != 0) + reflectKind = (BfReflectKind)(reflectKind | BfReflectKind_User); + } + } + } + + return reflectKind; +} + +BfReflectKind BfModule::GetReflectKind(BfReflectKind reflectKind, BfTypeInstance* typeInstance) +{ + auto checkTypeInstance = typeInstance; + while (checkTypeInstance != NULL) + { + if (checkTypeInstance->mCustomAttributes != NULL) + { + auto checkReflectKind = BfReflectKind_None; + + for (auto& customAttr : checkTypeInstance->mCustomAttributes->mAttributes) + { + if (customAttr.mType->mTypeDef->mName->ToString() == "ReflectAttribute") + { + if (customAttr.mCtorArgs.size() > 0) + { + auto constant = checkTypeInstance->mConstHolder->GetConstant(customAttr.mCtorArgs[0]); + checkReflectKind = (BfReflectKind)((int)checkReflectKind | constant->mInt32); + } + else + { + checkReflectKind = BfReflectKind_All; + } + } + else + { + auto userReflectKind = GetUserReflectKind(customAttr.mType); + checkReflectKind = (BfReflectKind)(checkReflectKind | userReflectKind); + } + } + + if ((checkTypeInstance == typeInstance) || + ((checkReflectKind & BfReflectKind_ApplyToInnerTypes) != 0)) + { + reflectKind = (BfReflectKind)(reflectKind | checkReflectKind); + } + } + + checkTypeInstance = mContext->mUnreifiedModule->GetOuterType(checkTypeInstance); + } + + return reflectKind; +} + bool BfModule::HasDeferredScopeCalls(BfScopeData* scope) { BfScopeData* checkScope = mCurMethodState->mCurScope; diff --git a/IDEHelper/Compiler/BfModule.h b/IDEHelper/Compiler/BfModule.h index e6f0a238..42190cba 100644 --- a/IDEHelper/Compiler/BfModule.h +++ b/IDEHelper/Compiler/BfModule.h @@ -1512,6 +1512,8 @@ public: BfTypedValue GetIntCoercible(const BfTypedValue& typedValue); bool WantsDebugInfo(); BfTypeOptions* GetTypeOptions(); + BfReflectKind GetUserReflectKind(BfTypeInstance* attrType); + BfReflectKind GetReflectKind(BfReflectKind reflectKind, BfTypeInstance* typeInstance); void CleanupFileInstances(); void AssertErrorState(); void AssertParseErrorState(); diff --git a/IDEHelper/Compiler/BfModuleTypeUtils.cpp b/IDEHelper/Compiler/BfModuleTypeUtils.cpp index 8b0082ad..d2d8f19b 100644 --- a/IDEHelper/Compiler/BfModuleTypeUtils.cpp +++ b/IDEHelper/Compiler/BfModuleTypeUtils.cpp @@ -3996,15 +3996,28 @@ void BfModule::DoTypeInstanceMethodProcessing(BfTypeInstance* typeInstance) isFailedType = true; } - bool typeOptionsIncludeAll = false; - if (typeOptions != NULL) - typeOptionsIncludeAll = typeOptions->Apply(typeOptionsIncludeAll, BfOptionFlags_ReflectAlwaysIncludeAll); + bool typeOptionsIncludeAll = false; + if (typeOptions != NULL) + typeOptionsIncludeAll = typeOptions->Apply(typeOptionsIncludeAll, BfOptionFlags_ReflectAlwaysIncludeAll); // Generate all methods. Pass 1 for (auto methodDef : typeDef->mMethods) { auto methodInstanceGroup = &typeInstance->mMethodInstanceGroups[methodDef->mIdx]; + if (typeOptions != NULL) + { + BfOptionFlags optionFlags = BfOptionFlags_ReflectNonStaticMethods; + if (methodDef->mMethodType == BfMethodType_Ctor) + optionFlags = BfOptionFlags_ReflectConstructors; + else if (methodDef->mIsStatic) + optionFlags = BfOptionFlags_ReflectStaticMethods; + methodInstanceGroup->mExplicitlyReflected = typeOptions->Apply(false, optionFlags); + methodInstanceGroup->mExplicitlyReflected = ApplyTypeOptionMethodFilters(methodInstanceGroup->mExplicitlyReflected, methodDef, typeOptions); + } + if ((typeInstance->mCustomAttributes != NULL) && (typeInstance->mCustomAttributes->Contains(mCompiler->mReflectAttributeTypeDef))) + methodInstanceGroup->mExplicitlyReflected = true; + if (methodInstanceGroup->mOnDemandKind == BfMethodOnDemandKind_AlwaysInclude) continue; diff --git a/IDEHelper/Compiler/BfResolvedTypeUtils.h b/IDEHelper/Compiler/BfResolvedTypeUtils.h index 51a58fa5..6270b571 100644 --- a/IDEHelper/Compiler/BfResolvedTypeUtils.h +++ b/IDEHelper/Compiler/BfResolvedTypeUtils.h @@ -1196,6 +1196,7 @@ public: int mMethodIdx; int mRefCount; // External references from BfMethodRefType BfMethodOnDemandKind mOnDemandKind; + bool mExplicitlyReflected; public: BfMethodInstanceGroup() @@ -1206,6 +1207,7 @@ public: mMethodIdx = -1; mOnDemandKind = BfMethodOnDemandKind_NotSet; mRefCount = 0; + mExplicitlyReflected = false; } ~BfMethodInstanceGroup(); diff --git a/IDEHelper/Compiler/BfSystem.h b/IDEHelper/Compiler/BfSystem.h index bdec8988..b6faaa93 100644 --- a/IDEHelper/Compiler/BfSystem.h +++ b/IDEHelper/Compiler/BfSystem.h @@ -1289,17 +1289,35 @@ enum BfOptionFlags BfOptionFlags_ReflectAlwaysIncludeType = 0x10, BfOptionFlags_ReflectAlwaysIncludeAll = 0x20, BfOptionFlags_ReflectAssumeInstantiated = 0x40, - BfOptionFlags_ReflectStaticFields = 0x80, - BfOptionFlags_ReflectNonStaticFields = 0x100, - BfOptionFlags_ReflectStaticMethods = 0x200, - BfOptionFlags_ReflectNonStaticMethods = 0x400, - BfOptionFlags_ReflectConstructors = 0x800, + BfOptionFlags_ReflectBoxing = 0x80, + BfOptionFlags_ReflectStaticFields = 0x100, + BfOptionFlags_ReflectNonStaticFields = 0x200, + BfOptionFlags_ReflectStaticMethods = 0x400, + BfOptionFlags_ReflectNonStaticMethods = 0x800, + BfOptionFlags_ReflectConstructors = 0x1000, BfOptionFlags_Reflect_MethodMask = BfOptionFlags_ReflectStaticMethods | BfOptionFlags_ReflectNonStaticMethods | BfOptionFlags_ReflectConstructors, BfOptionFlags_Mask = 0xFFF }; +enum BfReflectKind +{ + BfReflectKind_None = 0, + BfReflectKind_Type = 1, + BfReflectKind_NonStaticFields = 2, + BfReflectKind_StaticFields = 4, + BfReflectKind_DefaultConstructor = 8, + BfReflectKind_Constructors = 0x10, + BfReflectKind_StaticMethods = 0x20, + BfReflectKind_Methods = 0x40, + BfReflectKind_DynamicBoxing = 0x80, + BfReflectKind_User = 0x100, + BfReflectKind_All = 0x1FF, + + BfReflectKind_ApplyToInnerTypes = 0x200 +}; + class BfTypeOptions { public: