From b006b9833466933660e1c052454239e4ca3e3f4d Mon Sep 17 00:00:00 2001 From: Ziyao Date: Sun, 9 Apr 2023 06:06:10 +0800 Subject: [PATCH] Fix passing of large function arguments on riscv64 - Correct stack adjustment in gfunc_call() - Add a regression test (130_large_argument) --- riscv64-gen.c | 19 ++++++++---- tests/tests2/130_large_argument.c | 41 ++++++++++++++++++++++++++ tests/tests2/130_large_argument.expect | 3 ++ 3 files changed, 57 insertions(+), 6 deletions(-) create mode 100644 tests/tests2/130_large_argument.c create mode 100644 tests/tests2/130_large_argument.expect diff --git a/riscv64-gen.c b/riscv64-gen.c index 490eca79..8a17b701 100644 --- a/riscv64-gen.c +++ b/riscv64-gen.c @@ -627,10 +627,14 @@ ST_FUNC void gfunc_call(int nb_args) if ((vtop->r & VT_VALMASK) == VT_CMP) gv(RC_INT); + if (stack_add) { - if (stack_add >= 0x1000) { - o(0x37 | (5 << 7) | (-stack_add & 0xfffff000)); //lui t0, upper(v) - EI(0x13, 0, 5, 5, -stack_add << 20 >> 20); // addi t0, t0, lo(v) + if (stack_add >= 0x800) { + unsigned int bit11 = (((unsigned int)-stack_add) >> 11) & 1; + o(0x37 | (5 << 7) | + ((-stack_add + (bit11 << 12)) & 0xfffff000)); //lui t0, upper(v) + EI(0x13, 0, 5, 5, ((-stack_add & 0xfff) - bit11 * (1 << 12))); + // addi t0, t0, lo(v) ER(0x33, 0, 2, 2, 5, 0); // add sp, sp, t0 } else @@ -757,9 +761,12 @@ done: gcall_or_jmp(1); vtop -= nb_args + 1; if (stack_add) { - if (stack_add >= 0x1000) { - o(0x37 | (5 << 7) | (stack_add & 0xfffff000)); //lui t0, upper(v) - EI(0x13, 0, 5, 5, stack_add << 20 >> 20); // addi t0, t0, lo(v) + if (stack_add >= 0x800) { + unsigned int bit11 = ((unsigned int)stack_add >> 11) & 1; + o(0x37 | (5 << 7) | + ((stack_add + (bit11 << 12)) & 0xfffff000)); //lui t0, upper(v) + EI(0x13, 0, 5, 5, (stack_add & 0xfff) - bit11 * (1 << 12)); + // addi t0, t0, lo(v) ER(0x33, 0, 2, 2, 5, 0); // add sp, sp, t0 } else diff --git a/tests/tests2/130_large_argument.c b/tests/tests2/130_large_argument.c new file mode 100644 index 00000000..8415c85e --- /dev/null +++ b/tests/tests2/130_large_argument.c @@ -0,0 +1,41 @@ +#include + +struct large1 { + int a[768]; +}; + +struct large2 { + int a[1920]; +}; + +void pass_large_struct1(struct large1 in) +{ + printf("%d %d\n", in.a[200], in.a[767]); + return; +} + +void pass_large_struct2(struct large2 in) +{ + printf("%d %d %d\n", in.a[200], in.a[1023], in.a[1919]); + return; +} + +void pass_many_args(int a, int b, int c, int d, int e, int f, int g, int h, int i, + int j, int k, int l, int m) +{ + printf("%d %d %d %d %d %d %d %d %d %d %d %d %d\n", a, b, c, d, e, f, g, h, i, + j, k, l, m); + return; +} + +struct large1 l1 = { .a = { [200] = 1, [767] = 2 } }; +struct large2 l2 = { .a = { [200] = 3, [1023] = 4, [1919] = 5} }; + +int main(void) +{ + pass_large_struct1(l1); + pass_large_struct2(l2); + pass_many_args(13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1); + + return 0; +} diff --git a/tests/tests2/130_large_argument.expect b/tests/tests2/130_large_argument.expect new file mode 100644 index 00000000..8c5d9cd7 --- /dev/null +++ b/tests/tests2/130_large_argument.expect @@ -0,0 +1,3 @@ +1 2 +3 4 5 +13 12 11 10 9 8 7 6 5 4 3 2 1