diff options
Diffstat (limited to 'clang/lib')
-rw-r--r-- | clang/lib/AST/VTableBuilder.cpp | 96 | ||||
-rw-r--r-- | clang/lib/CodeGen/CGCXX.cpp | 9 | ||||
-rw-r--r-- | clang/lib/CodeGen/CGVTT.cpp | 11 | ||||
-rw-r--r-- | clang/lib/CodeGen/CGVTables.cpp | 33 | ||||
-rw-r--r-- | clang/lib/CodeGen/CGVTables.h | 10 | ||||
-rw-r--r-- | clang/lib/CodeGen/ItaniumCXXABI.cpp | 23 | ||||
-rw-r--r-- | clang/lib/CodeGen/MicrosoftCXXABI.cpp | 16 |
7 files changed, 103 insertions, 95 deletions
diff --git a/clang/lib/AST/VTableBuilder.cpp b/clang/lib/AST/VTableBuilder.cpp index 46308c2e506..e60ae33f2e5 100644 --- a/clang/lib/AST/VTableBuilder.cpp +++ b/clang/lib/AST/VTableBuilder.cpp @@ -777,9 +777,8 @@ public: typedef llvm::DenseMap<const CXXRecordDecl *, CharUnits> VBaseOffsetOffsetsMapTy; - - typedef llvm::DenseMap<BaseSubobject, uint64_t> - AddressPointsMapTy; + + typedef VTableLayout::AddressPointsMapTy AddressPointsMapTy; typedef llvm::DenseMap<GlobalDecl, int64_t> MethodVTableIndicesTy; @@ -817,7 +816,7 @@ private: /// VBaseOffsetOffsets - Contains the offsets of the virtual base offsets for /// the most derived class. VBaseOffsetOffsetsMapTy VBaseOffsetOffsets; - + /// Components - The components of the vtable being built. SmallVector<VTableComponent, 64> Components; @@ -982,6 +981,10 @@ private: } public: + /// Component indices of the first component of each of the vtables in the + /// vtable group. + SmallVector<size_t, 4> VTableIndices; + ItaniumVTableBuilder(ItaniumVTableContext &VTables, const CXXRecordDecl *MostDerivedClass, CharUnits MostDerivedClassOffset, @@ -1028,20 +1031,8 @@ public: return MethodVTableIndices.end(); } - /// getNumVTableComponents - Return the number of components in the vtable - /// currently built. - uint64_t getNumVTableComponents() const { - return Components.size(); - } + ArrayRef<VTableComponent> vtable_components() const { return Components; } - const VTableComponent *vtable_component_begin() const { - return Components.begin(); - } - - const VTableComponent *vtable_component_end() const { - return Components.end(); - } - AddressPointsMapTy::const_iterator address_points_begin() const { return AddressPoints.begin(); } @@ -1639,6 +1630,9 @@ void ItaniumVTableBuilder::LayoutPrimaryAndSecondaryVTables( bool BaseIsVirtualInLayoutClass, CharUnits OffsetInLayoutClass) { assert(Base.getBase()->isDynamicClass() && "class does not have a vtable!"); + unsigned VTableIndex = Components.size(); + VTableIndices.push_back(VTableIndex); + // Add vcall and vbase offsets for this vtable. VCallAndVBaseOffsetBuilder Builder(MostDerivedClass, LayoutClass, &Overriders, Base, BaseIsVirtualInLayoutClass, @@ -1695,9 +1689,11 @@ void ItaniumVTableBuilder::LayoutPrimaryAndSecondaryVTables( // Add all address points. while (true) { - AddressPoints.insert(std::make_pair( - BaseSubobject(RD, OffsetInLayoutClass), - AddressPoint)); + AddressPoints.insert( + std::make_pair(BaseSubobject(RD, OffsetInLayoutClass), + VTableLayout::AddressPointLocation{ + unsigned(VTableIndices.size() - 1), + unsigned(AddressPoint - VTableIndex)})); const ASTRecordLayout &Layout = Context.getASTRecordLayout(RD); const CXXRecordDecl *PrimaryBase = Layout.getPrimaryBase(); @@ -1901,7 +1897,8 @@ void ItaniumVTableBuilder::dumpLayout(raw_ostream &Out) { std::multimap<uint64_t, BaseSubobject> AddressPointsByIndex; for (const auto &AP : AddressPoints) { const BaseSubobject &Base = AP.first; - uint64_t Index = AP.second; + uint64_t Index = + VTableIndices[AP.second.VTableIndex] + AP.second.AddressPointIndex; AddressPointsByIndex.insert(std::make_pair(Index, Base)); } @@ -2203,30 +2200,24 @@ void ItaniumVTableBuilder::dumpLayout(raw_ostream &Out) { } } -VTableLayout::VTableLayout(uint64_t NumVTableComponents, - const VTableComponent *VTableComponents, - uint64_t NumVTableThunks, - const VTableThunkTy *VTableThunks, - const AddressPointsMapTy &AddressPoints, - bool IsMicrosoftABI) - : NumVTableComponents(NumVTableComponents), - VTableComponents(new VTableComponent[NumVTableComponents]), - NumVTableThunks(NumVTableThunks), - VTableThunks(new VTableThunkTy[NumVTableThunks]), - AddressPoints(AddressPoints), - IsMicrosoftABI(IsMicrosoftABI) { - std::copy(VTableComponents, VTableComponents+NumVTableComponents, - this->VTableComponents.get()); - std::copy(VTableThunks, VTableThunks+NumVTableThunks, - this->VTableThunks.get()); - std::sort(this->VTableThunks.get(), - this->VTableThunks.get() + NumVTableThunks, +VTableLayout::VTableLayout(ArrayRef<size_t> VTableIndices, + ArrayRef<VTableComponent> VTableComponents, + ArrayRef<VTableThunkTy> VTableThunks, + const AddressPointsMapTy &AddressPoints) + : VTableComponents(VTableComponents), VTableThunks(VTableThunks), + AddressPoints(AddressPoints) { + if (VTableIndices.size() <= 1) + assert(VTableIndices.size() == 1 && VTableIndices[0] == 0); + else + this->VTableIndices = OwningArrayRef<size_t>(VTableIndices); + + std::sort(this->VTableThunks.begin(), this->VTableThunks.end(), [](const VTableLayout::VTableThunkTy &LHS, const VTableLayout::VTableThunkTy &RHS) { - assert((LHS.first != RHS.first || LHS.second == RHS.second) && - "Different thunks should have unique indices!"); - return LHS.first < RHS.first; - }); + assert((LHS.first != RHS.first || LHS.second == RHS.second) && + "Different thunks should have unique indices!"); + return LHS.first < RHS.first; + }); } VTableLayout::~VTableLayout() { } @@ -2284,9 +2275,8 @@ CreateVTableLayout(const ItaniumVTableBuilder &Builder) { VTableThunks(Builder.vtable_thunks_begin(), Builder.vtable_thunks_end()); return llvm::make_unique<VTableLayout>( - Builder.getNumVTableComponents(), Builder.vtable_component_begin(), - VTableThunks.size(), VTableThunks.data(), Builder.getAddressPoints(), - /*IsMicrosoftABI=*/false); + Builder.VTableIndices, Builder.vtable_components(), VTableThunks, + Builder.getAddressPoints()); } void @@ -2568,15 +2558,7 @@ public: MethodVFTableLocations.end()); } - uint64_t getNumVTableComponents() const { return Components.size(); } - - const VTableComponent *vtable_component_begin() const { - return Components.begin(); - } - - const VTableComponent *vtable_component_end() const { - return Components.end(); - } + ArrayRef<VTableComponent> vtable_components() const { return Components; } VTableThunksMapTy::const_iterator vtable_thunks_begin() const { return VTableThunks.begin(); @@ -3591,8 +3573,8 @@ void MicrosoftVTableContext::computeVTableRelatedInformation( SmallVector<VTableLayout::VTableThunkTy, 1> VTableThunks( Builder.vtable_thunks_begin(), Builder.vtable_thunks_end()); VFTableLayouts[id] = llvm::make_unique<VTableLayout>( - Builder.getNumVTableComponents(), Builder.vtable_component_begin(), - VTableThunks.size(), VTableThunks.data(), EmptyAddressPointsMap, true); + ArrayRef<size_t>{0}, Builder.vtable_components(), VTableThunks, + EmptyAddressPointsMap); Thunks.insert(Builder.thunks_begin(), Builder.thunks_end()); for (const auto &Loc : Builder.vtable_locations()) { diff --git a/clang/lib/CodeGen/CGCXX.cpp b/clang/lib/CodeGen/CGCXX.cpp index 589dea00c43..59010f4407c 100644 --- a/clang/lib/CodeGen/CGCXX.cpp +++ b/clang/lib/CodeGen/CGCXX.cpp @@ -272,10 +272,11 @@ static CGCallee BuildAppleKextVirtualCall(CodeGenFunction &CGF, VTable = CGF.Builder.CreateBitCast(VTable, Ty); assert(VTable && "BuildVirtualCall = kext vtbl pointer is null"); uint64_t VTableIndex = CGM.getItaniumVTableContext().getMethodVTableIndex(GD); - uint64_t AddressPoint = - CGM.getItaniumVTableContext().getVTableLayout(RD) - .getAddressPoint(BaseSubobject(RD, CharUnits::Zero())); - VTableIndex += AddressPoint; + const VTableLayout &VTLayout = CGM.getItaniumVTableContext().getVTableLayout(RD); + VTableLayout::AddressPointLocation AddressPoint = + VTLayout.getAddressPoint(BaseSubobject(RD, CharUnits::Zero())); + VTableIndex += VTLayout.getVTableOffset(AddressPoint.VTableIndex) + + AddressPoint.AddressPointIndex; llvm::Value *VFuncPtr = CGF.Builder.CreateConstInBoundsGEP1_64(VTable, VTableIndex, "vfnkxt"); llvm::Value *VFunc = diff --git a/clang/lib/CodeGen/CGVTT.cpp b/clang/lib/CodeGen/CGVTT.cpp index 5b90ee60330..352d101d99b 100644 --- a/clang/lib/CodeGen/CGVTT.cpp +++ b/clang/lib/CodeGen/CGVTT.cpp @@ -23,7 +23,7 @@ GetAddrOfVTTVTable(CodeGenVTables &CGVT, CodeGenModule &CGM, const CXXRecordDecl *MostDerivedClass, const VTTVTable &VTable, llvm::GlobalVariable::LinkageTypes Linkage, - llvm::DenseMap<BaseSubobject, uint64_t> &AddressPoints) { + VTableLayout::AddressPointsMapTy &AddressPoints) { if (VTable.getBase() == MostDerivedClass) { assert(VTable.getBaseOffset().isZero() && "Most derived class vtable must have a zero offset!"); @@ -62,21 +62,22 @@ CodeGenVTables::EmitVTTDefinition(llvm::GlobalVariable *VTT, *e = Builder.getVTTComponents().end(); i != e; ++i) { const VTTVTable &VTTVT = Builder.getVTTVTables()[i->VTableIndex]; llvm::GlobalVariable *VTable = VTables[i->VTableIndex]; - uint64_t AddressPoint; + VTableLayout::AddressPointLocation AddressPoint; if (VTTVT.getBase() == RD) { // Just get the address point for the regular vtable. AddressPoint = getItaniumVTableContext().getVTableLayout(RD).getAddressPoint( i->VTableBase); - assert(AddressPoint != 0 && "Did not find vtable address point!"); } else { AddressPoint = VTableAddressPoints[i->VTableIndex].lookup(i->VTableBase); - assert(AddressPoint != 0 && "Did not find ctor vtable address point!"); + assert(AddressPoint.AddressPointIndex != 0 && + "Did not find ctor vtable address point!"); } llvm::Value *Idxs[] = { llvm::ConstantInt::get(Int32Ty, 0), - llvm::ConstantInt::get(Int32Ty, AddressPoint) + llvm::ConstantInt::get(Int32Ty, AddressPoint.VTableIndex), + llvm::ConstantInt::get(Int32Ty, AddressPoint.AddressPointIndex), }; llvm::Constant *Init = llvm::ConstantExpr::getInBoundsGetElementPtr( diff --git a/clang/lib/CodeGen/CGVTables.cpp b/clang/lib/CodeGen/CGVTables.cpp index be9c3115126..1a09830b52f 100644 --- a/clang/lib/CodeGen/CGVTables.cpp +++ b/clang/lib/CodeGen/CGVTables.cpp @@ -637,12 +637,27 @@ void CodeGenVTables::addVTableComponent( llvm_unreachable("Unexpected vtable component kind"); } -void CodeGenVTables::createVTableInitializer(ConstantArrayBuilder &builder, +llvm::Type *CodeGenVTables::getVTableType(const VTableLayout &layout) { + SmallVector<llvm::Type *, 4> tys; + for (unsigned i = 0, e = layout.getNumVTables(); i != e; ++i) { + tys.push_back(llvm::ArrayType::get(CGM.Int8PtrTy, layout.getVTableSize(i))); + } + + return llvm::StructType::get(CGM.getLLVMContext(), tys); +} + +void CodeGenVTables::createVTableInitializer(ConstantStructBuilder &builder, const VTableLayout &layout, llvm::Constant *rtti) { unsigned nextVTableThunkIndex = 0; - for (unsigned i = 0, e = layout.vtable_components().size(); i != e; ++i) { - addVTableComponent(builder, layout, i, rtti, nextVTableThunkIndex); + for (unsigned i = 0, e = layout.getNumVTables(); i != e; ++i) { + auto vtableElem = builder.beginArray(CGM.Int8PtrTy); + size_t thisIndex = layout.getVTableOffset(i); + size_t nextIndex = thisIndex + layout.getVTableSize(i); + for (unsigned i = thisIndex; i != nextIndex; ++i) { + addVTableComponent(vtableElem, layout, i, rtti, nextVTableThunkIndex); + } + vtableElem.finishAndAddTo(builder); } } @@ -670,8 +685,7 @@ CodeGenVTables::GenerateConstructionVTable(const CXXRecordDecl *RD, Base.getBase(), Out); StringRef Name = OutName.str(); - llvm::ArrayType *ArrayType = - llvm::ArrayType::get(CGM.Int8PtrTy, VTLayout->vtable_components().size()); + llvm::Type *VTType = getVTableType(*VTLayout); // Construction vtable symbols are not part of the Itanium ABI, so we cannot // guarantee that they actually will be available externally. Instead, when @@ -683,7 +697,7 @@ CodeGenVTables::GenerateConstructionVTable(const CXXRecordDecl *RD, // Create the variable that will hold the construction vtable. llvm::GlobalVariable *VTable = - CGM.CreateOrReplaceCXXRuntimeVariable(Name, ArrayType, Linkage); + CGM.CreateOrReplaceCXXRuntimeVariable(Name, VTType, Linkage); CGM.setGlobalVisibility(VTable, RD); // V-tables are always unnamed_addr. @@ -694,7 +708,7 @@ CodeGenVTables::GenerateConstructionVTable(const CXXRecordDecl *RD, // Create and set the initializer. ConstantInitBuilder builder(CGM); - auto components = builder.beginArray(CGM.Int8PtrTy); + auto components = builder.beginStruct(); createVTableInitializer(components, *VTLayout, RTTI); components.finishAndSetAsInitializer(VTable); @@ -938,7 +952,10 @@ void CodeGenModule::EmitVTableTypeMetadata(llvm::GlobalVariable *VTable, std::vector<BSEntry> BitsetEntries; // Create a bit set entry for each address point. for (auto &&AP : VTLayout.getAddressPoints()) - BitsetEntries.push_back(std::make_pair(AP.first.getBase(), AP.second)); + BitsetEntries.push_back( + std::make_pair(AP.first.getBase(), + VTLayout.getVTableOffset(AP.second.VTableIndex) + + AP.second.AddressPointIndex)); // Sort the bit set entries for determinism. std::sort(BitsetEntries.begin(), BitsetEntries.end(), diff --git a/clang/lib/CodeGen/CGVTables.h b/clang/lib/CodeGen/CGVTables.h index 1d06832c46b..b92212c368a 100644 --- a/clang/lib/CodeGen/CGVTables.h +++ b/clang/lib/CodeGen/CGVTables.h @@ -28,6 +28,7 @@ namespace clang { namespace CodeGen { class CodeGenModule; class ConstantArrayBuilder; + class ConstantStructBuilder; class CodeGenVTables { CodeGenModule &CGM; @@ -35,7 +36,7 @@ class CodeGenVTables { VTableContextBase *VTContext; /// VTableAddressPointsMapTy - Address points for a single vtable. - typedef llvm::DenseMap<BaseSubobject, uint64_t> VTableAddressPointsMapTy; + typedef VTableLayout::AddressPointsMapTy VTableAddressPointsMapTy; typedef std::pair<const CXXRecordDecl *, BaseSubobject> BaseSubobjectPairTy; typedef llvm::DenseMap<BaseSubobjectPairTy, uint64_t> SubVTTIndiciesMapTy; @@ -71,7 +72,7 @@ class CodeGenVTables { public: /// Add vtable components for the given vtable layout to the given /// global initializer. - void createVTableInitializer(ConstantArrayBuilder &builder, + void createVTableInitializer(ConstantStructBuilder &builder, const VTableLayout &layout, llvm::Constant *rtti); @@ -121,6 +122,11 @@ public: void GenerateClassData(const CXXRecordDecl *RD); bool isVTableExternal(const CXXRecordDecl *RD); + + /// Returns the type of a vtable with the given layout. Normally a struct of + /// arrays of pointers, with one struct element for each vtable in the vtable + /// group. + llvm::Type *getVTableType(const VTableLayout &layout); }; } // end namespace CodeGen diff --git a/clang/lib/CodeGen/ItaniumCXXABI.cpp b/clang/lib/CodeGen/ItaniumCXXABI.cpp index db648f23327..d32a131c6d0 100644 --- a/clang/lib/CodeGen/ItaniumCXXABI.cpp +++ b/clang/lib/CodeGen/ItaniumCXXABI.cpp @@ -1479,7 +1479,7 @@ void ItaniumCXXABI::emitVTableDefinitions(CodeGenVTables &CGVT, // Create and set the initializer. ConstantInitBuilder Builder(CGM); - auto Components = Builder.beginArray(CGM.Int8PtrTy); + auto Components = Builder.beginStruct(); CGVT.createVTableInitializer(Components, VTLayout, RTTI); Components.finishAndSetAsInitializer(VTable); @@ -1537,13 +1537,16 @@ ItaniumCXXABI::getVTableAddressPoint(BaseSubobject Base, const CXXRecordDecl *VTableClass) { llvm::GlobalValue *VTable = getAddrOfVTable(VTableClass, CharUnits()); - // Find the appropriate vtable within the vtable group. - uint64_t AddressPoint = CGM.getItaniumVTableContext() - .getVTableLayout(VTableClass) - .getAddressPoint(Base); + // Find the appropriate vtable within the vtable group, and the address point + // within that vtable. + VTableLayout::AddressPointLocation AddressPoint = + CGM.getItaniumVTableContext() + .getVTableLayout(VTableClass) + .getAddressPoint(Base); llvm::Value *Indices[] = { llvm::ConstantInt::get(CGM.Int32Ty, 0), - llvm::ConstantInt::get(CGM.Int32Ty, AddressPoint) + llvm::ConstantInt::get(CGM.Int32Ty, AddressPoint.VTableIndex), + llvm::ConstantInt::get(CGM.Int32Ty, AddressPoint.AddressPointIndex), }; return llvm::ConstantExpr::getInBoundsGetElementPtr(VTable->getValueType(), @@ -1589,12 +1592,12 @@ llvm::GlobalVariable *ItaniumCXXABI::getAddrOfVTable(const CXXRecordDecl *RD, llvm::raw_svector_ostream Out(Name); getMangleContext().mangleCXXVTable(RD, Out); - ItaniumVTableContext &VTContext = CGM.getItaniumVTableContext(); - llvm::ArrayType *ArrayType = llvm::ArrayType::get( - CGM.Int8PtrTy, VTContext.getVTableLayout(RD).vtable_components().size()); + const VTableLayout &VTLayout = + CGM.getItaniumVTableContext().getVTableLayout(RD); + llvm::Type *VTableType = CGM.getVTables().getVTableType(VTLayout); VTable = CGM.CreateOrReplaceCXXRuntimeVariable( - Name, ArrayType, llvm::GlobalValue::ExternalLinkage); + Name, VTableType, llvm::GlobalValue::ExternalLinkage); VTable->setUnnamedAddr(llvm::GlobalValue::UnnamedAddr::Global); if (RD->hasAttr<DLLImportAttr>()) diff --git a/clang/lib/CodeGen/MicrosoftCXXABI.cpp b/clang/lib/CodeGen/MicrosoftCXXABI.cpp index 08921b9628c..eb40a45c80d 100644 --- a/clang/lib/CodeGen/MicrosoftCXXABI.cpp +++ b/clang/lib/CodeGen/MicrosoftCXXABI.cpp @@ -1618,7 +1618,7 @@ void MicrosoftCXXABI::emitVTableDefinitions(CodeGenVTables &CGVT, RTTI = getMSCompleteObjectLocator(RD, *Info); ConstantInitBuilder Builder(CGM); - auto Components = Builder.beginArray(CGM.Int8PtrTy); + auto Components = Builder.beginStruct(); CGVT.createVTableInitializer(Components, VTLayout, RTTI); Components.finishAndSetAsInitializer(VTable); @@ -1739,17 +1739,14 @@ llvm::GlobalVariable *MicrosoftCXXABI::getAddrOfVTable(const CXXRecordDecl *RD, return VTable; } - uint64_t NumVTableSlots = - VTContext.getVFTableLayout(RD, VFPtr->FullOffsetInMDC) - .vtable_components() - .size(); + const VTableLayout &VTLayout = + VTContext.getVFTableLayout(RD, VFPtr->FullOffsetInMDC); llvm::GlobalValue::LinkageTypes VTableLinkage = VTableAliasIsRequred ? llvm::GlobalValue::PrivateLinkage : VFTableLinkage; StringRef VTableName = VTableAliasIsRequred ? StringRef() : VFTableName.str(); - llvm::ArrayType *VTableType = - llvm::ArrayType::get(CGM.Int8PtrTy, NumVTableSlots); + llvm::Type *VTableType = CGM.getVTables().getVTableType(VTLayout); // Create a backing variable for the contents of VTable. The VTable may // or may not include space for a pointer to RTTI data. @@ -1770,8 +1767,9 @@ llvm::GlobalVariable *MicrosoftCXXABI::getAddrOfVTable(const CXXRecordDecl *RD, // importing it. We never reference the RTTI data directly so there is no // need to make room for it. if (VTableAliasIsRequred) { - llvm::Value *GEPIndices[] = {llvm::ConstantInt::get(CGM.IntTy, 0), - llvm::ConstantInt::get(CGM.IntTy, 1)}; + llvm::Value *GEPIndices[] = {llvm::ConstantInt::get(CGM.Int32Ty, 0), + llvm::ConstantInt::get(CGM.Int32Ty, 0), + llvm::ConstantInt::get(CGM.Int32Ty, 1)}; // Create a GEP which points just after the first entry in the VFTable, // this should be the location of the first virtual method. llvm::Constant *VTableGEP = llvm::ConstantExpr::getInBoundsGetElementPtr( |