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:
parent
a27ef9beda
commit
cbc4888853
9 changed files with 109 additions and 19 deletions
|
@ -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);
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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()))
|
||||
{
|
||||
|
@ -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)
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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))
|
||||
{
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue