@@ -170,6 +170,7 @@ contents of any fixed registers like `gp` and `tp` never change,
170170NOTE: Calling convention for big-endian is *NOT* included in this specification
171171yet, we intend to define that in future version of this specification.
172172
173+ [#integer-cc]
173174=== Integer Calling Convention
174175
175176The base integer calling convention provides eight argument registers,
@@ -655,13 +656,35 @@ purposes of data races.
655656
656657=== va_list, va_start, and va_arg
657658
658- The `va_list` type is `void*`. A callee with variadic arguments is responsible
659- for copying the contents of registers used to pass variadic arguments to the
660- vararg save area, which must be contiguous with arguments passed on the stack.
661- The `va_start` macro initializes its `va_list` argument to point to the start
662- of the vararg save area. The `va_arg` macro will increment its `va_list`
663- argument according to the size of the given type, taking into account the
664- rules about 2×XLEN aligned arguments being passed in "aligned" register pairs.
659+ The `va_list` type has the same representation as `void*` and points to a
660+ sequence of zero or more arguments with preceding padding for alignment,
661+ formatted and aligned as variadic arguments passed on the stack according to
662+ the integer calling convention (<<integer-cc>>). All standard calling conventions use the
663+ same representation for variadic arguments to allow `va_list` types to be
664+ shared between them.
665+
666+ The `va_start` macro in a function initializes its `va_list` argument to point
667+ to the first address at which a variadic argument could be passed to the
668+ function. If all integer argument registers are used for named formal
669+ arguments, the first variadic argument will have been passed on the stack by
670+ the caller, and the `va_list` can point to the address immediately after the
671+ last named argument passed on the stack, or the `sp` value on entry if no named
672+ arguments were passed on the stack. If some integer argument registers were not
673+ used for named formal arguments, then the first variadic argument may have been
674+ passed in a register. The function is then expected to construct a _varargs
675+ save area_ immediately below the entry `sp` and fill it with the entry values
676+ of all integer argument registers not used for named arguments, in sequence.
677+ The `va_list` value can then be initialized to the start of the varargs save
678+ area, and it will iterate through any variadic arguments passed via registers
679+ before continuing to variadic arguments passed on the stack, if any.
680+
681+ The `va_arg` macro will align its `va_list` argument, fetch a value, and
682+ increment the `va_list` according to the alignment and size of a variadic
683+ argument of the given type, which may not be the same as the alignment and size
684+ of the given type in memory. If the type is passed by reference, the size and
685+ alignment used will be those of a pointer, and the fetched pointer will be used
686+ as the address of the actual argument. The `va_copy` macro is a single pointer
687+ copy and the `va_end` macro performs no operation.
665688
666689=== Vector type sizes and alignments
667690
0 commit comments