Add -ftls-model command-line flag.

This allows for setting the default TLS model. (PR9788)

git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@159336 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/lib/CodeGen/CGDecl.cpp b/lib/CodeGen/CGDecl.cpp
index 08a9382..be6638e 100644
--- a/lib/CodeGen/CGDecl.cpp
+++ b/lib/CodeGen/CGDecl.cpp
@@ -183,26 +183,20 @@
   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, TLM,
+                             CGM.EmitNullConstant(D.getType()), Name, 0,
+                             llvm::GlobalVariable::NotThreadLocal,
                              CGM.getContext().getTargetAddressSpace(Ty));
   GV->setAlignment(getContext().getDeclAlign(&D).getQuantity());
   if (Linkage != llvm::GlobalValue::InternalLinkage)
     GV->setVisibility(CurFn->getVisibility());
+
+  if (D.isThreadSpecified())
+    CGM.setTLSMode(GV, D);
+
   return GV;
 }
 
diff --git a/lib/CodeGen/CodeGenModule.cpp b/lib/CodeGen/CodeGenModule.cpp
index 8f769d9..25053b9 100644
--- a/lib/CodeGen/CodeGenModule.cpp
+++ b/lib/CodeGen/CodeGenModule.cpp
@@ -258,6 +258,45 @@
     GV->setVisibility(GetLLVMVisibility(LV.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);
+}
+
+static llvm::GlobalVariable::ThreadLocalMode GetLLVMTLSModel(
+    CodeGenOptions::TLSModel M) {
+  switch (M) {
+  case CodeGenOptions::GeneralDynamicTLSModel:
+    return llvm::GlobalVariable::GeneralDynamicTLSModel;
+  case CodeGenOptions::LocalDynamicTLSModel:
+    return llvm::GlobalVariable::LocalDynamicTLSModel;
+  case CodeGenOptions::InitialExecTLSModel:
+    return llvm::GlobalVariable::InitialExecTLSModel;
+  case CodeGenOptions::LocalExecTLSModel:
+    return llvm::GlobalVariable::LocalExecTLSModel;
+  }
+  llvm_unreachable("Invalid TLS model!");
+}
+
+void CodeGenModule::setTLSMode(llvm::GlobalVariable *GV,
+                               const VarDecl &D) const {
+  assert(D.isThreadSpecified() && "setting TLS mode on non-TLS var!");
+
+  llvm::GlobalVariable::ThreadLocalMode TLM;
+  TLM = GetLLVMTLSModel(CodeGenOpts.DefaultTLSModel);
+
+  // Override the TLS model if it is explicitly specified.
+  if (D.hasAttr<TLSModelAttr>()) {
+    const TLSModelAttr *Attr = D.getAttr<TLSModelAttr>();
+    TLM = GetLLVMTLSModel(Attr->getModel());
+  }
+
+  GV->setThreadLocalMode(TLM);
+}
+
 /// Set the symbol visibility of type information (vtable and RTTI)
 /// associated with the given type.
 void CodeGenModule::setTypeVisibility(llvm::GlobalValue *GV,
@@ -1212,13 +1251,8 @@
         GV->setVisibility(GetLLVMVisibility(LV.visibility()));
     }
 
-    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 (D->isThreadSpecified())
+      setTLSMode(GV, *D);
   }
 
   if (AddrSpace != Ty->getAddressSpace())
diff --git a/lib/CodeGen/CodeGenModule.h b/lib/CodeGen/CodeGenModule.h
index a742d84..d6ff50d 100644
--- a/lib/CodeGen/CodeGenModule.h
+++ b/lib/CodeGen/CodeGenModule.h
@@ -474,6 +474,10 @@
   /// GlobalValue.
   void setGlobalVisibility(llvm::GlobalValue *GV, const NamedDecl *D) const;
 
+  /// setTLSMode - Set the TLS mode for the given LLVM GlobalVariable
+  /// for the thread-local variable declaration D.
+  void setTLSMode(llvm::GlobalVariable *GV, const VarDecl &D) const;
+
   /// TypeVisibilityKind - The kind of global variable that is passed to 
   /// setTypeVisibility
   enum TypeVisibilityKind {
@@ -498,15 +502,6 @@
     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()),