From: Peter Collingbourne Date: Mon, 26 Sep 2011 01:56:50 +0000 (+0000) Subject: Move all vtable layout data into new VTableLayout class X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=e09cdf46aa2b86c24e6bf7a7ead2eaded964f2ff;p=clang Move all vtable layout data into new VTableLayout class git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@140506 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/lib/CodeGen/CGCXX.cpp b/lib/CodeGen/CGCXX.cpp index 27f5032ad9..b5e6e0d7d9 100644 --- a/lib/CodeGen/CGCXX.cpp +++ b/lib/CodeGen/CGCXX.cpp @@ -337,8 +337,8 @@ CodeGenFunction::BuildAppleKextVirtualCall(const CXXMethodDecl *MD, MD = MD->getCanonicalDecl(); uint64_t VTableIndex = CGM.getVTableContext().getMethodVTableIndex(MD); uint64_t AddressPoint = - CGM.getVTableContext() - .getAddressPoint(BaseSubobject(RD, CharUnits::Zero()), RD); + CGM.getVTableContext().getVTableLayout(RD) + .getAddressPoint(BaseSubobject(RD, CharUnits::Zero())); VTableIndex += AddressPoint; llvm::Value *VFuncPtr = Builder.CreateConstInBoundsGEP1_64(VTable, VTableIndex, "vfnkxt"); @@ -373,8 +373,8 @@ CodeGenFunction::BuildAppleKextVirtualDestructorCall( uint64_t VTableIndex = CGM.getVTableContext().getMethodVTableIndex(GlobalDecl(DD, Type)); uint64_t AddressPoint = - CGM.getVTableContext() - .getAddressPoint(BaseSubobject(RD, CharUnits::Zero()), RD); + CGM.getVTableContext().getVTableLayout(RD) + .getAddressPoint(BaseSubobject(RD, CharUnits::Zero())); VTableIndex += AddressPoint; llvm::Value *VFuncPtr = Builder.CreateConstInBoundsGEP1_64(VTable, VTableIndex, "vfnkxt"); diff --git a/lib/CodeGen/CGClass.cpp b/lib/CodeGen/CGClass.cpp index cafc95446d..17bd594280 100644 --- a/lib/CodeGen/CGClass.cpp +++ b/lib/CodeGen/CGClass.cpp @@ -1453,7 +1453,7 @@ CodeGenFunction::InitializeVTablePointer(BaseSubobject Base, VTableAddressPoint = Builder.CreateLoad(VTT); } else { uint64_t AddressPoint = - CGM.getVTableContext().getAddressPoint(Base, VTableClass); + CGM.getVTableContext().getVTableLayout(VTableClass).getAddressPoint(Base); VTableAddressPoint = Builder.CreateConstInBoundsGEP2_64(VTable, 0, AddressPoint); } diff --git a/lib/CodeGen/CGVTT.cpp b/lib/CodeGen/CGVTT.cpp index cb3b39fab3..ea7b8cb497 100644 --- a/lib/CodeGen/CGVTT.cpp +++ b/lib/CodeGen/CGVTT.cpp @@ -67,7 +67,8 @@ CodeGenVTables::EmitVTTDefinition(llvm::GlobalVariable *VTT, uint64_t AddressPoint; if (VTTVT.getBase() == RD) { // Just get the address point for the regular vtable. - AddressPoint = VTContext.getAddressPoint(i->VTableBase, RD); + AddressPoint = VTContext.getVTableLayout(RD) + .getAddressPoint(i->VTableBase); assert(AddressPoint != 0 && "Did not find vtable address point!"); } else { AddressPoint = VTableAddressPoints[i->VTableIndex].lookup(i->VTableBase); diff --git a/lib/CodeGen/CGVTables.cpp b/lib/CodeGen/CGVTables.cpp index 0aea31cd2a..2b187fdca7 100644 --- a/lib/CodeGen/CGVTables.cpp +++ b/lib/CodeGen/CGVTables.cpp @@ -1002,6 +1002,10 @@ public: LayoutVTable(); } + uint64_t getNumThunks() const { + return Thunks.size(); + } + ThunksMapTy::const_iterator thunks_begin() const { return Thunks.begin(); } @@ -1014,18 +1018,22 @@ public: return VBaseOffsetOffsets; } + const AddressPointsMapTy &getAddressPoints() const { + return AddressPoints; + } + /// getNumVTableComponents - Return the number of components in the vtable /// currently built. uint64_t getNumVTableComponents() const { return Components.size(); } - const uint64_t *vtable_components_data_begin() const { - return reinterpret_cast(Components.begin()); + const VTableComponent *vtable_component_begin() const { + return Components.begin(); } - const uint64_t *vtable_components_data_end() const { - return reinterpret_cast(Components.end()); + const VTableComponent *vtable_component_end() const { + return Components.end(); } AddressPointsMapTy::const_iterator address_points_begin() const { @@ -1572,6 +1580,11 @@ void VTableBuilder::LayoutVTable() { VBases.clear(); LayoutVTablesForVirtualBases(MostDerivedClass, VBases); + + // -fapple-kext adds an extra entry at end of vtbl. + bool IsAppleKext = Context.getLangOptions().AppleKext; + if (IsAppleKext) + Components.push_back(VTableComponent::MakeVCallOffset(CharUnits::Zero())); } void @@ -2134,6 +2147,29 @@ void VTableBuilder::dumpLayout(raw_ostream& Out) { } +VTableLayout::VTableLayout(uint64_t NumVTableComponents, + const VTableComponent *VTableComponents, + uint64_t NumVTableThunks, + const VTableThunkTy *VTableThunks, + const AddressPointsMapTy &AddressPoints) + : NumVTableComponents(NumVTableComponents), + VTableComponents(new VTableComponent[NumVTableComponents]), + NumVTableThunks(NumVTableThunks), + VTableThunks(new VTableThunkTy[NumVTableThunks]), + AddressPoints(AddressPoints) { + std::copy(VTableComponents, VTableComponents+NumVTableComponents, + this->VTableComponents); + std::copy(VTableThunks, VTableThunks+NumVTableThunks, this->VTableThunks); +} + +VTableLayout::~VTableLayout() { + delete[] VTableComponents; +} + +VTableContext::~VTableContext() { + llvm::DeleteContainerSeconds(VTableLayouts); +} + static void CollectPrimaryBases(const CXXRecordDecl *RD, ASTContext &Context, VTableBuilder::PrimaryBasesSetVectorTy &PrimaryBases) { @@ -2786,7 +2822,7 @@ void CodeGenVTables::EmitThunks(GlobalDecl GD) } void VTableContext::ComputeVTableRelatedInformation(const CXXRecordDecl *RD) { - uint64_t *&Entry = VTableLayoutMap[RD]; + const VTableLayout *&Entry = VTableLayouts[RD]; // Check if we've computed this information before. if (Entry) @@ -2795,53 +2831,19 @@ void VTableContext::ComputeVTableRelatedInformation(const CXXRecordDecl *RD) { VTableBuilder Builder(*this, RD, CharUnits::Zero(), /*MostDerivedClassIsVirtual=*/0, RD); - // Add the VTable layout. - uint64_t NumVTableComponents = Builder.getNumVTableComponents(); - // -fapple-kext adds an extra entry at end of vtbl. - bool IsAppleKext = Context.getLangOptions().AppleKext; - if (IsAppleKext) - NumVTableComponents += 1; - - uint64_t *LayoutData = new uint64_t[NumVTableComponents + 1]; - if (IsAppleKext) - LayoutData[NumVTableComponents] = 0; - Entry = LayoutData; - - // Store the number of components. - LayoutData[0] = NumVTableComponents; + llvm::SmallVector + VTableThunks(Builder.vtable_thunks_begin(), Builder.vtable_thunks_end()); + std::sort(VTableThunks.begin(), VTableThunks.end()); - // Store the components. - std::copy(Builder.vtable_components_data_begin(), - Builder.vtable_components_data_end(), - &LayoutData[1]); + Entry = new VTableLayout(Builder.getNumVTableComponents(), + Builder.vtable_component_begin(), + VTableThunks.size(), + VTableThunks.data(), + Builder.getAddressPoints()); // Add the known thunks. Thunks.insert(Builder.thunks_begin(), Builder.thunks_end()); - - // Add the thunks needed in this vtable. - assert(!VTableThunksMap.count(RD) && - "Thunks already exists for this vtable!"); - VTableThunksTy &VTableThunks = VTableThunksMap[RD]; - VTableThunks.append(Builder.vtable_thunks_begin(), - Builder.vtable_thunks_end()); - - // Sort them. - std::sort(VTableThunks.begin(), VTableThunks.end()); - - // Add the address points. - for (VTableBuilder::AddressPointsMapTy::const_iterator I = - Builder.address_points_begin(), E = Builder.address_points_end(); - I != E; ++I) { - - uint64_t &AddressPoint = AddressPoints[std::make_pair(RD, I->first)]; - - // Check if we already have the address points for this base. - assert(!AddressPoint && "Address point already exists for this base!"); - - AddressPoint = I->second; - } - // If we don't have the vbase information for this class, insert it. // getVirtualBaseOffsetOffset will compute it separately without computing // the rest of the vtable related information. @@ -2867,9 +2869,10 @@ void VTableContext::ComputeVTableRelatedInformation(const CXXRecordDecl *RD) { llvm::Constant * CodeGenVTables::CreateVTableInitializer(const CXXRecordDecl *RD, - const uint64_t *Components, + const VTableComponent *Components, unsigned NumComponents, - const VTableContext::VTableThunksTy &VTableThunks) { + const VTableLayout::VTableThunkTy *VTableThunks, + unsigned NumVTableThunks) { SmallVector Inits; llvm::Type *Int8PtrTy = llvm::Type::getInt8PtrTy(CGM.getLLVMContext()); @@ -2885,8 +2888,7 @@ CodeGenVTables::CreateVTableInitializer(const CXXRecordDecl *RD, llvm::Constant* PureVirtualFn = 0; for (unsigned I = 0; I != NumComponents; ++I) { - VTableComponent Component = - VTableComponent::getFromOpaqueInteger(Components[I]); + VTableComponent Component = Components[I]; llvm::Constant *Init = 0; @@ -2944,7 +2946,7 @@ CodeGenVTables::CreateVTableInitializer(const CXXRecordDecl *RD, Init = PureVirtualFn; } else { // Check if we should use a thunk. - if (NextVTableThunkIndex < VTableThunks.size() && + if (NextVTableThunkIndex < NumVTableThunks && VTableThunks[NextVTableThunkIndex].first == I) { const ThunkInfo &Thunk = VTableThunks[NextVTableThunkIndex].second; @@ -2992,7 +2994,8 @@ llvm::GlobalVariable *CodeGenVTables::GetAddrOfVTable(const CXXRecordDecl *RD) { llvm::Type *Int8PtrTy = llvm::Type::getInt8PtrTy(CGM.getLLVMContext()); llvm::ArrayType *ArrayType = - llvm::ArrayType::get(Int8PtrTy, VTContext.getNumVTableComponents(RD)); + llvm::ArrayType::get(Int8PtrTy, + VTContext.getVTableLayout(RD).getNumVTableComponents()); VTable = CGM.CreateOrReplaceCXXRuntimeVariable(Name, ArrayType, @@ -3013,12 +3016,15 @@ CodeGenVTables::EmitVTableDefinition(llvm::GlobalVariable *VTable, Builder.dumpLayout(llvm::errs()); } - const VTableContext::VTableThunksTy& Thunks = VTContext.getVTableThunks(RD); - + const VTableLayout &VTLayout = VTContext.getVTableLayout(RD); + // Create and set the initializer. llvm::Constant *Init = - CreateVTableInitializer(RD, VTContext.getVTableComponentsData(RD), - VTContext.getNumVTableComponents(RD), Thunks); + CreateVTableInitializer(RD, + VTLayout.vtable_component_begin(), + VTLayout.getNumVTableComponents(), + VTLayout.vtable_thunk_begin(), + VTLayout.getNumVTableThunks()); VTable->setInitializer(Init); // Set the correct linkage. @@ -3078,8 +3084,10 @@ CodeGenVTables::GenerateConstructionVTable(const CXXRecordDecl *RD, // Create and set the initializer. llvm::Constant *Init = CreateVTableInitializer(Base.getBase(), - Builder.vtable_components_data_begin(), - Builder.getNumVTableComponents(), VTableThunks); + Builder.vtable_component_begin(), + Builder.getNumVTableComponents(), + VTableThunks.begin(), + VTableThunks.size()); VTable->setInitializer(Init); return VTable; diff --git a/lib/CodeGen/CGVTables.h b/lib/CodeGen/CGVTables.h index f48978711e..537ce383ce 100644 --- a/lib/CodeGen/CGVTables.h +++ b/lib/CodeGen/CGVTables.h @@ -49,6 +49,8 @@ public: CK_UnusedFunctionPointer }; + VTableComponent() { } + static VTableComponent MakeVCallOffset(CharUnits Offset) { return VTableComponent(CK_VCallOffset, Offset); } @@ -194,6 +196,69 @@ private: int64_t Value; }; +class VTableLayout { +public: + typedef std::pair VTableThunkTy; + typedef llvm::SmallVector ThunkInfoVectorTy; + + typedef const VTableComponent *vtable_component_iterator; + typedef const VTableThunkTy *vtable_thunk_iterator; + + typedef llvm::DenseMap AddressPointsMapTy; +private: + uint64_t NumVTableComponents; + VTableComponent *VTableComponents; + + /// VTableThunks - Contains thunks needed by vtables. + uint64_t NumVTableThunks; + VTableThunkTy *VTableThunks; + + /// Address points - Address points for all vtables. + AddressPointsMapTy AddressPoints; + +public: + VTableLayout(uint64_t NumVTableComponents, + const VTableComponent *VTableComponents, + uint64_t NumVTableThunks, + const VTableThunkTy *VTableThunks, + const AddressPointsMapTy &AddressPoints); + ~VTableLayout(); + + uint64_t getNumVTableComponents() const { + return NumVTableComponents; + } + + vtable_component_iterator vtable_component_begin() const { + return VTableComponents; + } + + vtable_component_iterator vtable_component_end() const { + return VTableComponents+NumVTableComponents; + } + + uint64_t getNumVTableThunks() const { + return NumVTableThunks; + } + + vtable_thunk_iterator vtable_thunk_begin() const { + return VTableThunks; + } + + vtable_thunk_iterator vtable_thunk_end() const { + return VTableThunks+NumVTableThunks; + } + + uint64_t getAddressPoint(BaseSubobject Base) const { + assert(AddressPoints.count(Base) && + "Did not find address point!"); + + uint64_t AddressPoint = AddressPoints.lookup(Base); + assert(AddressPoint && "Address point must not be zero!"); + + return AddressPoint; + } +}; + class VTableContext { ASTContext &Context; @@ -208,6 +273,10 @@ private: typedef llvm::DenseMap MethodVTableIndicesTy; MethodVTableIndicesTy MethodVTableIndices; + typedef llvm::DenseMap + VTableLayoutMapTy; + VTableLayoutMapTy VTableLayouts; + /// NumVirtualFunctionPointers - Contains the number of virtual function /// pointers in the vtable for a given record decl. llvm::DenseMap NumVirtualFunctionPointers; @@ -222,32 +291,11 @@ private: VirtualBaseClassOffsetOffsetsMapTy; VirtualBaseClassOffsetOffsetsMapTy VirtualBaseClassOffsetOffsets; - // The layout entry. - typedef llvm::DenseMap VTableLayoutMapTy; - - /// VTableLayoutMap - Stores the vtable layout for all record decls. - /// The layout is stored as an array of 64-bit integers, where the first - /// integer is the number of vtable entries in the layout, and the subsequent - /// integers are the vtable components. - VTableLayoutMapTy VTableLayoutMap; - typedef llvm::DenseMap ThunksMapTy; /// Thunks - Contains all thunks that a given method decl will need. ThunksMapTy Thunks; - typedef llvm::DenseMap - VTableThunksMapTy; - - /// VTableThunksMap - Contains thunks needed by vtables. - VTableThunksMapTy VTableThunksMap; - - typedef std::pair BaseSubobjectPairTy; - typedef llvm::DenseMap AddressPointsMapTy; - - /// Address points - Address points for all vtables. - AddressPointsMapTy AddressPoints; - void ComputeMethodVTableIndices(const CXXRecordDecl *RD); /// ComputeVTableRelatedInformation - Compute and store all vtable related @@ -257,20 +305,13 @@ private: public: VTableContext(ASTContext &Context) : Context(Context) {} + ~VTableContext(); - uint64_t getNumVTableComponents(const CXXRecordDecl *RD) { + const VTableLayout &getVTableLayout(const CXXRecordDecl *RD) { ComputeVTableRelatedInformation(RD); - assert(VTableLayoutMap.count(RD) && "No vtable layout for this class!"); + assert(VTableLayouts.count(RD) && "No layout for this record decl!"); - return VTableLayoutMap.lookup(RD)[0]; - } - - const uint64_t *getVTableComponentsData(const CXXRecordDecl *RD) { - ComputeVTableRelatedInformation(RD); - assert(VTableLayoutMap.count(RD) && "No vtable layout for this class!"); - - uint64_t *Components = VTableLayoutMap.lookup(RD); - return &Components[1]; + return *VTableLayouts[RD]; } const ThunkInfoVectorTy *getThunkInfo(const CXXMethodDecl *MD) { @@ -285,25 +326,6 @@ public: return &I->second; } - const VTableThunksTy &getVTableThunks(const CXXRecordDecl *RD) { - ComputeVTableRelatedInformation(RD); - assert(VTableThunksMap.count(RD) && - "No thunk status for this record decl!"); - - return VTableThunksMap[RD]; - } - - uint64_t getAddressPoint(BaseSubobject Base, const CXXRecordDecl *RD) { - ComputeVTableRelatedInformation(RD); - assert(AddressPoints.count(std::make_pair(RD, Base)) && - "Did not find address point!"); - - uint64_t AddressPoint = AddressPoints.lookup(std::make_pair(RD, Base)); - assert(AddressPoint && "Address point must not be zero!"); - - return AddressPoint; - } - /// getNumVirtualFunctionPointers - Return the number of virtual function /// pointers in the vtable for a given record decl. uint64_t getNumVirtualFunctionPointers(const CXXRecordDecl *RD); @@ -361,9 +383,10 @@ class CodeGenVTables { /// \param Components - The vtable components; this is really an array of /// VTableComponents. llvm::Constant *CreateVTableInitializer(const CXXRecordDecl *RD, - const uint64_t *Components, + const VTableComponent *Components, unsigned NumComponents, - const VTableContext::VTableThunksTy &VTableThunks); + const VTableLayout::VTableThunkTy *VTableThunks, + unsigned NumVTableThunks); public: CodeGenVTables(CodeGenModule &CGM);