1
0
Fork 0
mirror of https://github.com/beefytech/Beef.git synced 2025-06-10 04:22:20 +02:00

Dynamic boxing

This commit is contained in:
Brian Fiete 2020-09-14 11:18:24 -07:00
parent 7036433e5d
commit da5b81f419
14 changed files with 266 additions and 151 deletions

View file

@ -46,9 +46,11 @@ namespace System
Constructors = 0x10, Constructors = 0x10,
StaticMethods = 0x20, StaticMethods = 0x20,
Methods = 0x40, Methods = 0x40,
All = 0x7F, DynamicBoxing = 0x80,
//User = 0x100, // Internal Use
All = 0xFF,
ApplyToInnerTypes = 0x80, ApplyToInnerTypes = 0x200,
} }
public enum AttributeFlags public enum AttributeFlags

View file

@ -83,20 +83,23 @@ namespace System.Reflection
return .Err; return .Err;
MethodInfo methodInfo = default; MethodInfo methodInfo = default;
for (int methodId < mMethodDataCount) if (!IsBoxed)
{ {
let methodData = &mMethodDataPtr[methodId]; for (int methodId < mMethodDataCount)
if ((!methodData.mFlags.HasFlag(.Constructor)) || (methodData.mFlags.HasFlag(.Static))) {
continue; let methodData = &mMethodDataPtr[methodId];
if (methodData.mParamCount != 0) if ((!methodData.mFlags.HasFlag(.Constructor)) || (methodData.mFlags.HasFlag(.Static)))
continue; continue;
if (methodData.mParamCount != 0)
methodInfo = .(this, methodData); continue;
break;
} methodInfo = .(this, methodData);
break;
}
if (!methodInfo.IsInitialized) if (!methodInfo.IsInitialized)
return .Err; return .Err;
}
Object obj; Object obj;
let objType = typeof(Object) as TypeInstance; let objType = typeof(Object) as TypeInstance;
@ -109,10 +112,13 @@ namespace System.Reflection
obj.[Friend]mClassVData = (.)(void*)mTypeClassVData; obj.[Friend]mClassVData = (.)(void*)mTypeClassVData;
#endif #endif
Internal.MemSet((uint8*)Internal.UnsafeCastToPtr(obj) + objType.mInstSize, 0, mInstSize - objType.mInstSize); Internal.MemSet((uint8*)Internal.UnsafeCastToPtr(obj) + objType.mInstSize, 0, mInstSize - objType.mInstSize);
if (methodInfo.Invoke(obj) case .Err) if (methodInfo.IsInitialized)
{ {
delete obj; if (methodInfo.Invoke(obj) case .Err)
return .Err; {
delete obj;
return .Err;
}
} }
return obj; return obj;

View file

