forked from OSchip/llvm-project
Add -ftls-model command-line flag.
This allows for setting the default TLS model. (PR9788) llvm-svn: 159336
This commit is contained in:
parent
608c0b65d7
commit
f60f6af9e8
|
@ -303,6 +303,14 @@ This flag sets the default visibility level.
|
|||
This flag specifies that variables without initializers get common linkage. It
|
||||
can be disabled with B<-fno-common>.
|
||||
|
||||
=item B<-ftls-model>
|
||||
|
||||
Set the default thread-local storage (TLS) model to use for thread-local
|
||||
variables. Valid values are: "global-dynamic", "local-dynamic", "initial-exec"
|
||||
and "local-exec". The default is "global-dynamic". The default model can be
|
||||
overridden with the tls_model attribute. The compiler will try to choose a more
|
||||
efficient model if possible.
|
||||
|
||||
=item B<-flto> B<-emit-llvm>
|
||||
|
||||
Generate output files in LLVM formats, suitable for link time optimization. When
|
||||
|
|
|
@ -648,6 +648,7 @@ def Wframe_larger_than_EQ : Joined<"-Wframe-larger-than=">, Alias<Wframe_larger_
|
|||
def fterminated_vtables : Flag<"-fterminated-vtables">, Alias<fapple_kext>;
|
||||
def fthreadsafe_statics : Flag<"-fthreadsafe-statics">, Group<f_Group>;
|
||||
def ftime_report : Flag<"-ftime-report">, Group<f_Group>, Flags<[CC1Option]>;
|
||||
def ftlsmodel_EQ : Joined<"-ftls-model=">, Group<f_Group>, Flags<[CC1Option]>;
|
||||
def ftrapv : Flag<"-ftrapv">, Group<f_Group>, Flags<[CC1Option]>,
|
||||
HelpText<"Trap on integer overflow">;
|
||||
def ftrapv_handler_EQ : Joined<"-ftrapv-handler=">, Group<f_Group>,
|
||||
|
|
|
@ -44,6 +44,13 @@ public:
|
|||
FullDebugInfo // Generate complete debug info.
|
||||
};
|
||||
|
||||
enum TLSModel {
|
||||
GeneralDynamicTLSModel,
|
||||
LocalDynamicTLSModel,
|
||||
InitialExecTLSModel,
|
||||
LocalExecTLSModel
|
||||
};
|
||||
|
||||
unsigned AsmVerbose : 1; ///< -dA, -fverbose-asm.
|
||||
unsigned ObjCAutoRefCountExceptions : 1; ///< Whether ARC should be EH-safe.
|
||||
unsigned CUDAIsDevice : 1; ///< Set when compiling for CUDA device.
|
||||
|
@ -175,6 +182,9 @@ public:
|
|||
/// The run-time penalty for bounds checking, or 0 to disable.
|
||||
unsigned char BoundsChecking;
|
||||
|
||||
/// The default TLS model to use.
|
||||
TLSModel DefaultTLSModel;
|
||||
|
||||
public:
|
||||
CodeGenOptions() {
|
||||
AsmVerbose = 0;
|
||||
|
@ -231,6 +241,7 @@ public:
|
|||
DebugInfo = NoDebugInfo;
|
||||
Inlining = NoInlining;
|
||||
RelocationModel = "pic";
|
||||
DefaultTLSModel = GeneralDynamicTLSModel;
|
||||
}
|
||||
|
||||
ObjCDispatchMethodKind getObjCDispatchMethod() const {
|
||||
|
|
|
@ -183,26 +183,20 @@ 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, 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;
|
||||
}
|
||||
|
||||
|
|
|
@ -258,6 +258,45 @@ void CodeGenModule::setGlobalVisibility(llvm::GlobalValue *GV,
|
|||
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 @@ CodeGenModule::GetOrCreateLLVMGlobal(StringRef MangledName,
|
|||
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())
|
||||
|
|
|
@ -474,6 +474,10 @@ public:
|
|||
/// 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 @@ 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()),
|
||||
|
|
|
@ -2209,6 +2209,8 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,
|
|||
|
||||
Args.AddLastArg(CmdArgs, options::OPT_fvisibility_inlines_hidden);
|
||||
|
||||
Args.AddLastArg(CmdArgs, options::OPT_ftlsmodel_EQ);
|
||||
|
||||
// -fhosted is default.
|
||||
if (Args.hasFlag(options::OPT_ffreestanding, options::OPT_fhosted, false) ||
|
||||
KernelOrKext)
|
||||
|
|
|
@ -307,6 +307,20 @@ static void CodeGenOptsToArgs(const CodeGenOptions &Opts, ToArgsList &Res) {
|
|||
Res.push_back("-disable-llvm-verifier");
|
||||
for (unsigned i = 0, e = Opts.BackendOptions.size(); i != e; ++i)
|
||||
Res.push_back("-backend-option", Opts.BackendOptions[i]);
|
||||
|
||||
switch (Opts.DefaultTLSModel) {
|
||||
case CodeGenOptions::GeneralDynamicTLSModel:
|
||||
break;
|
||||
case CodeGenOptions::LocalDynamicTLSModel:
|
||||
Res.push_back("-ftls-model=local-dynamic");
|
||||
break;
|
||||
case CodeGenOptions::InitialExecTLSModel:
|
||||
Res.push_back("-ftls-model=initial-exec");
|
||||
break;
|
||||
case CodeGenOptions::LocalExecTLSModel:
|
||||
Res.push_back("-ftls-model=local-exec");
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static void DependencyOutputOptsToArgs(const DependencyOutputOptions &Opts,
|
||||
|
@ -788,7 +802,7 @@ static void LangOptsToArgs(const LangOptions &Opts, ToArgsList &Res) {
|
|||
|
||||
if (Opts.AppleKext)
|
||||
Res.push_back("-fapple-kext");
|
||||
|
||||
|
||||
if (Opts.getVisibilityMode() != DefaultVisibility) {
|
||||
Res.push_back("-fvisibility");
|
||||
if (Opts.getVisibilityMode() == HiddenVisibility) {
|
||||
|
@ -1256,6 +1270,22 @@ static bool ParseCodeGenArgs(CodeGenOptions &Opts, ArgList &Args, InputKind IK,
|
|||
}
|
||||
}
|
||||
|
||||
if (Arg *A = Args.getLastArg(OPT_ftlsmodel_EQ)) {
|
||||
StringRef Name = A->getValue(Args);
|
||||
unsigned Model = llvm::StringSwitch<unsigned>(Name)
|
||||
.Case("global-dynamic", CodeGenOptions::GeneralDynamicTLSModel)
|
||||
.Case("local-dynamic", CodeGenOptions::LocalDynamicTLSModel)
|
||||
.Case("initial-exec", CodeGenOptions::InitialExecTLSModel)
|
||||
.Case("local-exec", CodeGenOptions::LocalExecTLSModel)
|
||||
.Default(~0U);
|
||||
if (Model == ~0U) {
|
||||
Diags.Report(diag::err_drv_invalid_value) << A->getAsString(Args) << Name;
|
||||
Success = false;
|
||||
} else {
|
||||
Opts.DefaultTLSModel = static_cast<CodeGenOptions::TLSModel>(Model);
|
||||
}
|
||||
}
|
||||
|
||||
return Success;
|
||||
}
|
||||
|
||||
|
|
|
@ -0,0 +1,28 @@
|
|||
// RUN: %clang_cc1 %s -triple x86_64-pc-linux-gnu -emit-llvm -o - | FileCheck %s -check-prefix=CHECK-GD
|
||||
// RUN: %clang_cc1 %s -triple x86_64-pc-linux-gnu -ftls-model=global-dynamic -emit-llvm -o - | FileCheck %s -check-prefix=CHECK-GD
|
||||
// RUN: %clang_cc1 %s -triple x86_64-pc-linux-gnu -ftls-model=local-dynamic -emit-llvm -o - | FileCheck %s -check-prefix=CHECK-LD
|
||||
// RUN: %clang_cc1 %s -triple x86_64-pc-linux-gnu -ftls-model=initial-exec -emit-llvm -o - | FileCheck %s -check-prefix=CHECK-IE
|
||||
// RUN: %clang_cc1 %s -triple x86_64-pc-linux-gnu -ftls-model=local-exec -emit-llvm -o - | FileCheck %s -check-prefix=CHECK-LE
|
||||
|
||||
int __thread x;
|
||||
int f() {
|
||||
static int __thread y;
|
||||
return y++;
|
||||
}
|
||||
int __thread __attribute__((tls_model("initial-exec"))) z;
|
||||
|
||||
// CHECK-GD: @f.y = internal thread_local global i32 0
|
||||
// CHECK-GD: @x = thread_local global i32 0
|
||||
// CHECK-GD: @z = thread_local(initialexec) global i32 0
|
||||
|
||||
// CHECK-LD: @f.y = internal thread_local(localdynamic) global i32 0
|
||||
// CHECK-LD: @x = thread_local(localdynamic) global i32 0
|
||||
// CHECK-LD: @z = thread_local(initialexec) global i32 0
|
||||
|
||||
// CHECK-IE: @f.y = internal thread_local(initialexec) global i32 0
|
||||
// CHECK-IE: @x = thread_local(initialexec) global i32 0
|
||||
// CHECK-IE: @z = thread_local(initialexec) global i32 0
|
||||
|
||||
// CHECK-LE: @f.y = internal thread_local(localexec) global i32 0
|
||||
// CHECK-LE: @x = thread_local(localexec) global i32 0
|
||||
// CHECK-LE: @z = thread_local(initialexec) global i32 0
|
Loading…
Reference in New Issue