Re: [WIP PATCH]: Add __builtin_va_arg_bitint, __builtin_bitint_unpack and __builtin_bitint_pack builtins

Martin Uecker <[email protected]>
Newsgroups gmane.comp.gcc.patches,gmane.comp.lib.glibc.alpha
Message-ID <[email protected]>
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
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.