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.

git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@159078 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/lib/CodeGen/CGDecl.cpp b/lib/CodeGen/CGDecl.cpp
index ff803c6..08a9382 100644
--- a/lib/CodeGen/CGDecl.cpp
+++ b/lib/CodeGen/CGDecl.cpp
@@ -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);
 
diff --git a/lib/CodeGen/CGExprConstant.cpp b/lib/CodeGen/CGExprConstant.cpp
index 854810b..97512ad 100644
--- a/lib/CodeGen/CGExprConstant.cpp
+++ b/lib/CodeGen/CGExprConstant.cpp
@@ -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;
     }
diff --git a/lib/CodeGen/CodeGenModule.cpp b/lib/CodeGen/CodeGenModule.cpp
index 43d5736..1d6ddd5 100644
--- a/lib/CodeGen/CodeGenModule.cpp
+++ b/lib/CodeGen/CodeGenModule.cpp
@@ -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())
diff --git a/lib/CodeGen/CodeGenModule.h b/lib/CodeGen/CodeGenModule.h
index 8f3bd78..d1ecfec 100644
--- a/lib/CodeGen/CodeGenModule.h
+++ b/lib/CodeGen/CodeGenModule.h
@@ -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()),