On Mon, Jul 06, 2026 at 05:09:53PM +0200, Martin Uecker wrote:
> The design looks very reasonable to me, but I have two
> comments/questions:
> 
> Do we need the full generality, i.e.  support for LE, BE and
> any limb type or could we simply fix this to whatever corresponds
> to the ABI?  Maybe I am missing something obvious.

Hardcoding some limb type to some _BitInt limb type (but which one,
on many architectures we have two, the ABI one which influences
size/alignment decision and another one, often smaller width
but sometimes the same, which is used in most of the operations)
would simplify it a little bit, but would be a nightmare for C library
writers or users which want to write similar APIs in their libraries.
As I wrote, at least for the libc built with older compiler which doesn't
support this (which is something that needs to be supported for at least
a few years), my plan was that one would compile these intrinsics/macros
into assembly and use in the library.  But the library better should be
able to choose what limb it wants to use and use it on all architectures,
rather than dealing with on aarch64 I need 128-bit limb type, on x86_64
64-bit limb type, on i686 32-bit limb type, ...

Now, one could hardcode some limb type for all users, say
unsigned long, but I wasn't sure that is the right choice for all the
C libraries and all users.  I'd say the most usual choices will be likely
unsinged long, unsigned int and unsigned long long, but already that that
point the intrinsic needs to support all the cases the posted patch handles,
namely when the user chosen limb has smaller width than the _BitInt internal
limb type (but right now the _BitInt internal limb type width has to be
divisible by the user chosen limb width in that case), or same width, or
larger width (the posted patch requires double the width in that case).
I intentionally chose not to support bit-precise integers in the
type-generic macro, don't think splitting some _BitInt(n) for runtime n
into an array of _BitInt(17) or array of _BitInt(925) is useful or
worth the effort.

Regarding endianity, sure, we could hardcode say little-endian ordering,
or always match the architecture endianity, but that again makes the
C library maintainance harder for little gain on the compiler side.

> In general for libraries (or user code) there is the issue
> that different systems may support a different number of bits,
> and once a library is compiled with one compiler could break
> (or have limitations) for code using another.  This may become
> a bigger concern when we want to introduce standard library
> functionality using _BitInt.   So I wonder  whether these 
> builtins could be made to work for an arbitrary number 
> of bits exceeding what the current limit for GCC is.

There are psABIs which specify the size/alignment/passing/returning of
_BitInt(N), and GCC chose to support _BitInt only on architectures
where this is specified or where GCC is a de-factor psABI for the arch.
For both the __builtin_va_arg_bitint va_arg side, and
__builtin_bitint_*pack (or __builtin_va_arg_bitint __builtin_bitint_unpack
side) the emitted code uses (matching the psABIs), something like
  if (n <= 8)
    load using _BitInt(8) (but with alias set matching anything or any _BitInt)
  else if (n <= 16)
    load using _BitInt(16) (but with alias set matching anything or any _BitInt)
  else if (n <= 32)
    load using _BitInt(32) (but with alias set matching anything or any _BitInt)
...
  else
    load or handle using VLA of the ABI and/or internal limb types with
    alias set matching anything or any _BitInt
so the first few n values are handled as special cases and rest handles the
larger ones of arbitrary sizes.  And what GCC emits in that case can handle
any BITINT_MAXWIDTH, doesn't stop at 65535, will happily handle even the
clang BITINT_MAXWIDTH it has on the 2 or 3 architectures (rest have I think
still 128 and don't follow psABI or follow it by accident).
Of course unless clang chooses to follow psABI for N <= 65535 and for some
larger ones chooses some completely different ABI.  I'm not aware of that
though, who would bother with something like that.  All that e.g. GCC
supports internally is some small width special cases and then anything
larger being treated usually as a struct with a single array member of
the ABI limb type.

        Jakub

Reply via email to