[cfe-commits] r159078 - in /cfe/trunk: docs/ReleaseNotes.html include/clang/Basic/Attr.td include/clang/Basic/DiagnosticSemaKinds.td lib/CodeGen/CGDecl.cpp lib/CodeGen/CGExprConstant.cpp lib/CodeGen/CodeGenModule.cpp lib/CodeGen/CodeGenModule.h lib/Sema/SemaDeclAttr.cpp test/CodeGen/thread-specifier.c test/Sema/attr-tls_model.c
Hans Wennborg
hans at hanshq.net
Sat Jun 23 04:51:46 PDT 2012
Author: hans
Date: Sat Jun 23 06:51:46 2012
New Revision: 159078
URL: http://llvm.org/viewvc/llvm-project?rev=159078&view=rev
Log:
Support the tls_model attribute (PR9788)
This adds support for the tls_model attribute. This allows the user to
choose a TLS model that is better than what LLVM would select by
default. For example, a variable might be declared as:
__thread int x __attribute__((tls_model("initial-exec")));
if it will not be used in a shared library that is dlopen'ed.
This depends on LLVM r159077.
Added:
cfe/trunk/test/Sema/attr-tls_model.c
Modified:
cfe/trunk/docs/ReleaseNotes.html
cfe/trunk/include/clang/Basic/Attr.td
cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td
cfe/trunk/lib/CodeGen/CGDecl.cpp
cfe/trunk/lib/CodeGen/CGExprConstant.cpp
cfe/trunk/lib/CodeGen/CodeGenModule.cpp
cfe/trunk/lib/CodeGen/CodeGenModule.h
cfe/trunk/lib/Sema/SemaDeclAttr.cpp
cfe/trunk/test/CodeGen/thread-specifier.c
Modified: cfe/trunk/docs/ReleaseNotes.html
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/docs/ReleaseNotes.html?rev=159078&r1=159077&r2=159078&view=diff
==============================================================================
--- cfe/trunk/docs/ReleaseNotes.html (original)
+++ cfe/trunk/docs/ReleaseNotes.html Sat Jun 23 06:51:46 2012
@@ -123,6 +123,20 @@
flag.</li>
</ul>
+<h4 id="tlsmodel">Support for <code>tls_model</code> attribute</h4>
+
+<p>Clang now supports the <code>tls_model</code> attribute, allowing code that
+uses thread-local storage to explicitly select which model to use. The available
+models are <code>"global-dynamic"</code>, <code>"local-dynamic"</code>,
+<code>"initial-exec"</code> and <code>"local-exec"</code>. See
+<a href="http://www.akkadia.org/drepper/tls.pdf">ELF Handling For Thread-Local
+ Storage</a> for more information.</p>
+
+<p>The compiler is free to choose a different model if the specified model is not
+supported by the target, or if the compiler determines that a more specific
+model can be used.
+</p>
+
<!-- = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = -->
<h3 id="newflags">New Compiler Flags</h3>
<!-- = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = -->
Modified: cfe/trunk/include/clang/Basic/Attr.td
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/Attr.td?rev=159078&r1=159077&r2=159078&view=diff
==============================================================================
--- cfe/trunk/include/clang/Basic/Attr.td (original)
+++ cfe/trunk/include/clang/Basic/Attr.td Sat Jun 23 06:51:46 2012
@@ -160,6 +160,12 @@
let Spellings = [GNU<"always_inline">];
}
+def TLSModel : InheritableAttr {
+ let Spellings = [GNU<"tls_model">];
+ let Subjects = [Var];
+ let Args = [StringArgument<"Model">];
+}
+
def AnalyzerNoReturn : InheritableAttr {
let Spellings = [GNU<"analyzer_noreturn">];
}
Modified: cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td?rev=159078&r1=159077&r2=159078&view=diff
==============================================================================
--- cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td (original)
+++ cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td Sat Jun 23 06:51:46 2012
@@ -1603,6 +1603,8 @@
"direct comparison of %select{a string literal|an array literal|"
"a dictionary literal|a numeric literal|a boxed expression|}0 is not "
"allowed%select{|; use -isEqual: instead}1">;
+def err_attr_tlsmodel_arg : Error<"tls_model must be \"global-dynamic\", "
+ "\"local-dynamic\", \"initial-exec\" or \"local-exec\"">;
let CategoryName = "Cocoa API Issue" in {
def warn_objc_redundant_literal_use : Warning<
@@ -1670,13 +1672,13 @@
"functions, methods and blocks|functions, methods, and parameters|"
"classes|variables|methods|variables, functions and labels|"
"fields and global variables|structs|"
- "variables, functions and tag types}1">;
+ "variables, functions and tag types|thread-local variables}1">;
def err_attribute_wrong_decl_type : Error<
"%0 attribute only applies to %select{functions|unions|"
"variables and functions|functions and methods|parameters|"
"functions, methods and blocks|functions, methods, and parameters|"
"classes|variables|methods|variables, functions and labels|"
- "fields and global variables|structs}1">;
+ "fields and global variables|structs|thread-local variables}1">;
def warn_function_attribute_wrong_type : Warning<
"'%0' only applies to function types; type here is %1">;
def warn_pointer_attribute_wrong_type : Warning<
Modified: cfe/trunk/lib/CodeGen/CGDecl.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CGDecl.cpp?rev=159078&r1=159077&r2=159078&view=diff
==============================================================================
--- cfe/trunk/lib/CodeGen/CGDecl.cpp (original)
+++ cfe/trunk/lib/CodeGen/CGDecl.cpp Sat Jun 23 06:51:46 2012
@@ -183,12 +183,22 @@
else
Name = GetStaticDeclName(*this, D, Separator);
+ llvm::GlobalVariable::ThreadLocalMode TLM;
+ TLM = D.isThreadSpecified() ? llvm::GlobalVariable::GeneralDynamicTLSModel
+ : llvm::GlobalVariable::NotThreadLocal;
+
+ // Set the TLS mode if it it's explicitly specified.
+ if (D.hasAttr<TLSModelAttr>()) {
+ assert(D.isThreadSpecified() && "Can't have TLS model on non-tls var.");
+ const TLSModelAttr *Attr = D.getAttr<TLSModelAttr>();
+ TLM = CodeGenModule::GetLLVMTLSModel(Attr->getModel());
+ }
+
llvm::Type *LTy = CGM.getTypes().ConvertTypeForMem(Ty);
llvm::GlobalVariable *GV =
new llvm::GlobalVariable(CGM.getModule(), LTy,
Ty.isConstant(getContext()), Linkage,
- CGM.EmitNullConstant(D.getType()), Name, 0,
- D.isThreadSpecified(),
+ CGM.EmitNullConstant(D.getType()), Name, 0, TLM,
CGM.getContext().getTargetAddressSpace(Ty));
GV->setAlignment(getContext().getDeclAlign(&D).getQuantity());
if (Linkage != llvm::GlobalValue::InternalLinkage)
@@ -239,7 +249,7 @@
OldGV->isConstant(),
OldGV->getLinkage(), Init, "",
/*InsertBefore*/ OldGV,
- D.isThreadSpecified(),
+ OldGV->getThreadLocalMode(),
CGM.getContext().getTargetAddressSpace(D.getType()));
GV->setVisibility(OldGV->getVisibility());
@@ -1066,7 +1076,7 @@
llvm::GlobalVariable *GV =
new llvm::GlobalVariable(CGM.getModule(), constant->getType(), true,
llvm::GlobalValue::PrivateLinkage,
- constant, Name, 0, false, 0);
+ constant, Name);
GV->setAlignment(alignment.getQuantity());
GV->setUnnamedAddr(true);
Modified: cfe/trunk/lib/CodeGen/CGExprConstant.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CGExprConstant.cpp?rev=159078&r1=159077&r2=159078&view=diff
==============================================================================
--- cfe/trunk/lib/CodeGen/CGExprConstant.cpp (original)
+++ cfe/trunk/lib/CodeGen/CGExprConstant.cpp Sat Jun 23 06:51:46 2012
@@ -932,7 +932,8 @@
C = new llvm::GlobalVariable(CGM.getModule(), C->getType(),
E->getType().isConstant(CGM.getContext()),
llvm::GlobalValue::InternalLinkage,
- C, ".compoundliteral", 0, false,
+ C, ".compoundliteral", 0,
+ llvm::GlobalVariable::NotThreadLocal,
CGM.getContext().getTargetAddressSpace(E->getType()));
return C;
}
Modified: cfe/trunk/lib/CodeGen/CodeGenModule.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CodeGenModule.cpp?rev=159078&r1=159077&r2=159078&view=diff
==============================================================================
--- cfe/trunk/lib/CodeGen/CodeGenModule.cpp (original)
+++ cfe/trunk/lib/CodeGen/CodeGenModule.cpp Sat Jun 23 06:51:46 2012
@@ -1187,7 +1187,7 @@
new llvm::GlobalVariable(getModule(), Ty->getElementType(), false,
llvm::GlobalValue::ExternalLinkage,
0, MangledName, 0,
- false, AddrSpace);
+ llvm::GlobalVariable::NotThreadLocal, AddrSpace);
// Handle things which are present even on external declarations.
if (D) {
@@ -1211,6 +1211,12 @@
}
GV->setThreadLocal(D->isThreadSpecified());
+
+ // Set the TLS model if it it's explicitly specified.
+ if (D->hasAttr<TLSModelAttr>()) {
+ const TLSModelAttr *Attr = D->getAttr<TLSModelAttr>();
+ GV->setThreadLocalMode(GetLLVMTLSModel(Attr->getModel()));
+ }
}
if (AddrSpace != Ty->getAddressSpace())
Modified: cfe/trunk/lib/CodeGen/CodeGenModule.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CodeGenModule.h?rev=159078&r1=159077&r2=159078&view=diff
==============================================================================
--- cfe/trunk/lib/CodeGen/CodeGenModule.h (original)
+++ cfe/trunk/lib/CodeGen/CodeGenModule.h Sat Jun 23 06:51:46 2012
@@ -496,6 +496,15 @@
llvm_unreachable("unknown visibility!");
}
+ static llvm::GlobalVariable::ThreadLocalMode GetLLVMTLSModel(StringRef S) {
+ return llvm::StringSwitch<llvm::GlobalVariable::ThreadLocalMode>(S)
+ .Case("global-dynamic", llvm::GlobalVariable::GeneralDynamicTLSModel)
+ .Case("local-dynamic", llvm::GlobalVariable::LocalDynamicTLSModel)
+ .Case("initial-exec", llvm::GlobalVariable::InitialExecTLSModel)
+ .Case("local-exec", llvm::GlobalVariable::LocalExecTLSModel)
+ .Default(llvm::GlobalVariable::NotThreadLocal);
+ }
+
llvm::Constant *GetAddrOfGlobal(GlobalDecl GD) {
if (isa<CXXConstructorDecl>(GD.getDecl()))
return GetAddrOfCXXConstructor(cast<CXXConstructorDecl>(GD.getDecl()),
Modified: cfe/trunk/lib/Sema/SemaDeclAttr.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaDeclAttr.cpp?rev=159078&r1=159077&r2=159078&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaDeclAttr.cpp (original)
+++ cfe/trunk/lib/Sema/SemaDeclAttr.cpp Sat Jun 23 06:51:46 2012
@@ -43,7 +43,8 @@
ExpectedMethod,
ExpectedVariableFunctionOrLabel,
ExpectedFieldOrGlobalVar,
- ExpectedStruct
+ ExpectedStruct,
+ ExpectedTLSVar
};
//===----------------------------------------------------------------------===//
@@ -1440,6 +1441,42 @@
D->addAttr(::new (S.Context) AlwaysInlineAttr(Attr.getRange(), S.Context));
}
+static void handleTLSModelAttr(Sema &S, Decl *D,
+ const AttributeList &Attr) {
+ // Check the attribute arguments.
+ if (Attr.getNumArgs() != 1) {
+ S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments) << 1;
+ return;
+ }
+
+ Expr *Arg = Attr.getArg(0);
+ Arg = Arg->IgnoreParenCasts();
+ StringLiteral *Str = dyn_cast<StringLiteral>(Arg);
+
+ // Check that it is a string.
+ if (!Str) {
+ S.Diag(Attr.getLoc(), diag::err_attribute_not_string) << "tls_model";
+ return;
+ }
+
+ if (!isa<VarDecl>(D) || !cast<VarDecl>(D)->isThreadSpecified()) {
+ S.Diag(Attr.getLoc(), diag::err_attribute_wrong_decl_type)
+ << Attr.getName() << ExpectedTLSVar;
+ return;
+ }
+
+ // Check that the value.
+ StringRef Model = Str->getString();
+ if (Model != "global-dynamic" && Model != "local-dynamic"
+ && Model != "initial-exec" && Model != "local-exec") {
+ S.Diag(Attr.getLoc(), diag::err_attr_tlsmodel_arg);
+ return;
+ }
+
+ D->addAttr(::new (S.Context) TLSModelAttr(Attr.getRange(), S.Context,
+ Model));
+}
+
static void handleMallocAttr(Sema &S, Decl *D, const AttributeList &Attr) {
// Check the attribute arguments.
if (Attr.hasParameterOrArguments()) {
@@ -3939,6 +3976,7 @@
handleAlwaysInlineAttr (S, D, Attr); break;
case AttributeList::AT_AnalyzerNoReturn:
handleAnalyzerNoReturnAttr (S, D, Attr); break;
+ case AttributeList::AT_TLSModel: handleTLSModelAttr (S, D, Attr); break;
case AttributeList::AT_Annotate: handleAnnotateAttr (S, D, Attr); break;
case AttributeList::AT_Availability:handleAvailabilityAttr(S, D, Attr); break;
case AttributeList::AT_CarriesDependency:
Modified: cfe/trunk/test/CodeGen/thread-specifier.c
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CodeGen/thread-specifier.c?rev=159078&r1=159077&r2=159078&view=diff
==============================================================================
--- cfe/trunk/test/CodeGen/thread-specifier.c (original)
+++ cfe/trunk/test/CodeGen/thread-specifier.c Sat Jun 23 06:51:46 2012
@@ -3,7 +3,13 @@
// CHECK: @b = external thread_local global
// CHECK: @d.e = internal thread_local global
// CHECK: @d.f = internal thread_local global
+// CHECK: @f.a = internal thread_local(initialexec) global
// CHECK: @a = thread_local global
+// CHECK: @g = thread_local global
+// CHECK: @h = thread_local(localdynamic) global
+// CHECK: @i = thread_local(initialexec) global
+// CHECK: @j = thread_local(localexec) global
+
__thread int a;
extern __thread int b;
int c() { return *&b; }
@@ -13,3 +19,12 @@
return 0;
}
+__thread int g __attribute__((tls_model("global-dynamic")));
+__thread int h __attribute__((tls_model("local-dynamic")));
+__thread int i __attribute__((tls_model("initial-exec")));
+__thread int j __attribute__((tls_model("local-exec")));
+
+int f() {
+ __thread static int a __attribute__((tls_model("initial-exec")));
+ return a++;
+}
Added: cfe/trunk/test/Sema/attr-tls_model.c
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Sema/attr-tls_model.c?rev=159078&view=auto
==============================================================================
--- cfe/trunk/test/Sema/attr-tls_model.c (added)
+++ cfe/trunk/test/Sema/attr-tls_model.c Sat Jun 23 06:51:46 2012
@@ -0,0 +1,14 @@
+// RUN: %clang -Xclang -verify -fsyntax-only %s
+
+#if !__has_attribute(tls_model)
+#error "Should support tls_model attribute"
+#endif
+
+int f() __attribute((tls_model("global-dynamic"))); // expected-error {{'tls_model' attribute only applies to thread-local variables}}
+
+int x __attribute((tls_model("global-dynamic"))); // expected-error {{'tls_model' attribute only applies to thread-local variables}}
+static __thread int y __attribute((tls_model("global-dynamic"))); // no-warning
+
+static __thread int y __attribute((tls_model("local", "dynamic"))); // expected-error {{attribute takes one argument}}
+static __thread int y __attribute((tls_model(123))); // expected-error {{argument to tls_model attribute was not a string literal}}
+static __thread int y __attribute((tls_model("foobar"))); // expected-error {{tls_model must be "global-dynamic", "local-dynamic", "initial-exec" or "local-exec"}}
More information about the cfe-commits
mailing list