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).

> 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.

        Jakub

Reply via email to