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

Improvements to multi-extension virtual overrides

This commit is contained in:
Brian Fiete 2022-07-04 10:21:31 -07:00
parent a27ef9beda
commit cbc4888853
9 changed files with 109 additions and 19 deletions

View file

@ -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);

View file

@ -5826,6 +5826,45 @@ void BfCompiler::PopulateReified()
continue;
if ((declaringMethod->mIsReified) && (declaringMethod->mMethodInstanceGroup->IsImplemented()))
{
if (vEntry.mImplementingMethod.mKind == BfMethodRefKind_AmbiguousRef)
{
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)))
@ -5837,6 +5876,7 @@ void BfCompiler::PopulateReified()
}
}
}
}
auto checkType = typeInst;
while (checkType != NULL)

View file

@ -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

View file

@ -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);

View file

@ -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);

View file

@ -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);

View file

@ -6283,7 +6283,7 @@ BfIRValue BfModule::CreateTypeData(BfType* type, Dictionary<int, int>& 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()))
{
@ -24647,6 +24647,32 @@ 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)

View file

@ -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);

View file

@ -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))
{