mirror of
https://github.com/mirror/tinycc.git
synced 2025-02-06 06:40:07 +08:00
Fix passing of large function arguments on riscv64
- Correct stack adjustment in gfunc_call() - Add a regression test (130_large_argument)
This commit is contained in:
parent
e7262accb6
commit
b006b98334
@ -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
|
||||
|
41
tests/tests2/130_large_argument.c
Normal file
41
tests/tests2/130_large_argument.c
Normal file
@ -0,0 +1,41 @@
|
||||
#include<stdio.h>
|
||||
|
||||
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;
|
||||
}
|
3
tests/tests2/130_large_argument.expect
Normal file
3
tests/tests2/130_large_argument.expect
Normal file
@ -0,0 +1,3 @@
|
||||
1 2
|
||||
3 4 5
|
||||
13 12 11 10 9 8 7 6 5 4 3 2 1
|
Loading…
Reference in New Issue
Block a user