1
0
Fork 0
mirror of https://github.com/beefytech/Beef.git synced 2025-06-08 11:38:21 +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); func->mName += StrFormat("__RENAME%d", curId);
} }
break; 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: case BfIRCmd_Func_SetLinkage:
{ {
CMD_PARAM(BeFunction*, func); CMD_PARAM(BeFunction*, func);

View file

@ -5827,13 +5827,53 @@ void BfCompiler::PopulateReified()
if ((declaringMethod->mIsReified) && (declaringMethod->mMethodInstanceGroup->IsImplemented())) if ((declaringMethod->mIsReified) && (declaringMethod->mMethodInstanceGroup->IsImplemented()))
{ {
BfMethodInstance* implMethod = vEntry.mImplementingMethod; if (vEntry.mImplementingMethod.mKind == BfMethodRefKind_AmbiguousRef)
if ((implMethod != NULL) && ((!implMethod->mMethodInstanceGroup->IsImplemented()) || (!implMethod->mIsReified)))
{ {
didWork = true; auto checkTypeInst = typeInst;
if (!typeInst->mModule->mIsModuleMutable)
typeInst->mModule->StartExtension(); while (checkTypeInst != NULL)
typeInst->mModule->GetMethodInstance(implMethod); {
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);
}
} }
} }
} }

View file

