#1095866 llvm: unsoundness/miscompilations on i386

Package:
llvm-19
Source:
llvm-19
Description:
Modular compiler and toolchain technologies
Submitter:
Fabian Grünbichler
Date:
2025-04-29 10:12:02 UTC
Severity:
normal
Tags:
#1095866#5
Date:
2025-02-13 06:51:29 UTC
From:
To:
Filing this bug to have a record in BTS - I'll file a separate one for
release.debian.org about the broader baseline question.

This issue came up back in November on debian-devel/-release:

https://lists.debian.org/debian-release/2024/11/msg00443.html

My original mail, partially wrongly summarizing the issue.

https://lists.debian.org/debian-release/2024/11/msg00445.html

My reponse linking to more upstream details, including why downgrading to i586
in LLVM/rustc doesn't work.

It boils down to the following:

- Debian's i386 baseline is currently 32-bit x86 without MMX or SSE (i686)
- Debian's LLVM and rustc packages accordingly patch their i686 targets to
  remove SSE support, which would be part of that target's baseline upstream
  otherwise [0,1]
- Upstream LLVM and rustc consider this combination unsound and unfixable (for
  IMHO valid reasons) because it can cause subtle miscompilations leading to
  runtime crashes, in addition to the (usual, expected) different semantics of
  x87 and SSE2 floating point implementations [2,3]

I see the following options:

A) bump i386 baseline for Trixie to match LLVM/rustc's upstream i686 target,
   i.e. Pentium 4 *with* MMX and SSE2 (separate RT bug will be filed shortly)

B) RC-ignore this bug and implications for Trixie, bump baseline for Trixie+1

C) remove LLVM and rustc and all their transitive rdeps (this includes Firefox
   and Chromium, most major Desktop environments, sequoia, and probably a bit
   more) on i386 from Trixie, further reducing the usefulness of this arch

Personally (with my rustc maintainer hat on) I have a strong preference for A).

Please keep responses on details of A) to the corresponding release.debian.org
bug!

Fabian

0: https://salsa.debian.org/rust-team/rust/-/blob/debian/sid/debian/patches/behaviour/d-rustc-i686-baseline.patch?ref_type=heads
1: https://salsa.debian.org/pkg-llvm-team/llvm-toolchain/-/blob/19/debian/patches/clang-baseline-fix-i386.patch
2: https://github.com/rust-lang/compiler-team/issues/808
3: https://github.com/rust-lang/rust/issues/114479#issuecomment-2072052116

#1095866#18
Date:
2025-04-25 09:56:20 UTC
From:
To:
Control: retitle -1 llvm-toolchain-19: unsoundness/miscompilations on i386
Control: block 1095863 by -1

This was discussed further with the release team in
https://bugs.debian.org/1095863 where I outlined some additional
options, not all of which had been mentioned as possibilities in #1095862.

The release team have chosen to keep the baseline as "officially" 32-bit
x86 without MMX or SSE, but allow rustc (and LLVM if necessary) to
intentionally violate that baseline in order to produce working code.

Paul Gevers wrote in https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=1095863#70:

However I'm a bit confused about the status of implementing this. There
have been uploads of llvm-toolchain-18 and rustc selecting pentium4
rather than i686 as their baseline, but rustc seems to use libLLVM
version 19 (the same as llvm-defaults), and there has been no upload of
llvm-toolchain-19 with an equivalent change.

Was the rustc upload sufficient to address this problem for Rust code,
or is an upload of llvm-toolchain-19 also needed?

Will llvm-toolchain-20 prereleases (in experimental) also need an
upload?  The llvm-toolchain-20 package doesn't seem to have a bug open
yet - should we clone this one?

     smcv
     (not a release team member)

#1095866#27
Date:
2025-04-25 15:19:49 UTC
From:
To:
I am not entirely sure. the change on the rustc side seems to fix both the
floating point behaviour/precision (no more excess x87 precision), as well
as the known Rust reproducers for the miscompilation part (no more segfaults).

I missed that the LLVM change was *only* done for 19 (and if the rustc
with the raised/reverted baseline would have behaved unexpectedly, I might
have realized sooner!).

IMHO llvm-19 should definitely be adapted as well to fix the issue on the
LLVM side as well. compiling and executing the C reproducer[0] on i386 using
`clang-18 -O3 code.c && ./a.out` works fine, doing the same with clang-19
causes a segfault. with clang-18 downgraded to 1:18.1.8-16 (last version
before the baseline bump) the segfault is back as expected.

0: https://github.com/llvm/llvm-project/issues/89885 , code attached

if they still use the lowered/old baseline, yes. 20 is not slated for
Trixie though, so it's not as pressing there atm.

#1095866#32
Date:
2025-04-25 15:35:39 UTC
From:
To:
and this 19 here should of course been an 18 (hopefully clear from context,
but better make it explicit rather than causing more confusion!).

#1095866#37
Date:
2025-04-29 10:09:31 UTC
From:
To:
Control: clone -1 -2
Control: unblock 1095863 by -2
Control: retitle -2 llvm-toolchain-20: unsoundness/miscompilations on i386
Control: reassign -2 src:llvm-toolchain-20

The 20 branch still seems to have disable-sse2-old-x86.diff and
clang-baseline-fix-i386.patch, which are the patches that were dropped
in order to resolve this in the 18 branch, so I think yes it is still
using the lower baseline. Cloning as requested.

If I'm reading correctly, disable-sse2-old-x86.diff and
clang-baseline-fix-i386.patch will need to be dropped from both the 20
branch (for src:llvm-toolchain-20) and the snapshot branch (for a future
src:llvm-toolchain-21) to avoid this regressing in future. The
equivalent of cherry-picking these commits from the 18 branch:

* https://salsa.debian.org/pkg-llvm-team/llvm-toolchain/-/commit/f3af06cdcb77523f7a461a2de35c52daafcab311
* https://salsa.debian.org/pkg-llvm-team/llvm-toolchain/-/commit/90035ab5f2c7b352faf6fd45c303d15f6ebeb25c
* https://salsa.debian.org/pkg-llvm-team/llvm-toolchain/-/commit/02b16baed84d68bdee9b6a48a76f0786fc24e7ff
* https://salsa.debian.org/pkg-llvm-team/llvm-toolchain/-/commit/b6c80b9fa2e547e2fabd5df45ed0b75af45da2cb

It's still an equally serious bug in the package, even if it's only
going to be a practical problem in forky, so I think it's worth
tracking. This seems like the sort of change that is best made
systematically across all branches as a batch, to avoid having it
accidentally regress when updating to a new LLVM branch.

     smcv