diff options
Diffstat (limited to 'contrib/llvm/tools/clang/lib/CodeGen/CGVTT.cpp')
-rw-r--r-- | contrib/llvm/tools/clang/lib/CodeGen/CGVTT.cpp | 421 |
1 files changed, 60 insertions, 361 deletions
diff --git a/contrib/llvm/tools/clang/lib/CodeGen/CGVTT.cpp b/contrib/llvm/tools/clang/lib/CodeGen/CGVTT.cpp index cec02cd..ea7b8cb 100644 --- a/contrib/llvm/tools/clang/lib/CodeGen/CGVTT.cpp +++ b/contrib/llvm/tools/clang/lib/CodeGen/CGVTT.cpp @@ -14,383 +14,81 @@ #include "CodeGenModule.h" #include "CGCXXABI.h" #include "clang/AST/RecordLayout.h" +#include "clang/AST/VTTBuilder.h" using namespace clang; using namespace CodeGen; #define D1(x) -namespace { - -/// VTT builder - Class for building VTT layout information. -class VTTBuilder { - - CodeGenModule &CGM; - - /// MostDerivedClass - The most derived class for which we're building this - /// vtable. - const CXXRecordDecl *MostDerivedClass; - - typedef llvm::SmallVector<llvm::Constant *, 64> VTTComponentsVectorTy; - - /// 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; - - typedef llvm::DenseMap<BaseSubobject, uint64_t> AddressPointsMapTy; - - /// SubVTTIndicies - The sub-VTT indices for the bases of the most derived - /// class. - llvm::DenseMap<BaseSubobject, 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; - - /// The linkage to use for any construction vtables required by this VTT. - /// Only required if we're building a definition. - llvm::GlobalVariable::LinkageTypes LinkageForConstructionVTables; - - /// 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, - llvm::GlobalVariable::LinkageTypes LinkageForConstructionVTables - = (llvm::GlobalVariable::LinkageTypes) -1); - - // 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<BaseSubobject, uint64_t> &getSubVTTIndicies() const { - return SubVTTIndicies; - } - - /// getSecondaryVirtualPointerIndices - Returns a reference to the secondary - /// virtual pointer indices. - const llvm::DenseMap<BaseSubobject, uint64_t> & - getSecondaryVirtualPointerIndices() const { - return SecondaryVirtualPointerIndices; - } - -}; - -VTTBuilder::VTTBuilder(CodeGenModule &CGM, - const CXXRecordDecl *MostDerivedClass, - bool GenerateDefinition, - llvm::GlobalVariable::LinkageTypes LinkageForConstructionVTables) - : CGM(CGM), MostDerivedClass(MostDerivedClass), - MostDerivedClassLayout(CGM.getContext().getASTRecordLayout(MostDerivedClass)), - GenerateDefinition(GenerateDefinition), - LinkageForConstructionVTables(LinkageForConstructionVTables) { - assert(!GenerateDefinition || - LinkageForConstructionVTables - != (llvm::GlobalVariable::LinkageTypes) -1); - - // Lay out this VTT. - LayoutVTT(BaseSubobject(MostDerivedClass, CharUnits::Zero()), - /*BaseIsVirtual=*/false); -} - -llvm::Constant * -VTTBuilder::GetAddrOfVTable(BaseSubobject Base, bool BaseIsVirtual, - AddressPointsMapTy& AddressPoints) { - if (!GenerateDefinition) - return 0; - - if (Base.getBase() == MostDerivedClass) { - assert(Base.getBaseOffset().isZero() && +llvm::Constant *GetAddrOfVTTVTable(CodeGenVTables &CGVT, + const CXXRecordDecl *MostDerivedClass, + const VTTVTable &VTable, + llvm::GlobalVariable::LinkageTypes Linkage, + llvm::DenseMap<BaseSubobject, uint64_t> &AddressPoints) { + if (VTable.getBase() == MostDerivedClass) { + assert(VTable.getBaseOffset().isZero() && "Most derived class vtable must have a zero offset!"); // This is a regular vtable. - return CGM.getVTables().GetAddrOfVTable(MostDerivedClass); + return CGVT.GetAddrOfVTable(MostDerivedClass); } - return CGM.getVTables().GenerateConstructionVTable(MostDerivedClass, - Base, BaseIsVirtual, - LinkageForConstructionVTables, - AddressPoints); + return CGVT.GenerateConstructionVTable(MostDerivedClass, + VTable.getBaseSubobject(), + VTable.isVirtual(), + Linkage, + AddressPoints); } -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(); - } - - if (!GenerateDefinition) { - VTTComponents.push_back(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); - assert(AddressPoint != 0 && "Did not find ctor vtable address point!"); - } else { - // Just get the address point for the regular vtable. - AddressPoint = CGM.getVTables().getAddressPoint(Base, VTableClass); - assert(AddressPoint != 0 && "Did not find vtable address point!"); - } +void +CodeGenVTables::EmitVTTDefinition(llvm::GlobalVariable *VTT, + llvm::GlobalVariable::LinkageTypes Linkage, + const CXXRecordDecl *RD) { + VTTBuilder Builder(CGM.getContext(), RD, /*GenerateDefinition=*/true); - if (!AddressPoint) AddressPoint = 0; - - 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); + llvm::Type *Int8PtrTy = llvm::Type::getInt8PtrTy(CGM.getLLVMContext()), + *Int64Ty = llvm::Type::getInt64Ty(CGM.getLLVMContext()); + llvm::ArrayType *ArrayType = + llvm::ArrayType::get(Int8PtrTy, Builder.getVTTComponents().size()); - VTTComponents.push_back(Init); -} - -void VTTBuilder::LayoutSecondaryVTTs(BaseSubobject Base) { - const CXXRecordDecl *RD = Base.getBase(); - - for (CXXRecordDecl::base_class_const_iterator I = RD->bases_begin(), - E = RD->bases_end(); I != E; ++I) { - - // Don't layout virtual bases. - if (I->isVirtual()) - continue; - - const CXXRecordDecl *BaseDecl = - cast<CXXRecordDecl>(I->getType()->getAs<RecordType>()->getDecl()); - - const ASTRecordLayout &Layout = CGM.getContext().getASTRecordLayout(RD); - CharUnits BaseOffset = Base.getBaseOffset() + - Layout.getBaseClassOffset(BaseDecl); - - // Layout the VTT for this base. - LayoutVTT(BaseSubobject(BaseDecl, BaseOffset), /*BaseIsVirtual=*/false); + SmallVector<llvm::Constant *, 8> VTables; + SmallVector<VTableAddressPointsMapTy, 8> VTableAddressPoints; + for (const VTTVTable *i = Builder.getVTTVTables().begin(), + *e = Builder.getVTTVTables().end(); i != e; ++i) { + VTableAddressPoints.push_back(VTableAddressPointsMapTy()); + VTables.push_back(GetAddrOfVTTVTable(*this, RD, *i, Linkage, + VTableAddressPoints.back())); } -} - -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; - 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; - CharUnits BaseOffset; - if (I->isVirtual()) { - // Ignore virtual bases that we've already visited. - if (!VBases.insert(BaseDecl)) - continue; - - BaseOffset = MostDerivedClassLayout.getVBaseClassOffset(BaseDecl); - BaseDeclIsMorallyVirtual = true; + SmallVector<llvm::Constant *, 8> VTTComponents; + for (const VTTComponent *i = Builder.getVTTComponents().begin(), + *e = Builder.getVTTComponents().end(); i != e; ++i) { + const VTTVTable &VTTVT = Builder.getVTTVTables()[i->VTableIndex]; + llvm::Constant *VTable = VTables[i->VTableIndex]; + uint64_t AddressPoint; + if (VTTVT.getBase() == RD) { + // Just get the address point for the regular vtable. + AddressPoint = VTContext.getVTableLayout(RD) + .getAddressPoint(i->VTableBase); + assert(AddressPoint != 0 && "Did not find vtable address point!"); } else { - const ASTRecordLayout &Layout = CGM.getContext().getASTRecordLayout(RD); - - BaseOffset = Base.getBaseOffset() + - Layout.getBaseClassOffset(BaseDecl); - - if (!Layout.isPrimaryBaseVirtual() && - Layout.getPrimaryBase() == BaseDecl) - BaseDeclIsNonVirtualPrimaryBase = true; + AddressPoint = VTableAddressPoints[i->VTableIndex].lookup(i->VTableBase); + assert(AddressPoint != 0 && "Did not find ctor vtable address point!"); } - // 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); - } + llvm::Value *Idxs[] = { + llvm::ConstantInt::get(Int64Ty, 0), + llvm::ConstantInt::get(Int64Ty, AddressPoint) + }; - // And lay out the secondary virtual pointers for the base class. - LayoutSecondaryVirtualPointers(BaseSubobject(BaseDecl, BaseOffset), - BaseDeclIsMorallyVirtual, VTable, - VTableClass, AddressPoints, VBases); - } -} + llvm::Constant *Init = + llvm::ConstantExpr::getInBoundsGetElementPtr(VTable, Idxs); -void -VTTBuilder::LayoutSecondaryVirtualPointers(BaseSubobject Base, - llvm::Constant *VTable, - const AddressPointsMapTy& AddressPoints) { - VisitedVirtualBasesSetTy VBases; - LayoutSecondaryVirtualPointers(Base, /*BaseIsMorallyVirtual=*/false, - VTable, Base.getBase(), AddressPoints, VBases); -} + Init = llvm::ConstantExpr::getBitCast(Init, Int8PtrTy); -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()); - - // Check if this is a virtual base. - if (I->isVirtual()) { - // Check if we've seen this base before. - if (!VBases.insert(BaseDecl)) - continue; - - CharUnits 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); + VTTComponents.push_back(Init); } -} -void VTTBuilder::LayoutVTT(BaseSubobject Base, bool BaseIsVirtual) { - const CXXRecordDecl *RD = Base.getBase(); - - // 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; - - if (!IsPrimaryVTT) { - // Remember the sub-VTT index. - SubVTTIndicies[Base] = 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); - - // 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); - } -} - -} - -void -CodeGenVTables::EmitVTTDefinition(llvm::GlobalVariable *VTT, - llvm::GlobalVariable::LinkageTypes Linkage, - const CXXRecordDecl *RD) { - VTTBuilder Builder(CGM, RD, /*GenerateDefinition=*/true, Linkage); - - const llvm::Type *Int8PtrTy = llvm::Type::getInt8PtrTy(CGM.getLLVMContext()); - const llvm::ArrayType *ArrayType = - llvm::ArrayType::get(Int8PtrTy, Builder.getVTTComponents().size()); - - llvm::Constant *Init = - llvm::ConstantArray::get(ArrayType, Builder.getVTTComponents()); + llvm::Constant *Init = llvm::ConstantArray::get(ArrayType, VTTComponents); VTT->setInitializer(Init); @@ -408,15 +106,16 @@ llvm::GlobalVariable *CodeGenVTables::GetAddrOfVTT(const CXXRecordDecl *RD) { llvm::raw_svector_ostream Out(OutName); CGM.getCXXABI().getMangleContext().mangleCXXVTT(RD, Out); Out.flush(); - llvm::StringRef Name = OutName.str(); + StringRef Name = OutName.str(); - ComputeVTableRelatedInformation(RD, /*VTableRequired=*/true); + // This will also defer the definition of the VTT. + (void) GetAddrOfVTable(RD); - VTTBuilder Builder(CGM, RD, /*GenerateDefinition=*/false); + VTTBuilder Builder(CGM.getContext(), RD, /*GenerateDefinition=*/false); - const llvm::Type *Int8PtrTy = + llvm::Type *Int8PtrTy = llvm::Type::getInt8PtrTy(CGM.getLLVMContext()); - const llvm::ArrayType *ArrayType = + llvm::ArrayType *ArrayType = llvm::ArrayType::get(Int8PtrTy, Builder.getVTTComponents().size()); llvm::GlobalVariable *GV = @@ -452,7 +151,7 @@ uint64_t CodeGenVTables::getSubVTTIndex(const CXXRecordDecl *RD, if (I != SubVTTIndicies.end()) return I->second; - VTTBuilder Builder(CGM, RD, /*GenerateDefinition=*/false); + VTTBuilder Builder(CGM.getContext(), RD, /*GenerateDefinition=*/false); for (llvm::DenseMap<BaseSubobject, uint64_t>::const_iterator I = Builder.getSubVTTIndicies().begin(), @@ -478,7 +177,7 @@ CodeGenVTables::getSecondaryVirtualPointerIndex(const CXXRecordDecl *RD, if (I != SecondaryVirtualPointerIndices.end()) return I->second; - VTTBuilder Builder(CGM, RD, /*GenerateDefinition=*/false); + VTTBuilder Builder(CGM.getContext(), RD, /*GenerateDefinition=*/false); // Insert all secondary vpointer indices. for (llvm::DenseMap<BaseSubobject, uint64_t>::const_iterator I = |