@ -2928,7 +2928,7 @@ void BfMethodMatcher::TryDevirtualizeCall(BfTypedValue target, BfTypedValue* ori
bool isBetter; bool isBetter;
bool isWorse; bool isWorse;
mModule->CompareDeclTypes(iface.mDeclaringType, bestIFaceEntry->mDeclaringType, isBetter, isWorse); mModule->CompareDeclTypes(NULL, iface.mDeclaringType, bestIFaceEntry->mDeclaringType, isBetter, isWorse);
if (isBetter == isWorse) if (isBetter == isWorse)
{ {
// Failed // Failed
@ -18669,7 +18669,7 @@ BfModuleMethodInstance BfExprEvaluator::GetPropertyMethodInstance(BfMethodDef* m
bool isBetter; bool isBetter;
bool isWorse; bool isWorse;
mModule->CompareDeclTypes(iface.mDeclaringType, bestIFaceEntry->mDeclaringType, isBetter, isWorse); mModule->CompareDeclTypes(NULL, iface.mDeclaringType, bestIFaceEntry->mDeclaringType, isBetter, isWorse);
if (isBetter == isWorse) if (isBetter == isWorse)
{ {
// Failed // Failed

View file

@ -5547,6 +5547,12 @@ void BfIRBuilder::Func_SafeRename(BfIRFunction func)
NEW_CMD_INSERTED; 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) void BfIRBuilder::Func_SetLinkage(BfIRFunction func, BfIRLinkageType linkage)
{ {
WriteCmd(BfIRCmd_Func_SetLinkage, func, (uint8)linkage); WriteCmd(BfIRCmd_Func_SetLinkage, func, (uint8)linkage);

View file

@ -299,6 +299,7 @@ enum BfIRCmd : uint8
BfIRCmd_Func_SetParamName, BfIRCmd_Func_SetParamName,
BfIRCmd_Func_DeleteBody, BfIRCmd_Func_DeleteBody,
BfIRCmd_Func_SafeRename, BfIRCmd_Func_SafeRename,
BfIRCmd_Func_SafeRenameFrom,
BfIRCmd_Func_SetLinkage, BfIRCmd_Func_SetLinkage,
BfIRCmd_Comptime_Error, BfIRCmd_Comptime_Error,
@ -1336,6 +1337,7 @@ public:
void Func_SetParamName(BfIRFunction func, int argIdx, const StringImpl& name); void Func_SetParamName(BfIRFunction func, int argIdx, const StringImpl& name);
void Func_DeleteBody(BfIRFunction func); void Func_DeleteBody(BfIRFunction func);
void Func_SafeRename(BfIRFunction func); void Func_SafeRename(BfIRFunction func);
void Func_SafeRenameFrom(BfIRFunction func, const StringImpl& prevName);
void Func_SetLinkage(BfIRFunction func, BfIRLinkageType linkage); void Func_SetLinkage(BfIRFunction func, BfIRLinkageType linkage);
void Comptime_Error(int errorKind); 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())); func->setName(llvm::Twine((Beefy::String(func->getName().data()) + StrFormat("__RENAME%d", curId)).c_str()));
} }
break; 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: case BfIRCmd_Func_SetLinkage:
{ {
CMD_PARAM(llvm::Function*, func); CMD_PARAM(llvm::Function*, func);

View file

@ -6283,7 +6283,7 @@ BfIRValue BfModule::CreateTypeData(BfType* type, Dictionary<int, int>& usedStrin
isWorse = false; isWorse = false;
} }
if (isBetter == isWorse) if (isBetter == isWorse)
CompareDeclTypes(interfaceEntry.mDeclaringType, prevEntry->mDeclaringType, isBetter, isWorse); CompareDeclTypes(checkTypeInst, interfaceEntry.mDeclaringType, prevEntry->mDeclaringType, isBetter, isWorse);
if (isBetter == isWorse) if (isBetter == isWorse)
{ {
if (matchEntry->mAmbiguousEntries.empty()) if (matchEntry->mAmbiguousEntries.empty())
@ -18675,7 +18675,7 @@ void BfModule::CallChainedMethods(BfMethodInstance* methodInstance, bool reverse
{ {
bool isBetter; bool isBetter;
bool isWorse; bool isWorse;
CompareDeclTypes(lhs->mMethodDef->mDeclaringType, rhs->mMethodDef->mDeclaringType, isBetter, isWorse); CompareDeclTypes(mCurTypeInstance, lhs->mMethodDef->mDeclaringType, rhs->mMethodDef->mDeclaringType, isBetter, isWorse);
if (isBetter == isWorse) if (isBetter == isWorse)
{ {
return false; 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); BfLogSysM("Function collision from inner override erased prevFunc %p: %d\n", methodInstance, prevFunc.mId);
if (!mIsComptimeModule) if (!mIsComptimeModule)
mBfIRBuilder->Func_SafeRename(prevFunc); mBfIRBuilder->Func_SafeRenameFrom(prevFunc, mangledName);
} }
} }
else if (methodDef->mIsExtern) 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); BfLogSysM("Function collision erased prevFunc %p: %d\n", methodInstance, prevFunc.mId);
if (!mIsComptimeModule) if (!mIsComptimeModule)
mBfIRBuilder->Func_SafeRename(prevFunc); mBfIRBuilder->Func_SafeRenameFrom(prevFunc, mangledName);
} }
} }
} }
@ -24387,7 +24387,7 @@ void BfModule::DoMethodDeclaration(BfMethodDeclaration* methodDeclaration, bool
{ {
bool isBetter; bool isBetter;
bool isWorse; bool isWorse;
CompareDeclTypes(checkMethodInstance->mMethodDef->mDeclaringType, methodInstance->mMethodDef->mDeclaringType, isBetter, isWorse); CompareDeclTypes(typeInstance, checkMethodInstance->mMethodDef->mDeclaringType, methodInstance->mMethodDef->mDeclaringType, isBetter, isWorse);
if (isBetter && !isWorse) if (isBetter && !isWorse)
{ {
methodInstance->mChainType = BfMethodChainType_ChainHead; 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())) if ((!prevDeclType->IsExtension()) && (newDeclType->IsExtension()))
{ {
@ -24647,6 +24647,32 @@ void BfModule::CompareDeclTypes(BfTypeDef* newDeclType, BfTypeDef* prevDeclType,
isBetter = newDeclType->mProject->ContainsReference(prevDeclType->mProject); isBetter = newDeclType->mProject->ContainsReference(prevDeclType->mProject);
isWorse = prevDeclType->mProject->ContainsReference(newDeclType->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) bool BfModule::SlotVirtualMethod(BfMethodInstance* methodInstance, BfAmbiguityContext* ambiguityContext)
@ -25028,7 +25054,7 @@ bool BfModule::SlotVirtualMethod(BfMethodInstance* methodInstance, BfAmbiguityCo
{ {
bool isBetter = false; bool isBetter = false;
bool isWorse = 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) if (isBetter == isWorse)
{ {
// We have to resolve later per-project // 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); isBetter = (methodInstance->mMethodInfoEx != NULL) && (methodInstance->mMethodInfoEx->mExplicitInterface != NULL);
isWorse = (prevMethod->mMethodInfoEx != NULL) && (prevMethod->mMethodInfoEx->mExplicitInterface != NULL); isWorse = (prevMethod->mMethodInfoEx != NULL) && (prevMethod->mMethodInfoEx->mExplicitInterface != NULL);
if (isBetter == isWorse) 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 (isBetter == isWorse)
{ {
if (ambiguityContext != NULL) if (ambiguityContext != NULL)

View file

@ -2027,7 +2027,7 @@ public:
bool StrictCompareMethodSignatures(BfMethodInstance* methodA, BfMethodInstance* methodB); // Compares return types and static bool StrictCompareMethodSignatures(BfMethodInstance* methodA, BfMethodInstance* methodB); // Compares return types and static
bool IsCompatibleInterfaceMethod(BfMethodInstance* methodA, BfMethodInstance* methodB); bool IsCompatibleInterfaceMethod(BfMethodInstance* methodA, BfMethodInstance* methodB);
void UniqueSlotVirtualMethod(BfMethodInstance* methodInstance); 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); bool SlotVirtualMethod(BfMethodInstance* methodInstance, BfAmbiguityContext* ambiguityContext = NULL);
void CheckOverridenMethod(BfMethodInstance* methodInstance, BfMethodInstance* methodOverriden); void CheckOverridenMethod(BfMethodInstance* methodInstance, BfMethodInstance* methodOverriden);
bool SlotInterfaceMethod(BfMethodInstance* methodInstance); bool SlotInterfaceMethod(BfMethodInstance* methodInstance);

View file

@ -6786,7 +6786,7 @@ void BfModule::DoTypeInstanceMethodProcessing(BfTypeInstance* typeInstance)
bool isWorse = TypeIsSubTypeOf(bestInterface, checkIFaceInst); bool isWorse = TypeIsSubTypeOf(bestInterface, checkIFaceInst);
if (isBetter == isWorse) 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)) if ((isBetter) && (!isWorse))
{ {