summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJohn McCall <rjmccall@apple.com>2010-05-25 04:30:21 +0000
committerJohn McCall <rjmccall@apple.com>2010-05-25 04:30:21 +0000
commit7cb0220e535958756f0c36788b370aebc07aea1f (patch)
tree9ded153a937343d25326b31eee351dff293d63bf
parent26fdebcae9321029dd0a474f2f38d669eebe1133 (diff)
downloadbcm5719-llvm-7cb0220e535958756f0c36788b370aebc07aea1f.tar.gz
bcm5719-llvm-7cb0220e535958756f0c36788b370aebc07aea1f.zip
If a function definition has any sort of weak linkage, its static local
variables should have that linkage. Otherwise, its static local variables should have internal linkage. To avoid computing this excessively, set a function's linkage before we emit code for it. Previously we were assigning weak linkage to the static variables of static inline functions in C++, with predictably terrible results. This fixes that and also gives better linkage than 'weak' when merging is required. llvm-svn: 104581
-rw-r--r--clang/lib/CodeGen/CGCXX.cpp2
-rw-r--r--clang/lib/CodeGen/CGDecl.cpp16
-rw-r--r--clang/lib/CodeGen/CGVTables.cpp2
-rw-r--r--clang/lib/CodeGen/CodeGenModule.cpp2
-rw-r--r--clang/lib/CodeGen/CodeGenModule.h4
-rw-r--r--clang/test/CodeGenCXX/static-init.cpp15
6 files changed, 29 insertions, 12 deletions
diff --git a/clang/lib/CodeGen/CGCXX.cpp b/clang/lib/CodeGen/CGCXX.cpp
index 74cf1134d5b..85222fe9dba 100644
--- a/clang/lib/CodeGen/CGCXX.cpp
+++ b/clang/lib/CodeGen/CGCXX.cpp
@@ -206,6 +206,7 @@ void CodeGenModule::EmitCXXConstructor(const CXXConstructorDecl *D,
return;
llvm::Function *Fn = cast<llvm::Function>(GetAddrOfCXXConstructor(D, Type));
+ setFunctionLinkage(D, Fn);
CodeGenFunction(*this).GenerateCode(GlobalDecl(D, Type), Fn);
@@ -269,6 +270,7 @@ void CodeGenModule::EmitCXXDestructor(const CXXDestructorDecl *D,
return;
llvm::Function *Fn = cast<llvm::Function>(GetAddrOfCXXDestructor(D, Type));
+ setFunctionLinkage(D, Fn);
CodeGenFunction(*this).GenerateCode(GlobalDecl(D, Type), Fn);
diff --git a/clang/lib/CodeGen/CGDecl.cpp b/clang/lib/CodeGen/CGDecl.cpp
index 611ebed5a3d..8115e384db8 100644
--- a/clang/lib/CodeGen/CGDecl.cpp
+++ b/clang/lib/CodeGen/CGDecl.cpp
@@ -114,14 +114,14 @@ void CodeGenFunction::EmitBlockVarDecl(const VarDecl &D) {
llvm::GlobalValue::LinkageTypes Linkage =
llvm::GlobalValue::InternalLinkage;
- // If this is a static declaration inside an inline function, it must have
- // weak linkage so that the linker will merge multiple definitions of it.
- if (getContext().getLangOptions().CPlusPlus) {
- if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(CurFuncDecl)) {
- if (FD->isInlined())
- Linkage = llvm::GlobalValue::WeakAnyLinkage;
- }
- }
+ // If the function definition has some sort of weak linkage, its
+ // static variables should also be weak so that they get properly
+ // uniqued. We can't do this in C, though, because there's no
+ // standard way to agree on which variables are the same (i.e.
+ // there's no mangling).
+ if (getContext().getLangOptions().CPlusPlus)
+ if (llvm::GlobalValue::isWeakForLinker(CurFn->getLinkage()))
+ Linkage = CurFn->getLinkage();
return EmitStaticBlockVarDecl(D, Linkage);
}
diff --git a/clang/lib/CodeGen/CGVTables.cpp b/clang/lib/CodeGen/CGVTables.cpp
index b66b9f84933..8bdd4588d4a 100644
--- a/clang/lib/CodeGen/CGVTables.cpp
+++ b/clang/lib/CodeGen/CGVTables.cpp
@@ -2723,7 +2723,7 @@ void CodeGenFunction::GenerateThunk(llvm::Function *Fn, GlobalDecl GD,
CXXThisDecl->Destroy(getContext());
// Set the right linkage.
- Fn->setLinkage(CGM.getFunctionLinkage(MD));
+ CGM.setFunctionLinkage(MD, Fn);
// Set the right visibility.
CGM.setGlobalVisibility(Fn, MD);
diff --git a/clang/lib/CodeGen/CodeGenModule.cpp b/clang/lib/CodeGen/CodeGenModule.cpp
index 05c7a87e5fd..2f8404e251e 100644
--- a/clang/lib/CodeGen/CodeGenModule.cpp
+++ b/clang/lib/CodeGen/CodeGenModule.cpp
@@ -361,7 +361,6 @@ CodeGenModule::getFunctionLinkage(const FunctionDecl *D) {
/// variables (these details are set in EmitGlobalVarDefinition for variables).
void CodeGenModule::SetFunctionDefinitionAttributes(const FunctionDecl *D,
llvm::GlobalValue *GV) {
- GV->setLinkage(getFunctionLinkage(D));
SetCommonAttributes(D, GV);
}
@@ -1330,6 +1329,7 @@ void CodeGenModule::EmitGlobalFunctionDefinition(GlobalDecl GD) {
}
llvm::Function *Fn = cast<llvm::Function>(Entry);
+ setFunctionLinkage(D, Fn);
CodeGenFunction(*this).GenerateCode(D, Fn);
diff --git a/clang/lib/CodeGen/CodeGenModule.h b/clang/lib/CodeGen/CodeGenModule.h
index 0e4f4a932ee..e225462fac8 100644
--- a/clang/lib/CodeGen/CodeGenModule.h
+++ b/clang/lib/CodeGen/CodeGenModule.h
@@ -436,6 +436,10 @@ public:
llvm::GlobalVariable::LinkageTypes
getFunctionLinkage(const FunctionDecl *FD);
+ void setFunctionLinkage(const FunctionDecl *FD, llvm::GlobalValue *V) {
+ V->setLinkage(getFunctionLinkage(FD));
+ }
+
/// getVTableLinkage - Return the appropriate linkage for the vtable, VTT,
/// and type information of the given class.
static llvm::GlobalVariable::LinkageTypes
diff --git a/clang/test/CodeGenCXX/static-init.cpp b/clang/test/CodeGenCXX/static-init.cpp
index f9604d96433..9ad87df8f0c 100644
--- a/clang/test/CodeGenCXX/static-init.cpp
+++ b/clang/test/CodeGenCXX/static-init.cpp
@@ -2,8 +2,9 @@
// CHECK: @_ZZ1hvE1i = internal global i32 0, align 4
-// CHECK: @_ZZ2h2vE1i = weak global i32 0
-// CHECK: @_ZGVZ2h2vE1i = weak global i64 0
+// CHECK: @_ZZN5test16getvarEiE3var = internal constant [4 x i32] [i32 1, i32 0, i32 2, i32 4], align 4
+// CHECK: @_ZZ2h2vE1i = linkonce_odr global i32 0
+// CHECK: @_ZGVZ2h2vE1i = linkonce_odr global i64 0
struct A {
A();
@@ -47,3 +48,13 @@ namespace test0 {
static A r;
}
}
+
+namespace test1 {
+ // CHECK: define internal i32 @_ZN5test16getvarEi(
+ static inline int getvar(int index) {
+ static const int var[] = { 1, 0, 2, 4 };
+ return var[index];
+ }
+
+ void test() { (void) getvar(2); }
+}
OpenPOWER on IntegriCloud