Am Freitag, dem 10.07.2026 um 15:08 +0200 schrieb Jakub Jelinek via Gcc: > On Fri, Jul 10, 2026 at 02:54:38PM +0200, Martin Uecker wrote: > > > If va_list is void */char *, then all ... arguments are passed > > > on the stack and so the pointed to object will have the lifetime > > > of the whole function. But if the ABI needs to store some of > > > the hard registers used for argument passing somewhere somewhere > > > into the stack, and especially if ABI allows partial passing of > > > _BitInt (say first word or two passed in registers, rest on the stack), > > > then one actually doesn't have a contiguous chunk of memory that contains > > > it, so va_arg_ptr or &va_arg would effectively need to create a temporary > > > which holds the whole value. > > > > On the other hand, for large _BitInts one might avoid > > unnecessary copies *if* it is continuously on the stack. > > In the posted GCC patch, there is no copying under the hood (while the > proposed wording in the paper draft suggests copying happens, it is not > observable in any way).
Yes, but I am wondering whether we could this make more useful also for users beyond supporting C libraries in implementing format strings and then avoiding copies for large _BitInts may be a concern. > > > Are there ABIs that do this differently? > > I don't know, that is to be determined. On x86/x86_64 no copying is needed > for sure. > Though, all the GCC target va_arg gimplification hooks return a MEM_REF, so > the va_arg result is in all cases just a deference of some pointer. Whether > that pointer can be dereferenced e.g. after next va_arg is yet to be > determined (and not needed in the proposed macros). > > > > Now, if everything is hidden under a single > > > macro, it is an implementation detail, but when it is exposed, for how > > > long > > > that temporary is in scope? > > > > Maybe it could just the block as if the va_arg creates > > a compound literals. I understand your argument though. > > > > > > > > > One could also possibly allow them in pointer types > > > > > > > > _BitInt(n) *ptr = va_arg(ap, _BitInt(n)*); > > > > > > > > > > > > All this seems relatively unproblematic to me and would essentially > > > > be just nicer syntax and better type safety for what you are proposing. > > > > > > But then the question is if one can dereference *ptr or just pass it to > > > some macro/function to decode it. > > > > If one allows dereferencing it in general than one ends up > > with lvalues of variable _BitInt type. While I think this > > would be useful, this would certainly make things a lot more > > complicated. But even without beind allowed to dereference > > it, I think this would be useful because one could copy it > > generically. > > > > _BitInt(n) *ptr = va_arg(ap, typeof(ptr)); > > > > char buf[sizeof *ptr] > > memcpy(buf, ptr, sizeof *buf); > > > > or something like this. Perhaps one could also allow dereferencing > > on the RHS of an assignment. > > To implement printf/scanf with _BitInt(n) support, we can't just memcpy > it around, we need to decode/encode it to something that e.g. GMP or > hand written code can deal with (and ideally shouldn't depend on the > implementation details how is a _BitInt(N) laid out for the particular N). > That encoding/decoding can be to/from _BitInt(BITINT_MAXWIDTH) if we don't > mind it being inefficient and in the clang case maybe running out of stack > (~1MiB; in gcc case 8KiB), or array of limbs the paper is proposing. I agree that the encoding/decoding into an array of limbs is what is needed for this purpose, but I am thinking more generally. Users may also want to pass generic _BitInts around. Martin
