1
0
Fork 0
mirror of https://github.com/beefytech/Beef.git synced 2025-06-08 03:28:20 +02:00

Added reflection category to distinct build options (wip)

This commit is contained in:
Brian Fiete 2020-07-11 16:24:07 -07:00
parent 5cb6570e14
commit 037b2ac1e4
15 changed files with 538 additions and 94 deletions

View file

@ -64,6 +64,15 @@ namespace IDE
Small,
Big
}
public enum AlwaysIncludeKind
{
NotSet,
No,
IncludeType,
AssumeInstantiated,
IncludeAll
}
}
public class DistinctBuildOptions
@ -94,6 +103,20 @@ namespace IDE
public bool? mEmitObjectAccessCheck; // Only valid with mObjectHasDebugFlags
[Reflect]
public int32? mAllocStackTraceDepth;
[Reflect]
public BuildOptions.AlwaysIncludeKind mReflectAlwaysInclude;
[Reflect]
public bool? mReflectStaticFields;
[Reflect]
public bool? mReflectNonStaticFields;
[Reflect]
public bool? mReflectStaticMethods;
[Reflect]
public bool? mReflectNonStaticMethods;
[Reflect]
public bool? mReflectConstructors;
[Reflect]
public String mReflectMethodFilter = new String() ~ delete _;
public ~this()
{
@ -111,6 +134,13 @@ namespace IDE
newVal.mEmitDynamicCastCheck = mEmitDynamicCastCheck;
newVal.mEmitObjectAccessCheck = mEmitObjectAccessCheck;
newVal.mAllocStackTraceDepth = mAllocStackTraceDepth;
newVal.mReflectAlwaysInclude = mReflectAlwaysInclude;
newVal.mReflectStaticFields = mReflectStaticFields;
newVal.mReflectNonStaticFields = mReflectNonStaticFields;
newVal.mReflectStaticMethods = mReflectStaticMethods;
newVal.mReflectNonStaticMethods = mReflectNonStaticMethods;
newVal.mReflectConstructors = mReflectConstructors;
newVal.mReflectMethodFilter.Set(mReflectMethodFilter);
return newVal;
}
@ -133,6 +163,20 @@ namespace IDE
mEmitObjectAccessCheck = data.GetBool("EmitObjectAccessCheck");
if (data.Contains("AllocStackTraceDepth"))
mAllocStackTraceDepth = data.GetInt("AllocStackTraceDepth");
if (data.Contains("ReflectAlwaysInclude"))
mReflectAlwaysInclude = data.GetEnum<BuildOptions.AlwaysIncludeKind>("ReflectAlwaysInclude");
if (data.Contains("ReflectStaticFields"))
mReflectStaticFields = data.GetBool("ReflectStaticFields");
if (data.Contains("ReflectNonStaticFields"))
mReflectNonStaticFields = data.GetBool("ReflectNonStaticFields");
if (data.Contains("ReflectStaticMethods"))
mReflectStaticMethods = data.GetBool("ReflectStaticMethods");
if (data.Contains("ReflectNonStaticMethods"))
mReflectNonStaticMethods = data.GetBool("ReflectNonStaticMethods");
if (data.Contains("ReflectConstructors"))
mReflectConstructors = data.GetBool("ReflectConstructors");
data.GetString("ReflectMethodFilter", mReflectMethodFilter);
}
public void Serialize(StructuredData data)
@ -146,6 +190,13 @@ namespace IDE
data.ConditionalAdd("EmitDynamicCastCheck", mEmitDynamicCastCheck);
data.ConditionalAdd("EmitObjectAccessCheck", mEmitObjectAccessCheck);
data.ConditionalAdd("AllocStackTraceDepth", mAllocStackTraceDepth);
data.ConditionalAdd("ReflectAlwaysInclude", mReflectAlwaysInclude);
data.ConditionalAdd("ReflectStaticFields", mReflectStaticFields);
data.ConditionalAdd("ReflectNonStaticFields", mReflectNonStaticFields);
data.ConditionalAdd("ReflectStaticMethods", mReflectStaticMethods);
data.ConditionalAdd("ReflectNonStaticMethods", mReflectNonStaticMethods);
data.ConditionalAdd("ReflectConstructors", mReflectConstructors);
data.ConditionalAdd("ReflectMethodFilter", mReflectMethodFilter);
}
}
}

View file

