summaryrefslogtreecommitdiffstats
path: root/clang
diff options
context:
space:
mode:
authorAnders Carlsson <andersca@mac.com>2009-12-06 00:53:22 +0000
committerAnders Carlsson <andersca@mac.com>2009-12-06 00:53:22 +0000
commit232324c5c08bdbc2dd289a2340849043e05ff485 (patch)
tree8d6a947a154ee57ffa17d7b51146fa5c752cfd95 /clang
parent0911ae8ef20f0251d51cb840cbe41b4255565351 (diff)
downloadbcm5719-llvm-232324c5c08bdbc2dd289a2340849043e05ff485.tar.gz
bcm5719-llvm-232324c5c08bdbc2dd289a2340849043e05ff485.zip
More linkage improvements.
llvm-svn: 90687
Diffstat (limited to 'clang')
-rw-r--r--clang/lib/CodeGen/CGVtable.cpp37
-rw-r--r--clang/lib/CodeGen/CGVtable.h10
-rw-r--r--clang/test/CodeGenCXX/vtable-linkage.cpp10
3 files changed, 42 insertions, 15 deletions
diff --git a/clang/lib/CodeGen/CGVtable.cpp b/clang/lib/CodeGen/CGVtable.cpp
index 6f8f9ebd834..67d8c6282b6 100644
--- a/clang/lib/CodeGen/CGVtable.cpp
+++ b/clang/lib/CodeGen/CGVtable.cpp
@@ -1113,6 +1113,7 @@ createGlobalVariable(CodeGenModule &CGM, const CXXRecordDecl *RD,
llvm::GlobalVariable *
CGVtableInfo::GenerateVtable(llvm::GlobalVariable::LinkageTypes Linkage,
+ bool GenerateDefinition,
const CXXRecordDecl *LayoutClass,
const CXXRecordDecl *RD, uint64_t Offset) {
llvm::SmallString<256> OutName;
@@ -1134,9 +1135,7 @@ CGVtableInfo::GenerateVtable(llvm::GlobalVariable::LinkageTypes Linkage,
if (AddressPoint == 0)
AddressPoint = 1;
} else {
- bool CreateDefinition = Linkage != llvm::GlobalVariable::ExternalLinkage;
-
- VtableBuilder b(RD, LayoutClass, Offset, CGM, CreateDefinition);
+ VtableBuilder b(RD, LayoutClass, Offset, CGM, GenerateDefinition);
D1(printf("vtable %s\n", RD->getNameAsCString()));
// First comes the vtables for all the non-virtual bases...
@@ -1150,12 +1149,15 @@ CGVtableInfo::GenerateVtable(llvm::GlobalVariable::LinkageTypes Linkage,
llvm::ArrayType *ArrayType =
llvm::ArrayType::get(Int8PtrTy, b.getVtable().size());
- if (CreateDefinition) {
+ if (GenerateDefinition)
Init = llvm::ConstantArray::get(ArrayType, &b.getVtable()[0],
b.getVtable().size());
- }
+
llvm::GlobalVariable *OGV = GV;
- GV = createGlobalVariable(CGM, LayoutClass, ArrayType, Init, Name);
+
+ GV = new llvm::GlobalVariable(CGM.getModule(), ArrayType,
+ /*isConstant=*/true, Linkage, Init, Name);
+
if (OGV) {
GV->takeName(OGV);
llvm::Constant *NewPtr =
@@ -1369,17 +1371,21 @@ llvm::Constant *CodeGenModule::GenerateVTT(const CXXRecordDecl *RD) {
return llvm::ConstantExpr::getBitCast(VTT, Int8PtrTy);
}
-void CGVtableInfo::GenerateClassData(const CXXRecordDecl *RD) {
- Vtables[RD] = GenerateVtable(llvm::GlobalValue::WeakODRLinkage, RD, RD, 0);
+void CGVtableInfo::GenerateClassData(llvm::GlobalVariable::LinkageTypes Linkage,
+ const CXXRecordDecl *RD) {
+ assert(!Vtables.count(RD) && "Vtable has already been generated!");
+
+ Vtables[RD] = GenerateVtable(Linkage, /*GenerateDefinition=*/true, RD, RD, 0);
CGM.GenerateRTTI(RD);
CGM.GenerateVTT(RD);
}
llvm::GlobalVariable *CGVtableInfo::getVtable(const CXXRecordDecl *RD) {
- llvm::GlobalVariable *Vtable = Vtables[RD];
+ llvm::GlobalVariable *Vtable = Vtables.lookup(RD);
if (!Vtable)
- Vtable = GenerateVtable(llvm::GlobalValue::ExternalLinkage, RD, RD, 0);
+ Vtable = GenerateVtable(llvm::GlobalValue::ExternalLinkage,
+ /*GenerateDefinition=*/false, RD, RD, 0);
return Vtable;
}
@@ -1388,6 +1394,7 @@ llvm::GlobalVariable *
CGVtableInfo::getCtorVtable(const CXXRecordDecl *LayoutClass,
const CXXRecordDecl *RD, uint64_t Offset) {
return GenerateVtable(llvm::GlobalValue::InternalLinkage,
+ /*GenerateDefinition=*/true,
LayoutClass, RD, Offset);
}
@@ -1420,7 +1427,15 @@ void CGVtableInfo::MaybeEmitVtable(GlobalDecl GD) {
return;
}
+ llvm::GlobalVariable::LinkageTypes Linkage;
+ if (RD->isInAnonymousNamespace())
+ Linkage = llvm::GlobalVariable::InternalLinkage;
+ else if (KeyFunction)
+ Linkage = llvm::GlobalVariable::ExternalLinkage;
+ else
+ Linkage = llvm::GlobalVariable::WeakODRLinkage;
+
// Emit the data.
- GenerateClassData(RD);
+ GenerateClassData(Linkage, RD);
}
diff --git a/clang/lib/CodeGen/CGVtable.h b/clang/lib/CodeGen/CGVtable.h
index 37fa1230f69..107db2f02a9 100644
--- a/clang/lib/CodeGen/CGVtable.h
+++ b/clang/lib/CodeGen/CGVtable.h
@@ -92,13 +92,15 @@ class CGVtableInfo {
/// GenerateClassData - Generate all the class data requires to be generated
/// upon definition of a KeyFunction. This includes the vtable, the
/// rtti data structure and the VTT.
- void GenerateClassData(const CXXRecordDecl *RD);
+ ///
+ /// \param Linkage - The desired linkage of the vtable, the RTTI and the VTT.
+ void GenerateClassData(llvm::GlobalVariable::LinkageTypes Linkage,
+ const CXXRecordDecl *RD);
llvm::GlobalVariable *
-
GenerateVtable(llvm::GlobalVariable::LinkageTypes Linkage,
- const CXXRecordDecl *LayoutClass, const CXXRecordDecl *RD,
- uint64_t Offset);
+ bool GenerateDefinition, const CXXRecordDecl *LayoutClass,
+ const CXXRecordDecl *RD, uint64_t Offset);
public:
CGVtableInfo(CodeGenModule &CGM)
diff --git a/clang/test/CodeGenCXX/vtable-linkage.cpp b/clang/test/CodeGenCXX/vtable-linkage.cpp
index 4eae3175a07..81ac0e43b4c 100644
--- a/clang/test/CodeGenCXX/vtable-linkage.cpp
+++ b/clang/test/CodeGenCXX/vtable-linkage.cpp
@@ -22,6 +22,12 @@ struct C {
C::C() { }
+struct D {
+ virtual void f();
+};
+
+void D::f() { }
+
// B has a key function that is not defined in this translation unit so its vtable
// has external linkage.
// CHECK: @_ZTV1B = external constant
@@ -29,6 +35,10 @@ C::C() { }
// C has no key function, so its vtable should have weak_odr linkage.
// CHECK: @_ZTV1C = weak_odr constant
+// D has a key function that is defined in this translation unit so its vtable is
+// defined in the translation unit.
+// CHECK: @_ZTV1D = constant
+
// The A vtable should have internal linkage since it is inside an anonymous
// namespace.
// CHECK: @_ZTVN12_GLOBAL__N_11AE = internal constant
OpenPOWER on IntegriCloud