Index: include/clang/Basic/DiagnosticDriverKinds.td =================================================================== --- include/clang/Basic/DiagnosticDriverKinds.td +++ include/clang/Basic/DiagnosticDriverKinds.td @@ -97,6 +97,8 @@ "failing because %select{environment variable 'FORCE_CLANG_DIAGNOSTICS_CRASH' is set|'-gen-reproducer' is used}0">; def err_drv_invalid_mfloat_abi : Error< "invalid float ABI '%0'">; +def err_drv_invalid_mtp : Error< + "invalid thread pointer reading mode '%0'">; def err_drv_invalid_libcxx_deployment : Error< "invalid deployment target for -stdlib=libc++ (requires %0 or later)">; def err_drv_invalid_argument_to_fdebug_prefix_map : Error< Index: include/clang/Driver/CC1Options.td =================================================================== --- include/clang/Driver/CC1Options.td +++ include/clang/Driver/CC1Options.td @@ -245,6 +245,8 @@ "precision">; def mfloat_abi : Separate<["-"], "mfloat-abi">, HelpText<"The float ABI to use">; +def mtp : Separate<["-"], "mtp">, + HelpText<"Mode for reading thread pointer">; def mlimit_float_precision : Separate<["-"], "mlimit-float-precision">, HelpText<"Limit float precision to the given value">; def split_stacks : Flag<["-"], "split-stacks">, Index: include/clang/Driver/Options.td =================================================================== --- include/clang/Driver/Options.td +++ include/clang/Driver/Options.td @@ -1661,6 +1661,8 @@ HelpText<"Disallow generation of data access to code sections (ARM only)">; def mno_execute_only : Flag<["-"], "mno-execute-only">, Group, HelpText<"Allow generation of data access to code sections (ARM only)">; +def mtp_mode_EQ : Joined<["-"], "mtp=">, Group, Values<"soft, cp15">, + HelpText<"Read thread pointer from coprocessor register (ARM only)">; def mpure_code : Flag<["-"], "mpure-code">, Alias; // Alias for GCC compatibility def mno_pure_code : Flag<["-"], "mno-pure-code">, Alias; def mtvos_version_min_EQ : Joined<["-"], "mtvos-version-min=">, Group; Index: lib/Driver/ToolChains/Arch/ARM.h =================================================================== --- lib/Driver/ToolChains/Arch/ARM.h +++ lib/Driver/ToolChains/Arch/ARM.h @@ -32,6 +32,12 @@ void appendEBLinkFlags(const llvm::opt::ArgList &Args, llvm::opt::ArgStringList &CmdArgs, const llvm::Triple &Triple); +enum class ReadTPMode { + Invalid, + Soft, + Cp15, +}; + enum class FloatABI { Invalid, Soft, @@ -40,6 +46,7 @@ }; FloatABI getARMFloatABI(const ToolChain &TC, const llvm::opt::ArgList &Args); +ReadTPMode getReadTPMode(const ToolChain &TC, const llvm::opt::ArgList &Args); bool useAAPCSForMachO(const llvm::Triple &T); void getARMArchCPUFromArgs(const llvm::opt::ArgList &Args, Index: lib/Driver/ToolChains/Arch/ARM.cpp =================================================================== --- lib/Driver/ToolChains/Arch/ARM.cpp +++ lib/Driver/ToolChains/Arch/ARM.cpp @@ -122,6 +122,27 @@ T.getOS() == llvm::Triple::UnknownOS || isARMMProfile(T); } +// Select mode for reading thread pointer (-mtp=soft/cp15). +arm::ReadTPMode arm::getReadTPMode(const ToolChain &TC, const ArgList &Args) { + const Driver &D = TC.getDriver(); + arm::ReadTPMode ThreadPointer = ReadTPMode::Invalid; + if (Arg *A = + Args.getLastArg(options::OPT_mtp_mode_EQ)) { + ThreadPointer = llvm::StringSwitch(A->getValue()) + .Case("cp15", ReadTPMode::Cp15) + .Case("soft", ReadTPMode::Soft) + .Default(ReadTPMode::Invalid); + if (ThreadPointer == ReadTPMode::Invalid && + !StringRef(A->getValue()).empty()) { + D.Diag(diag::err_drv_invalid_mtp) << A->getAsString(Args); + ThreadPointer = ReadTPMode::Soft; + } + } + if (ThreadPointer == ReadTPMode::Invalid) + ThreadPointer = ReadTPMode::Soft; + return ThreadPointer; +} + // Select the float ABI as determined by -msoft-float, -mhard-float, and // -mfloat-abi=. arm::FloatABI arm::getARMFloatABI(const ToolChain &TC, const ArgList &Args) { @@ -253,6 +274,7 @@ bool KernelOrKext = Args.hasArg(options::OPT_mkernel, options::OPT_fapple_kext); arm::FloatABI ABI = arm::getARMFloatABI(TC, Args); + arm::ReadTPMode ThreadPointer = arm::getReadTPMode(TC, Args); const Arg *WaCPU = nullptr, *WaFPU = nullptr; const Arg *WaHDiv = nullptr, *WaArch = nullptr; @@ -294,6 +316,10 @@ } } + + if (ThreadPointer == arm::ReadTPMode::Cp15) + Features.push_back("+read-tp-hard"); + // Check -march. ClangAs gives preference to -Wa,-march=. const Arg *ArchArg = Args.getLastArg(options::OPT_march_EQ); StringRef ArchName; Index: lib/Driver/ToolChains/Clang.cpp =================================================================== --- lib/Driver/ToolChains/Clang.cpp +++ lib/Driver/ToolChains/Clang.cpp @@ -1345,6 +1345,17 @@ CmdArgs.push_back("hard"); } + arm::ReadTPMode ThreadPointer = arm::getReadTPMode(getToolChain(), Args); + if (ThreadPointer == arm::ReadTPMode::Cp15) { + CmdArgs.push_back("-mtp"); + CmdArgs.push_back("cp15"); + } else { + assert(ThreadPointer == arm::ReadTPMode::Soft && + "Invalid mode for reading thread pointer"); + CmdArgs.push_back("-mtp"); + CmdArgs.push_back("soft"); + } + // Forward the -mglobal-merge option for explicit control over the pass. if (Arg *A = Args.getLastArg(options::OPT_mglobal_merge, options::OPT_mno_global_merge)) { Index: test/Driver/clang-translation.c =================================================================== --- test/Driver/clang-translation.c +++ test/Driver/clang-translation.c @@ -75,6 +75,12 @@ // ARMV5E: "-cc1" // ARMV5E: "-target-cpu" "arm1022e" +// RUN: %clang -target arm-linux -mtp=cp15 -### -S %s -arch armv7 2>&1 | \ +// RUN: FileCheck -check-prefix=ARMv7_THREAD_POINTER %s +// ARMv7_THREAD_POINTER: "-target-feature" "+read-tp-hard" +// ARMv7_THREAD_POINTER: "-mtp" "cp15" +// ARMv7_THREAD_POINTER-NOT: "mtp" "soft" + // RUN: %clang -target powerpc64-unknown-linux-gnu \ // RUN: -### -S %s -mcpu=G5 2>&1 | FileCheck -check-prefix=PPCG5 %s // PPCG5: clang