@ -9,6 +9,25 @@ namespace IDE.Compiler
{
public class BfSystem
{
enum BfOptionFlags
{
RuntimeChecks = 1,
InitLocalVariables = 2,
EmitDynamicCastCheck = 4,
EmitObjectAccessCheck = 8,
ReflectAlwaysIncludeType = 0x10,
ReflectAlwaysIncludeAll = 0x20,
ReflectAssumeInstantiated = 0x40,
ReflectStaticFields = 0x80,
ReflectNonStaticFields = 0x100,
ReflectStaticMethods = 0x200,
ReflectNonStaticMethods = 0x400,
ReflectConstructors = 0x800,
All = 0xFFF
};
[CallingConvention(.Stdcall), CLink]
static extern void BfSystem_CheckLock(void* bfSystem);
@ -37,8 +56,8 @@ namespace IDE.Compiler
static extern void BfSystem_ClearTypeOptions(void* bfSystem);
[CallingConvention(.Stdcall), CLink]
static extern void BfSystem_AddTypeOptions(void* bfSystem, char8* filter, int32 simdSetting, int32 optimizationLevel, int32 emitDebugInfo, int32 runtimeChecks,
int32 initLocalVariables, int32 emitDynamicCastCheck, int32 emitObjectAccessCheck, int32 allocStackTraceDepth);
static extern void BfSystem_AddTypeOptions(void* bfSystem, char8* filter, int32 simdSetting, int32 optimizationLevel, int32 emitDebugInfo, int32 andFlags, int32 orFlags,
int32 allocStackTraceDepth, char8* reflectMethodFilter);
[CallingConvention(.Stdcall), CLink]
static extern void* BfSystem_CreateParser(void* bfSystem, void* bfProject);
@ -343,25 +362,52 @@ namespace IDE.Compiler
BfSystem_ClearTypeOptions(mNativeBfSystem);
}
public void AddTypeOptions(String filter, BuildOptions.SIMDSetting? simdSetting, BuildOptions.BfOptimizationLevel? optimizationLevel, BuildOptions.EmitDebugInfo? emitDebugInfo, bool? runtimeChecks,
bool? initLocalVariables, bool? emitDynamicCastCheck, bool? emitObjectAccessCheck, int32? allocStackTraceDepth)
public void AddTypeOptions(String filter, BuildOptions.SIMDSetting? simdSetting, BuildOptions.BfOptimizationLevel? optimizationLevel, BuildOptions.EmitDebugInfo? emitDebugInfo, BfOptionFlags andFlags, BfOptionFlags orFlags, int32? allocStackTraceDepth, String reflectMethodFilter)
{
int32 simdSettingInt = (simdSetting == null) ? -1 : (int32)simdSetting.Value;
int32 optimizationLevelInt = (optimizationLevel == null) ? -1 : (int32)optimizationLevel.Value;
int32 emitDebugInfoInt = (emitDebugInfo == null) ? -1 : (int32)emitDebugInfo.Value;
int32 runtimeChecksInt = (runtimeChecks == null) ? -1 : runtimeChecks.Value ? 1 : 0;
/*int32 runtimeChecksInt = (runtimeChecks == null) ? -1 : runtimeChecks.Value ? 1 : 0;
int32 initLocalVariablesInt = (initLocalVariables == null) ? -1 : initLocalVariables.Value ? 1 : 0;
int32 emitDynamicCastCheckInt = (emitDynamicCastCheck == null) ? -1 : emitDynamicCastCheck.Value ? 1 : 0;
int32 emitObjectAccessCheckInt = (emitObjectAccessCheck == null) ? -1 : emitObjectAccessCheck.Value ? 1 : 0;
int32 emitObjectAccessCheckInt = (emitObjectAccessCheck == null) ? -1 : emitObjectAccessCheck.Value ? 1 : 0;*/
int32 allocStackTraceDepthInt = (allocStackTraceDepth == null) ? -1 : allocStackTraceDepth.Value;
BfSystem_AddTypeOptions(mNativeBfSystem, filter, simdSettingInt, optimizationLevelInt, emitDebugInfoInt, runtimeChecksInt,
initLocalVariablesInt, emitDynamicCastCheckInt, emitObjectAccessCheckInt, allocStackTraceDepthInt);
BfSystem_AddTypeOptions(mNativeBfSystem, filter, simdSettingInt, optimizationLevelInt, emitDebugInfoInt, (.)andFlags, (.)orFlags, allocStackTraceDepthInt, reflectMethodFilter);
}
public void AddTypeOptions(DistinctBuildOptions typeOption)
{
AddTypeOptions(typeOption.mFilter, typeOption.mBfSIMDSetting, typeOption.mBfOptimizationLevel, typeOption.mEmitDebugInfo, typeOption.mRuntimeChecks,
typeOption.mInitLocalVariables, typeOption.mEmitDynamicCastCheck, typeOption.mEmitObjectAccessCheck, typeOption.mAllocStackTraceDepth);
BfOptionFlags andFlags = .All;
BfOptionFlags orFlags = 0;
void SetFlag(bool? val, BfOptionFlags flag)
{
if (val == false)
andFlags &= ~flag;
if (val == true)
orFlags |= flag;
}
switch (typeOption.mReflectAlwaysInclude)
{
case .NotSet:
case .No:
andFlags &= ~(.ReflectAlwaysIncludeType | .ReflectAlwaysIncludeAll | .ReflectAssumeInstantiated);
case .IncludeType:
orFlags |= .ReflectAssumeInstantiated;
case .AssumeInstantiated:
orFlags |= .ReflectAssumeInstantiated;
case .IncludeAll:
orFlags |= .ReflectAlwaysIncludeType | .ReflectAlwaysIncludeAll | .ReflectAssumeInstantiated;
}
SetFlag(typeOption.mReflectStaticFields, .ReflectStaticFields);
SetFlag(typeOption.mReflectNonStaticFields, .ReflectNonStaticFields);
SetFlag(typeOption.mReflectStaticMethods, .ReflectStaticMethods);
SetFlag(typeOption.mReflectNonStaticMethods, .ReflectNonStaticMethods);
SetFlag(typeOption.mReflectConstructors, .ReflectConstructors);
AddTypeOptions(typeOption.mFilter, typeOption.mBfSIMDSetting, typeOption.mBfOptimizationLevel, typeOption.mEmitDebugInfo, andFlags, orFlags, typeOption.mAllocStackTraceDepth, typeOption.mReflectMethodFilter);
}
public void Log(String str)

View file

@ -145,6 +145,34 @@ namespace IDE.ui
typeName.Clear(); typeName.Append(optionsName, "mAllocStackTraceDepth");
AddPropertiesItem(category, "Alloc Stack Trace Depth", typeName);
let (reflectItem, ?) = AddPropertiesItem(category, "Reflect");
typeName.Clear(); typeName.Append(optionsName, "mReflectAlwaysInclude");
AddPropertiesItem(reflectItem, "Always Include", typeName);
typeName.Clear(); typeName.Append(optionsName, "mReflectStaticFields");
AddPropertiesItem(reflectItem, "Static Fields", typeName,
scope String[] { "No", "Yes" });
typeName.Clear(); typeName.Append(optionsName, "mReflectNonStaticFields");
AddPropertiesItem(reflectItem, "Non-Static Fields", typeName,
scope String[] { "No", "Yes" });
typeName.Clear(); typeName.Append(optionsName, "mReflectStaticMethods");
AddPropertiesItem(reflectItem, "Static Methods", typeName,
scope String[] { "No", "Yes" });
typeName.Clear(); typeName.Append(optionsName, "mReflectNonStaticMethods");
AddPropertiesItem(reflectItem, "Non-Static Methods", typeName,
scope String[] { "No", "Yes" });
typeName.Clear(); typeName.Append(optionsName, "mReflectConstructors");
AddPropertiesItem(reflectItem, "Constructors", typeName,
scope String[] { "No", "Yes" });
typeName.Clear(); typeName.Append(optionsName, "mReflectMethodFilter");
AddPropertiesItem(reflectItem, "Method Filter", typeName);
category.Open(true, true);
}

