diff options
author | Mike Stump <mrs@apple.com> | 2009-11-12 20:47:57 +0000 |
---|---|---|
committer | Mike Stump <mrs@apple.com> | 2009-11-12 20:47:57 +0000 |
commit | 9840c70c34fbe3c8c7ca8b3950447bade915139a (patch) | |
tree | 678b03bb60dc8128e3a5c664bb3f31e37199a54c | |
parent | b0069eebb604114d5c9d37d0856fc39d1dfffd6d (diff) |
Fix the offset calculations for non-virtual bases with overrides.
Refine the VTT entries for virtual bases to refer to the complete
object's vtable instead of constructor vtables.
Refine the AddressPoint calculations for VTT entries for virtual bases.
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@87021 91177308-0d34-0410-b5e6-96231b3b80d8
-rw-r--r-- | lib/CodeGen/CGVtable.cpp | 108 | ||||
-rw-r--r-- | lib/CodeGen/CodeGenModule.h | 14 |
2 files changed, 94 insertions, 28 deletions
diff --git a/lib/CodeGen/CGVtable.cpp b/lib/CodeGen/CGVtable.cpp index 64b30ab781..0844f52f2b 100644 --- a/lib/CodeGen/CGVtable.cpp +++ b/lib/CodeGen/CGVtable.cpp @@ -56,6 +56,12 @@ private: CanQualType> > CovariantThunks_t; CovariantThunks_t CovariantThunks; std::vector<Index_t> VCalls; + + typedef std::pair<const CXXRecordDecl *, uint64_t> CtorVtable_t; + // CtorVtable - Used to hold the AddressPoints (offsets) into the built vtable + // for use in computing the initializers for the VTT. + llvm::DenseMap<CtorVtable_t, int64_t> &AddressPoints; + typedef CXXRecordDecl::method_iterator method_iter; // FIXME: Linkage should follow vtable const bool Extern; @@ -69,7 +75,8 @@ public: CodeGenModule &cgm) : methods(meth), Class(c), BLayout(cgm.getContext().getASTRecordLayout(c)), rtti(cgm.GenerateRtti(c)), VMContext(cgm.getModule().getContext()), - CGM(cgm), Extern(true), + CGM(cgm), AddressPoints(*new llvm::DenseMap<CtorVtable_t, int64_t>), + Extern(true), LLVMPointerWidth(cgm.getContext().Target.getPointerWidth(0)) { Ptr8Ty = llvm::PointerType::get(llvm::Type::getInt8Ty(VMContext), 0); @@ -85,6 +92,9 @@ public: llvm::DenseMap<const CXXRecordDecl *, Index_t> &getVBIndex() { return VBIndex; } + llvm::DenseMap<CtorVtable_t, int64_t> *getAddressPoints() + { return &AddressPoints; } + llvm::Constant *wrap(Index_t i) { llvm::Constant *m; m = llvm::ConstantInt::get(llvm::Type::getInt64Ty(VMContext), i); @@ -471,10 +481,25 @@ public: MorallyVirtual, Offset, CurrentVBaseOffset, Path); if (ForVirtualBase) { - insertVCalls(VCallInsertionPoint); + // FIXME: We're adding to VCalls in callers, we need to do the overrides + // in the inner part, so that we know the complete set of vcalls during + // the build and don't have to insert into methods. Saving out the + // AddressPoint here, would need to be fixed, if we didn't do that. Also + // retroactively adding vcalls for overrides later wind up in the wrong + // place, the vcall slot has to be alloted during the walk of the base + // when the function is first introduces. AddressPoint += VCalls.size(); + insertVCalls(VCallInsertionPoint); } + if (MorallyVirtual) { + D1(printf("XXX address point for %s in %s at offset %d is %d\n", + RD->getNameAsCString(), Class->getNameAsCString(), + (int)Offset, (int)AddressPoint)); + AddressPoints[std::make_pair(RD, Offset)] = AddressPoint; + + } + if (alloc) { delete Path; } @@ -606,9 +631,14 @@ public: GenerateVtableForBase(Base, true, BaseOffset, true, CurrentVBaseOffset, Path); } - int64_t BaseOffset = Offset; + int64_t BaseOffset; if (i->isVirtual()) BaseOffset = BLayout.getVBaseClassOffset(Base); + else { + const ASTRecordLayout &Layout = CGM.getContext().getASTRecordLayout(RD); + BaseOffset = Offset + Layout.getBaseClassOffset(Base); + } + if (Base->getNumVBases()) { GenerateVtableForVBases(Base, BaseOffset, Path); } @@ -681,13 +711,13 @@ int64_t CGVtableInfo::getVirtualBaseOffsetIndex(const CXXRecordDecl *RD, return I->second; } -llvm::Constant *CodeGenModule::GenerateVtable(const CXXRecordDecl *RD, - const CXXRecordDecl *LayoutClass, +llvm::Constant *CodeGenModule::GenerateVtable(const CXXRecordDecl *LayoutClass, + const CXXRecordDecl *RD, uint64_t Offset) { llvm::SmallString<256> OutName; llvm::raw_svector_ostream Out(OutName); - if (LayoutClass) - mangleCXXCtorVtable(getMangleContext(), LayoutClass, Offset, RD, Out); + if (LayoutClass != RD) + mangleCXXCtorVtable(getMangleContext(), LayoutClass, Offset/8, RD, Out); else mangleCXXVtable(getMangleContext(), RD, Out); @@ -706,6 +736,9 @@ llvm::Constant *CodeGenModule::GenerateVtable(const CXXRecordDecl *RD, // then the vtables for all the virtual bases. b.GenerateVtableForVBases(RD); + if (LayoutClass == RD) + AddressPoints[RD] = b.getAddressPoints(); + llvm::Constant *C; llvm::ArrayType *type = llvm::ArrayType::get(Ptr8Ty, methods.size()); C = llvm::ConstantArray::get(type, methods); @@ -717,7 +750,8 @@ llvm::Constant *CodeGenModule::GenerateVtable(const CXXRecordDecl *RD, uint32_t LLVMPointerWidth = getContext().Target.getPointerWidth(0); AddressPointC = llvm::ConstantInt::get(llvm::Type::getInt64Ty(VMContext), AddressPoint*LLVMPointerWidth/8); - vtable = llvm::ConstantExpr::getGetElementPtr(vtable, &AddressPointC, 1); + vtable = llvm::ConstantExpr::getInBoundsGetElementPtr(vtable, &AddressPointC, + 1); return vtable; } @@ -732,8 +766,12 @@ class VTTBuilder { /// BLayout - Layout for the most derived class that this vtable is being /// built for. const ASTRecordLayout &BLayout; + // vtbl - A pointer to the vtable for Class. + llvm::Constant *ClassVtbl; + llvm::LLVMContext &VMContext; - /// Secondary - Add the secondary vtable pointers to Inits. + /// Secondary - Add the secondary vtable pointers to Inits. Offset is the + /// current offset in bits to the object we're working on. void Secondary(const CXXRecordDecl *RD, uint64_t Offset=0, bool MorallyVirtual=false) { if (RD->getNumVBases() == 0 && ! MorallyVirtual) @@ -759,24 +797,37 @@ class VTTBuilder { && !NonVirtualPrimaryBase) { // FIXME: Slightly too many of these for __ZTT8test8_B2 llvm::Constant *vtbl; - vtbl = CGM.getVtableInfo().getCtorVtable(Base, Class, BaseOffset/8); + vtbl = CGM.getVtableInfo().getCtorVtable(Class, Base, BaseOffset); Inits.push_back(vtbl); } Secondary(Base, BaseOffset, BaseMorallyVirtual); } } - /// BuiltVTT - Add the VTT to Inits. - void BuildVTT(const CXXRecordDecl *RD, uint64_t Offset, - bool MorallyVirtual=false) { + /// BuiltVTT - Add the VTT to Inits. Offset is the offset in bits to the + /// currnet object we're working on. + void BuildVTT(const CXXRecordDecl *RD, uint64_t Offset, bool MorallyVirtual) { if (RD->getNumVBases() == 0 && !MorallyVirtual) return; + llvm::Constant *init; // First comes the primary virtual table pointer... - Inits.push_back(CGM.getVtableInfo().getCtorVtable(RD, Class, Offset)); + if (MorallyVirtual) { + int64_t AddressPoint; + AddressPoint = (*CGM.AddressPoints[Class])[std::make_pair(RD, Offset)]; + D1(printf("XXX address point for %s in %s at offset %d was %d\n", + RD->getNameAsCString(), Class->getNameAsCString(), + (int)Offset, (int)AddressPoint)); + uint32_t LLVMPointerWidth = CGM.getContext().Target.getPointerWidth(0); + init = llvm::ConstantInt::get(llvm::Type::getInt64Ty(VMContext), + AddressPoint*LLVMPointerWidth/8); + init = llvm::ConstantExpr::getInBoundsGetElementPtr(ClassVtbl, &init, 1); + } else + init = CGM.getVtableInfo().getCtorVtable(Class, RD, Offset); + Inits.push_back(init); // then the secondary VTTs.... - SecondaryVTTs(RD, MorallyVirtual); + SecondaryVTTs(RD, Offset, MorallyVirtual); // and last the secondary vtable pointers. Secondary(RD, MorallyVirtual, Offset); @@ -785,14 +836,17 @@ class VTTBuilder { /// SecondaryVTTs - Add the secondary VTTs to Inits. The secondary VTTs are /// built from each direct non-virtual proper base that requires a VTT in /// declaration order. - void SecondaryVTTs(const CXXRecordDecl *RD, bool MorallyVirtual=false) { + void SecondaryVTTs(const CXXRecordDecl *RD, uint64_t Offset=0, + bool MorallyVirtual=false) { for (CXXRecordDecl::base_class_const_iterator i = RD->bases_begin(), e = RD->bases_end(); i != e; ++i) { const CXXRecordDecl *Base = cast<CXXRecordDecl>(i->getType()->getAs<RecordType>()->getDecl()); if (i->isVirtual()) continue; - BuildVTT(Base, MorallyVirtual); + const ASTRecordLayout &Layout = CGM.getContext().getASTRecordLayout(RD); + uint64_t BaseOffset = Offset + Layout.getBaseClassOffset(Base); + BuildVTT(Base, BaseOffset, MorallyVirtual); } } @@ -805,7 +859,8 @@ class VTTBuilder { cast<CXXRecordDecl>(i->getType()->getAs<RecordType>()->getDecl()); if (i->isVirtual() && !SeenVBase.count(Base)) { SeenVBase.insert(Base); - BuildVTT(Base, true); + uint64_t BaseOffset = BLayout.getVBaseClassOffset(Base); + BuildVTT(Base, BaseOffset, true); } VirtualVTTs(Base); } @@ -814,11 +869,14 @@ public: VTTBuilder(std::vector<llvm::Constant *> &inits, const CXXRecordDecl *c, CodeGenModule &cgm) : Inits(inits), Class(c), CGM(cgm), - BLayout(cgm.getContext().getASTRecordLayout(c)) { + BLayout(cgm.getContext().getASTRecordLayout(c)), + VMContext(cgm.getModule().getContext()) { // First comes the primary virtual table pointer for the complete class... - Inits.push_back(CGM.getVtableInfo().getVtable(Class)); - + ClassVtbl = CGM.getVtableInfo().getVtable(Class); + Inits.push_back(ClassVtbl); + ClassVtbl = dyn_cast<llvm::Constant>(ClassVtbl->getOperand(0)); + // then the secondary VTTs... SecondaryVTTs(Class); @@ -861,13 +919,13 @@ llvm::Constant *CGVtableInfo::getVtable(const CXXRecordDecl *RD) { llvm::Constant *&vtbl = Vtables[RD]; if (vtbl) return vtbl; - vtbl = CGM.GenerateVtable(RD); + vtbl = CGM.GenerateVtable(RD, RD); CGM.GenerateVTT(RD); return vtbl; } -llvm::Constant *CGVtableInfo::getCtorVtable(const CXXRecordDecl *RD, - const CXXRecordDecl *Class, +llvm::Constant *CGVtableInfo::getCtorVtable(const CXXRecordDecl *LayoutClass, + const CXXRecordDecl *RD, uint64_t Offset) { - return CGM.GenerateVtable(RD, Class, Offset); + return CGM.GenerateVtable(LayoutClass, RD, Offset); } diff --git a/lib/CodeGen/CodeGenModule.h b/lib/CodeGen/CodeGenModule.h index 749c8f5403..6fe6cf5584 100644 --- a/lib/CodeGen/CodeGenModule.h +++ b/lib/CodeGen/CodeGenModule.h @@ -250,9 +250,13 @@ public: llvm::Constant *GetAddrOfFunction(GlobalDecl GD, const llvm::Type *Ty = 0); - /// GenerateVtable - Generate the vtable for the given type. - llvm::Constant *GenerateVtable(const CXXRecordDecl *RD, - const CXXRecordDecl *Class=0, + /// GenerateVtable - Generate the vtable for the given type. LayoutClass is + /// the class to use for the virtual base layout information. For + /// non-construction vtables, this is always the same as RD. Offset is the + /// offset in bits for the RD object in the LayoutClass, if we're generating a + /// construction vtable, otherwise 0. + llvm::Constant *GenerateVtable(const CXXRecordDecl *LayoutClass, + const CXXRecordDecl *RD, uint64_t Offset=0); /// GenerateVTT - Generate the VTT for the given type. @@ -269,6 +273,10 @@ public: int64_t nv_t, int64_t v_t, int64_t nv_r, int64_t v_r); + typedef std::pair<const CXXRecordDecl *, uint64_t> CtorVtable_t; + llvm::DenseMap<const CXXRecordDecl *, llvm::DenseMap<CtorVtable_t, + int64_t>*> AddressPoints; + /// GetCXXBaseClassOffset - Returns the offset from a derived class to its /// base class. Returns null if the offset is 0. llvm::Constant *GetCXXBaseClassOffset(const CXXRecordDecl *ClassDecl, |