Clang rejects the casts on asm output operands in longlong.h
(-Winvalid-gnu-asm-cast is an error by default), so several of its
blocks do not build with clang. v1 dropped the casts. Richard pointed
out that they do check something, because GCC accepts a cast on an asm
output only when it is a no-op, so an output of the wrong size fails to
build. This version keeps that check.
Patches 1 and 2 are the fix. Patches 3 and 4 are an optional
simplification of patch 2. Patch 3 only exists to enable patch 4, and
it is fine to take 1-2 and stop there.
1. Remove the Z8000 block. GCC has no Z8000 port, so drop it instead
of editing code nobody can build, as Richard suggested.
2. Replace each output cast with a __ll_check_output (type, x)
statement before the asm. It is a sizeof check that fails the build
when the output's size differs from the type's. Macros whose body
was a bare asm statement are wrapped in do { } while (0) to make
room for it, so the diff is large (~350 lines).
3. Drop "register" from a few libquadmath locals that are passed as
macro outputs, so that patch 4 can take their address.
4. Replace __ll_check_output with __ll_out (type, x), which does the
same check inside the operand and yields it as an lvalue:
: "=r" (__ll_out (USItype, sh)),
That is a one-for-one replacement for the old casts. The macros no
longer need the do { } while (0) wrappers, and the total change to
longlong.h drops to ~100 lines. __ll_out takes the address of the
output, so the output can no longer be a register variable or a
bit-field. Patch 3 fixes the only such callers in the tree, but
out-of-tree copies of longlong.h may have others.
An exact type check with _Generic or __builtin_types_compatible_p does
not work: g++ supports neither, and it would reject callers the casts
accept today. Patch 2 has the details.
Testing: a test unit that instantiates every macro, compiled as C and C++
at -O2 for W_TYPE_SIZE 32 and 64 with every cross compiler I have (the
list is in patch 2). After each of patches 2 and 4:
- the generated assembly is byte-identical to master;
- outputs of the wrong size are rejected in every configuration where
they were rejected before;
- same-size outputs of a different type are still accepted.
With clang, x86_64, x32, i386, armv5, armv7 and sparcv9 fail to build
before the series and build after it, and wrong-size outputs are now
rejected there too.
Changes in v2:
- Keep the output size check instead of dropping it (patch 2).
- Remove the Z8000 block instead of editing it (patch 1).
- New, optional: patches 3 and 4.
- v1 patch 2/2 (sdiv_qrnnd parentheses) is already committed.
- Link to v1:
https://inbox.sourceware.org/gcc-patches/[email protected]/
---
Matt Turner (4):
include: Remove Z8000 support from longlong.h
include: Replace casts on asm output operands in longlong.h
libquadmath: Drop register from longlong.h macro outputs
include: Check longlong.h asm output sizes inside the operand
include/longlong.h | 227 +++++++++++++++++++-----------------------
libquadmath/printf/addmul_1.c | 8 +-
libquadmath/printf/mul_1.c | 6 +-
libquadmath/printf/submul_1.c | 8 +-
libquadmath/strtod/strtod_l.c | 2 +-
5 files changed, 112 insertions(+), 139 deletions(-)
---
base-commit: e47eccbe6d118023e4fe83bde14075729c40e030
change-id: 20260921-longlong-fixes-v2-d8f7bb2376cc
Best regards,
--
Matt Turner <[email protected]>