If we want an offical API in C2y we would need to submit
a proposal relatively soon.

Martin

Am Dienstag, dem 07.07.2026 um 05:51 +0200 schrieb Martin Uecker:
> Am Montag, dem 06.07.2026 um 19:23 +0200 schrieb Jakub Jelinek:
> > 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, ...
> 
> I would have assumed they might want to anyway use the same limb type
> that is also used by the ABI for _BitInt for large N.  Then one would
> need to expose this type to  the user somehow (__BITINT_LIMB_T__). 
> But Joseph also gave an argument why libraries might want to pick another
> type, so I guess it is better to allow a choice.
> 
> > 
> > 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.
> 
> That makes sense, so there is no arbitrary limit and - assuming no one
> switches to some new ABI for large N - no compatibility risks. 
> 
> 
> Martin

Reply via email to