From cbc4888853db2e3b66c91b7fc2edb7040539f8ef Mon Sep 17 00:00:00 2001 From: Brian Fiete Date: Mon, 4 Jul 2022 10:21:31 -0700 Subject: [PATCH] Improvements to multi-extension virtual overrides --- IDEHelper/Backend/BeIRCodeGen.cpp | 8 ++++ IDEHelper/Compiler/BfCompiler.cpp | 52 +++++++++++++++++++++--- IDEHelper/Compiler/BfExprEvaluator.cpp | 4 +- IDEHelper/Compiler/BfIRBuilder.cpp | 6 +++ IDEHelper/Compiler/BfIRBuilder.h | 2 + IDEHelper/Compiler/BfIRCodeGen.cpp | 8 ++++ IDEHelper/Compiler/BfModule.cpp | 44 ++++++++++++++++---- IDEHelper/Compiler/BfModule.h | 2 +- IDEHelper/Compiler/BfModuleTypeUtils.cpp | 2 +- 9 files changed, 109 insertions(+), 19 deletions(-) diff --git a/IDEHelper/Backend/BeIRCodeGen.cpp b/IDEHelper/Backend/BeIRCodeGen.cpp index 5dc6dca1..7d4ee7d7 100644 --- a/IDEHelper/Backend/BeIRCodeGen.cpp +++ b/IDEHelper/Backend/BeIRCodeGen.cpp @@ -2647,6 +2647,14 @@ void BeIRCodeGen::HandleNextCmd() func->mName += StrFormat("__RENAME%d", curId); } break; + case BfIRCmd_Func_SafeRenameFrom: + { + CMD_PARAM(BeFunction*, func); + CMD_PARAM(String, prevName); + if (func->mName == prevName) + func->mName += StrFormat("__RENAME%d", curId); + } + break; case BfIRCmd_Func_SetLinkage: { CMD_PARAM(BeFunction*, func); diff --git a/IDEHelper/Compiler/BfCompiler.cpp b/IDEHelper/Compiler/BfCompiler.cpp index a25743a4..074e4863 100644 --- a/IDEHelper/Compiler/BfCompiler.cpp +++ b/IDEHelper/Compiler/BfCompiler.cpp @@ -5827,13 +5827,53 @@ void BfCompiler::PopulateReified() if ((declaringMethod->mIsReified) && (declaringMethod->mMethodInstanceGroup->IsImplemented())) { - BfMethodInstance* implMethod = vEntry.mImplementingMethod; - if ((implMethod != NULL) && ((!implMethod->mMethodInstanceGroup->IsImplemented()) || (!implMethod->mIsReified))) + if (vEntry.mImplementingMethod.mKind == BfMethodRefKind_AmbiguousRef) { - didWork = true; - if (!typeInst->mModule->mIsModuleMutable) - typeInst->mModule->StartExtension(); - typeInst->mModule->GetMethodInstance(implMethod); + auto checkTypeInst = typeInst; + + while (checkTypeInst != NULL) + { + BfMemberSetEntry* memberSetEntry; + if (checkTypeInst->mTypeDef->mMethodSet.TryGetWith(String(declaringMethod->mMethodDef->mName), &memberSetEntry)) + { + BfMethodDef* methodDef = (BfMethodDef*)memberSetEntry->mMemberDef; + while (methodDef != NULL) + { + if ((methodDef->mIsOverride) && (methodDef->mParams.mSize == declaringMethod->mMethodDef->mParams.mSize)) + { + auto implMethod = typeInst->mModule->GetRawMethodInstance(typeInst, methodDef); + if (typeInst->mModule->CompareMethodSignatures(declaringMethod, implMethod)) + { + if ((implMethod != NULL) && ((!implMethod->mMethodInstanceGroup->IsImplemented()) || (!implMethod->mIsReified))) + { + didWork = true; + if (!typeInst->mModule->mIsModuleMutable) + typeInst->mModule->StartExtension(); + typeInst->mModule->GetMethodInstance(implMethod); + } + } + } + + methodDef = methodDef->mNextWithSameName; + } + } + + if (checkTypeInst == declaringMethod->GetOwner()) + break; + + checkTypeInst = checkTypeInst->mBaseType; + } + } + else + { + BfMethodInstance* implMethod = vEntry.mImplementingMethod; + if ((implMethod != NULL) && ((!implMethod->mMethodInstanceGroup->IsImplemented()) || (!implMethod->mIsReified))) + { + didWork = true; + if (!typeInst->mModule->mIsModuleMutable) + typeInst->mModule->StartExtension(); + typeInst->mModule->GetMethodInstance(implMethod); + } } } } diff --git a/IDEHelper/Compiler/BfExprEvaluator.cpp b/IDEHelper/Compiler/BfExprEvaluator.cpp index d39dd5c8..b8687600 100644 --- a/IDEHelper/Compiler/BfExprEvaluator.cpp +++ b/IDEHelper/Compiler/BfExprEvaluator.cpp @@ -2928,7 +2928,7 @@ void BfMethodMatcher::TryDevirtualizeCall(BfTypedValue target, BfTypedValue* ori bool isBetter; bool isWorse; - mModule->CompareDeclTypes(iface.mDeclaringType, bestIFaceEntry->mDeclaringType, isBetter, isWorse); + mModule->CompareDeclTypes(NULL, iface.mDeclaringType, bestIFaceEntry->mDeclaringType, isBetter, isWorse); if (isBetter == isWorse) { // Failed @@ -18669,7 +18669,7 @@ BfModuleMethodInstance BfExprEvaluator::GetPropertyMethodInstance(BfMethodDef* m bool isBetter; bool isWorse; - mModule->CompareDeclTypes(iface.mDeclaringType, bestIFaceEntry->mDeclaringType, isBetter, isWorse); + mModule->CompareDeclTypes(NULL, iface.mDeclaringType, bestIFaceEntry->mDeclaringType, isBetter, isWorse); if (isBetter == isWorse) { // Failed diff --git a/IDEHelper/Compiler/BfIRBuilder.cpp b/IDEHelper/Compiler/BfIRBuilder.cpp index 07806541..cdcc9465 100644 --- a/IDEHelper/Compiler/BfIRBuilder.cpp +++ b/IDEHelper/Compiler/BfIRBuilder.cpp @@ -5547,6 +5547,12 @@ void BfIRBuilder::Func_SafeRename(BfIRFunction func) NEW_CMD_INSERTED; } +void BfIRBuilder::Func_SafeRenameFrom(BfIRFunction func, const StringImpl& prevName) +{ + WriteCmd(BfIRCmd_Func_SafeRenameFrom, func, prevName); + NEW_CMD_INSERTED; +} + void BfIRBuilder::Func_SetLinkage(BfIRFunction func, BfIRLinkageType linkage) { WriteCmd(BfIRCmd_Func_SetLinkage, func, (uint8)linkage); diff --git a/IDEHelper/Compiler/BfIRBuilder.h b/IDEHelper/Compiler/BfIRBuilder.h index b8db716f..b634b692 100644 --- a/IDEHelper/Compiler/BfIRBuilder.h +++ b/IDEHelper/Compiler/BfIRBuilder.h @@ -299,6 +299,7 @@ enum BfIRCmd : uint8 BfIRCmd_Func_SetParamName, BfIRCmd_Func_DeleteBody, BfIRCmd_Func_SafeRename, + BfIRCmd_Func_SafeRenameFrom, BfIRCmd_Func_SetLinkage, BfIRCmd_Comptime_Error, @@ -1336,6 +1337,7 @@ public: void Func_SetParamName(BfIRFunction func, int argIdx, const StringImpl& name); void Func_DeleteBody(BfIRFunction func); void Func_SafeRename(BfIRFunction func); + void Func_SafeRenameFrom(BfIRFunction func, const StringImpl& prevName); void Func_SetLinkage(BfIRFunction func, BfIRLinkageType linkage); void Comptime_Error(int errorKind); diff --git a/IDEHelper/Compiler/BfIRCodeGen.cpp b/IDEHelper/Compiler/BfIRCodeGen.cpp index 0755fd9c..a7784802 100644 --- a/IDEHelper/Compiler/BfIRCodeGen.cpp +++ b/IDEHelper/Compiler/BfIRCodeGen.cpp @@ -3997,6 +3997,14 @@ void BfIRCodeGen::HandleNextCmd() func->setName(llvm::Twine((Beefy::String(func->getName().data()) + StrFormat("__RENAME%d", curId)).c_str())); } break; + case BfIRCmd_Func_SafeRenameFrom: + { + CMD_PARAM(llvm::Function*, func); + CMD_PARAM(String, prevName); + if (String(func->getName().data()) == prevName) + func->setName(llvm::Twine((Beefy::String(func->getName().data()) + StrFormat("__RENAME%d", curId)).c_str())); + } + break; case BfIRCmd_Func_SetLinkage: { CMD_PARAM(llvm::Function*, func); diff --git a/IDEHelper/Compiler/BfModule.cpp b/IDEHelper/Compiler/BfModule.cpp index 0524ae44..42726396 100644 --- a/IDEHelper/Compiler/BfModule.cpp +++ b/IDEHelper/Compiler/BfModule.cpp @@ -6283,7 +6283,7 @@ BfIRValue BfModule::CreateTypeData(BfType* type, Dictionary& usedStrin isWorse = false; } if (isBetter == isWorse) - CompareDeclTypes(interfaceEntry.mDeclaringType, prevEntry->mDeclaringType, isBetter, isWorse); + CompareDeclTypes(checkTypeInst, interfaceEntry.mDeclaringType, prevEntry->mDeclaringType, isBetter, isWorse); if (isBetter == isWorse) { if (matchEntry->mAmbiguousEntries.empty()) @@ -18675,7 +18675,7 @@ void BfModule::CallChainedMethods(BfMethodInstance* methodInstance, bool reverse { bool isBetter; bool isWorse; - CompareDeclTypes(lhs->mMethodDef->mDeclaringType, rhs->mMethodDef->mDeclaringType, isBetter, isWorse); + CompareDeclTypes(mCurTypeInstance, lhs->mMethodDef->mDeclaringType, rhs->mMethodDef->mDeclaringType, isBetter, isWorse); if (isBetter == isWorse) { return false; @@ -22975,7 +22975,7 @@ void BfModule::SetupIRFunction(BfMethodInstance* methodInstance, StringImpl& man { BfLogSysM("Function collision from inner override erased prevFunc %p: %d\n", methodInstance, prevFunc.mId); if (!mIsComptimeModule) - mBfIRBuilder->Func_SafeRename(prevFunc); + mBfIRBuilder->Func_SafeRenameFrom(prevFunc, mangledName); } } else if (methodDef->mIsExtern) @@ -23000,7 +23000,7 @@ void BfModule::SetupIRFunction(BfMethodInstance* methodInstance, StringImpl& man { BfLogSysM("Function collision erased prevFunc %p: %d\n", methodInstance, prevFunc.mId); if (!mIsComptimeModule) - mBfIRBuilder->Func_SafeRename(prevFunc); + mBfIRBuilder->Func_SafeRenameFrom(prevFunc, mangledName); } } } @@ -24387,7 +24387,7 @@ void BfModule::DoMethodDeclaration(BfMethodDeclaration* methodDeclaration, bool { bool isBetter; bool isWorse; - CompareDeclTypes(checkMethodInstance->mMethodDef->mDeclaringType, methodInstance->mMethodDef->mDeclaringType, isBetter, isWorse); + CompareDeclTypes(typeInstance, checkMethodInstance->mMethodDef->mDeclaringType, methodInstance->mMethodDef->mDeclaringType, isBetter, isWorse); if (isBetter && !isWorse) { methodInstance->mChainType = BfMethodChainType_ChainHead; @@ -24634,7 +24634,7 @@ void BfModule::UniqueSlotVirtualMethod(BfMethodInstance* methodInstance) } } -void BfModule::CompareDeclTypes(BfTypeDef* newDeclType, BfTypeDef* prevDeclType, bool& isBetter, bool& isWorse) +void BfModule::CompareDeclTypes(BfTypeInstance* typeInst, BfTypeDef* newDeclType, BfTypeDef* prevDeclType, bool& isBetter, bool& isWorse) { if ((!prevDeclType->IsExtension()) && (newDeclType->IsExtension())) { @@ -24646,7 +24646,33 @@ void BfModule::CompareDeclTypes(BfTypeDef* newDeclType, BfTypeDef* prevDeclType, { isBetter = newDeclType->mProject->ContainsReference(prevDeclType->mProject); isWorse = prevDeclType->mProject->ContainsReference(newDeclType->mProject); - } + } + + if ((isBetter == isWorse) && (typeInst != NULL) && (newDeclType->IsExtension()) && (prevDeclType->IsExtension())) + { + if ((typeInst->mGenericTypeInfo != NULL) && (typeInst->mGenericTypeInfo->mGenericExtensionInfo != NULL)) + { + isBetter = false; + isWorse = false; + + auto newConstraints = typeInst->GetGenericParamsVector(newDeclType); + auto prevConstraints = typeInst->GetGenericParamsVector(prevDeclType); + + for (int genericIdx = 0; genericIdx < (int)newConstraints->size(); genericIdx++) + { + auto newConstraint = (*newConstraints)[genericIdx]; + auto prevConstraint = (*prevConstraints)[genericIdx]; + + bool newIsSubset = AreConstraintsSubset(newConstraint, prevConstraint); + bool prevIsSubset = AreConstraintsSubset(prevConstraint, newConstraint); + + if ((prevIsSubset) && (!newIsSubset)) + isBetter = true; + if ((!prevIsSubset) && (newIsSubset)) + isWorse = true; + } + } + } } bool BfModule::SlotVirtualMethod(BfMethodInstance* methodInstance, BfAmbiguityContext* ambiguityContext) @@ -25028,7 +25054,7 @@ bool BfModule::SlotVirtualMethod(BfMethodInstance* methodInstance, BfAmbiguityCo { bool isBetter = false; bool isWorse = false; - CompareDeclTypes(methodInstance->mMethodDef->mDeclaringType, methodOverriden->mMethodDef->mDeclaringType, isBetter, isWorse); + CompareDeclTypes(typeInstance, methodInstance->mMethodDef->mDeclaringType, methodOverriden->mMethodDef->mDeclaringType, isBetter, isWorse); if (isBetter == isWorse) { // We have to resolve later per-project @@ -25250,7 +25276,7 @@ bool BfModule::SlotVirtualMethod(BfMethodInstance* methodInstance, BfAmbiguityCo isBetter = (methodInstance->mMethodInfoEx != NULL) && (methodInstance->mMethodInfoEx->mExplicitInterface != NULL); isWorse = (prevMethod->mMethodInfoEx != NULL) && (prevMethod->mMethodInfoEx->mExplicitInterface != NULL); if (isBetter == isWorse) - CompareDeclTypes(methodInstance->mMethodDef->mDeclaringType, prevMethod->mMethodDef->mDeclaringType, isBetter, isWorse); + CompareDeclTypes(typeInstance, methodInstance->mMethodDef->mDeclaringType, prevMethod->mMethodDef->mDeclaringType, isBetter, isWorse); if (isBetter == isWorse) { if (ambiguityContext != NULL) diff --git a/IDEHelper/Compiler/BfModule.h b/IDEHelper/Compiler/BfModule.h index f18221aa..c13606d4 100644 --- a/IDEHelper/Compiler/BfModule.h +++ b/IDEHelper/Compiler/BfModule.h @@ -2027,7 +2027,7 @@ public: bool StrictCompareMethodSignatures(BfMethodInstance* methodA, BfMethodInstance* methodB); // Compares return types and static bool IsCompatibleInterfaceMethod(BfMethodInstance* methodA, BfMethodInstance* methodB); void UniqueSlotVirtualMethod(BfMethodInstance* methodInstance); - void CompareDeclTypes(BfTypeDef* newDeclType, BfTypeDef* prevDeclType, bool& isBetter, bool& isWorse); + void CompareDeclTypes(BfTypeInstance* typeInst, BfTypeDef* newDeclType, BfTypeDef* prevDeclType, bool& isBetter, bool& isWorse); bool SlotVirtualMethod(BfMethodInstance* methodInstance, BfAmbiguityContext* ambiguityContext = NULL); void CheckOverridenMethod(BfMethodInstance* methodInstance, BfMethodInstance* methodOverriden); bool SlotInterfaceMethod(BfMethodInstance* methodInstance); diff --git a/IDEHelper/Compiler/BfModuleTypeUtils.cpp b/IDEHelper/Compiler/BfModuleTypeUtils.cpp index 9732ffb2..c08c7534 100644 --- a/IDEHelper/Compiler/BfModuleTypeUtils.cpp +++ b/IDEHelper/Compiler/BfModuleTypeUtils.cpp @@ -6786,7 +6786,7 @@ void BfModule::DoTypeInstanceMethodProcessing(BfTypeInstance* typeInstance) bool isWorse = TypeIsSubTypeOf(bestInterface, checkIFaceInst); if (isBetter == isWorse) { - CompareDeclTypes(checkIFaceMethodInst->mMethodDef->mDeclaringType, bestMethodInst->mMethodDef->mDeclaringType, isBetter, isWorse); + CompareDeclTypes(NULL, checkIFaceMethodInst->mMethodDef->mDeclaringType, bestMethodInst->mMethodDef->mDeclaringType, isBetter, isWorse); } if ((isBetter) && (!isWorse)) {