From: Chih-Hung Hsieh Date: Tue, 28 Jul 2015 16:27:56 +0000 (+0000) Subject: Add -femulated-tls flag to select the emulated TLS model. X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=9ec907c0785c7297d7d4ed3edb438b662ff15169;p=clang Add -femulated-tls flag to select the emulated TLS model. This will be used for old targets like Android that do not support ELF TLS models. Differential Revision: http://reviews.llvm.org/D10524 git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@243441 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/docs/UsersManual.rst b/docs/UsersManual.rst index 20ee5696e0..53d7286e26 100644 --- a/docs/UsersManual.rst +++ b/docs/UsersManual.rst @@ -1157,6 +1157,13 @@ are listed below. efficient model can be used. The TLS model can be overridden per variable using the ``tls_model`` attribute. +.. option:: -femulated-tls + + Select emulated TLS model, which overrides all -ftls-model choices. + + In emulated TLS mode, all access to TLS variables are converted to + calls to __emutls_get_address in the runtime library. + .. option:: -mhwdiv=[values] Select the ARM modes (arm or thumb) that support hardware division diff --git a/include/clang/Driver/Options.td b/include/clang/Driver/Options.td index 6e5dbf225b..5fa92e7d8e 100644 --- a/include/clang/Driver/Options.td +++ b/include/clang/Driver/Options.td @@ -510,6 +510,9 @@ def fno_elide_type : Flag<["-"], "fno-elide-type">, Group, def feliminate_unused_debug_symbols : Flag<["-"], "feliminate-unused-debug-symbols">, Group; def femit_all_decls : Flag<["-"], "femit-all-decls">, Group, Flags<[CC1Option]>, HelpText<"Emit all declarations, even if unused">; +def femulated_tls : Flag<["-"], "femulated-tls">, Group, Flags<[CC1Option]>, + HelpText<"Use emutls functions to access thread_local variables">; +def fno_emulated_tls : Flag<["-"], "fno-emulated-tls">, Group; def fencoding_EQ : Joined<["-"], "fencoding=">, Group; def ferror_limit_EQ : Joined<["-"], "ferror-limit=">, Group, Flags<[CoreOption]>; def fexceptions : Flag<["-"], "fexceptions">, Group, Flags<[CC1Option]>, diff --git a/include/clang/Frontend/CodeGenOptions.def b/include/clang/Frontend/CodeGenOptions.def index 482c9d04e6..72f88031f2 100644 --- a/include/clang/Frontend/CodeGenOptions.def +++ b/include/clang/Frontend/CodeGenOptions.def @@ -60,6 +60,7 @@ CODEGENOPT(EmitDeclMetadata , 1, 0) ///< Emit special metadata indicating what CODEGENOPT(EmitGcovArcs , 1, 0) ///< Emit coverage data files, aka. GCDA. CODEGENOPT(EmitGcovNotes , 1, 0) ///< Emit coverage "notes" files, aka GCNO. CODEGENOPT(EmitOpenCLArgMetadata , 1, 0) ///< Emit OpenCL kernel arg metadata. +CODEGENOPT(EmulatedTLS , 1, 0) ///< Set when -femulated-tls is enabled. /// \brief FP_CONTRACT mode (on/off/fast). ENUM_CODEGENOPT(FPContractMode, FPContractModeKind, 2, FPC_On) CODEGENOPT(ForbidGuardVariables , 1, 0) ///< Issue errors if C++ guard variables diff --git a/lib/CodeGen/BackendUtil.cpp b/lib/CodeGen/BackendUtil.cpp index 90da637ab8..05b3ac4305 100644 --- a/lib/CodeGen/BackendUtil.cpp +++ b/lib/CodeGen/BackendUtil.cpp @@ -542,6 +542,7 @@ TargetMachine *EmitAssemblyHelper::CreateTargetMachine(bool MustCreateTM) { Options.FunctionSections = CodeGenOpts.FunctionSections; Options.DataSections = CodeGenOpts.DataSections; Options.UniqueSectionNames = CodeGenOpts.UniqueSectionNames; + Options.EmulatedTLS = CodeGenOpts.EmulatedTLS; Options.MCOptions.MCRelaxAll = CodeGenOpts.RelaxAll; Options.MCOptions.MCSaveTempLabels = CodeGenOpts.SaveTempLabels; diff --git a/lib/Driver/Tools.cpp b/lib/Driver/Tools.cpp index dd281ad08f..f5cb90efa0 100644 --- a/lib/Driver/Tools.cpp +++ b/lib/Driver/Tools.cpp @@ -4036,6 +4036,12 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA, Args.AddLastArg(CmdArgs, options::OPT_fstandalone_debug); Args.AddLastArg(CmdArgs, options::OPT_fno_standalone_debug); Args.AddLastArg(CmdArgs, options::OPT_fno_operator_names); + // Emulated TLS is enabled by default on Android, and can be enabled manually + // with -femulated-tls. + bool EmulatedTLSDefault = Triple.getEnvironment() == llvm::Triple::Android; + if (Args.hasFlag(options::OPT_femulated_tls, options::OPT_fno_emulated_tls, + EmulatedTLSDefault)) + CmdArgs.push_back("-femulated-tls"); // AltiVec language extensions aren't relevant for assembling. if (!isa(JA) || Output.getType() != types::TY_PP_Asm) Args.AddLastArg(CmdArgs, options::OPT_faltivec); diff --git a/lib/Frontend/CompilerInvocation.cpp b/lib/Frontend/CompilerInvocation.cpp index e4cfba3b54..2fdbcb9ac4 100644 --- a/lib/Frontend/CompilerInvocation.cpp +++ b/lib/Frontend/CompilerInvocation.cpp @@ -593,6 +593,9 @@ static bool ParseCodeGenArgs(CodeGenOptions &Opts, ArgList &Args, InputKind IK, } } + Opts.EmulatedTLS = + Args.hasFlag(OPT_femulated_tls, OPT_fno_emulated_tls, false); + if (Arg *A = Args.getLastArg(OPT_ftlsmodel_EQ)) { StringRef Name = A->getValue(); unsigned Model = llvm::StringSwitch(Name) diff --git a/test/CodeGen/tls-model.c b/test/CodeGen/tls-model.c index b5bae77e97..41c8de0b0e 100644 --- a/test/CodeGen/tls-model.c +++ b/test/CodeGen/tls-model.c @@ -3,7 +3,12 @@ // 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 +// +// RUN: %clang_cc1 %s -triple x86_64-pc-linux-gnu -femulated-tls -emit-llvm -o - 2>&1 | \ +// RUN: FileCheck %s -check-prefix=CHECK-GD +int z1 = 0; +int z2; int __thread x; int f() { static int __thread y; @@ -11,18 +16,29 @@ int f() { } int __thread __attribute__((tls_model("initial-exec"))) z; +// Note that unlike normal C uninitialized global variables, +// uninitialized TLS variables do NOT have COMMON linkage. + +// CHECK-GD: @z1 = global i32 0 // CHECK-GD: @f.y = internal thread_local global i32 0 +// CHECK-GD: @z2 = common global i32 0 // CHECK-GD: @x = thread_local global i32 0 // CHECK-GD: @z = thread_local(initialexec) global i32 0 +// CHECK-LD: @z1 = global i32 0 // CHECK-LD: @f.y = internal thread_local(localdynamic) global i32 0 +// CHECK-LD: @z2 = common global i32 0 // CHECK-LD: @x = thread_local(localdynamic) global i32 0 // CHECK-LD: @z = thread_local(initialexec) global i32 0 +// CHECK-IE: @z1 = global i32 0 // CHECK-IE: @f.y = internal thread_local(initialexec) global i32 0 +// CHECK-IE: @z2 = common global i32 0 // CHECK-IE: @x = thread_local(initialexec) global i32 0 // CHECK-IE: @z = thread_local(initialexec) global i32 0 +// CHECK-LE: @z1 = global i32 0 // CHECK-LE: @f.y = internal thread_local(localexec) global i32 0 +// CHECK-LE: @z2 = common global i32 0 // CHECK-LE: @x = thread_local(localexec) global i32 0 // CHECK-LE: @z = thread_local(initialexec) global i32 0 diff --git a/test/CodeGenCXX/cxx11-thread-local.cpp b/test/CodeGenCXX/cxx11-thread-local.cpp index 9b16319088..39c480e737 100644 --- a/test/CodeGenCXX/cxx11-thread-local.cpp +++ b/test/CodeGenCXX/cxx11-thread-local.cpp @@ -1,4 +1,6 @@ // RUN: %clang_cc1 -std=c++11 -emit-llvm %s -o - -triple x86_64-linux-gnu | FileCheck %s +// RUN: %clang_cc1 -std=c++11 -femulated-tls -emit-llvm %s -o - \ +// RUN: -triple x86_64-linux-gnu 2>&1 | FileCheck --check-prefix=CHECK %s int f(); int g();