diff --git a/clang/lib/CodeGen/CodeGenModule.h b/clang/lib/CodeGen/CodeGenModule.h --- a/clang/lib/CodeGen/CodeGenModule.h +++ b/clang/lib/CodeGen/CodeGenModule.h @@ -790,6 +790,9 @@ /// variable declaration D. void setTLSMode(llvm::GlobalValue *GV, const VarDecl &D) const; + /// Get LLVM TLS mode from CodeGenOptions. + llvm::GlobalVariable::ThreadLocalMode GetDefaultLLVMTLSModel() const; + static llvm::GlobalValue::VisibilityTypes GetLLVMVisibility(Visibility V) { switch (V) { case DefaultVisibility: return llvm::GlobalValue::DefaultVisibility; diff --git a/clang/lib/CodeGen/CodeGenModule.cpp b/clang/lib/CodeGen/CodeGenModule.cpp --- a/clang/lib/CodeGen/CodeGenModule.cpp +++ b/clang/lib/CodeGen/CodeGenModule.cpp @@ -971,9 +971,9 @@ .Case("local-exec", llvm::GlobalVariable::LocalExecTLSModel); } -static llvm::GlobalVariable::ThreadLocalMode GetLLVMTLSModel( - CodeGenOptions::TLSModel M) { - switch (M) { +llvm::GlobalVariable::ThreadLocalMode +CodeGenModule::GetDefaultLLVMTLSModel() const { + switch (CodeGenOpts.getDefaultTLSModel()) { case CodeGenOptions::GeneralDynamicTLSModel: return llvm::GlobalVariable::GeneralDynamicTLSModel; case CodeGenOptions::LocalDynamicTLSModel: @@ -990,7 +990,7 @@ assert(D.getTLSKind() && "setting TLS mode on non-TLS var!"); llvm::GlobalValue::ThreadLocalMode TLM; - TLM = GetLLVMTLSModel(CodeGenOpts.getDefaultTLSModel()); + TLM = GetDefaultLLVMTLSModel(); // Override the TLS model if it is explicitly specified. if (const TLSModelAttr *Attr = D.getAttr()) { diff --git a/clang/lib/CodeGen/ItaniumCXXABI.cpp b/clang/lib/CodeGen/ItaniumCXXABI.cpp --- a/clang/lib/CodeGen/ItaniumCXXABI.cpp +++ b/clang/lib/CodeGen/ItaniumCXXABI.cpp @@ -2687,6 +2687,7 @@ llvm::GlobalVariable::InternalLinkage, llvm::ConstantInt::get(CGM.Int8Ty, 0), "__tls_guard"); Guard->setThreadLocal(true); + Guard->setThreadLocalMode(CGM.GetDefaultLLVMTLSModel()); CharUnits GuardAlign = CharUnits::One(); Guard->setAlignment(GuardAlign.getAsAlign()); diff --git a/clang/lib/CodeGen/MicrosoftCXXABI.cpp b/clang/lib/CodeGen/MicrosoftCXXABI.cpp --- a/clang/lib/CodeGen/MicrosoftCXXABI.cpp +++ b/clang/lib/CodeGen/MicrosoftCXXABI.cpp @@ -2523,7 +2523,7 @@ GuardVar->setComdat( CGM.getModule().getOrInsertComdat(GuardVar->getName())); if (D.getTLSKind()) - GuardVar->setThreadLocal(true); + CGM.setTLSMode(GuardVar, D); if (GI && !HasPerVariableGuard) GI->Guard = GuardVar; } diff --git a/clang/test/CodeGen/tls-model.c b/clang/test/CodeGen/tls-model.cpp rename from clang/test/CodeGen/tls-model.c rename to clang/test/CodeGen/tls-model.cpp --- a/clang/test/CodeGen/tls-model.c +++ b/clang/test/CodeGen/tls-model.cpp @@ -16,29 +16,52 @@ } int __thread __attribute__((tls_model("initial-exec"))) z; +struct S { + S(); + ~S(); +}; +struct T { + ~T(); +}; + +struct S thread_local s1; +struct T thread_local t1; + // Note that unlike normal C uninitialized global variables, // uninitialized TLS variables do NOT have COMMON linkage. // CHECK-GD: @z1 = global i32 0 -// CHECK-GD: @f.y = internal thread_local global i32 0 // CHECK-GD: @z2 = global i32 0 // CHECK-GD: @x = thread_local global i32 0 +// CHECK-GD: @_ZZ1fvE1y = internal thread_local global i32 0 // CHECK-GD: @z = thread_local(initialexec) global i32 0 +// CHECK-GD: @s1 = thread_local global %struct.S zeroinitializer +// CHECK-GD: @t1 = thread_local global %struct.T zeroinitializer +// CHECK-GD: @__tls_guard = internal thread_local global i8 0 // CHECK-LD: @z1 = global i32 0 -// CHECK-LD: @f.y = internal thread_local(localdynamic) global i32 0 // CHECK-LD: @z2 = global i32 0 // CHECK-LD: @x = thread_local(localdynamic) global i32 0 +// CHECK-LD: @_ZZ1fvE1y = internal thread_local(localdynamic) global i32 0 // CHECK-LD: @z = thread_local(initialexec) global i32 0 +// CHECK-LD: @s1 = thread_local(localdynamic) global %struct.S zeroinitializer +// CHECK-LD: @t1 = thread_local(localdynamic) global %struct.T zeroinitializer +// CHECK-LD: @__tls_guard = internal thread_local(localdynamic) global i8 0 // CHECK-IE: @z1 = global i32 0 -// CHECK-IE: @f.y = internal thread_local(initialexec) global i32 0 // CHECK-IE: @z2 = global i32 0 // CHECK-IE: @x = thread_local(initialexec) global i32 0 +// CHECK-IE: @_ZZ1fvE1y = internal thread_local(initialexec) global i32 0 // CHECK-IE: @z = thread_local(initialexec) global i32 0 +// CHECK-IE: @s1 = thread_local(initialexec) global %struct.S zeroinitializer +// CHECK-IE: @t1 = thread_local(initialexec) global %struct.T zeroinitializer +// CHECK-IE: @__tls_guard = internal thread_local(initialexec) global i8 0 // CHECK-LE: @z1 = global i32 0 -// CHECK-LE: @f.y = internal thread_local(localexec) global i32 0 // CHECK-LE: @z2 = global i32 0 // CHECK-LE: @x = thread_local(localexec) global i32 0 +// CHECK-LE: @_ZZ1fvE1y = internal thread_local(localexec) global i32 0 // CHECK-LE: @z = thread_local(initialexec) global i32 0 +// CHECK-LE: @s1 = thread_local(localexec) global %struct.S zeroinitializer +// CHECK-LE: @t1 = thread_local(localexec) global %struct.T zeroinitializer +// CHECK-LE: @__tls_guard = internal thread_local(localexec) global i8 0 diff --git a/clang/test/CodeGenCXX/ms-thread_local.cpp b/clang/test/CodeGenCXX/ms-thread_local.cpp --- a/clang/test/CodeGenCXX/ms-thread_local.cpp +++ b/clang/test/CodeGenCXX/ms-thread_local.cpp @@ -1,4 +1,5 @@ // RUN: %clang_cc1 %s -std=c++1y -triple=i686-pc-win32 -emit-llvm -o - | FileCheck %s +// RUN: %clang_cc1 %s -std=c++1y -triple=i686-pc-win32 -ftls-model=local-dynamic -emit-llvm -o - | FileCheck %s -check-prefix=CHECK-LD struct A { A(); @@ -8,15 +9,22 @@ // CHECK-DAG: $"??$a@X@@3UA@@A" = comdat any // CHECK-DAG: @"??$a@X@@3UA@@A" = linkonce_odr dso_local thread_local global %struct.A zeroinitializer, comdat, align 1 // CHECK-DAG: @"??__E?$a@X@@YAXXZ$initializer$" = internal constant void ()* @"??__E?$a@X@@YAXXZ", section ".CRT$XDU", comdat($"??$a@X@@3UA@@A") +// CHECK-LD-DAG: $"??$a@X@@3UA@@A" = comdat any +// CHECK-LD-DAG: @"??$a@X@@3UA@@A" = linkonce_odr dso_local thread_local(localdynamic) global %struct.A zeroinitializer, comdat, align 1 +// CHECK-LD-DAG: @"??__E?$a@X@@YAXXZ$initializer$" = internal constant void ()* @"??__E?$a@X@@YAXXZ", section ".CRT$XDU", comdat($"??$a@X@@3UA@@A") template thread_local A a = A(); // CHECK-DAG: @"?b@@3UA@@A" = dso_local thread_local global %struct.A zeroinitializer, align 1 // CHECK-DAG: @"__tls_init$initializer$" = internal constant void ()* @__tls_init, section ".CRT$XDU" +// CHECK-LD-DAG: @"?b@@3UA@@A" = dso_local thread_local(localdynamic) global %struct.A zeroinitializer, align 1 +// CHECK-LD-DAG: @"__tls_init$initializer$" = internal constant void ()* @__tls_init, section ".CRT$XDU" thread_local A b; // CHECK-LABEL: define internal void @__tls_init() // CHECK: call void @"??__Eb@@YAXXZ" +// CHECK-LD-LABEL: define internal void @__tls_init() +// CHECK-LD: call void @"??__Eb@@YAXXZ" thread_local A &c = b; thread_local A &d = c; @@ -29,3 +37,5 @@ // CHECK: !llvm.linker.options = !{![[dyn_tls_init:[0-9]+]]} // CHECK: ![[dyn_tls_init]] = !{!"/include:___dyn_tls_init@12"} +// CHECK-LD: !llvm.linker.options = !{![[dyn_tls_init:[0-9]+]]} +// CHECK-LD: ![[dyn_tls_init]] = !{!"/include:___dyn_tls_init@12"}