Age | Commit message (Collapse) | Author |
|
- update the test generation script to
match some manual changes
- fix some variadic calls to printf
- add a test case where an odd number of
slots is used on the stack before varargs
|
|
Some abis, like the riscv one, treat
arguments differently depending on
whether they are variadic or not.
To prepare for the upcomming riscv
target, we change the variadic call
syntax and give meaning to the
location of the '...' marker.
# new syntax
%ret =w call $f(w %regular, ..., w %variadic)
By nature of their abis, the change
is backwards compatible for existing
targets.
|
|
Different architectures use different types for va_list:
x86_64 uses an 1-length array of struct type[0]:
typedef struct {
unsigned int gp_offset;
unsigned int fp_offset;
void *overflow_arg_area;
void *reg_save_area;
} va_list[1];
aarch64 uses a struct type[1]
typedef struct {
void *__stack;
void *__gr_top;
void *__vr_top;
int __gr_offs;
int __vr_offs;
} va_list;
Consequently, C functions which takes a va_list as an argument,
such as vprintf, may pass va_list in different ways depending on
the architecture.
On x86_64, va_list is an array type, so parameter decays to a pointer
and passing the address of the va_list is correct.
On aarch64, the va_list struct is passed by value, but since it is
larger than 16 bytes, the parameter is replaced with a pointer to
caller-allocated memory. Thus, passing the address as an l argument
happens to work.
However, this pattern of passing the address of the va_list to
vprintf doesn't extend to other architectures. On riscv64, va_list
is defined as
typedef void *va_list;
which is *not* passed by reference. This means that tests that call
vprintf using the address of a va_list (vararg1 and vararg2) will
not work on riscv.
To fix this while keeping the tests architecture-neutral, add a
small wrapper function to the driver which takes a va_list *, and
let the C compiler deal with the details of passing va_list by
value.
[0] https://c9x.me/compile/bib/abi-x64.pdf#figure.3.34
[1] https://c9x.me/compile/bib/abi-arm64.pdf#%5B%7B%22num%22%3A63%2C%22gen%22%3A0%7D%2C%7B%22name%22%3A%22XYZ%22%7D%2C52%2C757%2C0%5D
[2] https://github.com/riscv/riscv-elf-psabi-doc/blob/master/riscv-cc.adoc#va_list-va_start-and-va_arg$
|
|
Though I am not aware of any architecture where this matters, it
is technically incorrect to call these stdio functions as if they
had no result.
The QBE documentation says
> Unless the called function does not return a value, a return
> temporary must be specified, even if it is never used afterwards.
so we should follow it in the tests as well.
|
|
The vararg tests had to be changed because
va_list is 32-bit wide on arm. The astute
reader will notice that the way we pass
va_list values is wrong, we should be using
the ':valist' type as defined below instead
of 'l'. But eh, that works for now, because
of the ABI.
type :valist = align 8 { 32 }
|
|
|