mirror of
https://github.com/beefytech/Beef.git
synced 2025-06-10 12:32:20 +02:00
Improved virtual overrides in extensions
This commit is contained in:
parent
8a84647bcd
commit
e1d7939081
11 changed files with 116 additions and 11 deletions
|
@ -2291,6 +2291,14 @@ void BeIRCodeGen::HandleNextCmd()
|
|||
SetResult(curId, mBeModule->CreateFunction(type, linkageType, name));
|
||||
}
|
||||
break;
|
||||
case BfIRCmd_SetFunctionName:
|
||||
{
|
||||
CMD_PARAM(BeValue*, func);
|
||||
CMD_PARAM(String, name);
|
||||
BeFunction* beFunc = BeValueDynCast<BeFunction>(func);
|
||||
beFunc->mName = name;
|
||||
}
|
||||
break;
|
||||
case BfIRCmd_EnsureFunctionPatchable:
|
||||
{
|
||||
|
||||
|
|
|
@ -5878,6 +5878,23 @@ void BfCompiler::PopulateReified()
|
|||
|
||||
checkType = checkType->mBaseType;
|
||||
}
|
||||
|
||||
for (auto& reifyDep : typeInst->mReifyMethodDependencies)
|
||||
{
|
||||
if ((reifyDep.mDepMethod.mTypeInstance == NULL) ||
|
||||
(reifyDep.mDepMethod.mTypeInstance->IsIncomplete()))
|
||||
continue;
|
||||
|
||||
BfMethodInstance* depMethod = reifyDep.mDepMethod;
|
||||
if (depMethod == NULL)
|
||||
continue;
|
||||
|
||||
if ((depMethod->mIsReified) && (depMethod->mMethodInstanceGroup->IsImplemented()))
|
||||
{
|
||||
auto methodDef = typeInst->mTypeDef->mMethods[reifyDep.mMethodIdx];
|
||||
typeInst->mModule->GetMethodInstance(typeInst, methodDef, BfTypeVector());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1226,6 +1226,7 @@ void BfContext::RebuildType(BfType* type, bool deleteOnDemandTypes, bool rebuild
|
|||
typeInst->mAttributeData = NULL;
|
||||
typeInst->mVirtualMethodTableSize = 0;
|
||||
typeInst->mVirtualMethodTable.Clear();
|
||||
typeInst->mReifyMethodDependencies.Clear();
|
||||
typeInst->mSize = -1;
|
||||
typeInst->mAlign = -1;
|
||||
typeInst->mInstSize = -1;
|
||||
|
|
|
@ -5314,6 +5314,12 @@ BfIRFunction BfIRBuilder::CreateFunction(BfIRFunctionType funcType, BfIRLinkageT
|
|||
return retVal;
|
||||
}
|
||||
|
||||
void BfIRBuilder::SetFunctionName(BfIRValue func, const StringImpl& name)
|
||||
{
|
||||
WriteCmd(BfIRCmd_SetFunctionName, func, name);
|
||||
NEW_CMD_INSERTED_IRVALUE;
|
||||
}
|
||||
|
||||
void BfIRBuilder::EnsureFunctionPatchable()
|
||||
{
|
||||
BfIRValue retVal = WriteCmd(BfIRCmd_EnsureFunctionPatchable);
|
||||
|
|
|
@ -278,6 +278,7 @@ enum BfIRCmd : uint8
|
|||
BfIRCmd_GetIntrinsic,
|
||||
BfIRCmd_CreateFunctionType,
|
||||
BfIRCmd_CreateFunction,
|
||||
BfIRCmd_SetFunctionName,
|
||||
BfIRCmd_EnsureFunctionPatchable,
|
||||
BfIRCmd_RemapBindFunction,
|
||||
BfIRCmd_SetActiveFunction,
|
||||
|
@ -1305,6 +1306,7 @@ public:
|
|||
BfIRFunctionType MapMethod(BfMethodInstance* methodInstance);
|
||||
BfIRFunctionType CreateFunctionType(BfIRType resultType, const BfSizedArray<BfIRType>& paramTypes, bool isVarArg = false);
|
||||
BfIRFunction CreateFunction(BfIRFunctionType funcType, BfIRLinkageType linkageType, const StringImpl& name);
|
||||
void SetFunctionName(BfIRValue func, const StringImpl& name);
|
||||
void EnsureFunctionPatchable();
|
||||
BfIRValue RemapBindFunction(BfIRValue func);
|
||||
void SetActiveFunction(BfIRFunction func);
|
||||
|
|
|
@ -2968,6 +2968,14 @@ void BfIRCodeGen::HandleNextCmd()
|
|||
SetResult(curId, func);
|
||||
}
|
||||
break;
|
||||
case BfIRCmd_SetFunctionName:
|
||||
{
|
||||
CMD_PARAM(llvm::Value*, func);
|
||||
CMD_PARAM(String, name);
|
||||
llvm::Function* llvmFunc = llvm::dyn_cast<llvm::Function>(func);
|
||||
llvmFunc->setName(name.c_str());
|
||||
}
|
||||
break;
|
||||
case BfIRCmd_EnsureFunctionPatchable:
|
||||
{
|
||||
int minPatchSize = 5;
|
||||
|
|
|
@ -22547,7 +22547,9 @@ void BfModule::SetupIRFunction(BfMethodInstance* methodInstance, StringImpl& man
|
|||
auto checkMethodInstance = mCurTypeInstance->mMethodInstanceGroups[checkMethod->mIdx].mDefault;
|
||||
if (checkMethodInstance == NULL)
|
||||
continue;
|
||||
if ((checkMethodInstance->mIRFunction == prevFunc) && (checkMethodInstance->mMethodDef->mMethodDeclaration != NULL))
|
||||
if ((checkMethodInstance->mIRFunction == prevFunc) &&
|
||||
(checkMethodInstance->mMethodDef->mMethodDeclaration != NULL) &&
|
||||
(checkMethodInstance->mVirtualTableIdx < 0))
|
||||
{
|
||||
BfAstNode* refNode = methodDef->GetRefNode();
|
||||
if (auto propertyMethodDeclaration = methodDef->GetPropertyMethodDeclaration())
|
||||
|
@ -24633,12 +24635,38 @@ bool BfModule::SlotVirtualMethod(BfMethodInstance* methodInstance, BfAmbiguityCo
|
|||
auto declMethodInstance = (BfMethodInstance*)typeInstance->mVirtualMethodTable[virtualMethodMatchIdx].mDeclaringMethod;
|
||||
_AddVirtualDecl(declMethodInstance);
|
||||
setMethodInstance->mVirtualTableIdx = virtualMethodMatchIdx;
|
||||
|
||||
auto& implMethodRef = typeInstance->mVirtualMethodTable[virtualMethodMatchIdx].mImplementingMethod;
|
||||
if ((!mCompiler->mIsResolveOnly) && (implMethodRef.mMethodNum >= 0) &&
|
||||
(implMethodRef.mTypeInstance == typeInstance) && (methodInstance->GetOwner() == typeInstance))
|
||||
{
|
||||
auto prevImplMethodInstance = (BfMethodInstance*)implMethodRef;
|
||||
if (prevImplMethodInstance->mMethodDef->mDeclaringType->mProject != methodInstance->mMethodDef->mDeclaringType->mProject)
|
||||
{
|
||||
// We may need to have to previous method reified when we must re-slot in another project during vdata creation
|
||||
BfReifyMethodDependency dep;
|
||||
dep.mDepMethod = typeInstance->mVirtualMethodTable[virtualMethodMatchIdx].mDeclaringMethod;
|
||||
dep.mMethodIdx = implMethodRef.mMethodNum;
|
||||
typeInstance->mReifyMethodDependencies.Add(dep);
|
||||
}
|
||||
|
||||
if (!methodInstance->mMangleWithIdx)
|
||||
{
|
||||
// Keep mangled names from conflicting
|
||||
methodInstance->mMangleWithIdx = true;
|
||||
if ((methodInstance->mIRFunction) && (methodInstance->mDeclModule->mIsModuleMutable))
|
||||
{
|
||||
StringT<4096> mangledName;
|
||||
BfMangler::Mangle(mangledName, mCompiler->GetMangleKind(), methodInstance);
|
||||
methodInstance->mDeclModule->mBfIRBuilder->SetFunctionName(methodInstance->mIRFunction, mangledName);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
typeInstance->mVirtualMethodTable[virtualMethodMatchIdx].mImplementingMethod = setMethodInstance;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
if (methodOverriden != NULL)
|
||||
{
|
||||
CheckOverridenMethod(methodInstance, methodOverriden);
|
||||
|
|
|
@ -1903,6 +1903,13 @@ public:
|
|||
|
||||
class BfCeTypeInfo;
|
||||
|
||||
struct BfReifyMethodDependency
|
||||
{
|
||||
public:
|
||||
BfNonGenericMethodRef mDepMethod;
|
||||
int mMethodIdx;
|
||||
};
|
||||
|
||||
// Instance of struct or class
|
||||
class BfTypeInstance : public BfDependedType
|
||||
{
|
||||
|
@ -1912,7 +1919,6 @@ public:
|
|||
int mInheritanceId;
|
||||
int mInheritanceCount;
|
||||
BfModule* mModule;
|
||||
|
||||
BfTypeDef* mTypeDef;
|
||||
BfTypeInstance* mBaseType;
|
||||
BfCustomAttributes* mCustomAttributes;
|
||||
|
@ -1920,12 +1926,12 @@ public:
|
|||
BfTypeInfoEx* mTypeInfoEx;
|
||||
BfGenericTypeInfo* mGenericTypeInfo;
|
||||
BfCeTypeInfo* mCeTypeInfo;
|
||||
|
||||
Array<BfTypeInterfaceEntry> mInterfaces;
|
||||
Array<BfTypeInterfaceMethodEntry> mInterfaceMethodTable;
|
||||
Array<BfMethodInstanceGroup> mMethodInstanceGroups;
|
||||
Array<BfOperatorInfo*> mOperatorInfo;
|
||||
Array<BfVirtualMethodEntry> mVirtualMethodTable;
|
||||
Array<BfReifyMethodDependency> mReifyMethodDependencies;
|
||||
BfHotTypeData* mHotTypeData;
|
||||
int mVirtualMethodTableSize; // With hot reloading, mVirtualMethodTableSize can be larger than mInterfaceMethodTable (live vtable versioning)
|
||||
Array<BfFieldInstance> mFieldInstances;
|
||||
|
|
|
@ -45,6 +45,19 @@ namespace LibA
|
|||
T val = default;
|
||||
return Overload0(val);
|
||||
}
|
||||
|
||||
public virtual int GetA()
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
extension LibA0
|
||||
{
|
||||
public override int GetA()
|
||||
{
|
||||
return 2;
|
||||
}
|
||||
}
|
||||
|
||||
struct Handler
|
||||
|
|
|
@ -42,6 +42,10 @@ namespace TestsB
|
|||
Test.Assert(ca.mB == 1008);
|
||||
Test.Assert(ca.mC == 9);
|
||||
Test.Assert(ca.GetVal2() == 11);
|
||||
|
||||
LibA.LibA0 la0 = scope .();
|
||||
int la0a = la0.GetA();
|
||||
Test.Assert(la0a == 2);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -57,6 +57,14 @@ extension LibClassA
|
|||
|
||||
namespace LibA
|
||||
{
|
||||
extension LibA0
|
||||
{
|
||||
public new override int GetA()
|
||||
{
|
||||
return 3;
|
||||
}
|
||||
}
|
||||
|
||||
extension LibA3
|
||||
{
|
||||
this
|
||||
|
@ -386,6 +394,10 @@ namespace Tests
|
|||
delete ca;
|
||||
Test.Assert(LibClassA.sMagic == 7771);
|
||||
|
||||
LibA.LibA0 la0 = scope .();
|
||||
int la0a = la0.GetA();
|
||||
Test.Assert(la0a == 3);
|
||||
|
||||
LibA.LibA3 la3 = scope .();
|
||||
Test.Assert(la3.mA == 114);
|
||||
Test.Assert(la3.mB == 7);
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue