summaryrefslogtreecommitdiffstats
path: root/clang/lib
diff options
context:
space:
mode:
Diffstat (limited to 'clang/lib')
-rw-r--r--clang/lib/CodeGen/CGDecl.cpp18
-rw-r--r--clang/lib/CodeGen/CGExprConstant.cpp3
-rw-r--r--clang/lib/CodeGen/CodeGenModule.cpp8
-rw-r--r--clang/lib/CodeGen/CodeGenModule.h9
-rw-r--r--clang/lib/Sema/SemaDeclAttr.cpp40
5 files changed, 71 insertions, 7 deletions
diff --git a/clang/lib/CodeGen/CGDecl.cpp b/clang/lib/CodeGen/CGDecl.cpp
index ff803c612fb..08a938254ba 100644
--- a/clang/lib/CodeGen/CGDecl.cpp
+++ b/clang/lib/CodeGen/CGDecl.cpp
@@ -183,12 +183,22 @@ CodeGenFunction::CreateStaticVarDecl(const VarDecl &D,
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 @@ CodeGenFunction::AddInitializerToStaticVarDecl(const VarDecl &D,
OldGV->isConstant(),
OldGV->getLinkage(), Init, "",
/*InsertBefore*/ OldGV,
- D.isThreadSpecified(),
+ OldGV->getThreadLocalMode(),
CGM.getContext().getTargetAddressSpace(D.getType()));
GV->setVisibility(OldGV->getVisibility());
@@ -1066,7 +1076,7 @@ void CodeGenFunction::EmitAutoVarInit(const AutoVarEmission &emission) {
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);
diff --git a/clang/lib/CodeGen/CGExprConstant.cpp b/clang/lib/CodeGen/CGExprConstant.cpp
index 854810b310d..97512ad5307 100644
--- a/clang/lib/CodeGen/CGExprConstant.cpp
+++ b/clang/lib/CodeGen/CGExprConstant.cpp
@@ -932,7 +932,8 @@ public:
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;
}
diff --git a/clang/lib/CodeGen/CodeGenModule.cpp b/clang/lib/CodeGen/CodeGenModule.cpp
index 43d573689c9..1d6ddd56de3 100644
--- a/clang/lib/CodeGen/CodeGenModule.cpp
+++ b/clang/lib/CodeGen/CodeGenModule.cpp
@@ -1187,7 +1187,7 @@ CodeGenModule::GetOrCreateLLVMGlobal(StringRef MangledName,
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 @@ CodeGenModule::GetOrCreateLLVMGlobal(StringRef MangledName,
}
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())
diff --git a/clang/lib/CodeGen/CodeGenModule.h b/clang/lib/CodeGen/CodeGenModule.h
index 8f3bd78ac42..d1ecfec78a7 100644
--- a/clang/lib/CodeGen/CodeGenModule.h
+++ b/clang/lib/CodeGen/CodeGenModule.h
@@ -496,6 +496,15 @@ public:
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()),
diff --git a/clang/lib/Sema/SemaDeclAttr.cpp b/clang/lib/Sema/SemaDeclAttr.cpp
index b443911daf9..744d18bfd9f 100644
--- a/clang/lib/Sema/SemaDeclAttr.cpp
+++ b/clang/lib/Sema/SemaDeclAttr.cpp
@@ -43,7 +43,8 @@ enum AttributeDeclKind {
ExpectedMethod,
ExpectedVariableFunctionOrLabel,
ExpectedFieldOrGlobalVar,
- ExpectedStruct
+ ExpectedStruct,
+ ExpectedTLSVar
};
//===----------------------------------------------------------------------===//
@@ -1440,6 +1441,42 @@ static void handleAlwaysInlineAttr(Sema &S, Decl *D,
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 @@ static void ProcessInheritableDeclAttr(Sema &S, Scope *scope, Decl *D,
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:
OpenPOWER on IntegriCloud