diff --git a/IDE/Tests/Test1/scripts/HotSwap_Virtual02.txt b/IDE/Tests/Test1/scripts/HotSwap_Virtual02.txt new file mode 100644 index 00000000..5a3364f1 --- /dev/null +++ b/IDE/Tests/Test1/scripts/HotSwap_Virtual02.txt @@ -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() \ No newline at end of file diff --git a/IDE/Tests/Test1/src/HotSwap_Virtuals02.bf b/IDE/Tests/Test1/src/HotSwap_Virtuals02.bf new file mode 100644 index 00000000..6c778196 --- /dev/null +++ b/IDE/Tests/Test1/src/HotSwap_Virtuals02.bf @@ -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(); + } +} \ No newline at end of file diff --git a/IDE/Tests/Test1/src/Program.bf b/IDE/Tests/Test1/src/Program.bf index e17d8dd2..f0c8cff0 100644 --- a/IDE/Tests/Test1/src/Program.bf +++ b/IDE/Tests/Test1/src/Program.bf @@ -33,6 +33,7 @@ namespace IDETest Unions.Test(); UsingFields.Test(); Virtuals.Test(); + Virtuals02.Test(); Bug001.Test(); Bug002.Test(); diff --git a/IDEHelper/Compiler/BfExprEvaluator.cpp b/IDEHelper/Compiler/BfExprEvaluator.cpp index b3257506..986e361c 100644 --- a/IDEHelper/Compiler/BfExprEvaluator.cpp +++ b/IDEHelper/Compiler/BfExprEvaluator.cpp @@ -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)); }