cc-wrapper: enable tlsdesc on i686, x86_64 linux

TLSDESC is a more performant way of doing TLS, since it has a custom
calling convention that does not require the caller (of what's usually
__tls_get_addr) to spill clobbered registers and assumes that the callee
preserves all registers.

This adds corresponding plumbing in the machineFlags in the cc-wrapper
that includes version gates for compilers. TLSDESC needs to be supported
by the bintools and libc, so I've only enabled it for architectures that
our packaged glibc, musl, GNU binutils support (x86, x86_64).
We package a lot of LLVM versions and support for -mtls-dialect in the
Clang driver has only landed in LLVM 19, so a version check is added
there too.

Ideally we'd set the default at GCC build-time, but LLVM lacks such an
option, so we'd have to keep it in the compiler wrapper for now.

Gentoo is already building with it by default [1], as is Fedora [2].

In glibc < 2.40 [3] there existed a bug with not all registers being
preserved, but it has since been resolved. x86 support has existed
since basically forever with LLVM adding support in LLVM >= 19.1.
LoongArch support has been added recently too, but it's only available
since musl 1.2.6 while we are stuck at 1.2.5 for now, so I haven't dug
deeper. Aarch64 uses TLSDESC by default already.

The support status on non-Linux is a bit unclear, so these defaults are
scoped only to linux targets.

Sadly RISC-V support is still cooking apparently [4].

See: https://maskray.me/blog/2021-02-14-all-about-thread-local-storage
See: https://groups.google.com/g/x86-64-abi/c/0tjmaQx6nZ0

[1]: https://github.com/gentoo/gentoo/commit/46191b478ebcb6bc6831627526da44f04dfcd1be
[2]: https://src.fedoraproject.org/rpms/gcc/c/8f8d2ea9c326784bce044ff86547107611dda338?branch=rawhide
[3]: https://sourceware.org/bugzilla/show_bug.cgi?id=31372
[4]: https://github.com/riscv-non-isa/riscv-elf-psabi-doc/issues/494
This commit is contained in:
Sergei Zimmerman
2026-05-17 14:03:02 +03:00
parent 35072876b9
commit c87a95cbd3
+18 -1
View File
@@ -316,6 +316,17 @@ let
tune =
if targetPlatform ? gcc.tune then findBestTuneApproximation targetPlatform.gcc.tune else null;
tlsDialect =
if
# Support status on non-Linux systems is a bit unclear.
targetPlatform.isLinux
# Support added in https://github.com/llvm/llvm-project/commit/36b4a9ccd9f7e04010476e6b2a311f2052a4ac20 (19.1.0)
&& (isClang -> versionAtLeast ccVersion "19.1")
then
(if targetPlatform.isx86 then "gnu2" else null)
else
null;
# Machine flags. These are necessary to support
# TODO: We should make a way to support miscellaneous machine
@@ -353,7 +364,13 @@ let
# TODO: clang on powerpcspe also needs a condition: https://github.com/llvm/llvm-project/issues/71356
# https://releases.llvm.org/18.1.6/tools/clang/docs/ReleaseNotes.html#loongarch-support
((targetPlatform.isLoongArch64 && isClang) -> versionAtLeast ccVersion "18.1")
) "-mcmodel=${targetPlatform.gcc.cmodel}";
) "-mcmodel=${targetPlatform.gcc.cmodel}"
# Enable TLSDESC. This needs to be supported by the libc and bintools.
# See: https://maskray.me/blog/2021-02-14-all-about-thread-local-storage
# Aarch64 uses TLSDESC by default and the option is completely ignored (at least on LLVM).
# TODO: Enable by default in GCC via --with-tls since https://gcc.gnu.org/cgit/gcc/commit/?id=96a291c4bb0b8a00b0a125e6a60f60072ffe53a7 (GCC 16).
# No equivalent build-time option for LLVM yet.
++ optional (tlsDialect != null) "-mtls-dialect=${tlsDialect}";
defaultHardeningFlags = bintools.defaultHardeningFlags or [ ];