@ -304,6 +304,14 @@ namespace System
} }
} }
public TypeInstance BoxedType
{
get
{
return (TypeInstance)GetType(mBoxedType);
}
}
public bool IsEnum public bool IsEnum
{ {
get get

View file

@ -296,6 +296,22 @@ namespace System
return *(T*)(void*)mData; return *(T*)(void*)mData;
} }
public Result<Object> 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<T>(ref T val) /*public void Get<T>(ref T val)
{ {
if (VariantType != typeof(T)) if (VariantType != typeof(T))

View file

@ -106,6 +106,8 @@ namespace IDE
[Reflect] [Reflect]
public BuildOptions.AlwaysIncludeKind mReflectAlwaysInclude; public BuildOptions.AlwaysIncludeKind mReflectAlwaysInclude;
[Reflect] [Reflect]
public bool? mReflectBoxing;
[Reflect]
public bool? mReflectStaticFields; public bool? mReflectStaticFields;
[Reflect] [Reflect]
public bool? mReflectNonStaticFields; public bool? mReflectNonStaticFields;
@ -135,6 +137,7 @@ namespace IDE
newVal.mEmitObjectAccessCheck = mEmitObjectAccessCheck; newVal.mEmitObjectAccessCheck = mEmitObjectAccessCheck;
newVal.mAllocStackTraceDepth = mAllocStackTraceDepth; newVal.mAllocStackTraceDepth = mAllocStackTraceDepth;
newVal.mReflectAlwaysInclude = mReflectAlwaysInclude; newVal.mReflectAlwaysInclude = mReflectAlwaysInclude;
newVal.mReflectBoxing = mReflectBoxing;
newVal.mReflectStaticFields = mReflectStaticFields; newVal.mReflectStaticFields = mReflectStaticFields;
newVal.mReflectNonStaticFields = mReflectNonStaticFields; newVal.mReflectNonStaticFields = mReflectNonStaticFields;
newVal.mReflectStaticMethods = mReflectStaticMethods; newVal.mReflectStaticMethods = mReflectStaticMethods;
@ -166,6 +169,8 @@ namespace IDE
if (data.Contains("ReflectAlwaysInclude")) if (data.Contains("ReflectAlwaysInclude"))
mReflectAlwaysInclude = data.GetEnum<BuildOptions.AlwaysIncludeKind>("ReflectAlwaysInclude"); mReflectAlwaysInclude = data.GetEnum<BuildOptions.AlwaysIncludeKind>("ReflectAlwaysInclude");
if (data.Contains("ReflectBoxing"))
mReflectStaticFields = data.GetBool("ReflectBoxing");
if (data.Contains("ReflectStaticFields")) if (data.Contains("ReflectStaticFields"))
mReflectStaticFields = data.GetBool("ReflectStaticFields"); mReflectStaticFields = data.GetBool("ReflectStaticFields");
if (data.Contains("ReflectNonStaticFields")) if (data.Contains("ReflectNonStaticFields"))
@ -191,6 +196,7 @@ namespace IDE
data.ConditionalAdd("EmitObjectAccessCheck", mEmitObjectAccessCheck); data.ConditionalAdd("EmitObjectAccessCheck", mEmitObjectAccessCheck);
data.ConditionalAdd("AllocStackTraceDepth", mAllocStackTraceDepth); data.ConditionalAdd("AllocStackTraceDepth", mAllocStackTraceDepth);
data.ConditionalAdd("ReflectAlwaysInclude", mReflectAlwaysInclude); data.ConditionalAdd("ReflectAlwaysInclude", mReflectAlwaysInclude);
data.ConditionalAdd("ReflectBoxing", mReflectBoxing);
data.ConditionalAdd("ReflectStaticFields", mReflectStaticFields); data.ConditionalAdd("ReflectStaticFields", mReflectStaticFields);
data.ConditionalAdd("ReflectNonStaticFields", mReflectNonStaticFields); data.ConditionalAdd("ReflectNonStaticFields", mReflectNonStaticFields);
data.ConditionalAdd("ReflectStaticMethods", mReflectStaticMethods); data.ConditionalAdd("ReflectStaticMethods", mReflectStaticMethods);

View file

@ -18,14 +18,15 @@ namespace IDE.Compiler
ReflectAlwaysIncludeType = 0x10, ReflectAlwaysIncludeType = 0x10,
ReflectAlwaysIncludeAll = 0x20, ReflectAlwaysIncludeAll = 0x20,
ReflectAssumeInstantiated = 0x40, ReflectAssumeInstantiated = 0x40,
ReflectStaticFields = 0x80, ReflectBoxing = 0x80,
ReflectNonStaticFields = 0x100, ReflectStaticFields = 0x100,
ReflectStaticMethods = 0x200, ReflectNonStaticFields = 0x200,
ReflectNonStaticMethods = 0x400, ReflectStaticMethods = 0x400,
ReflectConstructors = 0x800, ReflectNonStaticMethods = 0x800,
ReflectConstructors = 0x1000,
All = 0xFFF All = 0x1FFF
}; };
[CallingConvention(.Stdcall), CLink] [CallingConvention(.Stdcall), CLink]
@ -401,6 +402,7 @@ namespace IDE.Compiler
orFlags |= .ReflectAlwaysIncludeType | .ReflectAlwaysIncludeAll | .ReflectAssumeInstantiated; orFlags |= .ReflectAlwaysIncludeType | .ReflectAlwaysIncludeAll | .ReflectAssumeInstantiated;
} }
SetFlag(typeOption.mReflectBoxing, .ReflectBoxing);
SetFlag(typeOption.mReflectStaticFields, .ReflectStaticFields); SetFlag(typeOption.mReflectStaticFields, .ReflectStaticFields);
SetFlag(typeOption.mReflectNonStaticFields, .ReflectNonStaticFields); SetFlag(typeOption.mReflectNonStaticFields, .ReflectNonStaticFields);
SetFlag(typeOption.mReflectStaticMethods, .ReflectStaticMethods); SetFlag(typeOption.mReflectStaticMethods, .ReflectStaticMethods);

View file

@ -151,6 +151,10 @@ namespace IDE.ui
typeName.Clear(); typeName.Append(optionsName, "mReflectAlwaysInclude"); typeName.Clear(); typeName.Append(optionsName, "mReflectAlwaysInclude");
AddPropertiesItem(reflectItem, "Always Include", typeName); 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"); typeName.Clear(); typeName.Append(optionsName, "mReflectStaticFields");
AddPropertiesItem(reflectItem, "Static Fields", typeName, AddPropertiesItem(reflectItem, "Static Fields", typeName,
scope String[] ( "No", "Yes" )); scope String[] ( "No", "Yes" ));

View file

@ -438,6 +438,7 @@ BfCompiler::BfCompiler(BfSystem* bfSystem, bool isResolveOnly)
mErrorAttributeTypeDef = NULL; mErrorAttributeTypeDef = NULL;
mWarnAttributeTypeDef = NULL; mWarnAttributeTypeDef = NULL;
mIgnoreErrorsAttributeTypeDef = NULL; mIgnoreErrorsAttributeTypeDef = NULL;
mReflectAttributeTypeDef = NULL;
mLastAutocompleteModule = NULL; mLastAutocompleteModule = NULL;
} }
@ -4247,7 +4248,7 @@ void BfCompiler::ProcessAutocompleteTempType()
BP_ZONE("ProcessAutocompleteTempType.CheckMethod"); BP_ZONE("ProcessAutocompleteTempType.CheckMethod");
BfMethodInstanceGroup methodInstanceGroup; BfMethodInstanceGroup methodInstanceGroup;
methodInstanceGroup.mOwner = typeInst; methodInstanceGroup.mOwner = typeInst;
methodInstanceGroup.mOnDemandKind = BfMethodOnDemandKind_AlwaysInclude; methodInstanceGroup.mOnDemandKind = BfMethodOnDemandKind_AlwaysInclude;
BfMethodInstance* methodInstance = new BfMethodInstance(); BfMethodInstance* methodInstance = new BfMethodInstance();
@ -5111,9 +5112,37 @@ void BfCompiler::PopulateReified()
if (!unspecializedType->mIsReified) if (!unspecializedType->mIsReified)
unspecializedType->mIsReified = true; 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 // 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())) && (typeInst->mHasBeenInstantiated) && (!typeInst->IsIncomplete()))
{ {
// If we have chained methods, make sure we implement the chain members if the chain head is implemented and reified // 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++) 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())) if ((ifaceMethodInst == NULL) || (!ifaceMethodInst->IsReifiedAndImplemented()))
continue; continue;
@ -6348,6 +6390,7 @@ bool BfCompiler::DoCompile(const StringImpl& outputDirectory)
mErrorAttributeTypeDef = _GetRequiredType("System.ErrorAttribute"); mErrorAttributeTypeDef = _GetRequiredType("System.ErrorAttribute");
mWarnAttributeTypeDef = _GetRequiredType("System.WarnAttribute"); mWarnAttributeTypeDef = _GetRequiredType("System.WarnAttribute");
mIgnoreErrorsAttributeTypeDef = _GetRequiredType("System.IgnoreErrorsAttribute"); mIgnoreErrorsAttributeTypeDef = _GetRequiredType("System.IgnoreErrorsAttribute");
mReflectAttributeTypeDef = _GetRequiredType("System.ReflectAttribute");
for (int i = 0; i < BfTypeCode_Length; i++) for (int i = 0; i < BfTypeCode_Length; i++)
mContext->mPrimitiveStructTypes[i] = NULL; mContext->mPrimitiveStructTypes[i] = NULL;

View file

@ -404,6 +404,7 @@ public:
BfTypeDef* mErrorAttributeTypeDef; BfTypeDef* mErrorAttributeTypeDef;
BfTypeDef* mWarnAttributeTypeDef; BfTypeDef* mWarnAttributeTypeDef;
BfTypeDef* mIgnoreErrorsAttributeTypeDef; BfTypeDef* mIgnoreErrorsAttributeTypeDef;
BfTypeDef* mReflectAttributeTypeDef;
int mCurTypeId; int mCurTypeId;

View file

@ -5530,120 +5530,24 @@ BfIRValue BfModule::CreateTypeData(BfType* type, Dictionary<int, int>& usedStrin
reflectIncludeAllMethods = true; reflectIncludeAllMethods = true;
} }
enum ReflectKind BfReflectKind reflectKind = BfReflectKind_Type;
{
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;
};
auto _GetReflectUserFromDirective = [&](BfAttributeDirective* attributesDirective, BfAttributeTargets attrTarget) auto _GetReflectUserFromDirective = [&](BfAttributeDirective* attributesDirective, BfAttributeTargets attrTarget)
{ {
ReflectKind reflectKind = ReflectKind_None; BfReflectKind reflectKind = BfReflectKind_None;
auto customAttrs = GetCustomAttributes(attributesDirective, attrTarget); auto customAttrs = GetCustomAttributes(attributesDirective, attrTarget);
if (customAttrs != NULL) if (customAttrs != NULL)
{ {
for (auto& attr : customAttrs->mAttributes) for (auto& attr : customAttrs->mAttributes)
{ {
reflectKind = (ReflectKind)(reflectKind | _GetReflectUser(attr.mType)); reflectKind = (BfReflectKind)(reflectKind | GetUserReflectKind(attr.mType));
} }
} }
return reflectKind; return reflectKind;
}; };
// reflectKind = GetReflectKind(reflectKind, typeInstance);
{
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);
}
}
// Fields // Fields
BfType* reflectFieldDataType = ResolveTypeDef(mCompiler->mReflectFieldDataDef); BfType* reflectFieldDataType = ResolveTypeDef(mCompiler->mReflectFieldDataDef);
BfIRValue emptyValueType = mBfIRBuilder->CreateConstStruct(mBfIRBuilder->MapTypeInst(reflectFieldDataType->ToTypeInstance()->mBaseType), SizedArray<BfIRValue, 1>()); BfIRValue emptyValueType = mBfIRBuilder->CreateConstStruct(mBfIRBuilder->MapTypeInst(reflectFieldDataType->ToTypeInstance()->mBaseType), SizedArray<BfIRValue, 1>());
@ -5836,7 +5740,7 @@ BfIRValue BfModule::CreateTypeData(BfType* type, Dictionary<int, int>& usedStrin
if (fieldDef == NULL) if (fieldDef == NULL)
continue; continue;
auto fieldReflectKind = (ReflectKind)(reflectKind & ~ReflectKind_User); auto fieldReflectKind = (BfReflectKind)(reflectKind & ~BfReflectKind_User);
bool includeField = reflectIncludeAllFields; bool includeField = reflectIncludeAllFields;
@ -5850,17 +5754,17 @@ BfIRValue BfModule::CreateTypeData(BfType* type, Dictionary<int, int>& usedStrin
} }
else else
{ {
auto userReflectKind = _GetReflectUser(customAttr.mType); auto userReflectKind = GetUserReflectKind(customAttr.mType);
fieldReflectKind = (ReflectKind)(fieldReflectKind | userReflectKind); fieldReflectKind = (BfReflectKind)(fieldReflectKind | userReflectKind);
} }
} }
} }
if ((fieldReflectKind & ReflectKind_User) != 0) if ((fieldReflectKind & BfReflectKind_User) != 0)
includeField = true; includeField = true;
if ((!fieldDef->mIsStatic) && ((fieldReflectKind & ReflectKind_NonStaticFields) != 0)) if ((!fieldDef->mIsStatic) && ((fieldReflectKind & BfReflectKind_NonStaticFields) != 0))
includeField = true; includeField = true;
if ((fieldDef->mIsStatic) && ((fieldReflectKind & ReflectKind_StaticFields) != 0)) if ((fieldDef->mIsStatic) && ((fieldReflectKind & BfReflectKind_StaticFields) != 0))
includeField = true; includeField = true;
if ((!fieldDef->mIsStatic) && (typeOptions != NULL)) if ((!fieldDef->mIsStatic) && (typeOptions != NULL))
@ -6142,7 +6046,7 @@ BfIRValue BfModule::CreateTypeData(BfType* type, Dictionary<int, int>& usedStrin
if (defaultMethod->mMethodDef->mMethodType == BfMethodType_CtorNoBody) if (defaultMethod->mMethodDef->mMethodType == BfMethodType_CtorNoBody)
continue; continue;
auto methodReflectKind = (ReflectKind)(reflectKind & ~ReflectKind_User); auto methodReflectKind = (BfReflectKind)(reflectKind & ~BfReflectKind_User);
bool includeMethod = reflectIncludeAllMethods; bool includeMethod = reflectIncludeAllMethods;
@ -6158,8 +6062,8 @@ BfIRValue BfModule::CreateTypeData(BfType* type, Dictionary<int, int>& usedStrin
} }
else else
{ {
auto userReflectKind = _GetReflectUser(customAttr.mType); auto userReflectKind = GetUserReflectKind(customAttr.mType);
methodReflectKind = (ReflectKind)(methodReflectKind | userReflectKind); methodReflectKind = (BfReflectKind)(methodReflectKind | userReflectKind);
} }
} }
} }
@ -6172,15 +6076,15 @@ BfIRValue BfModule::CreateTypeData(BfType* type, Dictionary<int, int>& usedStrin
for (BfParameterDeclaration* paramDecl : methodDeclaration->mParams) for (BfParameterDeclaration* paramDecl : methodDeclaration->mParams)
{ {
if (paramDecl->mAttributes != NULL) if (paramDecl->mAttributes != NULL)
methodReflectKind = (ReflectKind)(methodReflectKind | _GetReflectUserFromDirective(paramDecl->mAttributes, BfAttributeTargets_Parameter)); methodReflectKind = (BfReflectKind)(methodReflectKind | _GetReflectUserFromDirective(paramDecl->mAttributes, BfAttributeTargets_Parameter));
} }
if (methodDeclaration->mReturnAttributes != NULL) 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; includeMethod = true;
if ((methodDef->mIsStatic) && ((methodReflectKind & ReflectKind_StaticMethods) != 0)) if ((methodDef->mIsStatic) && ((methodReflectKind & BfReflectKind_StaticMethods) != 0))
includeMethod = true; includeMethod = true;
if ((!includeMethod) && (typeOptions != NULL)) if ((!includeMethod) && (typeOptions != NULL))
@ -6395,6 +6299,11 @@ BfIRValue BfModule::CreateTypeData(BfType* type, Dictionary<int, int>& usedStrin
if ((!typeInstance->IsInterface()) && (typeInstance->mIsReified) && (!typeInstance->IsUnspecializedType()) if ((!typeInstance->IsInterface()) && (typeInstance->mIsReified) && (!typeInstance->IsUnspecializedType())
&& (!typeInstance->mInterfaceMethodTable.IsEmpty())) && (!typeInstance->mInterfaceMethodTable.IsEmpty()))
{ {
if (typeDef->mName->ToString() == "StructA")
{
NOP;
}
SizedArray<BfIRValue, 16> methods; SizedArray<BfIRValue, 16> methods;
for (auto& methodEntry : typeInstance->mInterfaceMethodTable) for (auto& methodEntry : typeInstance->mInterfaceMethodTable)
{ {
@ -6412,8 +6321,8 @@ BfIRValue BfModule::CreateTypeData(BfType* type, Dictionary<int, int>& usedStrin
methods.Add(funcVal); methods.Add(funcVal);
} }
while ((!methods.IsEmpty()) && (methods.back() == voidPtrNull)) // while ((!methods.IsEmpty()) && (methods.back() == voidPtrNull))
methods.pop_back(); // methods.pop_back();
BfIRType methodDataArrayType = mBfIRBuilder->GetSizedArrayType(mBfIRBuilder->MapType(voidPtrType, BfIRPopulateType_Full), (int)methods.size()); BfIRType methodDataArrayType = mBfIRBuilder->GetSizedArrayType(mBfIRBuilder->MapType(voidPtrType, BfIRPopulateType_Full), (int)methods.size());
BfIRValue methodDataConst = mBfIRBuilder->CreateConstArray(methodDataArrayType, methods); BfIRValue methodDataConst = mBfIRBuilder->CreateConstArray(methodDataArrayType, methods);
@ -13461,6 +13370,89 @@ BfTypeOptions* BfModule::GetTypeOptions()
return mSystem->GetTypeOptions(mCurTypeInstance->mTypeOptionsIdx); 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) bool BfModule::HasDeferredScopeCalls(BfScopeData* scope)
{ {
BfScopeData* checkScope = mCurMethodState->mCurScope; BfScopeData* checkScope = mCurMethodState->mCurScope;

View file

@ -1512,6 +1512,8 @@ public:
BfTypedValue GetIntCoercible(const BfTypedValue& typedValue); BfTypedValue GetIntCoercible(const BfTypedValue& typedValue);
bool WantsDebugInfo(); bool WantsDebugInfo();
BfTypeOptions* GetTypeOptions(); BfTypeOptions* GetTypeOptions();
BfReflectKind GetUserReflectKind(BfTypeInstance* attrType);
BfReflectKind GetReflectKind(BfReflectKind reflectKind, BfTypeInstance* typeInstance);
void CleanupFileInstances(); void CleanupFileInstances();
void AssertErrorState(); void AssertErrorState();
void AssertParseErrorState(); void AssertParseErrorState();

View file

@ -3996,15 +3996,28 @@ void BfModule::DoTypeInstanceMethodProcessing(BfTypeInstance* typeInstance)
isFailedType = true; isFailedType = true;
} }
bool typeOptionsIncludeAll = false; bool typeOptionsIncludeAll = false;
if (typeOptions != NULL) if (typeOptions != NULL)
typeOptionsIncludeAll = typeOptions->Apply(typeOptionsIncludeAll, BfOptionFlags_ReflectAlwaysIncludeAll); typeOptionsIncludeAll = typeOptions->Apply(typeOptionsIncludeAll, BfOptionFlags_ReflectAlwaysIncludeAll);
// Generate all methods. Pass 1 // Generate all methods. Pass 1
for (auto methodDef : typeDef->mMethods) for (auto methodDef : typeDef->mMethods)
{ {
auto methodInstanceGroup = &typeInstance->mMethodInstanceGroups[methodDef->mIdx]; 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) if (methodInstanceGroup->mOnDemandKind == BfMethodOnDemandKind_AlwaysInclude)
continue; continue;

View file

@ -1196,6 +1196,7 @@ public:
int mMethodIdx; int mMethodIdx;
int mRefCount; // External references from BfMethodRefType int mRefCount; // External references from BfMethodRefType
BfMethodOnDemandKind mOnDemandKind; BfMethodOnDemandKind mOnDemandKind;
bool mExplicitlyReflected;
public: public:
BfMethodInstanceGroup() BfMethodInstanceGroup()
@ -1206,6 +1207,7 @@ public:
mMethodIdx = -1; mMethodIdx = -1;
mOnDemandKind = BfMethodOnDemandKind_NotSet; mOnDemandKind = BfMethodOnDemandKind_NotSet;
mRefCount = 0; mRefCount = 0;
mExplicitlyReflected = false;
} }
~BfMethodInstanceGroup(); ~BfMethodInstanceGroup();

View file

@ -1289,17 +1289,35 @@ enum BfOptionFlags
BfOptionFlags_ReflectAlwaysIncludeType = 0x10, BfOptionFlags_ReflectAlwaysIncludeType = 0x10,
BfOptionFlags_ReflectAlwaysIncludeAll = 0x20, BfOptionFlags_ReflectAlwaysIncludeAll = 0x20,
BfOptionFlags_ReflectAssumeInstantiated = 0x40, BfOptionFlags_ReflectAssumeInstantiated = 0x40,
BfOptionFlags_ReflectStaticFields = 0x80, BfOptionFlags_ReflectBoxing = 0x80,
BfOptionFlags_ReflectNonStaticFields = 0x100, BfOptionFlags_ReflectStaticFields = 0x100,
BfOptionFlags_ReflectStaticMethods = 0x200, BfOptionFlags_ReflectNonStaticFields = 0x200,
BfOptionFlags_ReflectNonStaticMethods = 0x400, BfOptionFlags_ReflectStaticMethods = 0x400,
BfOptionFlags_ReflectConstructors = 0x800, BfOptionFlags_ReflectNonStaticMethods = 0x800,
BfOptionFlags_ReflectConstructors = 0x1000,
BfOptionFlags_Reflect_MethodMask = BfOptionFlags_ReflectStaticMethods | BfOptionFlags_ReflectNonStaticMethods | BfOptionFlags_ReflectConstructors, BfOptionFlags_Reflect_MethodMask = BfOptionFlags_ReflectStaticMethods | BfOptionFlags_ReflectNonStaticMethods | BfOptionFlags_ReflectConstructors,
BfOptionFlags_Mask = 0xFFF 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 class BfTypeOptions
{ {
public: public: