From c87a95cbd3a3b06d829d86bf30c093016a47e2bb Mon Sep 17 00:00:00 2001 From: Sergei Zimmerman Date: Sun, 17 May 2026 14:03:02 +0300 Subject: [PATCH 1/3] 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 --- pkgs/build-support/cc-wrapper/default.nix | 19 ++++++++++++++++++- 1 file changed, 18 insertions(+), 1 deletion(-) diff --git a/pkgs/build-support/cc-wrapper/default.nix b/pkgs/build-support/cc-wrapper/default.nix index d95fbddc4e89..617bd299a41d 100644 --- a/pkgs/build-support/cc-wrapper/default.nix +++ b/pkgs/build-support/cc-wrapper/default.nix @@ -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 [ ]; From 851fd9401f8f79454d1e3e0b786ba4afcaecd134 Mon Sep 17 00:00:00 2001 From: Sergei Zimmerman Date: Wed, 13 May 2026 02:00:12 +0300 Subject: [PATCH 2/3] elfutils: apply patch allowing R_386_TLS_DESC in shared libraries with elflint Submitted a patch upstream that already got merged to main, so grab it now. Tests fail without it on i686-linux. [1]: https://patchwork.sourceware.org/project/elfutils/patch/20260512211127.4157383-1-sergei@zimmerman.foo/ --- pkgs/by-name/el/elfutils/package.nix | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/pkgs/by-name/el/elfutils/package.nix b/pkgs/by-name/el/elfutils/package.nix index 4a73d364c75c..fe3de1161954 100644 --- a/pkgs/by-name/el/elfutils/package.nix +++ b/pkgs/by-name/el/elfutils/package.nix @@ -57,6 +57,11 @@ stdenv.mkDerivation (finalAttrs: { url = "https://git.alpinelinux.org/aports/plain/main/elfutils/musl-strndupa.patch?id=2e3d4976eeffb4704cf83e2cc3306293b7c7b2e9"; sha256 = "sha256-7daehJj1t0wPtQzTv+/Rpuqqs5Ng/EYnZzrcf2o/Lb0="; }) + (fetchpatch { + name = "fix-i386_tlsdesc_relocation.patch"; + url = "https://sourceware.org/git/?p=elfutils.git;a=patch;h=bfd519cc58e190544a6785d3f0a27fcfaf7d8da3"; + hash = "sha256-N7DL2FG1AWLc+hcnxGMbUl5TuieoAc9OD6gc0sbsiGI="; + }) ] ++ lib.optionals stdenv.hostPlatform.isMusl [ ./musl-error_h.patch ]; From 817b0e1338faca6deebeb9fca8beeef8409dbeea Mon Sep 17 00:00:00 2001 From: Sergei Zimmerman Date: Wed, 13 May 2026 23:00:47 +0300 Subject: [PATCH 3/3] ffmpeg: use unwrapped clang for cuda-llvm support The build system retargets clang for the appropriate nvidia arch and doesn't depend on anything from the wrappers. Since the wrappped compiler sets the flags for the original arch, it now includes `-mtls-dialect=gnu2` on x86_64, which is not a supported flag for the retargeted clang. --- pkgs/development/libraries/ffmpeg/generic.nix | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pkgs/development/libraries/ffmpeg/generic.nix b/pkgs/development/libraries/ffmpeg/generic.nix index b1f682050f21..26b365ad17de 100644 --- a/pkgs/development/libraries/ffmpeg/generic.nix +++ b/pkgs/development/libraries/ffmpeg/generic.nix @@ -841,7 +841,7 @@ stdenv.mkDerivation ( ++ optionals stdenv.hostPlatform.isx86 [ nasm ] # Texinfo version 7.1 introduced breaking changes, which older versions of ffmpeg do not handle. ++ optionals (lib.versionAtLeast version "6") [ texinfo ] - ++ optionals withCudaLLVM [ clang ] + ++ optionals withCudaLLVM [ clang.cc ] ++ optionals withCudaNVCC [ cuda_nvcc ]; buildInputs =