summaryrefslogtreecommitdiffstats
path: root/clang/lib
diff options
context:
space:
mode:
authorRafael Espindola <rafael.espindola@gmail.com>2013-11-04 18:38:59 +0000
committerRafael Espindola <rafael.espindola@gmail.com>2013-11-04 18:38:59 +0000
commit3f643bd1248b77f5e87af2f7ee5e4f0881729e93 (patch)
treefdbd27dae71ba4270064ab2520256ec33c185150 /clang/lib
parenta6775b622f45ff0693133e2fdc685eea6a147abe (diff)
downloadbcm5719-llvm-3f643bd1248b77f5e87af2f7ee5e4f0881729e93.tar.gz
bcm5719-llvm-3f643bd1248b77f5e87af2f7ee5e4f0881729e93.zip
Use aliases for more constructors and destructors.
With this patch we produce alias for cases like template<typename T> struct foobar { foobar() { } }; template struct foobar<void>; We just have to be careful to produce the same aliases in every TU because of comdats. llvm-svn: 194000
Diffstat (limited to 'clang/lib')
-rw-r--r--clang/lib/CodeGen/CGCXX.cpp85
-rw-r--r--clang/lib/CodeGen/CGVTables.cpp4
-rw-r--r--clang/lib/CodeGen/CodeGenModule.h3
3 files changed, 50 insertions, 42 deletions
diff --git a/clang/lib/CodeGen/CGCXX.cpp b/clang/lib/CodeGen/CGCXX.cpp
index 7dd850be0bd..25f3e6f4daa 100644
--- a/clang/lib/CodeGen/CGCXX.cpp
+++ b/clang/lib/CodeGen/CGCXX.cpp
@@ -95,12 +95,16 @@ bool CodeGenModule::TryEmitBaseDestructorAsAlias(const CXXDestructorDecl *D) {
return true;
return TryEmitDefinitionAsAlias(GlobalDecl(D, Dtor_Base),
- GlobalDecl(BaseD, Dtor_Base));
+ GlobalDecl(BaseD, Dtor_Base),
+ false);
}
/// Try to emit a definition as a global alias for another definition.
+/// If \p InEveryTU is true, we know that an equivalent alias can be produced
+/// in every translation unit.
bool CodeGenModule::TryEmitDefinitionAsAlias(GlobalDecl AliasDecl,
- GlobalDecl TargetDecl) {
+ GlobalDecl TargetDecl,
+ bool InEveryTU) {
if (!getCodeGenOpts().CXXCtorDtorAliases)
return true;
@@ -108,34 +112,34 @@ bool CodeGenModule::TryEmitDefinitionAsAlias(GlobalDecl AliasDecl,
// support aliases with that linkage, fail.
llvm::GlobalValue::LinkageTypes Linkage = getFunctionLinkage(AliasDecl);
- switch (Linkage) {
- // We can definitely emit aliases to definitions with external linkage.
- case llvm::GlobalValue::ExternalLinkage:
- case llvm::GlobalValue::ExternalWeakLinkage:
- break;
-
- // Same with local linkage.
- case llvm::GlobalValue::InternalLinkage:
- case llvm::GlobalValue::PrivateLinkage:
- case llvm::GlobalValue::LinkerPrivateLinkage:
- break;
-
- // We should try to support linkonce linkages.
- case llvm::GlobalValue::LinkOnceAnyLinkage:
- case llvm::GlobalValue::LinkOnceODRLinkage:
- return true;
-
- // Other linkages will probably never be supported.
- default:
- return true;
- }
-
llvm::GlobalValue::LinkageTypes TargetLinkage
= getFunctionLinkage(TargetDecl);
- if (llvm::GlobalValue::isWeakForLinker(TargetLinkage))
+ // Don't create an alias to a linker weak symbol unless we know we can do
+ // that in every TU. This avoids producing different COMDATs in different
+ // TUs.
+ if (llvm::GlobalValue::isWeakForLinker(TargetLinkage)) {
+ if (!InEveryTU)
+ return true;
+
+ // In addition to making sure we produce it in every TU, we have to make
+ // sure llvm keeps it.
+ // FIXME: Instead of outputting an alias we could just replace every use of
+ // AliasDecl with TargetDecl.
+ assert(Linkage == TargetLinkage);
+ Linkage = llvm::GlobalValue::WeakODRLinkage;
+ }
+
+ // We can't use an alias if the linkage is not valid for one.
+ if (!llvm::GlobalAlias::isValidLinkage(Linkage))
return true;
+ // Check if we have it already.
+ StringRef MangledName = getMangledName(AliasDecl);
+ llvm::GlobalValue *Entry = GetGlobalValue(MangledName);
+ if (Entry && !Entry->isDeclaration())
+ return false;
+
// Derive the type for the alias.
llvm::PointerType *AliasType
= getTypes().GetFunctionType(AliasDecl)->getPointerTo();
@@ -153,10 +157,7 @@ bool CodeGenModule::TryEmitDefinitionAsAlias(GlobalDecl AliasDecl,
new llvm::GlobalAlias(AliasType, Linkage, "", Aliasee, &getModule());
// Switch any previous uses to the alias.
- StringRef MangledName = getMangledName(AliasDecl);
- llvm::GlobalValue *Entry = GetGlobalValue(MangledName);
if (Entry) {
- assert(Entry->isDeclaration() && "definition already exists for alias");
assert(Entry->getType() == AliasType &&
"declaration exists with different type");
Alias->takeName(Entry);
@@ -177,11 +178,14 @@ void CodeGenModule::EmitCXXConstructor(const CXXConstructorDecl *ctor,
// The complete constructor is equivalent to the base constructor
// for classes with no virtual bases. Try to emit it as an alias.
if (getTarget().getCXXABI().hasConstructorVariants() &&
- ctorType == Ctor_Complete &&
!ctor->getParent()->getNumVBases() &&
- !TryEmitDefinitionAsAlias(GlobalDecl(ctor, Ctor_Complete),
- GlobalDecl(ctor, Ctor_Base)))
- return;
+ (ctorType == Ctor_Complete || ctorType == Ctor_Base)) {
+ bool ProducedAlias =
+ !TryEmitDefinitionAsAlias(GlobalDecl(ctor, Ctor_Complete),
+ GlobalDecl(ctor, Ctor_Base), true);
+ if (ctorType == Ctor_Complete && ProducedAlias)
+ return;
+ }
const CGFunctionInfo &fnInfo =
getTypes().arrangeCXXConstructorDeclaration(ctor, ctorType);
@@ -218,11 +222,18 @@ void CodeGenModule::EmitCXXDestructor(const CXXDestructorDecl *dtor,
CXXDtorType dtorType) {
// The complete destructor is equivalent to the base destructor for
// classes with no virtual bases, so try to emit it as an alias.
- if (dtorType == Dtor_Complete &&
- !dtor->getParent()->getNumVBases() &&
- !TryEmitDefinitionAsAlias(GlobalDecl(dtor, Dtor_Complete),
- GlobalDecl(dtor, Dtor_Base)))
- return;
+ if (!dtor->getParent()->getNumVBases() &&
+ (dtorType == Dtor_Complete || dtorType == Dtor_Base)) {
+ bool ProducedAlias =
+ !TryEmitDefinitionAsAlias(GlobalDecl(dtor, Dtor_Complete),
+ GlobalDecl(dtor, Dtor_Base), true);
+ if (ProducedAlias) {
+ if (dtorType == Dtor_Complete)
+ return;
+ if (dtor->isVirtual())
+ getVTables().EmitThunks(GlobalDecl(dtor, Dtor_Complete));
+ }
+ }
// The base destructor is equivalent to the base destructor of its
// base class if there is exactly one non-virtual base class with a
diff --git a/clang/lib/CodeGen/CGVTables.cpp b/clang/lib/CodeGen/CGVTables.cpp
index 0956fee037a..996bd905f67 100644
--- a/clang/lib/CodeGen/CGVTables.cpp
+++ b/clang/lib/CodeGen/CGVTables.cpp
@@ -387,10 +387,6 @@ void CodeGenVTables::emitThunk(GlobalDecl GD, const ThunkInfo &Thunk,
return;
}
- // If a function has a body, it should have available_externally linkage.
- assert(ThunkFn->hasAvailableExternallyLinkage() &&
- "Function should have available_externally linkage!");
-
// Change the linkage.
CGM.setFunctionLinkage(GD, ThunkFn);
return;
diff --git a/clang/lib/CodeGen/CodeGenModule.h b/clang/lib/CodeGen/CodeGenModule.h
index 25aaae61e48..249ad331759 100644
--- a/clang/lib/CodeGen/CodeGenModule.h
+++ b/clang/lib/CodeGen/CodeGenModule.h
@@ -1034,7 +1034,8 @@ private:
// C++ related functions.
- bool TryEmitDefinitionAsAlias(GlobalDecl Alias, GlobalDecl Target);
+ bool TryEmitDefinitionAsAlias(GlobalDecl Alias, GlobalDecl Target,
+ bool InEveryTU);
bool TryEmitBaseDestructorAsAlias(const CXXDestructorDecl *D);
void EmitNamespace(const NamespaceDecl *D);
OpenPOWER on IntegriCloud