diff --git a/CfrontCodeGenerator.cpp b/CfrontCodeGenerator.cpp index 79d9ede..92c11c4 100644 --- a/CfrontCodeGenerator.cpp +++ b/CfrontCodeGenerator.cpp @@ -438,6 +438,27 @@ void CfrontCodeGenerator::InsertArg(const CXXOperatorCallExpr* stmt) } //----------------------------------------------------------------------------- +static void InsertVtblPtr(const CXXMethodDecl* stmt, const CXXRecordDecl* cur, StmtsContainer& bodyStmts) +{ + if(cur->isPolymorphic() and (0 == cur->getNumBases())) { + auto* fieldDecl = CfrontCodeGenerator::VtableData().VtblPtrField(cur); + auto* lhsMemberExpr = AccessMember(kwInternalThis, fieldDecl, Ptr(GetRecordDeclType(cur))); + + // struct __mptr *__ptbl_vec__c___src_C_[] + auto* vtablAr = CfrontCodeGenerator::VtableData().VtblArrayVar(1); + auto* vtblArrayPos = + ArraySubscript(mkDeclRefExpr(vtablAr), GetGlobalVtablePos(stmt->getParent(), cur), fieldDecl->getType()); + + bodyStmts.AddBodyStmts(Assign(lhsMemberExpr, fieldDecl, vtblArrayPos)); + + } else if(cur->isPolymorphic() and (0 < cur->getNumBases()) and (cur != stmt->getParent())) { + for(const auto& base : cur->bases()) { + InsertVtblPtr(stmt, base.getType()->getAsCXXRecordDecl(), bodyStmts); + } + } +} +//----------------------------------------------------------------------------- + void CfrontCodeGenerator::InsertCXXMethodDecl(const CXXMethodDecl* stmt, SkipBody) { OutputFormatHelper initOutputFormatHelper{}; @@ -565,26 +586,12 @@ void CfrontCodeGenerator::InsertCXXMethodDecl(const CXXMethodDecl* stmt, SkipBod insertFields(baseType->getAsRecordDecl()); } - auto insertVtblPtr = [&](const CXXRecordDecl* cur) { - if(cur->isPolymorphic() and (0 == cur->getNumBases())) { - auto* fieldDecl = VtableData().VtblPtrField(cur); - auto* lhsMemberExpr = AccessMember(kwInternalThis, fieldDecl, Ptr(GetRecordDeclType(cur))); - - // struct __mptr *__ptbl_vec__c___src_C_[] - auto* vtablAr = VtableData().VtblArrayVar(1); - auto* vtblArrayPos = ArraySubscript( - mkDeclRefExpr(vtablAr), GetGlobalVtablePos(stmt->getParent(), cur), fieldDecl->getType()); - - bodyStmts.AddBodyStmts(Assign(lhsMemberExpr, fieldDecl, vtblArrayPos)); - } - }; - // insert our vtable pointer - insertVtblPtr(stmt->getParent()); + InsertVtblPtr(stmt, stmt->getParent(), bodyStmts); // in case of multi inheritance insert additional vtable pointers for(const auto& base : parent->bases()) { - insertVtblPtr(base.getType()->getAsCXXRecordDecl()); + InsertVtblPtr(stmt, base.getType()->getAsCXXRecordDecl(), bodyStmts); } // insert own fields diff --git a/tests/EduCfrontTest7.expect b/tests/EduCfrontTest7.expect index 7baf796..795c73b 100644 --- a/tests/EduCfrontTest7.expect +++ b/tests/EduCfrontTest7.expect @@ -172,6 +172,7 @@ inline Derived * Constructor_Derived(Derived * __this) Constructor_Type(&__this->mY, 5); Constructor_BaseThird((BaseThird *)__this); Constructor_Type(&__this->mZ, 5); + __this->__vptrBase = __vtbl_array[3]; __this->__vptrBaseThird = __vtbl_array[4]; /* dt // trivial type, maybe uninitialized */ __this->g = 4; diff --git a/tests/EduCfrontVtable3Test.expect b/tests/EduCfrontVtable3Test.expect index 78d3ea5..544c61b 100644 --- a/tests/EduCfrontVtable3Test.expect +++ b/tests/EduCfrontVtable3Test.expect @@ -126,6 +126,7 @@ inline C * Constructor_C(C * __this) { Constructor_B((B *)__this); __this->mX = 5; + __this->__vptrA = __vtbl_array[2]; __this->mB = 8; return __this; } diff --git a/tests/EduCfrontVtable4Test.expect b/tests/EduCfrontVtable4Test.expect index 152c608..8b49e8f 100644 --- a/tests/EduCfrontVtable4Test.expect +++ b/tests/EduCfrontVtable4Test.expect @@ -135,6 +135,7 @@ inline C * Constructor_C(C * __this) { Constructor_B((B *)__this); __this->mX = 5; + __this->__vptrA = __vtbl_array[2]; __this->mB = 8; return __this; } diff --git a/tests/EduCfrontVtable7Test.cpp b/tests/EduCfrontVtable7Test.cpp new file mode 100644 index 0000000..a2417c7 --- /dev/null +++ b/tests/EduCfrontVtable7Test.cpp @@ -0,0 +1,29 @@ +// cmdlineinsights:-edu-show-cfront + +#include + +struct Fruit { + double md; + virtual ~Fruit() { puts("~Fruit"); } + virtual void Fun() { puts("Fruit's Fun"); } +}; + +struct Apple : Fruit { + int mX{5}; + void Fun() override { printf("Apple's Fun: %d\n", mX); } +}; + +struct PinkLady : Apple { + int mApple{8}; + void Fun() override { printf("Pink Ladies Fun: %d\n", mApple); } +}; + +int main() +{ + PinkLady delicious{}; + delicious.Fun(); + + Fruit* f{static_cast(&delicious)}; + f->Fun(); +} + diff --git a/tests/EduCfrontVtable7Test.expect b/tests/EduCfrontVtable7Test.expect new file mode 100644 index 0000000..4d62a2b --- /dev/null +++ b/tests/EduCfrontVtable7Test.expect @@ -0,0 +1,169 @@ +/************************************************************************************* + * NOTE: This an educational hand-rolled transformation. Things can be incorrect or * + * buggy. * + *************************************************************************************/ +void __cxa_start(void); +void __cxa_atexit(void); +typedef int (*__vptp)(); + +struct __mptr +{ + short d; + short i; + __vptp f; +}; + +extern struct __mptr* __vtbl_array[]; + + +#include + +typedef struct Fruit +{ + __mptr * __vptrFruit; + double md; +} Fruit; + +inline void Destructor_Fruit(Fruit * __this) +{ + puts("~Fruit"); +} + +inline void FunFruit(Fruit * __this) +{ + puts("Fruit's Fun"); +} + +inline Fruit * operatorEqual(Fruit * __this, const Fruit * __rhs) +{ + __this->md = __rhs->md; + return __this; +} + +inline Fruit * Constructor_Fruit(Fruit * __this) +{ + __this->__vptrFruit = __vtbl_array[0]; + return __this; +} + + +typedef struct Apple +{ + __mptr * __vptrFruit; + double md; + int mX; +} Apple; + +inline void FunApple(Apple * __this) +{ + printf("Apple's Fun: %d\n", __this->mX); +} + +inline Apple * operatorEqual(Apple * __this, const Apple * __rhs) +{ + __this->md = __rhs->md; + operatorEqual((Fruit *)__this, (Fruit *)__rhs); + __this->mX = __rhs->mX; + return __this; +} + +inline Apple * operatorEqual(Apple * __this, Apple * __rhs) +{ + __this->md = __rhs->md; + operatorEqual((Fruit *)__this, (Fruit *)__rhs); + __this->mX = __rhs->mX; + return __this; +} + +inline void Destructor_Apple(Apple * __this) +{ + Destructor_Fruit((Fruit *)__this); +} + +inline Apple * Constructor_Apple(Apple * __this) +{ + Constructor_Fruit((Fruit *)__this); + __this->__vptrFruit = __vtbl_array[1]; + __this->mX = 5; + return __this; +} + + +typedef struct PinkLady +{ + __mptr * __vptrFruit; + double md; + int mX; + int mApple; +} PinkLady; + +inline void FunPinkLady(PinkLady * __this) +{ + printf("Pink Ladies Fun: %d\n", __this->mApple); +} + +inline PinkLady * operatorEqual(PinkLady * __this, const PinkLady * __rhs) +{ + __this->mX = __rhs->mX; + operatorEqual((Apple *)__this, (Apple *)__rhs); + __this->mApple = __rhs->mApple; + return __this; +} + +inline PinkLady * operatorEqual(PinkLady * __this, PinkLady * __rhs) +{ + __this->mX = __rhs->mX; + operatorEqual((Apple *)__this, (Apple *)__rhs); + __this->mApple = __rhs->mApple; + return __this; +} + +inline void Destructor_PinkLady(PinkLady * __this) +{ + Destructor_Apple((Apple *)__this); +} + +inline PinkLady * Constructor_PinkLady(PinkLady * __this) +{ + Constructor_Apple((Apple *)__this); + __this->mX = 5; + __this->__vptrFruit = __vtbl_array[2]; + __this->mApple = 8; + return __this; +} + + +int __main(void) +{ + PinkLady delicious; + Constructor_PinkLady((PinkLady *)&delicious); + (*((void (*)(PinkLady *))((&delicious)->__vptrFruit[0]).f))((((PinkLady *)(char *)(&delicious)) + ((&delicious)->__vptrFruit[0]).d)); + Fruit * f = (Fruit *)&delicious; + (*((void (*)(Fruit *))((f)->__vptrFruit[0]).f))((((Fruit *)(char *)(f)) + ((f)->__vptrFruit[0]).d)); + return 0; + (*((void (*)(PinkLady *))((&delicious)->__vptrFruit[0]).f))((((PinkLady *)(char *)(&delicious)) + ((&delicious)->__vptrFruit[0]).d)); +} + +int main(void) +{ + __cxa_start(); + int ret = __main(); + __cxa_atexit(); + return ret; + /* ret // lifetime ends here */ +} + +__mptr __vtbl_Fruit[2] = {{0, 0, (__vptp)Destructor_Fruit}, {0, 0, (__vptp)FunFruit}}; +__mptr __vtbl_Apple[2] = {{0, 0, (__vptp)Destructor_Apple}, {0, 0, (__vptp)FunApple}}; +__mptr __vtbl_PinkLady[2] = {{0, 0, (__vptp)Destructor_PinkLady}, {0, 0, (__vptp)FunPinkLady}}; + +__mptr * __vtbl_array[3] = {__vtbl_Fruit, __vtbl_Apple, __vtbl_PinkLady}; + +void __cxa_start(void) +{ +} + +void __cxa_atexit(void) +{ +} +