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 3854c40..890b437 100644
--- a/lib/CodeGen/CGVtable.cpp
+++ b/lib/CodeGen/CGVtable.cpp
@@ -1091,6 +1091,9 @@
typedef llvm::SmallSetVector<const CXXRecordDecl *, 8>
PrimaryBasesSetVectorTy;
+ typedef llvm::DenseMap<const CXXRecordDecl *, int64_t>
+ VBaseOffsetOffsetsMapTy;
+
private:
/// VTables - Global vtable information.
CodeGenVTables &VTables;
@@ -1122,9 +1125,6 @@
/// bases in this vtable.
llvm::DenseMap<const CXXRecordDecl *, VCallOffsetMap> VCallOffsetsForVBases;
- typedef llvm::DenseMap<const CXXRecordDecl *, int64_t>
- VBaseOffsetOffsetsMapTy;
-
/// VBaseOffsetOffsets - Contains the offsets of the virtual base offsets for
/// the most derived class.
VBaseOffsetOffsetsMapTy VBaseOffsetOffsets;
@@ -1299,6 +1299,24 @@
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<const uint64_t *>(Components.begin());
+ }
+
+ const uint64_t *vtable_components_data_end() {
+ return reinterpret_cast<const uint64_t *>(Components.end());
+ }
+
/// dumpLayout - Dump the vtable layout.
void dumpLayout(llvm::raw_ostream&);
};
@@ -3874,34 +3892,67 @@
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<RecordType>();
+ const CXXRecordDecl *VBase = cast<CXXRecordDecl>(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 @@
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 4a92443..6670b4e 100644
--- a/lib/CodeGen/CGVtable.h
+++ b/lib/CodeGen/CGVtable.h
@@ -260,11 +260,21 @@
/// 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<const CXXRecordDecl *> ClassesWithKnownThunkStatus;
+ typedef llvm::DenseMap<const CXXRecordDecl *, uint64_t *> 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<ClassPairTy, uint64_t> SubVTTIndiciesTy;
SubVTTIndiciesTy SubVTTIndicies;
@@ -290,6 +300,11 @@
/// 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 4d40372..2f7c79b 100644
--- a/test/CodeGenCXX/copy-constructor-synthesis-2.cpp
+++ b/test/CodeGenCXX/copy-constructor-synthesis-2.cpp
@@ -4,4 +4,4 @@
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 bf8575a..75620ab 100644
--- a/test/CodeGenCXX/vtable-pointer-initialization.cpp
+++ b/test/CodeGenCXX/vtable-pointer-initialization.cpp
@@ -21,13 +21,13 @@
// 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 @@
// 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