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
