summaryrefslogtreecommitdiffstats
path: root/clang/lib
diff options
context:
space:
mode:
Diffstat (limited to 'clang/lib')
-rw-r--r--clang/lib/CodeGen/CGCXX.cpp39
-rw-r--r--clang/lib/CodeGen/CodeGenModule.cpp15
-rw-r--r--clang/lib/CodeGen/CodeGenModule.h6
3 files changed, 42 insertions, 18 deletions
diff --git a/clang/lib/CodeGen/CGCXX.cpp b/clang/lib/CodeGen/CGCXX.cpp
index 31134be810d..15686f7ff6e 100644
--- a/clang/lib/CodeGen/CGCXX.cpp
+++ b/clang/lib/CodeGen/CGCXX.cpp
@@ -112,33 +112,20 @@ bool CodeGenModule::TryEmitDefinitionAsAlias(GlobalDecl AliasDecl,
// support aliases with that linkage, fail.
llvm::GlobalValue::LinkageTypes Linkage = getFunctionLinkage(AliasDecl);
- llvm::GlobalValue::LinkageTypes TargetLinkage
- = getFunctionLinkage(TargetDecl);
-
- // 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;
+ llvm::GlobalValue::LinkageTypes TargetLinkage =
+ getFunctionLinkage(TargetDecl);
+
// Check if we have it already.
StringRef MangledName = getMangledName(AliasDecl);
llvm::GlobalValue *Entry = GetGlobalValue(MangledName);
if (Entry && !Entry->isDeclaration())
return false;
+ if (Replacements.count(MangledName))
+ return false;
// Derive the type for the alias.
llvm::PointerType *AliasType
@@ -152,6 +139,22 @@ bool CodeGenModule::TryEmitDefinitionAsAlias(GlobalDecl AliasDecl,
if (Ref->getType() != AliasType)
Aliasee = llvm::ConstantExpr::getBitCast(Ref, AliasType);
+ // 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;
+
+ assert(Linkage == TargetLinkage);
+ // Instead of creating as alias to a linkonce_odr, replace all of the uses
+ // of the aliassee.
+ if (TargetLinkage == llvm::GlobalValue::LinkOnceODRLinkage) {
+ Replacements[MangledName] = Aliasee;
+ return false;
+ }
+ }
+
// Create the alias with no name.
llvm::GlobalAlias *Alias =
new llvm::GlobalAlias(AliasType, Linkage, "", Aliasee, &getModule());
diff --git a/clang/lib/CodeGen/CodeGenModule.cpp b/clang/lib/CodeGen/CodeGenModule.cpp
index c34f8332699..d7f33c9f1e5 100644
--- a/clang/lib/CodeGen/CodeGenModule.cpp
+++ b/clang/lib/CodeGen/CodeGenModule.cpp
@@ -172,6 +172,20 @@ void CodeGenModule::createCUDARuntime() {
CUDARuntime = CreateNVCUDARuntime(*this);
}
+void CodeGenModule::applyReplacements() {
+ for (ReplacementsTy::iterator I = Replacements.begin(),
+ E = Replacements.end();
+ I != E; ++I) {
+ StringRef MangledName = I->first();
+ llvm::Constant *Replacement = I->second;
+ llvm::GlobalValue *Entry = GetGlobalValue(MangledName);
+ if (!Entry)
+ continue;
+ Entry->replaceAllUsesWith(Replacement);
+ Entry->eraseFromParent();
+ }
+}
+
void CodeGenModule::checkAliases() {
bool Error = false;
for (std::vector<GlobalDecl>::iterator I = Aliases.begin(),
@@ -207,6 +221,7 @@ void CodeGenModule::checkAliases() {
void CodeGenModule::Release() {
EmitDeferred();
+ applyReplacements();
checkAliases();
EmitCXXGlobalInitFunc();
EmitCXXGlobalDtorFunc();
diff --git a/clang/lib/CodeGen/CodeGenModule.h b/clang/lib/CodeGen/CodeGenModule.h
index 45a9e20a510..02b9ce6471b 100644
--- a/clang/lib/CodeGen/CodeGenModule.h
+++ b/clang/lib/CodeGen/CodeGenModule.h
@@ -279,6 +279,9 @@ class CodeGenModule : public CodeGenTypeCache {
/// is defined once we get to the end of the of the translation unit.
std::vector<GlobalDecl> Aliases;
+ typedef llvm::StringMap<llvm::TrackingVH<llvm::Constant> > ReplacementsTy;
+ ReplacementsTy Replacements;
+
/// DeferredVTables - A queue of (optional) vtables to consider emitting.
std::vector<const CXXRecordDecl*> DeferredVTables;
@@ -1082,6 +1085,9 @@ private:
/// was deferred.
void EmitDeferred();
+ /// Call replaceAllUsesWith on all pairs in Replacements.
+ void applyReplacements();
+
void checkAliases();
/// EmitDeferredVTables - Emit any vtables which we deferred and
OpenPOWER on IntegriCloud