View file

@ -5906,8 +5906,13 @@ void BfCompiler::CompileReified()
if (typeDef->mIsPartial)
continue;
auto scratchModule = mContext->mScratchModule;
bool isAlwaysInclude = (typeDef->mIsAlwaysInclude) || (typeDef->mProject->mAlwaysIncludeAll);
auto typeOptions = scratchModule->GetTypeOptions(typeDef);
if (typeOptions != NULL)
typeOptions->Apply(isAlwaysInclude, BfOptionFlags_ReflectAlwaysIncludeType);
if (typeDef->mProject->IsTestProject())
{
for (auto methodDef : typeDef->mMethods)
@ -5922,8 +5927,7 @@ void BfCompiler::CompileReified()
//TODO: Just because the type is required doesn't mean we want to reify it. Why did we have that check?
if ((mOptions.mCompileOnDemandKind != BfCompileOnDemandKind_AlwaysInclude) && (!isAlwaysInclude))
continue;
auto scratchModule = mContext->mScratchModule;
scratchModule->ResolveTypeDef(typeDef, BfPopulateType_Full);
}
@ -6396,7 +6400,15 @@ bool BfCompiler::DoCompile(const StringImpl& outputDirectory)
for (auto typeDef : mSystem->mTypeDefs)
{
if ((typeDef->mIsAlwaysInclude) && (!typeDef->mIsPartial))
if (typeDef->mIsPartial)
continue;
bool isAlwaysInclude = (typeDef->mIsAlwaysInclude) || (typeDef->mProject->mAlwaysIncludeAll);
auto typeOptions = mContext->mScratchModule->GetTypeOptions(typeDef);
if (typeOptions != NULL)
isAlwaysInclude = typeOptions->Apply(isAlwaysInclude, BfOptionFlags_ReflectAlwaysIncludeType);
if (isAlwaysInclude)
{
auto requiredType = mContext->mScratchModule->ResolveTypeDef(typeDef);
if (requiredType != NULL)

View file

@ -1896,10 +1896,14 @@ void BfContext::UpdateRevisedTypes()
workspaceConfigHashCtx.Mixin(typeOptions.mSIMDSetting);
workspaceConfigHashCtx.Mixin(typeOptions.mOptimizationLevel);
workspaceConfigHashCtx.Mixin(typeOptions.mEmitDebugInfo);
workspaceConfigHashCtx.Mixin(typeOptions.mRuntimeChecks);
workspaceConfigHashCtx.Mixin(typeOptions.mInitLocalVariables);
workspaceConfigHashCtx.Mixin(typeOptions.mEmitDynamicCastCheck);
workspaceConfigHashCtx.Mixin(typeOptions.mEmitObjectAccessCheck);
workspaceConfigHashCtx.Mixin(typeOptions.mAndFlags);
workspaceConfigHashCtx.Mixin(typeOptions.mOrFlags);
workspaceConfigHashCtx.Mixin(typeOptions.mReflectMethodFilters.size());
for (auto& filter : typeOptions.mReflectMethodFilters)
workspaceConfigHashCtx.MixinStr(filter);
workspaceConfigHashCtx.Mixin(typeOptions.mReflectMethodAttributeFilters.size());
for (auto& filter : typeOptions.mReflectMethodAttributeFilters)
workspaceConfigHashCtx.MixinStr(filter);
workspaceConfigHashCtx.Mixin(typeOptions.mAllocStackTraceDepth);
}
@ -2629,7 +2633,10 @@ void BfContext::TryUnreifyModules()
bool isRequired = false;
for (auto typeInst : module->mOwnedTypeInstances)
{
if ((typeInst->mTypeDef->mIsAlwaysInclude) || (typeInst->mTypeDef->IsGlobalsContainer()))
if (typeInst->mTypeDef->IsGlobalsContainer())
isRequired = true;
if (typeInst->IsAlwaysInclude())
isRequired = true;
}

View file

@ -3341,7 +3341,7 @@ BfCheckedKind BfModule::GetDefaultCheckedKind()
bool runtimeChecks = mCompiler->mOptions.mRuntimeChecks;
auto typeOptions = GetTypeOptions();
if (typeOptions != NULL)
runtimeChecks = BfTypeOptions::Apply(runtimeChecks, typeOptions->mRuntimeChecks);
runtimeChecks = typeOptions->Apply(runtimeChecks, BfOptionFlags_RuntimeChecks);
return runtimeChecks ? BfCheckedKind_Checked : BfCheckedKind_Unchecked;
}
@ -4738,6 +4738,8 @@ BfIRValue BfModule::CreateTypeData(BfType* type, Dictionary<int, int>& usedStrin
typeFlags |= BfTypeFlags_Union;
if (type->IsDelegate())
typeFlags |= BfTypeFlags_Delegate;
if (type->IsFunction())
typeFlags |= BfTypeFlags_Function;
if (type->WantsGCMarking())
typeFlags |= BfTypeFlags_WantsMarking;
@ -4839,7 +4841,8 @@ BfIRValue BfModule::CreateTypeData(BfType* type, Dictionary<int, int>& usedStrin
// Reserve position
mTypeDataRefs[typeInstance] = BfIRValue();
PopulateType(typeInstance, BfPopulateType_DataAndMethods);
if (typeInstance->IsReified())
PopulateType(typeInstance, BfPopulateType_DataAndMethods);
BfTypeDef* typeDef = typeInstance->mTypeDef;
StringT<128> mangledName;
@ -6198,12 +6201,14 @@ BfIRValue BfModule::CreateTypeData(BfType* type, Dictionary<int, int>& usedStrin
if ((typeInstance->IsTypedPrimitive()) || (typeInstance->IsBoxed()))
{
underlyingType = typeInstance->GetUnderlyingType()->mTypeId;
}
}
int outerTypeId = 0;
auto outerType = mContext->mUnreifiedModule->GetOuterType(typeInstance);
if (outerType != NULL)
{
outerTypeId = outerType->mTypeId;
}
BfIRValue customAttrDataPtr;
if (customAttrs.size() > 0)
@ -8753,7 +8758,7 @@ void BfModule::EmitObjectAccessCheck(BfTypedValue typedVal)
bool emitObjectAccessCheck = mCompiler->mOptions.mEmitObjectAccessCheck;
auto typeOptions = GetTypeOptions();
if (typeOptions != NULL)
emitObjectAccessCheck = BfTypeOptions::Apply(emitObjectAccessCheck, typeOptions->mEmitObjectAccessCheck);
emitObjectAccessCheck = typeOptions->Apply(emitObjectAccessCheck, BfOptionFlags_EmitObjectAccessCheck);
if (!emitObjectAccessCheck)
return;
@ -8875,7 +8880,7 @@ void BfModule::EmitDynamicCastCheck(BfTypedValue typedVal, BfType* type, bool al
bool emitDynamicCastCheck = mCompiler->mOptions.mEmitDynamicCastCheck;
auto typeOptions = GetTypeOptions();
if (typeOptions != NULL)
emitDynamicCastCheck = BfTypeOptions::Apply(emitDynamicCastCheck, typeOptions->mEmitDynamicCastCheck);
emitDynamicCastCheck = typeOptions->Apply(emitDynamicCastCheck, BfOptionFlags_EmitDynamicCastCheck);
if (emitDynamicCastCheck)
{
@ -12715,7 +12720,7 @@ BfIRValue BfModule::AllocLocalVariable(BfType* type, const StringImpl& name, boo
bool initLocalVariables = mCompiler->mOptions.mInitLocalVariables;
auto typeOptions = GetTypeOptions();
if (typeOptions != NULL)
initLocalVariables = BfTypeOptions::Apply(initLocalVariables, typeOptions->mInitLocalVariables);
initLocalVariables = typeOptions->Apply(initLocalVariables, BfOptionFlags_InitLocalVariables);
// Local variable inits are implicitly handled in the Beef Backend
if ((initLocalVariables) && (!IsTargetingBeefBackend()))
{
@ -18448,6 +18453,7 @@ BfMethodDef* BfModule::GetLocalMethodDef(BfLocalMethod* localMethod)
if (methodDeclaration != NULL)
{
BfDefBuilder defBuilder(mCompiler->mSystem);
defBuilder.mCurSource = localMethod->mMethodDeclaration->GetParser();
defBuilder.mPassInstance = mCompiler->mPassInstance;
defBuilder.mCurTypeDef = mCurMethodInstance->mMethodDef->mDeclaringType;

View file

@ -1603,6 +1603,7 @@ public:
void MarkDerivedDirty(BfTypeInstance* typeInst);
void CheckAddFailType();
bool PopulateType(BfType* resolvedTypeRef, BfPopulateType populateType = BfPopulateType_Data);
BfTypeOptions* GetTypeOptions(BfTypeDef* typeDef);
int GenerateTypeOptions(BfCustomAttributes* customAttributes, BfTypeInstance* typeInstance, bool checkTypeName);
void SetTypeOptions(BfTypeInstance* typeInstance);
BfModuleOptions GetModuleOptions();

View file

@ -1234,6 +1234,245 @@ bool BfModule::PopulateType(BfType* resolvedTypeRef, BfPopulateType populateType
return result;
}
BfTypeOptions* BfModule::GetTypeOptions(BfTypeDef* typeDef)
{
if (mContext->mSystem->mTypeOptions.size() == 0)
{
return NULL;
}
Array<int> matchedIndices;
if (!mCompiler->mAttributeTypeOptionMap.IsEmpty())
{
auto customAttributes = typeDef->mTypeDeclaration->mAttributes;
while (customAttributes != NULL)
{
if (!mCompiler->mAttributeTypeOptionMap.IsEmpty())
{
SetAndRestoreValue<bool> prevIgnoreErrors(mIgnoreErrors, true);
auto typeRef = customAttributes->mAttributeTypeRef;
// StringT<128> attrName;
// for (auto& customAttrs : customAttributes->mAttributeTypeRef)
// {
// attrName.Clear();
// customAttrs.mType->mTypeDef->mFullName.ToString(attrName);
// Array<int>* arrPtr;
// if (mCompiler->mAttributeTypeOptionMap.TryGetValue(attrName, &arrPtr))
// {
// for (auto optionsIdx : *arrPtr)
// {
// matchedIndices.Add(optionsIdx);
// }
// }
// }
}
customAttributes = customAttributes->mNextAttribute;
}
}
int typeOptionsCount = (int)mContext->mSystem->mTypeOptions.size();
auto _CheckTypeName = [&](const StringImpl& typeName)
{
for (int optionIdx = 0; optionIdx < (int)mContext->mSystem->mTypeOptions.size(); optionIdx++)
{
auto& typeOptions = mContext->mSystem->mTypeOptions[optionIdx];
bool matched = false;
for (auto& filter : typeOptions.mTypeFilters)
{
int filterIdx = 0;
int typeNameIdx = 0;
const char* filterPtr = filter.c_str();
const char* namePtr = typeName.c_str();
char prevFilterC = 0;
while (true)
{
char filterC;
while (true)
{
filterC = *(filterPtr++);
if (filterC != ' ')
break;
}
char nameC;
while (true)
{
nameC = *(namePtr++);
if (nameC != ' ')
break;
}
if ((filterC == 0) || (nameC == 0))
{
matched = (filterC == 0) && (nameC == 0);
break;
}
bool doWildcard = false;
if (nameC != filterC)
{
if (filterC == '*')
doWildcard = true;
else if (((filterC == ',') || (filterC == '>')) &&
((prevFilterC == '<') || (prevFilterC == ',')))
{
doWildcard = true;
filterPtr--;
}
if (!doWildcard)
{
matched = false;
break;
}
}
if (doWildcard)
{
int openDepth = 0;
const char* startNamePtr = namePtr;
while (true)
{
nameC = *(namePtr++);
if (nameC == 0)
{
namePtr--;
if (openDepth != 0)
matched = false;
break;
}
if ((nameC == '>') && (openDepth == 0))
{
namePtr--;
break;
}
if (nameC == '<')
openDepth++;
else if (nameC == '>')
openDepth--;
else if ((nameC == ',') && (openDepth == 0))
{
namePtr--;
break;
}
}
if (!matched)
break;
}
prevFilterC = filterC;
}
}
if (matched)
matchedIndices.push_back(optionIdx);
}
};
// if (typeInstance->IsTypedPrimitive())
// {
// auto underlyingType = typeInstance->GetUnderlyingType();
// if (underlyingType != NULL)
// {
// String typeName = TypeToString(underlyingType);
// _CheckTypeName(typeName);
// }
// else
// {
// // Can this only happen for functions that are being extended?
// }
// }
//
// if ((!typeInstance->IsBoxed()) && (typeInstance->mTypeDef == mCompiler->mPointerTTypeDef))
// {
// BF_ASSERT(typeInstance->IsGenericTypeInstance());
// auto innerType = typeInstance->mGenericTypeInfo->mTypeGenericArguments[0];
// auto ptrType = CreatePointerType(innerType);
// String typeName = TypeToString(ptrType);
// _CheckTypeName(typeName);
// }
String typeName = BfTypeUtils::TypeToString(typeDef);
_CheckTypeName(typeName);
int matchedIdx = -1;
if (matchedIndices.size() == 1)
{
matchedIdx = matchedIndices[0];
}
else if (matchedIndices.size() > 1)
{
// Try to find a merged typeoptions with these indices
for (int mergedIdx = 0; mergedIdx < (int)mContext->mSystem->mMergedTypeOptions.size(); mergedIdx++)
{
auto& typeOptions = mContext->mSystem->mMergedTypeOptions[mergedIdx];
if (typeOptions.mMatchedIndices == matchedIndices)
{
matchedIdx = typeOptionsCount + mergedIdx;
break;
}
}
// Otherwise make one...
if (matchedIdx == -1)
{
auto& first = mContext->mSystem->mTypeOptions[matchedIndices[0]];
BfTypeOptions mergedTypeOptions;
mergedTypeOptions.mSIMDSetting = first.mSIMDSetting;
mergedTypeOptions.mOptimizationLevel = first.mOptimizationLevel;
mergedTypeOptions.mEmitDebugInfo = first.mEmitDebugInfo;
mergedTypeOptions.mAndFlags = first.mAndFlags;
mergedTypeOptions.mOrFlags = first.mOrFlags;
mergedTypeOptions.mAllocStackTraceDepth = first.mAllocStackTraceDepth;
mergedTypeOptions.mReflectMethodFilters = first.mReflectMethodFilters;
mergedTypeOptions.mReflectMethodAttributeFilters = first.mReflectMethodAttributeFilters;
mergedTypeOptions.mMatchedIndices = matchedIndices;
for (int idx = 1; idx < (int)matchedIndices.size(); idx++)
{
auto& typeOptions = mContext->mSystem->mTypeOptions[matchedIndices[idx]];
if (typeOptions.mSIMDSetting != -1)
mergedTypeOptions.mSIMDSetting = typeOptions.mSIMDSetting;
if (typeOptions.mOptimizationLevel != -1)
mergedTypeOptions.mOptimizationLevel = typeOptions.mOptimizationLevel;
if (typeOptions.mEmitDebugInfo != -1)
mergedTypeOptions.mEmitDebugInfo = typeOptions.mEmitDebugInfo;
mergedTypeOptions.mOrFlags = (BfOptionFlags)(mergedTypeOptions.mOrFlags | typeOptions.mOrFlags);
mergedTypeOptions.mAndFlags = (BfOptionFlags)(mergedTypeOptions.mAndFlags | typeOptions.mOrFlags);
mergedTypeOptions.mAndFlags = (BfOptionFlags)(mergedTypeOptions.mAndFlags & typeOptions.mAndFlags);
mergedTypeOptions.mOrFlags = (BfOptionFlags)(mergedTypeOptions.mOrFlags & typeOptions.mAndFlags);
if (typeOptions.mAllocStackTraceDepth != -1)
mergedTypeOptions.mAllocStackTraceDepth = typeOptions.mAllocStackTraceDepth;
for (auto filter : typeOptions.mReflectMethodFilters)
mergedTypeOptions.mReflectMethodFilters.Add(filter);
for (auto filter : typeOptions.mReflectMethodAttributeFilters)
mergedTypeOptions.mReflectMethodAttributeFilters.Add(filter);
}
matchedIdx = typeOptionsCount + (int)mContext->mSystem->mMergedTypeOptions.size();
mContext->mSystem->mMergedTypeOptions.push_back(mergedTypeOptions);
}
}
return mSystem->GetTypeOptions( matchedIdx);
}
int BfModule::GenerateTypeOptions(BfCustomAttributes* customAttributes, BfTypeInstance* typeInstance, bool checkTypeName)
{
if (mContext->mSystem->mTypeOptions.size() == 0)
@ -1379,14 +1618,14 @@ int BfModule::GenerateTypeOptions(BfCustomAttributes* customAttributes, BfTypeIn
}
if (matched)
matchedIndices.push_back(optionIdx);
matchedIndices.push_back(optionIdx);
}
};
if (typeInstance->IsTypedPrimitive())
{
auto underlyingType = typeInstance->GetUnderlyingType();
if (underlyingType != NULL)
if (underlyingType != NULL)
{
String typeName = TypeToString(underlyingType);
_CheckTypeName(typeName);
@ -1407,7 +1646,7 @@ int BfModule::GenerateTypeOptions(BfCustomAttributes* customAttributes, BfTypeIn
}
String typeName = TypeToString(typeInstance);
_CheckTypeName(typeName);
_CheckTypeName(typeName);
}
int matchedIdx = -1;
@ -1436,11 +1675,11 @@ int BfModule::GenerateTypeOptions(BfCustomAttributes* customAttributes, BfTypeIn
mergedTypeOptions.mSIMDSetting = first.mSIMDSetting;
mergedTypeOptions.mOptimizationLevel = first.mOptimizationLevel;
mergedTypeOptions.mEmitDebugInfo = first.mEmitDebugInfo;
mergedTypeOptions.mRuntimeChecks = first.mRuntimeChecks;
mergedTypeOptions.mInitLocalVariables = first.mInitLocalVariables;
mergedTypeOptions.mEmitDynamicCastCheck = first.mEmitDynamicCastCheck;
mergedTypeOptions.mEmitObjectAccessCheck = first.mEmitObjectAccessCheck;
mergedTypeOptions.mAllocStackTraceDepth = first.mAllocStackTraceDepth;
mergedTypeOptions.mAndFlags = first.mAndFlags;
mergedTypeOptions.mOrFlags = first.mOrFlags;
mergedTypeOptions.mAllocStackTraceDepth = first.mAllocStackTraceDepth;
mergedTypeOptions.mReflectMethodFilters = first.mReflectMethodFilters;
mergedTypeOptions.mReflectMethodAttributeFilters = first.mReflectMethodAttributeFilters;
mergedTypeOptions.mMatchedIndices = matchedIndices;
for (int idx = 1; idx < (int)matchedIndices.size(); idx++)
@ -1452,16 +1691,19 @@ int BfModule::GenerateTypeOptions(BfCustomAttributes* customAttributes, BfTypeIn
mergedTypeOptions.mOptimizationLevel = typeOptions.mOptimizationLevel;
if (typeOptions.mEmitDebugInfo != -1)
mergedTypeOptions.mEmitDebugInfo = typeOptions.mEmitDebugInfo;
if (typeOptions.mRuntimeChecks != BfOptionalBool_NotSet)
mergedTypeOptions.mRuntimeChecks = typeOptions.mRuntimeChecks;
if (typeOptions.mInitLocalVariables != BfOptionalBool_NotSet)
mergedTypeOptions.mInitLocalVariables = typeOptions.mInitLocalVariables;
if (typeOptions.mEmitDynamicCastCheck != BfOptionalBool_NotSet)
mergedTypeOptions.mEmitDynamicCastCheck = typeOptions.mEmitDynamicCastCheck;
if (typeOptions.mEmitObjectAccessCheck != BfOptionalBool_NotSet)
mergedTypeOptions.mEmitObjectAccessCheck = typeOptions.mEmitObjectAccessCheck;
mergedTypeOptions.mOrFlags = (BfOptionFlags)(mergedTypeOptions.mOrFlags | typeOptions.mOrFlags);
mergedTypeOptions.mAndFlags = (BfOptionFlags)(mergedTypeOptions.mAndFlags | typeOptions.mOrFlags);
mergedTypeOptions.mAndFlags = (BfOptionFlags)(mergedTypeOptions.mAndFlags & typeOptions.mAndFlags);
mergedTypeOptions.mOrFlags = (BfOptionFlags)(mergedTypeOptions.mOrFlags & typeOptions.mAndFlags);
if (typeOptions.mAllocStackTraceDepth != -1)
mergedTypeOptions.mAllocStackTraceDepth = typeOptions.mAllocStackTraceDepth;
for (auto filter : typeOptions.mReflectMethodFilters)
mergedTypeOptions.mReflectMethodFilters.Add(filter);
for (auto filter : typeOptions.mReflectMethodAttributeFilters)
mergedTypeOptions.mReflectMethodAttributeFilters.Add(filter);
}
matchedIdx = typeOptionsCount + (int)mContext->mSystem->mMergedTypeOptions.size();
mContext->mSystem->mMergedTypeOptions.push_back(mergedTypeOptions);
@ -1880,6 +2122,7 @@ bool BfModule::DoPopulateType(BfType* resolvedTypeRef, BfPopulateType populateTy
{
BfTypeReference* mTypeRef;
BfTypeInstance* mGenericType;
bool mIgnoreErrors;
};
Array<_DeferredValidate> deferredTypeValidateList;
@ -1930,7 +2173,7 @@ bool BfModule::DoPopulateType(BfType* resolvedTypeRef, BfPopulateType populateTy
{
// Specialized type variations don't need to validate their constraints
if (!typeInstance->IsUnspecializedTypeVariation())
deferredTypeValidateList.Add({ checkTypeRef, genericTypeInst });
deferredTypeValidateList.Add({ checkTypeRef, genericTypeInst, false });
}
auto checkTypeInst = checkType->ToTypeInstance();
@ -2077,8 +2320,7 @@ bool BfModule::DoPopulateType(BfType* resolvedTypeRef, BfPopulateType populateTy
{
if ((genericTypeInst->IsSpecializedType()) && (!genericTypeInst->mGenericTypeInfo->mValidatedGenericConstraints) && (!typeInstance->IsBoxed()))
{
SetAndRestoreValue<bool> ignoreErrors(mIgnoreErrors, true);
ValidateGenericConstraints(NULL, genericTypeInst, false);
deferredTypeValidateList.Add({ NULL, genericTypeInst, true });
}
}
@ -2086,15 +2328,14 @@ bool BfModule::DoPopulateType(BfType* resolvedTypeRef, BfPopulateType populateTy
{
BfType* outerType = GetOuterType(typeInstance);
if (outerType != NULL)
{
PopulateType(outerType, BfPopulateType_BaseType);
AddDependency(outerType, typeInstance, BfDependencyMap::DependencyFlag_OuterType);
}
}
if ((baseTypeInst != NULL) && (typeInstance->mBaseType == NULL))
{
//curFieldDataIdx = 1;
// if (!typeInstance->mTypeFailed)
// PopulateType(baseTypeInst, BfPopulateType_Data);
if (typeInstance->mTypeFailed)
{
if (baseTypeInst->IsDataIncomplete())
@ -2217,6 +2458,7 @@ bool BfModule::DoPopulateType(BfType* resolvedTypeRef, BfPopulateType populateTy
for (auto& validateEntry : deferredTypeValidateList)
{
SetAndRestoreValue<bool> ignoreErrors(mIgnoreErrors, mIgnoreErrors | validateEntry.mIgnoreErrors);
ValidateGenericConstraints(validateEntry.mTypeRef, validateEntry.mGenericType, false);
}
@ -8564,6 +8806,8 @@ BfType* BfModule::ResolveTypeRef(BfTypeReference* typeRef, BfPopulateType popula
resolvedEntry->mValue = delegateType;
AddDependency(directTypeRef->mType, delegateType, BfDependencyMap::DependencyFlag_ParamOrReturnValue);
if (delegateInfo->mFunctionThisType != NULL)
AddDependency(delegateInfo->mFunctionThisType, delegateType, BfDependencyMap::DependencyFlag_ParamOrReturnValue);
for (auto paramType : paramTypes)
AddDependency(paramType, delegateType, BfDependencyMap::DependencyFlag_ParamOrReturnValue);

View file

@ -6936,7 +6936,7 @@ BfInvocationExpression* BfReducer::CreateInvocationExpression(BfAstNode* target,
return invocationExpr;
}
BfInitializerExpression * BfReducer::TryCreateInitializerExpression(BfExpression* target)
BfInitializerExpression* BfReducer::TryCreateInitializerExpression(BfExpression* target)
{
auto block = BfNodeDynCast<BfBlock>(mVisitorPos.GetNext());
if (block == NULL)

View file

@ -1909,6 +1909,17 @@ void BfTypeInstance::GenerateProjectsReferenced()
BfTypeUtils::GetProjectList(genericArgType, &mGenericTypeInfo->mProjectsReferenced, 0);
}
bool BfTypeInstance::IsAlwaysInclude()
{
bool alwaysInclude = mTypeDef->mIsAlwaysInclude || mTypeDef->mProject->mAlwaysIncludeAll;
if (mTypeOptionsIdx > 0)
{
auto typeOptions = mModule->mSystem->GetTypeOptions(mTypeOptionsIdx);
typeOptions->Apply(alwaysInclude, BfOptionFlags_ReflectAlwaysIncludeType);
}
return alwaysInclude;
}
bool BfTypeInstance::IsSpecializedByAutoCompleteMethod()
{
if (mGenericTypeInfo == NULL)

View file

@ -1878,6 +1878,7 @@ public:
bool GetResultInfo(BfType*& valueType, int& okTagId);
BfGenericTypeInfo::GenericParamsVector* GetGenericParamsVector(BfTypeDef* declaringTypeDef);
void GenerateProjectsReferenced();
bool IsAlwaysInclude();
virtual void ReportMemory(MemReporter* memReporter) override;
};

View file

@ -6412,7 +6412,7 @@ void BfModule::Visit(BfForEachStatement* forEachStmt)
bool boundsCheck = mCompiler->mOptions.mRuntimeChecks;
auto typeOptions = GetTypeOptions();
if (typeOptions != NULL)
boundsCheck = BfTypeOptions::Apply(boundsCheck, typeOptions->mRuntimeChecks);
boundsCheck = typeOptions->Apply(boundsCheck, BfOptionFlags_RuntimeChecks);
BfMethodMatcher methodMatcher(forEachStmt->mVariableName, this, "get__", argValues.mResolvedArgs, NULL);
methodMatcher.mMethodType = BfMethodType_PropertyGetter;

View file

@ -3617,51 +3617,57 @@ BF_EXPORT void BF_CALLTYPE BfSystem_ClearTypeOptions(BfSystem* bfSystem)
bfSystem->mTypeOptions.Clear();
}
BF_EXPORT void BF_CALLTYPE BfSystem_AddTypeOptions(BfSystem* bfSystem, char* filter, int32 simdSetting, int32 optimizationLevel, int32 emitDebugInfo, int32 runtimeChecks,
int32 initLocalVariables, int32 emitDynamicCastCheck, int32 emitObjectAccessCheck, int32 allocStackTraceDepth)
BF_EXPORT void BF_CALLTYPE BfSystem_AddTypeOptions(BfSystem* bfSystem, char* filter, int32 simdSetting, int32 optimizationLevel, int32 emitDebugInfo, int32 andFlags, int32 orFlags, int32 allocStackTraceDepth, char* reflectMethodFilter)
{
AutoCrit autoCrit(bfSystem->mDataLock);
BfTypeOptions typeOptions;
String filterStr = filter;
int idx = 0;
while (true)
auto _ParseFilters = [&](char* filter, Array<String>& filters, Array<String>& attributeFilters)
{
int semiIdx = (int)filterStr.IndexOf(';', idx);
String newFilter;
if (semiIdx == -1)
newFilter = filterStr.Substring(idx);
else
newFilter = filterStr.Substring(idx, semiIdx - idx);
newFilter.Trim();
if (!newFilter.IsEmpty())
String filterStr = filter;
int idx = 0;
while (true)
{
if (newFilter.StartsWith('['))
{
newFilter.Remove(0);
if (newFilter.EndsWith(']'))
newFilter.Remove(newFilter.length() - 1);
newFilter.Trim();
typeOptions.mAttributeFilters.Add(newFilter);
}
int semiIdx = (int)filterStr.IndexOf(';', idx);
String newFilter;
if (semiIdx == -1)
newFilter = filterStr.Substring(idx);
else
typeOptions.mTypeFilters.Add(newFilter);
}
newFilter = filterStr.Substring(idx, semiIdx - idx);
newFilter.Trim();
if (!newFilter.IsEmpty())
{
if (newFilter.StartsWith('['))
{
newFilter.Remove(0);
if (newFilter.EndsWith(']'))
newFilter.Remove(newFilter.length() - 1);
newFilter.Trim();
attributeFilters.Add(newFilter);
}
else
filters.Add(newFilter);
}
if (semiIdx == -1)
break;
idx = semiIdx + 1;
}
};
_ParseFilters(filter, typeOptions.mTypeFilters, typeOptions.mAttributeFilters);
if (semiIdx == -1)
break;
idx = semiIdx + 1;
}
if ((typeOptions.mTypeFilters.IsEmpty()) && (typeOptions.mAttributeFilters.IsEmpty()))
return;
typeOptions.mSIMDSetting = simdSetting;
typeOptions.mOptimizationLevel = optimizationLevel;
typeOptions.mEmitDebugInfo = emitDebugInfo;
typeOptions.mRuntimeChecks = (BfOptionalBool)runtimeChecks;
typeOptions.mInitLocalVariables = (BfOptionalBool)initLocalVariables;
typeOptions.mEmitDynamicCastCheck = (BfOptionalBool)emitDynamicCastCheck;
typeOptions.mEmitObjectAccessCheck = (BfOptionalBool)emitObjectAccessCheck;
typeOptions.mAndFlags = (BfOptionFlags)andFlags;
typeOptions.mOrFlags = (BfOptionFlags)orFlags;
typeOptions.mAllocStackTraceDepth = allocStackTraceDepth;
_ParseFilters(reflectMethodFilter, typeOptions.mReflectMethodFilters, typeOptions.mReflectMethodAttributeFilters);
bfSystem->mTypeOptions.push_back(typeOptions);
}

View file

@ -180,7 +180,8 @@ enum BfTypeFlags
//
BfTypeFlags_WantsMarking = 0x8000,
BfTypeFlags_Delegate = 0x10000,
BfTypeFlags_HasDestructor = 0x20000,
BfTypeFlags_Function = 0x20000,
BfTypeFlags_HasDestructor = 0x40000,
};
enum BfObjectFlags : uint8
@ -1267,11 +1268,23 @@ public:
void WriteErrorSummary();
};
enum BfOptionalBool
enum BfOptionFlags
{
BfOptionalBool_NotSet = -1,
BfOptionalBool_False = 0,
BfOptionalBool_True = 1
BfOptionFlags_None = 0,
BfOptionFlags_RuntimeChecks = 1,
BfOptionFlags_InitLocalVariables = 2,
BfOptionFlags_EmitDynamicCastCheck = 4,
BfOptionFlags_EmitObjectAccessCheck = 8,
BfOptionFlags_ReflectAlwaysIncludeType = 0x10,
BfOptionFlags_ReflectAlwaysIncludeAll = 0x20,
BfOptionFlags_ReflectAssumeInstantiated = 0x40,
BfOptionFlags_ReflectStaticFields = 0x80,
BfOptionFlags_ReflectNonStaticFields = 0x100,
BfOptionFlags_ReflectStaticMethods = 0x200,
BfOptionFlags_ReflectNonStaticMethods = 0x400,
BfOptionFlags_ReflectConstructors = 0x800,
};
class BfTypeOptions
@ -1283,10 +1296,10 @@ public:
int mSIMDSetting;
int mOptimizationLevel;
int mEmitDebugInfo;
BfOptionalBool mRuntimeChecks;
BfOptionalBool mInitLocalVariables;
BfOptionalBool mEmitDynamicCastCheck;
BfOptionalBool mEmitObjectAccessCheck;
BfOptionFlags mAndFlags;
BfOptionFlags mOrFlags;
Array<String> mReflectMethodFilters;
Array<String> mReflectMethodAttributeFilters;
int mAllocStackTraceDepth;
public:
@ -1295,13 +1308,14 @@ public:
if (applyVal != -1)
return applyVal;
return val;
}
}
static bool Apply(bool val, BfOptionalBool applyVal)
bool Apply(bool val, BfOptionFlags flags)
{
if (applyVal != BfOptionalBool_NotSet)
return applyVal == BfOptionalBool_True;
return val;
if (val)
return (mAndFlags & flags) != 0;
else
return (mOrFlags & flags) != 0;
}
};

View file

@ -47,6 +47,20 @@ namespace Tests
}
}
class Singleton<T> where T : Singleton<T>
{
public static T mInstance;
protected this()
{
mInstance = (T)this;
}
}
class ClassC : Singleton<ClassC>
{
}
static void DoDispose<T>(mut T val) where T : IDisposable
{
val.Dispose();
@ -119,6 +133,9 @@ namespace Tests
Test.Assert(MethodA("") == 1);
Test.Assert(MethodA(1.2f) == 2);
Test.Assert(MethodA(TypeCode.Boolean) == 3);
ClassC cc = scope .();
Test.Assert(ClassC.mInstance == cc);
}
}