diff --git a/IDEHelper/Compiler/BfContext.cpp b/IDEHelper/Compiler/BfContext.cpp index 2e9dfc4b..102675e7 100644 --- a/IDEHelper/Compiler/BfContext.cpp +++ b/IDEHelper/Compiler/BfContext.cpp @@ -838,7 +838,7 @@ void BfContext::RebuildType(BfType* type, bool deleteOnDemandTypes, bool rebuild { return; } - + type->mDirty = true; bool wantDeleteType = (type->IsOnDemand()) && (deleteOnDemandTypes); @@ -870,6 +870,8 @@ void BfContext::RebuildType(BfType* type, bool deleteOnDemandTypes, bool rebuild return; } + BF_ASSERT_REL(typeInst->mDefineState != BfTypeDefineState_DefinedAndMethodsSlotting); + // We need to verify lookups before we rebuild the type, because a type lookup change needs to count as a TypeDataChanged VerifyTypeLookups(typeInst); diff --git a/IDEHelper/Compiler/BfIRBuilder.cpp b/IDEHelper/Compiler/BfIRBuilder.cpp index 484b613e..39c6b638 100644 --- a/IDEHelper/Compiler/BfIRBuilder.cpp +++ b/IDEHelper/Compiler/BfIRBuilder.cpp @@ -3604,7 +3604,15 @@ void BfIRBuilder::CreateTypeDefinition(BfType* type, bool forceDbgDefine) // isDefiningModule = true; if ((isDefiningModule) || (type->IsValueType())) - populateModule->PopulateType(type, BfPopulateType_DataAndMethods); + { + if ((typeInstance != NULL) && (typeInstance->mDefineState == BfTypeDefineState_DefinedAndMethodsSlotting)) + { + // Don't re-enter + BfLogSys(mModule->mSystem, "BfIRBuilder::CreateTypeDefinition avoided PopulateType BfPopulateType_DataAndMethods re-entry typeInst: %p\n", typeInstance); + } + else + populateModule->PopulateType(type, BfPopulateType_DataAndMethods); + } if ((!isDefiningModule) && (!type->IsUnspecializedType()) && (type->IsValueType()) && (mHasDebugInfo)) { diff --git a/IDEHelper/Compiler/BfModule.cpp b/IDEHelper/Compiler/BfModule.cpp index ddba0956..190f3ff9 100644 --- a/IDEHelper/Compiler/BfModule.cpp +++ b/IDEHelper/Compiler/BfModule.cpp @@ -11079,8 +11079,10 @@ void BfModule::GetCustomAttributes(BfCustomAttributes* customAttributes, BfAttri BfTypeInstance* attrTypeInst = NULL; if (attrType == NULL) continue; - mContext->mUnreifiedModule->PopulateType(attrType, BfPopulateType_DataAndMethods); attrTypeInst = attrType->ToTypeInstance(); + if ((attrTypeInst != NULL) && (attrTypeInst->mDefineState != BfTypeDefineState_DefinedAndMethodsSlotting)) + mContext->mUnreifiedModule->PopulateType(attrType, BfPopulateType_DataAndMethods); + if ((attrTypeInst == NULL) || (!TypeIsSubTypeOf(attrTypeInst, baseAttrTypeInst)) || (attrTypeInst->mAttributeData == NULL)) { Fail(StrFormat("'%s' is not an attribute class", TypeToString(attrType).c_str()), attributesDirective->mAttributeTypeRef); //CS0616 @@ -16315,8 +16317,8 @@ void BfModule::SetupIRMethod(BfMethodInstance* methodInstance, BfIRFunction func addDeref = resolvedTypeRef->mSize; } else if ((methodInstance->WantsStructsAttribByVal()) && (!resolvedTypeRef->IsSizedArray())) - { - mBfIRBuilder->PopulateType(resolvedTypeRef); + { + mBfIRBuilder->PopulateType(resolvedTypeRef, BfIRPopulateType_Full); BF_ASSERT(resolvedTypeRef->mAlign > 0); mBfIRBuilder->Func_AddAttribute(func, argIdx + 1, BfIRAttribute_ByVal, mSystem->mPtrSize); } @@ -23546,7 +23548,7 @@ bool BfModule::SlotVirtualMethod(BfMethodInstance* methodInstance, BfAmbiguityCo } } } - + if (doesMethodSignatureMatch) { usedMethod = true; @@ -23587,15 +23589,15 @@ bool BfModule::SlotVirtualMethod(BfMethodInstance* methodInstance, BfAmbiguityCo storeIFaceMethod = isBetter; } } - } - + } + if (storeIFaceMethod) { if (methodInstance->GetNumGenericParams() != 0) _AddVirtualDecl(iMethodInst); *iMethodPtr = methodInstance; } - + checkMethodDef = checkMethodDef->mNextWithSameName; } diff --git a/IDEHelper/Compiler/BfModuleTypeUtils.cpp b/IDEHelper/Compiler/BfModuleTypeUtils.cpp index 103e870c..73af5357 100644 --- a/IDEHelper/Compiler/BfModuleTypeUtils.cpp +++ b/IDEHelper/Compiler/BfModuleTypeUtils.cpp @@ -4426,7 +4426,9 @@ void BfModule::DoPopulateType(BfType* resolvedTypeRef, BfPopulateType populateTy CheckAddFailType(); - BfLogSysM("Setting mNeedsMethodProcessing on %p\n", typeInstance); + BF_ASSERT_REL(typeInstance->mDefineState != BfTypeDefineState_DefinedAndMethodsSlotting); + + BfLogSysM("Setting mNeedsMethodProcessing=true on %p\n", typeInstance); typeInstance->mNeedsMethodProcessing = true; typeInstance->mIsFinishingType = false; @@ -4830,7 +4832,17 @@ void BfModule::DoTypeInstanceMethodProcessing(BfTypeInstance* typeInstance) { if (typeInstance->IsSpecializedByAutoCompleteMethod()) return; - + + if (typeInstance->mDefineState == BfTypeDefineState_DefinedAndMethodsSlotting) + { + BfLogSysM("DoTypeInstanceMethodProcessing %p re-entrancy exit\n", typeInstance); + return; + } + + BF_ASSERT_REL(typeInstance->mNeedsMethodProcessing); + BF_ASSERT_REL(typeInstance->mDefineState == BfTypeDefineState_Defined); + typeInstance->mDefineState = BfTypeDefineState_DefinedAndMethodsSlotting; + BF_ASSERT(typeInstance->mModule == this); //TODO: This is new, make sure this is in the right place @@ -4839,9 +4851,9 @@ void BfModule::DoTypeInstanceMethodProcessing(BfTypeInstance* typeInstance) AutoDisallowYield disableYield(mSystem); SetAndRestoreValue prevTypeInstance(mCurTypeInstance, typeInstance); - SetAndRestoreValue prevMethodInstance(mCurMethodInstance, NULL); + SetAndRestoreValue prevMethodInstance(mCurMethodInstance, NULL); - BfLogSysM("DoTypeInstanceMethodProcessing: %p %s Revision:%d\n", typeInstance, TypeToString(typeInstance).c_str(), typeInstance->mRevision); + BfLogSysM("DoTypeInstanceMethodProcessing: %p %s Revision:%d DefineState:%d\n", typeInstance, TypeToString(typeInstance).c_str(), typeInstance->mRevision, typeInstance->mDefineState); auto typeDef = typeInstance->mTypeDef; @@ -4929,7 +4941,7 @@ void BfModule::DoTypeInstanceMethodProcessing(BfTypeInstance* typeInstance) // Reserve empty entries for (int methodIdx = 0; methodIdx < (int)interfaceTypeDef->mMethods.size(); methodIdx++) - typeInstance->mInterfaceMethodTable.push_back(BfTypeInterfaceMethodEntry()); + typeInstance->mInterfaceMethodTable.push_back(BfTypeInterfaceMethodEntry()); } } @@ -5288,6 +5300,7 @@ void BfModule::DoTypeInstanceMethodProcessing(BfTypeInstance* typeInstance) } } + BF_ASSERT_REL(typeInstance->mDefineState < BfTypeDefineState_DefinedAndMethodsSlotted); BfLogSysM("Starting DoTypeInstanceMethodProcessing %p GetMethodInstance pass. OnDemandMethods: %d\n", typeInstance, mOnDemandMethodCount); // Def passes. First non-overrides then overrides (for in-place overrides in methods) @@ -5721,7 +5734,8 @@ void BfModule::DoTypeInstanceMethodProcessing(BfTypeInstance* typeInstance) auto checkIFaceMethodInst = checkIFaceInst->mMethodInstanceGroups[checkIMethodIdx].mDefault; if ((checkIFaceMethodInst != NULL) && (checkIFaceMethodInst->mMethodDef->mIsOverride)) { - if (CompareMethodSignatures(checkIFaceMethodInst, ifaceMethodInst)) + bool cmpResult = CompareMethodSignatures(checkIFaceMethodInst, ifaceMethodInst); + if (cmpResult) { bool isBetter = TypeIsSubTypeOf(checkIFaceInst, bestInterface); bool isWorse = TypeIsSubTypeOf(bestInterface, checkIFaceInst); @@ -5819,6 +5833,8 @@ void BfModule::DoTypeInstanceMethodProcessing(BfTypeInstance* typeInstance) methodString = MethodToString(ifaceMethodInst); } + OutputDebugStrF("Failed in %s %p\n", mModuleName.c_str(), this); + BfTypeDeclaration* typeDecl = declTypeDef->mTypeDeclaration; BfError* error = Fail(StrFormat("'%s' does not implement interface member '%s'", TypeToString(typeInstance).c_str(), methodString.c_str()), typeDecl->mNameNode, true); if ((matchedMethod != NULL) && (error != NULL)) @@ -5880,7 +5896,9 @@ void BfModule::DoTypeInstanceMethodProcessing(BfTypeInstance* typeInstance) mCompiler->mStats.mTypesPopulated++; mCompiler->UpdateCompletion(); - BfLogSysM("Finished DoTypeInstanceMethodProcessing %p. OnDemandMethods: %d Virtual Size: %d\n", typeInstance, mOnDemandMethodCount, typeInstance->mVirtualMethodTable.size()); + BF_ASSERT_REL(!typeInstance->mNeedsMethodProcessing); + + BfLogSysM("Finished DoTypeInstanceMethodProcessing %p. OnDemandMethods: %d Virtual Size: %d InterfaceMethodTableSize: %d\n", typeInstance, mOnDemandMethodCount, typeInstance->mVirtualMethodTable.size(), typeInstance->mInterfaceMethodTable.size()); } void BfModule::RebuildMethods(BfTypeInstance* typeInstance) @@ -5888,6 +5906,9 @@ void BfModule::RebuildMethods(BfTypeInstance* typeInstance) if (typeInstance->IsIncomplete()) return; + BfLogSysM("RebuildMethods setting mNeedsMethodProcessing=true on %p\n", typeInstance); + + BF_ASSERT_REL(typeInstance->mDefineState != BfTypeDefineState_DefinedAndMethodsSlotting); typeInstance->mNeedsMethodProcessing = true; typeInstance->mDefineState = BfTypeDefineState_Defined; typeInstance->mTypeIncomplete = true; diff --git a/IDEHelper/Compiler/BfResolvedTypeUtils.h b/IDEHelper/Compiler/BfResolvedTypeUtils.h index 9020d3d1..77e6cf5f 100644 --- a/IDEHelper/Compiler/BfResolvedTypeUtils.h +++ b/IDEHelper/Compiler/BfResolvedTypeUtils.h @@ -436,6 +436,7 @@ enum BfTypeDefineState : uint8 BfTypeDefineState_CEPostTypeInit, BfTypeDefineState_Defined, BfTypeDefineState_CEAfterFields, + BfTypeDefineState_DefinedAndMethodsSlotting, BfTypeDefineState_DefinedAndMethodsSlotted, }; diff --git a/IDEHelper/Compiler/BfSystem.cpp b/IDEHelper/Compiler/BfSystem.cpp index 731953f2..6bb003a3 100644 --- a/IDEHelper/Compiler/BfSystem.cpp +++ b/IDEHelper/Compiler/BfSystem.cpp @@ -13,6 +13,9 @@ #include "BeefySysLib/util/AllocDebug.h" +#define STB_SPRINTF_DECORATE(name) BF_stbsp_##name +#include "../../third_party/stb/stb_sprintf.h" + USING_NS_BF; using namespace llvm; @@ -64,11 +67,8 @@ void Beefy::DoBfLog(int fileIdx, const char* fmt ...) va_list argList; va_start(argList, fmt); -#ifdef _WIN32 - int numChars = _vsnprintf(lineStr + strOfs, maxChars, fmt, argList); -#else - int numChars = vsnprintf(lineStr+ strOfs, maxChars, fmt, argList); -#endif + + int numChars = BF_stbsp_vsnprintf(lineStr + strOfs, maxChars, fmt, argList); if (numChars <= maxChars) { if (strOfs + numChars > 0)