From 0c12363fd3e82b8c1e7b37c9c43fdca66cf8c520 Mon Sep 17 00:00:00 2001 From: kbkpbot Date: Fri, 11 Jul 2025 22:13:30 +0800 Subject: [PATCH] arm64: Save func results before struct args In gfunc_call(), structure members are loaded into registers during argument handling. This operation may overwrite previous function call results stored in registers (e.g., s0). To prevent this, we must save function call results to the stack before processing structure arguments. --- arm64-gen.c | 3 +++ tests/tests2/137_funcall_struct_args.c | 23 +++++++++++++++++++++ tests/tests2/137_funcall_struct_args.expect | 2 ++ 3 files changed, 28 insertions(+) create mode 100644 tests/tests2/137_funcall_struct_args.c create mode 100644 tests/tests2/137_funcall_struct_args.expect diff --git a/arm64-gen.c b/arm64-gen.c index d15446d3..ccb5a5c1 100644 --- a/arm64-gen.c +++ b/arm64-gen.c @@ -1101,6 +1101,9 @@ ST_FUNC void gfunc_call(int nb_args) // value in floating-point registers if ((vtop->type.t & VT_BTYPE) == VT_STRUCT) { uint32_t j, sz, n = arm64_hfa(&vtop->type, &sz); + // save regs because struct may overwrite previous func call result + save_regs(0); + vtop->type.t = VT_PTR; gaddrof(); gv(RC_R30); diff --git a/tests/tests2/137_funcall_struct_args.c b/tests/tests2/137_funcall_struct_args.c new file mode 100644 index 00000000..20768e34 --- /dev/null +++ b/tests/tests2/137_funcall_struct_args.c @@ -0,0 +1,23 @@ +#include + +// arm64-gen.c: gfunc_call() Second pass when struct args may overwrite previous func call result +struct vec { + float x; + float y; +}; + +void bug(float x, float y) { + printf("x=%f\ny=%f\n", x, y); +} + +float dot(struct vec v) { + return 999.5; +} + +void main(void) { + struct vec a; + a.x = 33.0f; + a.y = 77.0f; + bug(dot(a), dot(a)); +} + diff --git a/tests/tests2/137_funcall_struct_args.expect b/tests/tests2/137_funcall_struct_args.expect new file mode 100644 index 00000000..ea381eae --- /dev/null +++ b/tests/tests2/137_funcall_struct_args.expect @@ -0,0 +1,2 @@ +x=999.500000 +y=999.500000