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

Comptime reentrancy fixes, deleting rebuild, static field fixes

This commit is contained in:
Brian Fiete 2021-11-26 08:59:46 -08:00
parent 0bb273b898
commit c5e2b78199
5 changed files with 145 additions and 57 deletions

View file

@ -3464,20 +3464,25 @@ void BfModule::AddDependency(BfType* usedType, BfType* userType, BfDependencyMap
if (addType) if (addType)
{ {
auto checkTypeInst = checkType->ToTypeInstance(); auto checkTypeInst = checkType->ToTypeInstance();
auto hotTypeVersion = checkTypeInst->mHotTypeData->GetLatestVersion(); if (checkTypeInst->mHotTypeData != NULL)
BF_ASSERT(hotTypeVersion != NULL); {
auto hotTypeVersion = checkTypeInst->mHotTypeData->GetLatestVersion();
BF_ASSERT(hotTypeVersion != NULL);
if (hotTypeVersion != NULL)
{
bool isAllocation = ((flags & BfDependencyMap::DependencyFlag_Allocates) != 0);
if (((flags & BfDependencyMap::DependencyFlag_LocalUsage) != 0) &&
(checkType->IsComposite()))
isAllocation = true;
bool isAllocation = ((flags & BfDependencyMap::DependencyFlag_Allocates) != 0); if (isAllocation)
if (((flags & BfDependencyMap::DependencyFlag_LocalUsage) != 0) && {
(checkType->IsComposite())) mCurMethodState->mHotDataReferenceBuilder->mAllocatedData.Add(hotTypeVersion);
isAllocation = true; }
else
if (isAllocation) mCurMethodState->mHotDataReferenceBuilder->mUsedData.Add(hotTypeVersion);
{ }
mCurMethodState->mHotDataReferenceBuilder->mAllocatedData.Add(hotTypeVersion);
} }
else
mCurMethodState->mHotDataReferenceBuilder->mUsedData.Add(hotTypeVersion);
} }
} }
@ -6432,9 +6437,10 @@ BfIRValue BfModule::CreateTypeData(BfType* type, Dictionary<int, int>& usedStrin
} }
} }
else if (fieldInstance->GetFieldDef()->mIsStatic) else if (fieldInstance->GetFieldDef()->mIsStatic)
{ {
auto refVal = ReferenceStaticField(fieldInstance); BfTypedValue refVal;
if (!mIsComptimeModule) // This can create circular reference issues for a `Self` static
refVal = ReferenceStaticField(fieldInstance);
if (refVal.mValue.IsConst()) if (refVal.mValue.IsConst())
{ {
auto constant = mBfIRBuilder->GetConstant(refVal.mValue); auto constant = mBfIRBuilder->GetConstant(refVal.mValue);

View file

@ -1178,11 +1178,6 @@ void BfModule::PopulateType(BfType* resolvedTypeRef, BfPopulateType populateType
else else
resolvedTypeRef->mTypeId = mCompiler->mCurTypeId++; resolvedTypeRef->mTypeId = mCompiler->mCurTypeId++;
if (resolvedTypeRef->mTypeId == 2568)
{
NOP;
}
while (resolvedTypeRef->mTypeId >= (int)mContext->mTypes.size()) while (resolvedTypeRef->mTypeId >= (int)mContext->mTypes.size())
mContext->mTypes.Add(NULL); mContext->mTypes.Add(NULL);
mContext->mTypes[resolvedTypeRef->mTypeId] = resolvedTypeRef; mContext->mTypes[resolvedTypeRef->mTypeId] = resolvedTypeRef;
@ -2158,6 +2153,9 @@ void BfModule::HandleCEAttributes(CeEmitContext* ceEmitContext, BfTypeInstance*
auto result = ceContext->Call(customAttribute.mRef, this, methodInstance, args, CeEvalFlags_None, NULL); auto result = ceContext->Call(customAttribute.mRef, this, methodInstance, args, CeEvalFlags_None, NULL);
if (typeInstance->mDefineState == BfTypeDefineState_DefinedAndMethodsSlotted)
return;
if (typeInstance->mDefineState != BfTypeDefineState_CETypeInit) if (typeInstance->mDefineState != BfTypeDefineState_CETypeInit)
{ {
// We populated before we could finish // We populated before we could finish
@ -2438,6 +2436,9 @@ void BfModule::DoCEEmit(BfTypeInstance* typeInstance, bool& hadNewMembers)
ceEmitContext.mType = typeInstance; ceEmitContext.mType = typeInstance;
ExecuteCEOnCompile(&ceEmitContext, typeInstance, BfCEOnCompileKind_TypeInit); ExecuteCEOnCompile(&ceEmitContext, typeInstance, BfCEOnCompileKind_TypeInit);
hadNewMembers = (typeInstance->mTypeDef->mEmitParent != NULL); hadNewMembers = (typeInstance->mTypeDef->mEmitParent != NULL);
if (ceEmitContext.mFailed)
TypeFailed(typeInstance);
} }
void BfModule::DoCEEmit(BfMethodInstance* methodInstance) void BfModule::DoCEEmit(BfMethodInstance* methodInstance)
@ -3939,26 +3940,46 @@ void BfModule::DoPopulateType(BfType* resolvedTypeRef, BfPopulateType populateTy
} }
} }
bool tryCE = true;
if (typeInstance->mDefineState == BfTypeDefineState_CETypeInit) if (typeInstance->mDefineState == BfTypeDefineState_CETypeInit)
{ {
if (populateType <= BfPopulateType_AllowStaticMethods) if (populateType <= BfPopulateType_AllowStaticMethods)
return; return;
String error = "OnCompile const evaluation creates a data dependency during TypeInit"; int foundTypeCount = 0;
if (mCompiler->mCEMachine->mCurBuilder != NULL) auto typeState = mContext->mCurTypeState;
while (typeState != NULL)
{ {
error += StrFormat(" during const-eval generation of '%s'", MethodToString(mCompiler->mCEMachine->mCurBuilder->mCeFunction->mMethodInstance).c_str()); if (typeState->mType == typeInstance)
{
foundTypeCount++;
if (foundTypeCount == 2)
break;
}
typeState = typeState->mPrevState;
} }
auto refNode = typeDef->GetRefNode(); if ((foundTypeCount >= 2) || (typeInstance->mTypeDef->IsEmitted()))
Fail(error, refNode); {
if ((mCompiler->mCEMachine->mCurContext != NULL) && (mCompiler->mCEMachine->mCurContext->mCurFrame != NULL)) String error = "OnCompile const evaluation creates a data dependency during TypeInit";
mCompiler->mCEMachine->mCurContext->Fail(*mCompiler->mCEMachine->mCurContext->mCurFrame, error); if (mCompiler->mCEMachine->mCurBuilder != NULL)
else if (mCompiler->mCEMachine->mCurContext != NULL) {
mCompiler->mCEMachine->mCurContext->Fail(error); error += StrFormat(" during const-eval generation of '%s'", MethodToString(mCompiler->mCEMachine->mCurBuilder->mCeFunction->mMethodInstance).c_str());
}
auto refNode = typeDef->GetRefNode();
Fail(error, refNode);
if ((mCompiler->mCEMachine->mCurContext != NULL) && (mCompiler->mCEMachine->mCurContext->mCurFrame != NULL))
mCompiler->mCEMachine->mCurContext->Fail(*mCompiler->mCEMachine->mCurContext->mCurFrame, error);
else if (mCompiler->mCEMachine->mCurContext != NULL)
mCompiler->mCEMachine->mCurContext->Fail(error);
}
} }
else if (typeInstance->mDefineState < BfTypeDefineState_CEPostTypeInit)
{ if ((typeInstance->mDefineState < BfTypeDefineState_CEPostTypeInit) && (tryCE))
{
BF_ASSERT(!typeInstance->mTypeDef->IsEmitted());
typeInstance->mDefineState = BfTypeDefineState_CETypeInit; typeInstance->mDefineState = BfTypeDefineState_CETypeInit;
bool hadNewMembers = false; bool hadNewMembers = false;
DoCEEmit(typeInstance, hadNewMembers); DoCEEmit(typeInstance, hadNewMembers);
@ -3991,9 +4012,17 @@ void BfModule::DoPopulateType(BfType* resolvedTypeRef, BfPopulateType populateTy
{ {
if ((typeInstance->mCeTypeInfo->mHash != typeInstance->mCeTypeInfo->mNext->mHash) && (!typeInstance->mCeTypeInfo->mHash.IsZero())) if ((typeInstance->mCeTypeInfo->mHash != typeInstance->mCeTypeInfo->mNext->mHash) && (!typeInstance->mCeTypeInfo->mHash.IsZero()))
{ {
int prevDeletedTypes = mCompiler->mStats.mTypesDeleted;
if (mCompiler->mIsResolveOnly) if (mCompiler->mIsResolveOnly)
mCompiler->mNeedsFullRefresh = true; mCompiler->mNeedsFullRefresh = true;
BfLogSysM("Type %p hash changed, rebuilding dependent types\n", typeInstance);
mContext->RebuildDependentTypes(typeInstance); mContext->RebuildDependentTypes(typeInstance);
if (mCompiler->mStats.mTypesDeleted != prevDeletedTypes)
{
BfLogSysM("Type %p hash changed, rebuilding dependent types - updating after deleting types\n", typeInstance);
mContext->UpdateAfterDeletingTypes();
}
} }
typeInstance->mCeTypeInfo->mOnCompileMap = typeInstance->mCeTypeInfo->mNext->mOnCompileMap; typeInstance->mCeTypeInfo->mOnCompileMap = typeInstance->mCeTypeInfo->mNext->mOnCompileMap;
typeInstance->mCeTypeInfo->mTypeIFaceMap = typeInstance->mCeTypeInfo->mNext->mTypeIFaceMap; typeInstance->mCeTypeInfo->mTypeIFaceMap = typeInstance->mCeTypeInfo->mNext->mTypeIFaceMap;
@ -6205,6 +6234,15 @@ void BfModule::AddMethodToWorkList(BfMethodInstance* methodInstance)
auto typeInstance = methodInstance->GetOwner(); auto typeInstance = methodInstance->GetOwner();
BfMethodProcessRequest* methodProcessRequest = mContext->mMethodWorkList.Alloc(); BfMethodProcessRequest* methodProcessRequest = mContext->mMethodWorkList.Alloc();
if (mCompiler->mCompileState == BfCompiler::CompileState_Unreified)
{
if (methodInstance->mIsReified)
{
BfLogSysM("Marking method %d as unreified due to CompileState_Unreified\n", methodInstance);
methodInstance->mIsReified = false;
}
}
//BF_ASSERT(!methodInstance->mIsReified);
methodProcessRequest->mType = typeInstance; methodProcessRequest->mType = typeInstance;
methodProcessRequest->mMethodInstance = methodInstance; methodProcessRequest->mMethodInstance = methodInstance;
methodProcessRequest->mRevision = typeInstance->mRevision; methodProcessRequest->mRevision = typeInstance->mRevision;
@ -9976,6 +10014,7 @@ BfType* BfModule::ResolveTypeRef(BfTypeReference* typeRef, BfPopulateType popula
if (!inserted) if (!inserted)
{ {
BF_ASSERT(resolvedEntry->mValue != NULL); BF_ASSERT(resolvedEntry->mValue != NULL);
BF_ASSERT(!resolvedEntry->mValue->IsDeleting());
return ResolveTypeResult(typeRef, resolvedEntry->mValue, populateType, resolveFlags); return ResolveTypeResult(typeRef, resolvedEntry->mValue, populateType, resolveFlags);
} }

View file

@ -1120,7 +1120,7 @@ CeOperand CeBuilder::GetOperand(BeValue* value, bool allowAlloca, bool allowImme
if (checkBuilder->mInnerFunctionMap.TryGetValue(beFunction, &innerFunctionIdx)) if (checkBuilder->mInnerFunctionMap.TryGetValue(beFunction, &innerFunctionIdx))
{ {
auto innerFunction = checkBuilder->mCeFunction->mInnerFunctions[innerFunctionIdx]; auto innerFunction = checkBuilder->mCeFunction->mInnerFunctions[innerFunctionIdx];
if (!innerFunction->mInitialized) if (innerFunction->mInitializeState < CeFunction::InitializeState_Initialized)
mCeMachine->PrepareFunction(innerFunction, checkBuilder); mCeMachine->PrepareFunction(innerFunction, checkBuilder);
CeOperand result = FrameAlloc(mCeMachine->GetBeContext()->GetPrimitiveType((sizeof(BfMethodInstance*) == 8) ? BeTypeCode_Int64 : BeTypeCode_Int32)); CeOperand result = FrameAlloc(mCeMachine->GetBeContext()->GetPrimitiveType((sizeof(BfMethodInstance*) == 8) ? BeTypeCode_Int64 : BeTypeCode_Int32));
@ -1288,7 +1288,7 @@ void CeBuilder::Build()
auto methodInstance = mCeFunction->mMethodInstance; auto methodInstance = mCeFunction->mMethodInstance;
if (methodInstance != NULL) if (methodInstance != NULL)
{ {
BfMethodInstance dupMethodInstance; BfMethodInstance dupMethodInstance;
dupMethodInstance.CopyFrom(methodInstance); dupMethodInstance.CopyFrom(methodInstance);
auto methodDef = methodInstance->mMethodDef; auto methodDef = methodInstance->mMethodDef;
@ -1313,7 +1313,9 @@ void CeBuilder::Build()
int startFunctionCount = (int)beModule->mFunctions.size(); int startFunctionCount = (int)beModule->mFunctions.size();
ProcessMethod(methodInstance, &dupMethodInstance); ProcessMethod(methodInstance, &dupMethodInstance);
if (mCeFunction->mInitializeState == CeFunction::InitializeState_Initialized)
return;
if (!dupMethodInstance.mIRFunction) if (!dupMethodInstance.mIRFunction)
{ {
mCeFunction->mFailed = true; mCeFunction->mFailed = true;
@ -2855,6 +2857,7 @@ void CeBuilder::Build()
CeContext::CeContext() CeContext::CeContext()
{ {
mPrevContext = NULL;
mCurEvalFlags = CeEvalFlags_None; mCurEvalFlags = CeEvalFlags_None;
mCeMachine = NULL; mCeMachine = NULL;
mReflectTypeIdOffset = -1; mReflectTypeIdOffset = -1;
@ -2876,6 +2879,8 @@ CeContext::~CeContext()
BfError* CeContext::Fail(const StringImpl& error) BfError* CeContext::Fail(const StringImpl& error)
{ {
if (mCurEmitContext != NULL)
mCurEmitContext->mFailed = true;
auto bfError = mCurModule->Fail(StrFormat("Unable to comptime %s", mCurModule->MethodToString(mCurMethodInstance).c_str()), mCurTargetSrc, (mCurEvalFlags & CeEvalFlags_PersistantError) != 0); auto bfError = mCurModule->Fail(StrFormat("Unable to comptime %s", mCurModule->MethodToString(mCurMethodInstance).c_str()), mCurTargetSrc, (mCurEvalFlags & CeEvalFlags_PersistantError) != 0);
if (bfError == NULL) if (bfError == NULL)
return NULL; return NULL;
@ -2885,6 +2890,8 @@ BfError* CeContext::Fail(const StringImpl& error)
BfError* CeContext::Fail(const CeFrame& curFrame, const StringImpl& str) BfError* CeContext::Fail(const CeFrame& curFrame, const StringImpl& str)
{ {
if (mCurEmitContext != NULL)
mCurEmitContext->mFailed = true;
auto bfError = mCurModule->Fail(StrFormat("Unable to comptime %s", mCurModule->MethodToString(mCurMethodInstance).c_str()), mCurTargetSrc, auto bfError = mCurModule->Fail(StrFormat("Unable to comptime %s", mCurModule->MethodToString(mCurMethodInstance).c_str()), mCurTargetSrc,
(mCurEvalFlags & CeEvalFlags_PersistantError) != 0, (mCurEvalFlags & CeEvalFlags_PersistantError) != 0,
((mCurEvalFlags & CeEvalFlags_DeferIfNotOnlyError) != 0) && !mCurModule->mHadBuildError); ((mCurEvalFlags & CeEvalFlags_DeferIfNotOnlyError) != 0) && !mCurModule->mHadBuildError);
@ -2966,6 +2973,10 @@ BfError* CeContext::Fail(const CeFrame& curFrame, const StringImpl& str)
moreInfo->mLocation = location; moreInfo->mLocation = location;
} }
} }
else
{
auto moreInfo = passInstance->MoreInfo(err, mCeMachine->mCeModule->mCompiler->GetAutoComplete() != NULL);
}
} }
return bfError; return bfError;
@ -3939,6 +3950,7 @@ BfTypedValue CeContext::Call(BfAstNode* targetSrc, BfModule* module, BfMethodIns
AutoTimer autoTimer(mCeMachine->mRevisionExecuteTime); AutoTimer autoTimer(mCeMachine->mRevisionExecuteTime);
SetAndRestoreValue<CeContext*> curPrevContext(mPrevContext, mCeMachine->mCurContext);
SetAndRestoreValue<CeContext*> prevContext(mCeMachine->mCurContext, this); SetAndRestoreValue<CeContext*> prevContext(mCeMachine->mCurContext, this);
SetAndRestoreValue<CeEvalFlags> prevEvalFlags(mCurEvalFlags, flags); SetAndRestoreValue<CeEvalFlags> prevEvalFlags(mCurEvalFlags, flags);
SetAndRestoreValue<BfAstNode*> prevTargetSrc(mCurTargetSrc, targetSrc); SetAndRestoreValue<BfAstNode*> prevTargetSrc(mCurTargetSrc, targetSrc);
@ -4042,13 +4054,24 @@ BfTypedValue CeContext::Call(BfAstNode* targetSrc, BfModule* module, BfMethodIns
bool added = false; bool added = false;
CeFunction* ceFunction = mCeMachine->GetFunction(methodInstance, BfIRValue(), added); CeFunction* ceFunction = mCeMachine->GetFunction(methodInstance, BfIRValue(), added);
if (ceFunction->mGenerating) if (ceFunction->mInitializeState == CeFunction::InitializeState_Initializing_ReEntry)
{ {
Fail("Recursive var-inference"); String error = "Comptime method preparation recursion";
auto curContext = this;
while (curContext != NULL)
{
if (curContext->mCurMethodInstance != NULL)
error += StrFormat("\n %s", module->MethodToString(curContext->mCurMethodInstance).c_str());
curContext = curContext->mPrevContext;
if ((curContext != NULL) && (curContext->mCurMethodInstance == mCurMethodInstance))
break;
}
Fail(error);
return BfTypedValue(); return BfTypedValue();
} }
if (!ceFunction->mInitialized) if (ceFunction->mInitializeState < CeFunction::InitializeState_Initialized)
mCeMachine->PrepareFunction(ceFunction, NULL); mCeMachine->PrepareFunction(ceFunction, NULL);
auto stackPtr = &mMemory[0] + BF_CE_STACK_SIZE; auto stackPtr = &mMemory[0] + BF_CE_STACK_SIZE;
@ -4926,7 +4949,7 @@ bool CeContext::Execute(CeFunction* startFunction, uint8* startStackPtr, uint8*
if (!checkFunction->mFailed) if (!checkFunction->mFailed)
return true; return true;
auto error = Fail(_GetCurFrame(), StrFormat("Method call '%s' failed", ceModule->MethodToString(checkFunction->mMethodInstance).c_str())); auto error = Fail(_GetCurFrame(), StrFormat("Method call preparation '%s' failed", ceModule->MethodToString(checkFunction->mMethodInstance).c_str()));
if ((error != NULL) && (!checkFunction->mGenError.IsEmpty())) if ((error != NULL) && (!checkFunction->mGenError.IsEmpty()))
mCeMachine->mCompiler->mPassInstance->MoreInfo("Comptime method generation error: " + checkFunction->mGenError); mCeMachine->mCompiler->mPassInstance->MoreInfo("Comptime method generation error: " + checkFunction->mGenError);
return false; return false;
@ -5394,7 +5417,7 @@ bool CeContext::Execute(CeFunction* startFunction, uint8* startStackPtr, uint8*
bool added = false; bool added = false;
ctorCallFunction = mCeMachine->GetFunction(moduleMethodInstance.mMethodInstance, moduleMethodInstance.mFunc, added); ctorCallFunction = mCeMachine->GetFunction(moduleMethodInstance.mMethodInstance, moduleMethodInstance.mFunc, added);
if (!ctorCallFunction->mInitialized) if (ctorCallFunction->mInitializeState < CeFunction::InitializeState_Initialized)
mCeMachine->PrepareFunction(ctorCallFunction, NULL); mCeMachine->PrepareFunction(ctorCallFunction, NULL);
} }
@ -5469,11 +5492,11 @@ bool CeContext::Execute(CeFunction* startFunction, uint8* startStackPtr, uint8*
} }
callEntry.mFunction = callEntry.mFunctionInfo->mCeFunction; callEntry.mFunction = callEntry.mFunctionInfo->mCeFunction;
if (!callEntry.mFunction->mInitialized) if (callEntry.mFunction->mInitializeState < CeFunction::InitializeState_Initialized)
{ {
auto curFrame = _GetCurFrame(); auto curFrame = _GetCurFrame();
SetAndRestoreValue<CeFrame*> prevFrame(mCurFrame, &curFrame); SetAndRestoreValue<CeFrame*> prevFrame(mCurFrame, &curFrame);
BF_ASSERT(!callEntry.mFunction->mInitialized); BF_ASSERT(callEntry.mFunction->mInitializeState < CeFunction::InitializeState_Initialized);
mCeMachine->PrepareFunction(callEntry.mFunction, NULL); mCeMachine->PrepareFunction(callEntry.mFunction, NULL);
} }
@ -6912,7 +6935,7 @@ void CeMachine::CheckFunctionKind(CeFunction* ceFunction)
ceFunction->mFunctionKind = CeFunctionKind_Math_Tanh; ceFunction->mFunctionKind = CeFunctionKind_Math_Tanh;
} }
ceFunction->mInitialized = true; ceFunction->mInitializeState = CeFunction::InitializeState_Initialized;
return; return;
} }
} }
@ -6923,19 +6946,27 @@ void CeMachine::PrepareFunction(CeFunction* ceFunction, CeBuilder* parentBuilder
AutoTimer autoTimer(mRevisionExecuteTime); AutoTimer autoTimer(mRevisionExecuteTime);
SetAndRestoreValue<CeFunction*> prevCEFunction(mPreparingFunction, ceFunction); SetAndRestoreValue<CeFunction*> prevCEFunction(mPreparingFunction, ceFunction);
BF_ASSERT(!ceFunction->mInitialized); BF_ASSERT(ceFunction->mInitializeState <= CeFunction::InitializeState_Initialized);
if (ceFunction->mFunctionKind == CeFunctionKind_NotSet) if (ceFunction->mFunctionKind == CeFunctionKind_NotSet)
{ {
CheckFunctionKind(ceFunction); CheckFunctionKind(ceFunction);
if (ceFunction->mInitialized) if (ceFunction->mInitializeState == CeFunction::InitializeState_Initialized)
return; return;
} }
BF_ASSERT(!ceFunction->mInitialized); BF_ASSERT(ceFunction->mInitializeState <= CeFunction::InitializeState_Initialized);
ceFunction->mInitialized = true; if (ceFunction->mInitializeState == CeFunction::InitializeState_Initializing_ReEntry)
ceFunction->mGenerating = true; {
//Fail("Function generation re-entry");
return;
}
if (ceFunction->mInitializeState == CeFunction::InitializeState_Initializing)
ceFunction->mInitializeState = CeFunction::InitializeState_Initializing_ReEntry;
else
ceFunction->mInitializeState = CeFunction::InitializeState_Initializing;
CeBuilder ceBuilder; CeBuilder ceBuilder;
SetAndRestoreValue<CeBuilder*> prevBuilder(mCurBuilder, &ceBuilder); SetAndRestoreValue<CeBuilder*> prevBuilder(mCurBuilder, &ceBuilder);
ceBuilder.mParentBuilder = parentBuilder; ceBuilder.mParentBuilder = parentBuilder;
@ -6944,7 +6975,7 @@ void CeMachine::PrepareFunction(CeFunction* ceFunction, CeBuilder* parentBuilder
ceBuilder.mCeFunction = ceFunction; ceBuilder.mCeFunction = ceFunction;
ceBuilder.Build(); ceBuilder.Build();
ceFunction->mGenerating = false; ceFunction->mInitializeState = CeFunction::InitializeState_Initialized;
/*if (!ceFunction->mCode.IsEmpty()) /*if (!ceFunction->mCode.IsEmpty())
{ {
@ -6980,8 +7011,8 @@ CeFunction* CeMachine::GetFunction(BfMethodInstance* methodInstance, BfIRValue f
CeFunction* ceFunction = NULL; CeFunction* ceFunction = NULL;
if (!mFunctions.TryAdd(methodInstance, NULL, &functionInfoPtr)) if (!mFunctions.TryAdd(methodInstance, NULL, &functionInfoPtr))
{ {
ceFunctionInfo = *functionInfoPtr; ceFunctionInfo = *functionInfoPtr;
BF_ASSERT(ceFunctionInfo->mCeFunction != NULL); BF_ASSERT(ceFunctionInfo->mCeFunction != NULL);
return ceFunctionInfo->mCeFunction; return ceFunctionInfo->mCeFunction;
} }
@ -7048,7 +7079,7 @@ CeFunction* CeMachine::GetPreparedFunction(BfMethodInstance* methodInstance)
auto ceFunction = GetFunction(methodInstance, BfIRValue(), added); auto ceFunction = GetFunction(methodInstance, BfIRValue(), added);
if (ceFunction == NULL) if (ceFunction == NULL)
return NULL; return NULL;
if (!ceFunction->mInitialized) if (ceFunction->mInitializeState < CeFunction::InitializeState_Initialized)
PrepareFunction(ceFunction, NULL); PrepareFunction(ceFunction, NULL);
return ceFunction; return ceFunction;
} }

View file

@ -395,14 +395,22 @@ public:
class CeFunction class CeFunction
{ {
public:
enum InitializeState
{
InitializeState_None,
InitializeState_Initializing,
InitializeState_Initializing_ReEntry,
InitializeState_Initialized
};
public: public:
CeMachine* mCeMachine; CeMachine* mCeMachine;
CeFunctionInfo* mCeFunctionInfo; CeFunctionInfo* mCeFunctionInfo;
CeInnerFunctionInfo* mCeInnerFunctionInfo; CeInnerFunctionInfo* mCeInnerFunctionInfo;
BfMethodInstance* mMethodInstance; BfMethodInstance* mMethodInstance;
CeFunctionKind mFunctionKind; CeFunctionKind mFunctionKind;
bool mGenerating; InitializeState mInitializeState;
bool mInitialized;
bool mFailed; bool mFailed;
bool mIsVarReturn; bool mIsVarReturn;
Array<uint8> mCode; Array<uint8> mCode;
@ -425,9 +433,8 @@ public:
mCeMachine = NULL; mCeMachine = NULL;
mCeFunctionInfo = NULL; mCeFunctionInfo = NULL;
mCeInnerFunctionInfo = NULL; mCeInnerFunctionInfo = NULL;
mFunctionKind = CeFunctionKind_NotSet; mFunctionKind = CeFunctionKind_NotSet;
mGenerating = false; mInitializeState = InitializeState_None;
mInitialized = false;
mMethodInstance = NULL; mMethodInstance = NULL;
mFailed = false; mFailed = false;
mIsVarReturn = false; mIsVarReturn = false;
@ -682,11 +689,13 @@ public:
BfMethodInstance* mMethodInstance; BfMethodInstance* mMethodInstance;
String mEmitData; String mEmitData;
String mExitEmitData; String mExitEmitData;
bool mFailed;
CeEmitContext() CeEmitContext()
{ {
mType = NULL; mType = NULL;
mMethodInstance = NULL; mMethodInstance = NULL;
mFailed = false;
} }
}; };
@ -694,6 +703,7 @@ class CeContext
{ {
public: public:
CeMachine* mCeMachine; CeMachine* mCeMachine;
CeContext* mPrevContext;
int mReflectTypeIdOffset; int mReflectTypeIdOffset;
int mExecuteId; int mExecuteId;
CeEvalFlags mCurEvalFlags; CeEvalFlags mCurEvalFlags;

View file

@ -84,6 +84,8 @@ namespace Tests
struct StructA struct StructA
{ {
public int mA = 123; public int mA = 123;
public static StructA sSA;
public const StructA cSA = .();
[OnCompile(.TypeInit), Comptime] [OnCompile(.TypeInit), Comptime]
public static void Generate() public static void Generate()