diff options
Diffstat (limited to 'lib/CodeGen/CGVTT.cpp')
-rw-r--r-- | lib/CodeGen/CGVTT.cpp | 608 |
1 files changed, 347 insertions, 261 deletions
diff --git a/lib/CodeGen/CGVTT.cpp b/lib/CodeGen/CGVTT.cpp index 96c104b..91d9f76 100644 --- a/lib/CodeGen/CGVTT.cpp +++ b/lib/CodeGen/CGVTT.cpp @@ -19,283 +19,355 @@ using namespace CodeGen; #define D1(x) namespace { + +/// VTT builder - Class for building VTT layout information. class VTTBuilder { - /// Inits - The list of values built for the VTT. - std::vector<llvm::Constant *> &Inits; - /// Class - The most derived class that this vtable is being built for. - const CXXRecordDecl *Class; - CodeGenModule &CGM; // Per-module state. - llvm::SmallSet<const CXXRecordDecl *, 32> SeenVBase; - /// BLayout - Layout for the most derived class that this vtable is being - /// built for. - const ASTRecordLayout &BLayout; - CGVtableInfo::AddrMap_t &AddressPoints; - // vtbl - A pointer to the vtable for Class. - llvm::Constant *ClassVtbl; - llvm::LLVMContext &VMContext; - - /// SeenVBasesInSecondary - The seen virtual bases when building the - /// secondary virtual pointers. - llvm::SmallPtrSet<const CXXRecordDecl *, 32> SeenVBasesInSecondary; + + CodeGenModule &CGM; - llvm::DenseMap<const CXXRecordDecl *, uint64_t> SubVTTIndicies; + /// MostDerivedClass - The most derived class for which we're building this + /// vtable. + const CXXRecordDecl *MostDerivedClass; + + typedef llvm::SmallVector<llvm::Constant *, 64> VTTComponentsVectorTy; - bool GenerateDefinition; + /// VTTComponents - The VTT components. + VTTComponentsVectorTy VTTComponents; + + /// MostDerivedClassLayout - the AST record layout of the most derived class. + const ASTRecordLayout &MostDerivedClassLayout; + + typedef llvm::SmallPtrSet<const CXXRecordDecl *, 4> VisitedVirtualBasesSetTy; - llvm::DenseMap<BaseSubobject, llvm::Constant *> CtorVtables; - llvm::DenseMap<std::pair<const CXXRecordDecl *, BaseSubobject>, uint64_t> - CtorVtableAddressPoints; + typedef llvm::DenseMap<BaseSubobject, uint64_t> AddressPointsMapTy; + + /// SubVTTIndicies - The sub-VTT indices for the bases of the most derived + /// class. + llvm::DenseMap<const CXXRecordDecl *, uint64_t> SubVTTIndicies; + + /// SecondaryVirtualPointerIndices - The secondary virtual pointer indices of + /// all subobjects of the most derived class. + llvm::DenseMap<BaseSubobject, uint64_t> SecondaryVirtualPointerIndices; + + /// GenerateDefinition - Whether the VTT builder should generate LLVM IR for + /// the VTT. + bool GenerateDefinition; - llvm::Constant *getCtorVtable(const BaseSubobject &Base, - bool BaseIsVirtual) { - if (!GenerateDefinition) - return 0; - - llvm::Constant *&CtorVtable = CtorVtables[Base]; - if (!CtorVtable) { - // Build the vtable. - CGVtableInfo::CtorVtableInfo Info - = CGM.getVtableInfo().getCtorVtable(Class, Base, BaseIsVirtual); - - CtorVtable = Info.Vtable; - - // Add the address points for this base. - for (CGVtableInfo::AddressPointsMapTy::const_iterator I = - Info.AddressPoints.begin(), E = Info.AddressPoints.end(); - I != E; ++I) { - uint64_t &AddressPoint = - CtorVtableAddressPoints[std::make_pair(Base.getBase(), I->first)]; - - // Check if we already have the address points for this base. - if (AddressPoint) - break; - - // Otherwise, insert it. - AddressPoint = I->second; - } - } - - return CtorVtable; + /// GetAddrOfVTable - Returns the address of the vtable for the base class in + /// the given vtable class. + /// + /// \param AddressPoints - If the returned vtable is a construction vtable, + /// this will hold the address points for it. + llvm::Constant *GetAddrOfVTable(BaseSubobject Base, bool BaseIsVirtual, + AddressPointsMapTy& AddressPoints); + + /// AddVTablePointer - Add a vtable pointer to the VTT currently being built. + /// + /// \param AddressPoints - If the vtable is a construction vtable, this has + /// the address points for it. + void AddVTablePointer(BaseSubobject Base, llvm::Constant *VTable, + const CXXRecordDecl *VTableClass, + const AddressPointsMapTy& AddressPoints); + + /// LayoutSecondaryVTTs - Lay out the secondary VTTs of the given base + /// subobject. + void LayoutSecondaryVTTs(BaseSubobject Base); + + /// LayoutSecondaryVirtualPointers - Lay out the secondary virtual pointers + /// for the given base subobject. + /// + /// \param BaseIsMorallyVirtual whether the base subobject is a virtual base + /// or a direct or indirect base of a virtual base. + /// + /// \param AddressPoints - If the vtable is a construction vtable, this has + /// the address points for it. + void LayoutSecondaryVirtualPointers(BaseSubobject Base, + bool BaseIsMorallyVirtual, + llvm::Constant *VTable, + const CXXRecordDecl *VTableClass, + const AddressPointsMapTy& AddressPoints, + VisitedVirtualBasesSetTy &VBases); + + /// LayoutSecondaryVirtualPointers - Lay out the secondary virtual pointers + /// for the given base subobject. + /// + /// \param AddressPoints - If the vtable is a construction vtable, this has + /// the address points for it. + void LayoutSecondaryVirtualPointers(BaseSubobject Base, + llvm::Constant *VTable, + const AddressPointsMapTy& AddressPoints); + + /// LayoutVirtualVTTs - Lay out the VTTs for the virtual base classes of the + /// given record decl. + void LayoutVirtualVTTs(const CXXRecordDecl *RD, + VisitedVirtualBasesSetTy &VBases); + + /// LayoutVTT - Will lay out the VTT for the given subobject, including any + /// secondary VTTs, secondary virtual pointers and virtual VTTs. + void LayoutVTT(BaseSubobject Base, bool BaseIsVirtual); + +public: + VTTBuilder(CodeGenModule &CGM, const CXXRecordDecl *MostDerivedClass, + bool GenerateDefinition); + + // getVTTComponents - Returns a reference to the VTT components. + const VTTComponentsVectorTy &getVTTComponents() const { + return VTTComponents; } + /// getSubVTTIndicies - Returns a reference to the sub-VTT indices. + const llvm::DenseMap<const CXXRecordDecl *, uint64_t> & + getSubVTTIndicies() const { + return SubVTTIndicies; + } - /// BuildVtablePtr - Build up a referene to the given secondary vtable - llvm::Constant *BuildVtablePtr(llvm::Constant *Vtable, - const CXXRecordDecl *VtableClass, - const CXXRecordDecl *RD, - uint64_t Offset) { - if (!GenerateDefinition) - return 0; - - uint64_t AddressPoint; - - if (VtableClass != Class) { - // We have a ctor vtable, look for the address point in the ctor vtable - // address points. - AddressPoint = - CtorVtableAddressPoints[std::make_pair(VtableClass, - BaseSubobject(RD, Offset))]; - } else { - AddressPoint = - (*AddressPoints[VtableClass])[std::make_pair(RD, Offset)]; - } + /// getSecondaryVirtualPointerIndices - Returns a reference to the secondary + /// virtual pointer indices. + const llvm::DenseMap<BaseSubobject, uint64_t> & + getSecondaryVirtualPointerIndices() const { + return SecondaryVirtualPointerIndices; + } - // FIXME: We can never have 0 address point. Do this for now so gepping - // retains the same structure. Later we'll just assert. - if (AddressPoint == 0) - AddressPoint = 1; - D1(printf("XXX address point for %s in %s layout %s at offset %d was %d\n", - RD->getNameAsCString(), VtblClass->getNameAsCString(), - Class->getNameAsCString(), (int)Offset, (int)AddressPoint)); - - llvm::Value *Idxs[] = { - llvm::ConstantInt::get(llvm::Type::getInt64Ty(VMContext), 0), - llvm::ConstantInt::get(llvm::Type::getInt64Ty(VMContext), AddressPoint) - }; +}; + +VTTBuilder::VTTBuilder(CodeGenModule &CGM, + const CXXRecordDecl *MostDerivedClass, + bool GenerateDefinition) + : CGM(CGM), MostDerivedClass(MostDerivedClass), + MostDerivedClassLayout(CGM.getContext().getASTRecordLayout(MostDerivedClass)), + GenerateDefinition(GenerateDefinition) { - llvm::Constant *Init = - llvm::ConstantExpr::getInBoundsGetElementPtr(Vtable, Idxs, 2); + // Lay out this VTT. + LayoutVTT(BaseSubobject(MostDerivedClass, 0), /*BaseIsVirtual=*/false); +} - const llvm::Type *Int8PtrTy = llvm::Type::getInt8PtrTy(VMContext); - return llvm::ConstantExpr::getBitCast(Init, Int8PtrTy); +llvm::Constant * +VTTBuilder::GetAddrOfVTable(BaseSubobject Base, bool BaseIsVirtual, + AddressPointsMapTy& AddressPoints) { + if (!GenerateDefinition) + return 0; + + if (Base.getBase() == MostDerivedClass) { + assert(Base.getBaseOffset() == 0 && + "Most derived class vtable must have a zero offset!"); + // This is a regular vtable. + return CGM.getVTables().GetAddrOfVTable(MostDerivedClass); } + + return CGM.getVTables().GenerateConstructionVTable(MostDerivedClass, + Base, BaseIsVirtual, + AddressPoints); +} - /// 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, llvm::Constant *vtbl, - const CXXRecordDecl *VtblClass, uint64_t Offset=0, - bool MorallyVirtual=false) { - if (RD->getNumVBases() == 0 && ! MorallyVirtual) - return; - - 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()); - - // We only want to visit each virtual base once. - if (i->isVirtual() && SeenVBasesInSecondary.count(Base)) - continue; - - // Itanium C++ ABI 2.6.2: - // Secondary virtual pointers are present for all bases with either - // virtual bases or virtual function declarations overridden along a - // virtual path. - // - // If the base class is not dynamic, we don't want to add it, nor any - // of its base classes. - if (!Base->isDynamicClass()) - continue; +void VTTBuilder::AddVTablePointer(BaseSubobject Base, llvm::Constant *VTable, + const CXXRecordDecl *VTableClass, + const AddressPointsMapTy& AddressPoints) { + // Store the vtable pointer index if we're generating the primary VTT. + if (VTableClass == MostDerivedClass) { + assert(!SecondaryVirtualPointerIndices.count(Base) && + "A virtual pointer index already exists for this base subobject!"); + SecondaryVirtualPointerIndices[Base] = VTTComponents.size(); + } - const ASTRecordLayout &Layout = CGM.getContext().getASTRecordLayout(RD); - const CXXRecordDecl *PrimaryBase = Layout.getPrimaryBase(); - const bool PrimaryBaseWasVirtual = Layout.getPrimaryBaseWasVirtual(); - bool NonVirtualPrimaryBase; - NonVirtualPrimaryBase = !PrimaryBaseWasVirtual && Base == PrimaryBase; - bool BaseMorallyVirtual = MorallyVirtual | i->isVirtual(); - uint64_t BaseOffset; - if (!i->isVirtual()) { - const ASTRecordLayout &Layout = CGM.getContext().getASTRecordLayout(RD); - BaseOffset = Offset + Layout.getBaseClassOffset(Base); - } else - BaseOffset = BLayout.getVBaseClassOffset(Base); - llvm::Constant *subvtbl = vtbl; - const CXXRecordDecl *subVtblClass = VtblClass; - if ((Base->getNumVBases() || BaseMorallyVirtual) - && !NonVirtualPrimaryBase) { - llvm::Constant *init; - if (BaseMorallyVirtual || VtblClass == Class) - init = BuildVtablePtr(vtbl, VtblClass, Base, BaseOffset); - else { - init = getCtorVtable(BaseSubobject(Base, BaseOffset), i->isVirtual()); - - subvtbl = init; - subVtblClass = Base; - - init = BuildVtablePtr(init, Class, Base, BaseOffset); - } - - Inits.push_back(init); - } - - if (i->isVirtual()) - SeenVBasesInSecondary.insert(Base); - - Secondary(Base, subvtbl, subVtblClass, BaseOffset, BaseMorallyVirtual); - } + if (!GenerateDefinition) { + VTTComponents.push_back(0); + return; } - /// 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 BaseIsVirtual, - bool MorallyVirtual) { - // Itanium C++ ABI 2.6.2: - // An array of virtual table addresses, called the VTT, is declared for - // each class type that has indirect or direct virtual base classes. - if (RD->getNumVBases() == 0) - return; + uint64_t AddressPoint; + if (VTableClass != MostDerivedClass) { + // The vtable is a construction vtable, look in the construction vtable + // address points. + AddressPoint = AddressPoints.lookup(Base); + } else { + // Just get the address point for the regular vtable. + AddressPoint = CGM.getVTables().getAddressPoint(Base, VTableClass); + } - // Remember the sub-VTT index. - SubVTTIndicies[RD] = Inits.size(); + if (!AddressPoint) AddressPoint = 0; + assert(AddressPoint != 0 && "Did not find an address point!"); + + llvm::Value *Idxs[] = { + llvm::ConstantInt::get(llvm::Type::getInt64Ty(CGM.getLLVMContext()), 0), + llvm::ConstantInt::get(llvm::Type::getInt64Ty(CGM.getLLVMContext()), + AddressPoint) + }; + + llvm::Constant *Init = + llvm::ConstantExpr::getInBoundsGetElementPtr(VTable, Idxs, 2); + + const llvm::Type *Int8PtrTy = llvm::Type::getInt8PtrTy(CGM.getLLVMContext()); + Init = llvm::ConstantExpr::getBitCast(Init, Int8PtrTy); + + VTTComponents.push_back(Init); +} - llvm::Constant *Vtable; - const CXXRecordDecl *VtableClass; +void VTTBuilder::LayoutSecondaryVTTs(BaseSubobject Base) { + const CXXRecordDecl *RD = Base.getBase(); - // First comes the primary virtual table pointer... - if (MorallyVirtual) { - Vtable = ClassVtbl; - VtableClass = Class; - } else { - Vtable = getCtorVtable(BaseSubobject(RD, Offset), - /*IsVirtual=*/BaseIsVirtual); - VtableClass = RD; - } + for (CXXRecordDecl::base_class_const_iterator I = RD->bases_begin(), + E = RD->bases_end(); I != E; ++I) { - llvm::Constant *Init = BuildVtablePtr(Vtable, VtableClass, RD, Offset); - Inits.push_back(Init); - - // then the secondary VTTs.... - SecondaryVTTs(RD, Offset, MorallyVirtual); + // Don't layout virtual bases. + if (I->isVirtual()) + continue; - // Make sure to clear the set of seen virtual bases. - SeenVBasesInSecondary.clear(); + const CXXRecordDecl *BaseDecl = + cast<CXXRecordDecl>(I->getType()->getAs<RecordType>()->getDecl()); - // and last the secondary vtable pointers. - Secondary(RD, Vtable, VtableClass, Offset, MorallyVirtual); + const ASTRecordLayout &Layout = CGM.getContext().getASTRecordLayout(RD); + uint64_t BaseOffset = Base.getBaseOffset() + + Layout.getBaseClassOffset(BaseDecl); + + // Layout the VTT for this base. + LayoutVTT(BaseSubobject(BaseDecl, BaseOffset), /*BaseIsVirtual=*/false); } +} + +void +VTTBuilder::LayoutSecondaryVirtualPointers(BaseSubobject Base, + bool BaseIsMorallyVirtual, + llvm::Constant *VTable, + const CXXRecordDecl *VTableClass, + const AddressPointsMapTy& AddressPoints, + VisitedVirtualBasesSetTy &VBases) { + const CXXRecordDecl *RD = Base.getBase(); + + // We're not interested in bases that don't have virtual bases, and not + // morally virtual bases. + if (!RD->getNumVBases() && !BaseIsMorallyVirtual) + return; - /// 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, 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()) + for (CXXRecordDecl::base_class_const_iterator I = RD->bases_begin(), + E = RD->bases_end(); I != E; ++I) { + const CXXRecordDecl *BaseDecl = + cast<CXXRecordDecl>(I->getType()->getAs<RecordType>()->getDecl()); + + // Itanium C++ ABI 2.6.2: + // Secondary virtual pointers are present for all bases with either + // virtual bases or virtual function declarations overridden along a + // virtual path. + // + // If the base class is not dynamic, we don't want to add it, nor any + // of its base classes. + if (!BaseDecl->isDynamicClass()) + continue; + + bool BaseDeclIsMorallyVirtual = BaseIsMorallyVirtual; + bool BaseDeclIsNonVirtualPrimaryBase = false; + uint64_t BaseOffset; + if (I->isVirtual()) { + // Ignore virtual bases that we've already visited. + if (!VBases.insert(BaseDecl)) continue; + + BaseOffset = MostDerivedClassLayout.getVBaseClassOffset(BaseDecl); + BaseDeclIsMorallyVirtual = true; + } else { const ASTRecordLayout &Layout = CGM.getContext().getASTRecordLayout(RD); - uint64_t BaseOffset = Offset + Layout.getBaseClassOffset(Base); - BuildVTT(Base, BaseOffset, /*BaseIsVirtual=*/false, MorallyVirtual); + BaseOffset = Base.getBaseOffset() + Layout.getBaseClassOffset(BaseDecl); + + if (!Layout.getPrimaryBaseWasVirtual() && + Layout.getPrimaryBase() == BaseDecl) + BaseDeclIsNonVirtualPrimaryBase = true; } - } - /// VirtualVTTs - Add the VTT for each proper virtual base in inheritance - /// graph preorder. - void VirtualVTTs(const CXXRecordDecl *RD) { - 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() && !SeenVBase.count(Base)) { - SeenVBase.insert(Base); - uint64_t BaseOffset = BLayout.getVBaseClassOffset(Base); - BuildVTT(Base, BaseOffset, /*BaseIsVirtual=*/true, false); - } - VirtualVTTs(Base); + // Itanium C++ ABI 2.6.2: + // Secondary virtual pointers: for each base class X which (a) has virtual + // bases or is reachable along a virtual path from D, and (b) is not a + // non-virtual primary base, the address of the virtual table for X-in-D + // or an appropriate construction virtual table. + if (!BaseDeclIsNonVirtualPrimaryBase && + (BaseDecl->getNumVBases() || BaseDeclIsMorallyVirtual)) { + // Add the vtable pointer. + AddVTablePointer(BaseSubobject(BaseDecl, BaseOffset), VTable, VTableClass, + AddressPoints); } + + // And lay out the secondary virtual pointers for the base class. + LayoutSecondaryVirtualPointers(BaseSubobject(BaseDecl, BaseOffset), + BaseDeclIsMorallyVirtual, VTable, + VTableClass, AddressPoints, VBases); } +} -public: - VTTBuilder(std::vector<llvm::Constant *> &inits, const CXXRecordDecl *c, - CodeGenModule &cgm, bool GenerateDefinition) - : Inits(inits), Class(c), CGM(cgm), - BLayout(cgm.getContext().getASTRecordLayout(c)), - AddressPoints(*cgm.getVtableInfo().AddressPoints[c]), - VMContext(cgm.getModule().getContext()), - GenerateDefinition(GenerateDefinition) { - - // First comes the primary virtual table pointer for the complete class... - ClassVtbl = GenerateDefinition ? CGM.getVtableInfo().getVtable(Class) : 0; +void +VTTBuilder::LayoutSecondaryVirtualPointers(BaseSubobject Base, + llvm::Constant *VTable, + const AddressPointsMapTy& AddressPoints) { + VisitedVirtualBasesSetTy VBases; + LayoutSecondaryVirtualPointers(Base, /*BaseIsMorallyVirtual=*/false, + VTable, Base.getBase(), AddressPoints, VBases); +} - llvm::Constant *Init = BuildVtablePtr(ClassVtbl, Class, Class, 0); - Inits.push_back(Init); +void VTTBuilder::LayoutVirtualVTTs(const CXXRecordDecl *RD, + VisitedVirtualBasesSetTy &VBases) { + for (CXXRecordDecl::base_class_const_iterator I = RD->bases_begin(), + E = RD->bases_end(); I != E; ++I) { + const CXXRecordDecl *BaseDecl = + cast<CXXRecordDecl>(I->getType()->getAs<RecordType>()->getDecl()); - // then the secondary VTTs... - SecondaryVTTs(Class); + // Check if this is a virtual base. + if (I->isVirtual()) { + // Check if we've seen this base before. + if (!VBases.insert(BaseDecl)) + continue; + + uint64_t BaseOffset = + MostDerivedClassLayout.getVBaseClassOffset(BaseDecl); + + LayoutVTT(BaseSubobject(BaseDecl, BaseOffset), /*BaseIsVirtual=*/true); + } + + // We only need to layout virtual VTTs for this base if it actually has + // virtual bases. + if (BaseDecl->getNumVBases()) + LayoutVirtualVTTs(BaseDecl, VBases); + } +} - // Make sure to clear the set of seen virtual bases. - SeenVBasesInSecondary.clear(); +void VTTBuilder::LayoutVTT(BaseSubobject Base, bool BaseIsVirtual) { + const CXXRecordDecl *RD = Base.getBase(); - // then the secondary vtable pointers... - Secondary(Class, ClassVtbl, Class); + // Itanium C++ ABI 2.6.2: + // An array of virtual table addresses, called the VTT, is declared for + // each class type that has indirect or direct virtual base classes. + if (RD->getNumVBases() == 0) + return; + + bool IsPrimaryVTT = Base.getBase() == MostDerivedClass; - // and last, the virtual VTTs. - VirtualVTTs(Class); + if (!IsPrimaryVTT) { + // Remember the sub-VTT index. + SubVTTIndicies[RD] = VTTComponents.size(); } + + AddressPointsMapTy AddressPoints; + llvm::Constant *VTable = GetAddrOfVTable(Base, BaseIsVirtual, AddressPoints); + + // Add the primary vtable pointer. + AddVTablePointer(Base, VTable, RD, AddressPoints); + + // Add the secondary VTTs. + LayoutSecondaryVTTs(Base); - llvm::DenseMap<const CXXRecordDecl *, uint64_t> &getSubVTTIndicies() { - return SubVTTIndicies; + // Add the secondary virtual pointers. + LayoutSecondaryVirtualPointers(Base, VTable, AddressPoints); + + // If this is the primary VTT, we want to lay out virtual VTTs as well. + if (IsPrimaryVTT) { + VisitedVirtualBasesSetTy VBases; + LayoutVirtualVTTs(Base.getBase(), VBases); } -}; +} + } llvm::GlobalVariable * -CGVtableInfo::GenerateVTT(llvm::GlobalVariable::LinkageTypes Linkage, - bool GenerateDefinition, - const CXXRecordDecl *RD) { +CodeGenVTables::GenerateVTT(llvm::GlobalVariable::LinkageTypes Linkage, + bool GenerateDefinition, + const CXXRecordDecl *RD) { // Only classes that have virtual bases need a VTT. if (RD->getNumVBases() == 0) return 0; @@ -311,13 +383,15 @@ CGVtableInfo::GenerateVTT(llvm::GlobalVariable::LinkageTypes Linkage, const llvm::Type *Int8PtrTy = llvm::Type::getInt8PtrTy(CGM.getLLVMContext()); - std::vector<llvm::Constant *> inits; - VTTBuilder b(inits, RD, CGM, GenerateDefinition); + VTTBuilder Builder(CGM, RD, GenerateDefinition); + + const llvm::ArrayType *Type = + llvm::ArrayType::get(Int8PtrTy, Builder.getVTTComponents().size()); - const llvm::ArrayType *Type = llvm::ArrayType::get(Int8PtrTy, inits.size()); llvm::Constant *Init = 0; if (GenerateDefinition) - Init = llvm::ConstantArray::get(Type, inits); + Init = llvm::ConstantArray::get(Type, Builder.getVTTComponents().data(), + Builder.getVTTComponents().size()); llvm::GlobalVariable *OldGV = GV; GV = new llvm::GlobalVariable(CGM.getModule(), Type, /*isConstant=*/true, @@ -336,26 +410,12 @@ CGVtableInfo::GenerateVTT(llvm::GlobalVariable::LinkageTypes Linkage, return GV; } -CGVtableInfo::CtorVtableInfo -CGVtableInfo::getCtorVtable(const CXXRecordDecl *RD, - const BaseSubobject &Base, bool BaseIsVirtual) { - CtorVtableInfo Info; - - Info.Vtable = GenerateVtable(llvm::GlobalValue::InternalLinkage, - /*GenerateDefinition=*/true, - RD, Base.getBase(), Base.getBaseOffset(), - BaseIsVirtual, Info.AddressPoints); - return Info; -} - -llvm::GlobalVariable *CGVtableInfo::getVTT(const CXXRecordDecl *RD) { +llvm::GlobalVariable *CodeGenVTables::getVTT(const CXXRecordDecl *RD) { return GenerateVTT(llvm::GlobalValue::ExternalLinkage, /*GenerateDefinition=*/false, RD); - } - -bool CGVtableInfo::needsVTTParameter(GlobalDecl GD) { +bool CodeGenVTables::needsVTTParameter(GlobalDecl GD) { const CXXMethodDecl *MD = cast<CXXMethodDecl>(GD.getDecl()); // We don't have any virtual bases, just return early. @@ -373,19 +433,17 @@ bool CGVtableInfo::needsVTTParameter(GlobalDecl GD) { return false; } -uint64_t CGVtableInfo::getSubVTTIndex(const CXXRecordDecl *RD, - const CXXRecordDecl *Base) { +uint64_t CodeGenVTables::getSubVTTIndex(const CXXRecordDecl *RD, + const CXXRecordDecl *Base) { ClassPairTy ClassPair(RD, Base); - SubVTTIndiciesTy::iterator I = - SubVTTIndicies.find(ClassPair); + SubVTTIndiciesMapTy::iterator I = SubVTTIndicies.find(ClassPair); if (I != SubVTTIndicies.end()) return I->second; - std::vector<llvm::Constant *> inits; - VTTBuilder Builder(inits, RD, CGM, /*GenerateDefinition=*/false); + VTTBuilder Builder(CGM, RD, /*GenerateDefinition=*/false); - for (llvm::DenseMap<const CXXRecordDecl *, uint64_t>::iterator I = + for (llvm::DenseMap<const CXXRecordDecl *, uint64_t>::const_iterator I = Builder.getSubVTTIndicies().begin(), E = Builder.getSubVTTIndicies().end(); I != E; ++I) { // Insert all indices. @@ -399,3 +457,31 @@ uint64_t CGVtableInfo::getSubVTTIndex(const CXXRecordDecl *RD, return I->second; } + +uint64_t +CodeGenVTables::getSecondaryVirtualPointerIndex(const CXXRecordDecl *RD, + BaseSubobject Base) { + SecondaryVirtualPointerIndicesMapTy::iterator I = + SecondaryVirtualPointerIndices.find(std::make_pair(RD, Base)); + + if (I != SecondaryVirtualPointerIndices.end()) + return I->second; + + VTTBuilder Builder(CGM, RD, /*GenerateDefinition=*/false); + + // Insert all secondary vpointer indices. + for (llvm::DenseMap<BaseSubobject, uint64_t>::const_iterator I = + Builder.getSecondaryVirtualPointerIndices().begin(), + E = Builder.getSecondaryVirtualPointerIndices().end(); I != E; ++I) { + std::pair<const CXXRecordDecl *, BaseSubobject> Pair = + std::make_pair(RD, I->first); + + SecondaryVirtualPointerIndices.insert(std::make_pair(Pair, I->second)); + } + + I = SecondaryVirtualPointerIndices.find(std::make_pair(RD, Base)); + assert(I != SecondaryVirtualPointerIndices.end() && "Did not find index!"); + + return I->second; +} + |