From e81d015e3cc2cb0c352792d0cac12f1594281bc2 Mon Sep 17 00:00:00 2001 From: Xavier Leroy Date: Sun, 10 Jan 2021 14:34:58 +0100 Subject: RISC-V: wrong fixup code generated for vararg calls with fixed FP args This is a follow-up to 2076a3bb3. Integer registers were wrongly reserved for fixed FP arguments, causing variadic FP arguments to end up in the wrong integer registers. Added regression test in test/regression/varargs2.c --- riscV/Asmexpand.ml | 30 ++++++++++++++++++------------ test/regression/Results/varargs2 | 1 + test/regression/varargs2.c | 16 ++++++++++++++++ 3 files changed, 35 insertions(+), 12 deletions(-) diff --git a/riscV/Asmexpand.ml b/riscV/Asmexpand.ml index f01ecb23..da97c4a8 100644 --- a/riscV/Asmexpand.ml +++ b/riscV/Asmexpand.ml @@ -72,27 +72,33 @@ let rec fixup_variadic_call fixed ri rf tyl = | (Tint | Tany32) :: tyl -> fixup_variadic_call (fixed - 1) (ri + 1) rf tyl | Tsingle :: tyl -> - if fixed <= 0 then begin + if fixed > 0 then + fixup_variadic_call (fixed - 1) ri (rf + 1) tyl + else begin let rs = float_param_regs.(rf) and rd = int_param_regs.(ri) in - emit (Pfmvxs(rd, rs)) - end; - fixup_variadic_call (fixed - 1) (ri + 1) (rf + 1) tyl + emit (Pfmvxs(rd, rs)); + fixup_variadic_call (fixed - 1) (ri + 1) (rf + 1) tyl + end | Tlong :: tyl -> let ri' = if Archi.ptr64 then ri + 1 else align ri 2 + 2 in fixup_variadic_call (fixed - 1) ri' rf tyl | (Tfloat | Tany64) :: tyl -> if Archi.ptr64 then begin - if fixed <= 0 then begin + if fixed > 0 then + fixup_variadic_call (fixed - 1) ri (rf + 1) tyl + else begin let rs = float_param_regs.(rf) and rd = int_param_regs.(ri) in - emit (Pfmvxd(rd, rs)) - end; - fixup_variadic_call (fixed - 1) (ri + 1) (rf + 1) tyl + emit (Pfmvxd(rd, rs)); + fixup_variadic_call (fixed - 1) (ri + 1) (rf + 1) tyl + end end else begin let ri = align ri 2 in if ri < 8 then begin - if fixed <= 0 then begin + if fixed > 0 then + fixup_variadic_call (fixed - 1) ri (rf + 1) tyl + else begin let rs = float_param_regs.(rf) and rd1 = int_param_regs.(ri) and rd2 = int_param_regs.(ri + 1) in @@ -100,9 +106,9 @@ let rec fixup_variadic_call fixed ri rf tyl = emit (Pfsd(rs, X2, Ofsimm _0)); emit (Plw(rd1, X2, Ofsimm _0)); emit (Plw(rd2, X2, Ofsimm _4)); - emit (Paddiw(X2, X X2, _16)) - end; - fixup_variadic_call (fixed - 1) (ri + 2) (rf + 1) tyl + emit (Paddiw(X2, X X2, _16)); + fixup_variadic_call (fixed - 1) (ri + 2) (rf + 1) tyl + end end end diff --git a/test/regression/Results/varargs2 b/test/regression/Results/varargs2 index 96ee9d63..050b6331 100644 --- a/test/regression/Results/varargs2 +++ b/test/regression/Results/varargs2 @@ -10,4 +10,5 @@ Twice: -1 1.23 With va_copy: -1 1.23 With va_copy: -1 1.23 With extra args: x & Hello, world! & 42 & 123456789012345 & 3.141592654 & 2.718281746 +With extra FP args: 123456789012345 & 3.141592654 & 2.718281746 va_list compatibility: x & Hello, world! & 42 & 123456789012345 & 3.141592654 & 2.718281746 diff --git a/test/regression/varargs2.c b/test/regression/varargs2.c index b96d1940..32140d5c 100644 --- a/test/regression/varargs2.c +++ b/test/regression/varargs2.c @@ -104,6 +104,17 @@ void miniprintf_extra(int i1, int i2, int i3, int i4, va_end(va); } +/* Add a few dummy FP arguments to test passing of variadic FP arguments + in integer registers (mostly relevant for RISC-V) */ + +void miniprintf_float(double f1, double f2, const char * fmt, ...) +{ + va_list va; + va_start(va, fmt); + minivprintf(fmt, va); + va_end(va); +} + /* Test va_list compatibility with the C library */ void printf_compat(const char * fmt, ...) @@ -143,6 +154,11 @@ int main() 123456789012345LL, 3.141592654, 2.71828182); + miniprintf_float(0.0, 1.0, + "With extra FP args: %l & %e & %f\n", + 123456789012345LL, + 3.141592654, + 2.71828182); printf_compat("va_list compatibility: %c & %s & %d & %lld & %.10g & %.10g\n", 'x', "Hello, world!", -- cgit