diff --git a/IDEHelper/Compiler/BfCompiler.cpp b/IDEHelper/Compiler/BfCompiler.cpp index 7a40decb..e7c3362d 100644 --- a/IDEHelper/Compiler/BfCompiler.cpp +++ b/IDEHelper/Compiler/BfCompiler.cpp @@ -355,6 +355,7 @@ BfCompiler::BfCompiler(BfSystem* bfSystem, bool isResolveOnly) mHasRequiredTypes = false; mNeedsFullRefresh = false; mFastFinish = false; + mExtraCompileRequested = false; mHasQueuedTypeRebuilds = false; mIsResolveOnly = isResolveOnly; mResolvePassData = NULL; @@ -7182,6 +7183,7 @@ bool BfCompiler::DoCompile(const StringImpl& outputDirectory) mOutputDirectory = outputDirectory; mSystem->StartYieldSection(); + mExtraCompileRequested = false; mFastFinish = false; mHasQueuedTypeRebuilds = false; mCanceling = false; @@ -8082,7 +8084,23 @@ bool BfCompiler::DoCompile(const StringImpl& outputDirectory) bool BfCompiler::Compile(const StringImpl& outputDirectory) { - bool success = DoCompile(outputDirectory); + int passIdx = 0; + bool success = false; + while (true) + { + auto passState = mPassInstance->GetState(); + + success = DoCompile(outputDirectory); + if (!mExtraCompileRequested) + break; + + mPassInstance->RestoreState(passState); + + if (passIdx == 1) + break; + passIdx++; + } + if (!success) return false; if (mPassInstance->HasFailed()) @@ -8132,6 +8150,11 @@ void BfCompiler::RequestFastFinish() BpEvent("BfCompiler::RequestFastFinish", ""); } +void BfCompiler::RequestExtraCompile() +{ + mExtraCompileRequested = true; +} + //#define WANT_COMPILE_LOG void BfCompiler::CompileLog(const char* fmt ...) diff --git a/IDEHelper/Compiler/BfCompiler.h b/IDEHelper/Compiler/BfCompiler.h index dada8f41..a4d30622 100644 --- a/IDEHelper/Compiler/BfCompiler.h +++ b/IDEHelper/Compiler/BfCompiler.h @@ -334,6 +334,7 @@ public: bool mHasRequiredTypes; bool mNeedsFullRefresh; bool mFastFinish; + bool mExtraCompileRequested; bool mHasQueuedTypeRebuilds; // Infers we had a fast finish that requires a type rebuild bool mHadCancel; bool mWantsDeferMethodDecls; @@ -545,6 +546,7 @@ public: void GetSymbolReferences(); void Cancel(); void RequestFastFinish(); + void RequestExtraCompile(); String GetTypeDefList(bool includeLocation); String GetGeneratorString(BfTypeDef* typeDef, BfTypeInstance* typeInst, const StringImpl& generatorMethodName, const StringImpl* args); void HandleGeneratorErrors(StringImpl& result); diff --git a/IDEHelper/Compiler/BfExprEvaluator.cpp b/IDEHelper/Compiler/BfExprEvaluator.cpp index b92aac05..ef1924aa 100644 --- a/IDEHelper/Compiler/BfExprEvaluator.cpp +++ b/IDEHelper/Compiler/BfExprEvaluator.cpp @@ -5646,6 +5646,7 @@ BfTypedValue BfExprEvaluator::LoadField(BfAstNode* targetSrc, BfTypedValue targe if (fieldInstance->mDataIdx < 0) { + mModule->mCompiler->RequestExtraCompile(); mModule->InternalError("LoadField field DataIdx<0 where InstSize>0"); mModule->DeferRebuildType(typeInstance); return mModule->GetDefaultTypedValue(resolvedFieldType); diff --git a/IDEHelper/Compiler/BfModule.cpp b/IDEHelper/Compiler/BfModule.cpp index 98310d3f..e45bf759 100644 --- a/IDEHelper/Compiler/BfModule.cpp +++ b/IDEHelper/Compiler/BfModule.cpp @@ -4730,6 +4730,7 @@ BfTypedValue BfModule::GetFieldInitializerValue(BfFieldInstance* fieldInstance, if (fieldType->IsDeleting()) { + mCompiler->RequestExtraCompile(); InternalError("Field using deleted type", fieldDef->GetRefNode()); } else if (fieldType->IsVar()) @@ -11264,6 +11265,7 @@ BfMethodInstance* BfModule::GetRawMethodInstanceAtIdx(BfTypeInstance* typeInstan { if (typeInstance->IsDeleting()) { + mCompiler->RequestExtraCompile(); InternalError("GetRawMethodInstanceAtIdx for deleted type", typeInstance->mTypeDef->GetRefNode()); return NULL; } @@ -20301,6 +20303,13 @@ void BfModule::EmitGCMarkValue(BfTypedValue& thisValue, BfType* checkType, int m if (!checkType->WantsGCMarking()) return; + if (checkType->IsDeleting()) + { + mCompiler->RequestExtraCompile(); + InternalError("EmitGCMarkValue deleted type"); + return; + } + auto typeInstance = checkType->ToTypeInstance(); bool callMarkMethod = false; diff --git a/IDEHelper/Compiler/BfSystem.cpp b/IDEHelper/Compiler/BfSystem.cpp index 9dbe5c53..2e7c6ec9 100644 --- a/IDEHelper/Compiler/BfSystem.cpp +++ b/IDEHelper/Compiler/BfSystem.cpp @@ -1223,6 +1223,37 @@ BfPassInstance::~BfPassInstance() delete bfError; } +BfPassInstance::StateInfo BfPassInstance::GetState() +{ + StateInfo stateInfo; + stateInfo.mOutStreamSize = (int)mOutStream.mSize; + stateInfo.mErrorsSize = mErrors.mSize; + stateInfo.mWarningCount = mWarningCount; + stateInfo.mDeferredErrorCount = mDeferredErrorCount; + stateInfo.mFailedIdx = mFailedIdx; + stateInfo.mWarnIdx = mWarnIdx; + return stateInfo; +} + +void BfPassInstance::RestoreState(StateInfo stateInfo) +{ + while (mOutStream.mSize > stateInfo.mOutStreamSize) + mOutStream.pop_back(); + + while (mErrors.mSize > stateInfo.mErrorsSize) + { + auto error = mErrors.back(); + mErrors.pop_back(); + mErrorSet.Remove(error); + delete error; + } + + mWarningCount = stateInfo.mWarningCount; + mDeferredErrorCount = stateInfo.mDeferredErrorCount; + mFailedIdx = stateInfo.mFailedIdx; + mWarnIdx = stateInfo.mWarnIdx; +} + void BfPassInstance::ClearErrors() { mFailedIdx = 0; diff --git a/IDEHelper/Compiler/BfSystem.h b/IDEHelper/Compiler/BfSystem.h index eefbe3ba..df0ea772 100644 --- a/IDEHelper/Compiler/BfSystem.h +++ b/IDEHelper/Compiler/BfSystem.h @@ -1594,6 +1594,17 @@ public: class BfPassInstance { +public: + struct StateInfo + { + int mOutStreamSize; + int mErrorsSize; + int mWarningCount; + int mDeferredErrorCount; + int mFailedIdx; + int mWarnIdx; + }; + public: const int sMaxDisplayErrors = 100; const int sMaxErrors = 1000; @@ -1636,6 +1647,9 @@ public: ~BfPassInstance(); + StateInfo GetState(); + void RestoreState(StateInfo stateInfo); + void ClearErrors(); bool HasFailed(); bool HasMessages();