From: Mike Stump Date: Wed, 14 Oct 2009 18:14:51 +0000 (+0000) Subject: Shift the vcall slots for non-virtual bases of a virtual base, up into X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=0ca4279d84635e1e54951761bd6fe89a45a23ff1;p=clang Shift the vcall slots for non-virtual bases of a virtual base, up into the virtual base so they can be reused properly. Don't reuse vcall slots across a virtual boundary. WIP. I have a testcase, but there are still things that need to be fixed before the testcase can go in. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@84120 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/lib/CodeGen/CGVtable.cpp b/lib/CodeGen/CGVtable.cpp index 41f7eefbe8..b84f34cf44 100644 --- a/lib/CodeGen/CGVtable.cpp +++ b/lib/CodeGen/CGVtable.cpp @@ -332,6 +332,22 @@ public: } } +// #define D(X) do { X; } while (0) +#define D(X) + + void insertVCalls(int InsertionPoint) { + llvm::Constant *e = 0; + D(VCalls.insert(VCalls.begin(), 673)); + D(VCalls.push_back(672)); + methods.insert(methods.begin() + InsertionPoint, VCalls.size()/*+2*/, e); + // The vcalls come first... + for (std::vector::reverse_iterator i = VCalls.rbegin(), + e = VCalls.rend(); + i != e; ++i) + methods[InsertionPoint++] = wrap((0?600:0) + *i); + VCalls.clear(); + } + Index_t end(const CXXRecordDecl *RD, std::vector &offsets, const ASTRecordLayout &Layout, const CXXRecordDecl *PrimaryBase, @@ -341,24 +357,27 @@ public: extra = 0; // FIXME: Cleanup. if (!ForVirtualBase) { + D(methods.push_back(wrap(666))); // then virtual base offsets... for (std::vector::reverse_iterator i = offsets.rbegin(), e = offsets.rend(); i != e; ++i) methods.push_back(*i); + D(methods.push_back(wrap(667))); } - // The vcalls come first... - for (std::vector::reverse_iterator i=VCalls.rbegin(), - e=VCalls.rend(); - i != e; ++i) - methods.push_back(wrap((0?600:0) + *i)); - VCalls.clear(); + bool DeferVCalls = MorallyVirtual || ForVirtualBase; + int VCallInsertionPoint = methods.size(); + if (!DeferVCalls) { + insertVCalls(VCallInsertionPoint); + } if (ForVirtualBase) { + D(methods.push_back(wrap(668))); // then virtual base offsets... for (std::vector::reverse_iterator i = offsets.rbegin(), e = offsets.rend(); i != e; ++i) methods.push_back(*i); + D(methods.push_back(wrap(669))); } methods.push_back(wrap(-(Offset/8))); @@ -372,6 +391,14 @@ public: // and then the non-virtual bases. NonVirtualBases(RD, Layout, PrimaryBase, PrimaryBaseWasVirtual, MorallyVirtual, Offset); + + if (ForVirtualBase) { + D(methods.push_back(wrap(670))); + insertVCalls(VCallInsertionPoint); + AddressPoint += VCalls.size(); + D(methods.push_back(wrap(671))); + } + return AddressPoint; } @@ -450,6 +477,7 @@ public: // Mark it so we don't output it twice. IndirectPrimary.insert(Base); StartNewTable(); + VCall.clear(); int64_t BaseOffset = BLayout.getVBaseClassOffset(Base); GenerateVtableForBase(Base, true, BaseOffset, true, Path); }