From: Anders Carlsson Date: Wed, 24 Mar 2010 16:42:11 +0000 (+0000) Subject: More vtable improvements. We now compute and keep track of all vtable related informa... X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=ccd83d748c82c5255100f38e3f07537b949853b3;p=clang More vtable improvements. We now compute and keep track of all vtable related information which avoids computing the same vtable layout over and over. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@99403 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/lib/CodeGen/CGVtable.cpp b/lib/CodeGen/CGVtable.cpp index 3854c404c2..890b437c4b 100644 --- a/lib/CodeGen/CGVtable.cpp +++ b/lib/CodeGen/CGVtable.cpp @@ -1091,6 +1091,9 @@ public: typedef llvm::SmallSetVector PrimaryBasesSetVectorTy; + typedef llvm::DenseMap + VBaseOffsetOffsetsMapTy; + private: /// VTables - Global vtable information. CodeGenVTables &VTables; @@ -1122,9 +1125,6 @@ private: /// bases in this vtable. llvm::DenseMap VCallOffsetsForVBases; - typedef llvm::DenseMap - VBaseOffsetOffsetsMapTy; - /// VBaseOffsetOffsets - Contains the offsets of the virtual base offsets for /// the most derived class. VBaseOffsetOffsetsMapTy VBaseOffsetOffsets; @@ -1299,6 +1299,24 @@ public: return Thunks.end(); } + const VBaseOffsetOffsetsMapTy &getVBaseOffsetOffsets() const { + return VBaseOffsetOffsets; + } + + /// 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() { + return reinterpret_cast(Components.begin()); + } + + const uint64_t *vtable_components_data_end() { + return reinterpret_cast(Components.end()); + } + /// dumpLayout - Dump the vtable layout. void dumpLayout(llvm::raw_ostream&); }; @@ -3874,34 +3892,67 @@ void CodeGenVTables::EmitThunks(GlobalDecl GD) const CXXRecordDecl *RD = MD->getParent(); + // Compute VTable related info for this class. + ComputeVTableRelatedInformation(RD); + ThunksMapTy::const_iterator I = Thunks.find(MD); if (I == Thunks.end()) { - // We did not find a thunk for this method. Check if we've collected thunks - // for this record. - if (!ClassesWithKnownThunkStatus.insert(RD).second) { - // This member function doesn't have any associated thunks. - return; - } - - // Use the vtable builder to build thunks for this class. - VtableBuilder Builder(*this, RD, 0, /*MostDerivedClassIsVirtual=*/0, RD); - - // Add the known thunks. - Thunks.insert(Builder.thunks_begin(), Builder.thunks_end()); - - // Look for the thunk again. - I = Thunks.find(MD); - if (I == Thunks.end()) { - // Looks like this function doesn't have any associated thunks after all. - return; - } + // We did not find a thunk for this method. + return; } - + const ThunkInfoVectorTy &ThunkInfoVector = I->second; for (unsigned I = 0, E = ThunkInfoVector.size(); I != E; ++I) EmitThunk(GD, ThunkInfoVector[I]); } +void CodeGenVTables::ComputeVTableRelatedInformation(const CXXRecordDecl *RD) { + uint64_t *&LayoutData = VTableLayoutMap[RD]; + + // Check if we've computed this information before. + if (LayoutData) + return; + + VtableBuilder Builder(*this, RD, 0, /*MostDerivedClassIsVirtual=*/0, RD); + + // Add the VTable layout. + uint64_t NumVTableComponents = Builder.getNumVTableComponents(); + LayoutData = new uint64_t[NumVTableComponents + 1]; + + // Store the number of components. + LayoutData[0] = NumVTableComponents; + + // Store the components. + std::copy(Builder.vtable_components_data_begin(), + Builder.vtable_components_data_end(), + &LayoutData[1]); + + // Add the known thunks. + Thunks.insert(Builder.thunks_begin(), Builder.thunks_end()); + + // 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. + if (!RD->getNumVBases()) + return; + + const RecordType *VBaseRT = + RD->vbases_begin()->getType()->getAs(); + const CXXRecordDecl *VBase = cast(VBaseRT->getDecl()); + + if (VirtualBaseClassOffsetOffsets.count(std::make_pair(RD, VBase))) + return; + + for (VtableBuilder::VBaseOffsetOffsetsMapTy::const_iterator I = + Builder.getVBaseOffsetOffsets().begin(), + E = Builder.getVBaseOffsetOffsets().end(); I != E; ++I) { + // Insert all types. + ClassPairTy ClassPair(RD, I->first); + + VirtualBaseClassOffsetOffsets.insert(std::make_pair(ClassPair, I->second)); + } +} + void CodeGenVTables::GenerateClassData(llvm::GlobalVariable::LinkageTypes Linkage, const CXXRecordDecl *RD) { @@ -3923,8 +3974,11 @@ llvm::Constant *CodeGenVTables::GetAddrOfVTable(const CXXRecordDecl *RD) { CGM.getMangleContext().mangleCXXVtable(RD, OutName); llvm::StringRef Name = OutName.str(); + ComputeVTableRelatedInformation(RD); + const llvm::Type *Int8PtrTy = llvm::Type::getInt8PtrTy(CGM.getLLVMContext()); - llvm::ArrayType *ArrayType = llvm::ArrayType::get(Int8PtrTy, 0); + llvm::ArrayType *ArrayType = + llvm::ArrayType::get(Int8PtrTy, getNumVTableComponents(RD)); llvm::GlobalVariable *GV = CGM.getModule().getNamedGlobal(Name); if (GV) { diff --git a/lib/CodeGen/CGVtable.h b/lib/CodeGen/CGVtable.h index 4a924431af..6670b4ed72 100644 --- a/lib/CodeGen/CGVtable.h +++ b/lib/CodeGen/CGVtable.h @@ -260,11 +260,21 @@ private: /// Thunks - Contains all thunks that a given method decl will need. ThunksMapTy Thunks; - - /// ClassesWithKnownThunkStatus - Contains all the classes for which we know - /// whether their virtual member functions have thunks or not. - llvm::DenseSet ClassesWithKnownThunkStatus; + 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; + + uint64_t getNumVTableComponents(const CXXRecordDecl *RD) const { + assert(VTableLayoutMap.count(RD) && "No vtable layout for this class!"); + + return VTableLayoutMap.lookup(RD)[0]; + } + typedef llvm::DenseMap SubVTTIndiciesTy; SubVTTIndiciesTy SubVTTIndicies; @@ -290,6 +300,11 @@ private: /// EmitThunks - Emit the associated thunks for the given global decl. void EmitThunks(GlobalDecl GD); + /// ComputeVTableRelatedInformation - Compute and store all vtable related + /// information (vtable layout, vbase offset offsets, thunks etc) for the + /// given record decl. + void ComputeVTableRelatedInformation(const CXXRecordDecl *RD); + public: CodeGenVTables(CodeGenModule &CGM) : CGM(CGM) { } diff --git a/test/CodeGenCXX/copy-constructor-synthesis-2.cpp b/test/CodeGenCXX/copy-constructor-synthesis-2.cpp index 4d40372a56..2f7c79b903 100644 --- a/test/CodeGenCXX/copy-constructor-synthesis-2.cpp +++ b/test/CodeGenCXX/copy-constructor-synthesis-2.cpp @@ -4,4 +4,4 @@ struct A { virtual void a(); }; A x(A& y) { return y; } // CHECK: define linkonce_odr void @_ZN1AC1ERKS_( -// CHECK: store i8** getelementptr inbounds ([0 x i8*]* @_ZTV1A, i64 0, i64 2) +// CHECK: store i8** getelementptr inbounds ([3 x i8*]* @_ZTV1A, i64 0, i64 2) diff --git a/test/CodeGenCXX/vtable-pointer-initialization.cpp b/test/CodeGenCXX/vtable-pointer-initialization.cpp index bf8575a268..75620ab8e6 100644 --- a/test/CodeGenCXX/vtable-pointer-initialization.cpp +++ b/test/CodeGenCXX/vtable-pointer-initialization.cpp @@ -21,13 +21,13 @@ struct A : Base { // CHECK: define void @_ZN1AC2Ev( // CHECK: call void @_ZN4BaseC2Ev( -// CHECK: store i8** getelementptr inbounds ([0 x i8*]* @_ZTV1A, i64 0, i64 2) +// CHECK: store i8** getelementptr inbounds ([3 x i8*]* @_ZTV1A, i64 0, i64 2) // CHECK: call void @_ZN5FieldC1Ev( // CHECK: ret void A::A() { } // CHECK: define void @_ZN1AD2Ev( -// CHECK: store i8** getelementptr inbounds ([0 x i8*]* @_ZTV1A, i64 0, i64 2) +// CHECK: store i8** getelementptr inbounds ([3 x i8*]* @_ZTV1A, i64 0, i64 2) // CHECK: call void @_ZN5FieldD1Ev( // CHECK: call void @_ZN4BaseD2Ev( // CHECK: ret void @@ -45,13 +45,13 @@ void f() { B b; } // CHECK: call void @_ZN1BC2Ev( // CHECK: define linkonce_odr void @_ZN1BD1Ev( -// CHECK: store i8** getelementptr inbounds ([0 x i8*]* @_ZTV1B, i64 0, i64 2) +// CHECK: store i8** getelementptr inbounds ([3 x i8*]* @_ZTV1B, i64 0, i64 2) // CHECK: call void @_ZN5FieldD1Ev( // CHECK: call void @_ZN4BaseD2Ev( // CHECK: ret void // CHECK: define linkonce_odr void @_ZN1BC2Ev( // CHECK: call void @_ZN4BaseC2Ev( -// CHECK: store i8** getelementptr inbounds ([0 x i8*]* @_ZTV1B, i64 0, i64 2) +// CHECK: store i8** getelementptr inbounds ([3 x i8*]* @_ZTV1B, i64 0, i64 2) // CHECK: call void @_ZN5FieldC1Ev // CHECK: ret void