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

Fixed hot vtable index adjustment with override

This commit is contained in:
Brian Fiete 2025-01-20 09:58:52 -08:00
parent 4e55f62fd5
commit 45ff0b341b
4 changed files with 94 additions and 8 deletions

View file

@ -0,0 +1,13 @@
ShowFile("src/HotSwap_Virtuals02.bf")
GotoText("//Test_Start")
ToggleBreakpoint()
RunWithCompiling()
StepOver()
ToggleCommentAt("ClassA_GetVal01")
Compile()
StepOver()
ToggleCommentAt("ClassB_GetVal04")
Compile()
StepOver()

View file

@ -0,0 +1,67 @@
using System;
#pragma warning disable 168
namespace IDETest;
class Virtuals02
{
class ClassA
{
public virtual int GetVal01() => 100;
public
/*ClassA_GetVal01
virtual
*/
int GetVal02() => 200;
public virtual int GetVal03() => 300;
}
class ClassB : ClassA
{
public override int GetVal03()
{
return 301;
}
public virtual int GetVal04() => 400;
public
/*ClassB_GetVal04
virtual
*/
int GetVal05() => 500;
}
static void TestFuncs()
{
ClassA ca = scope .();
ClassB cb = scope .();
int val;
void** funcs = (.)(void*)(cb.[Friend]mClassVData & ~0xFF);
int valA1 = ca.GetVal01();
int valA2 = ca.GetVal02();
int valB1 = cb.GetVal01();
int valB2 = cb.GetVal02();
int valB3 = cb.GetVal03();
int valB4 = cb.GetVal04();
int valB5 = cb.GetVal05();
Runtime.Assert(valA1 == 100);
Runtime.Assert(valA2 == 200);
Runtime.Assert(valB1 == 100);
Runtime.Assert(valB2 == 200);
Runtime.Assert(valB3 == 301);
Runtime.Assert(valB4 == 400);
Runtime.Assert(valB5 == 500);
}
public static void Test()
{
//Test_Start
TestFuncs();
TestFuncs();
TestFuncs();
}
}

View file

@ -33,6 +33,7 @@ namespace IDETest
Unions.Test();
UsingFields.Test();
Virtuals.Test();
Virtuals02.Test();
Bug001.Test();
Bug002.Test();

View file

@ -6799,20 +6799,25 @@ BfTypedValue BfExprEvaluator::CreateCall(BfAstNode* targetSrc, BfMethodInstance*
else
{
// Map this new virtual index back to the original index
//vDataIdx += (methodInstance->mVirtualTableIdx - typeInst->GetBaseVTableSize()) + typeInst->GetOrigBaseVTableSize();
//vDataIdx = mModule->mBfIRBuilder->CreateConst(BfTypeCode_Int32, 1 + methodInstance->GetOwner()->GetDynCastVDataCount() + mModule->mCompiler->mMaxInterfaceSlots);
// Find the type instance that declared the original method
auto declTypeInst = typeInst;
while (declTypeInst->mBaseType != NULL)
{
mModule->PopulateType(declTypeInst->mBaseType, BfPopulateType_DataAndMethods);
if (methodInstance->mVirtualTableIdx >= declTypeInst->mBaseType->mVirtualMethodTableSize)
break;
BF_ASSERT(methodInstance->mMethodDef->mIsOverride);
declTypeInst = declTypeInst->mBaseType;
}
vDataIdx = mModule->mBfIRBuilder->GetConfigConst(BfIRConfigConst_VirtualMethodOfs, BfTypeCode_Int32);
vDataIdx = mModule->mBfIRBuilder->CreateAdd(vDataIdx, mModule->mBfIRBuilder->CreateConst(BfTypeCode_Int32,
(methodInstance->mVirtualTableIdx - typeInst->GetImplBaseVTableSize()) + typeInst->GetOrigImplBaseVTableSize()));
(methodInstance->mVirtualTableIdx - declTypeInst->GetImplBaseVTableSize()) + declTypeInst->GetOrigImplBaseVTableSize()));
}
}
else
{
//vDataIdx += methodInstance->mVirtualTableIdx;
//vDataIdx = mModule->mBfIRBuilder->CreateConst(BfTypeCode_Int32, 1 + methodInstance->GetOwner()->GetDynCastVDataCount() + mModule->mCompiler->mMaxInterfaceSlots);
{
vDataIdx = mModule->mBfIRBuilder->GetConfigConst(BfIRConfigConst_VirtualMethodOfs, BfTypeCode_Int32);
vDataIdx = mModule->mBfIRBuilder->CreateAdd(vDataIdx, mModule->mBfIRBuilder->CreateConst(BfTypeCode_Int32, methodInstance->mVirtualTableIdx));
}