Riscv struct saving
Some checks are pending
build and test / test-x86_64-linux (push) Waiting to run
build and test / test-x86_64-osx (push) Waiting to run
build and test / test-aarch64-osx (push) Waiting to run
build and test / test-x86_64-win32 (push) Waiting to run
build and test / test-i386-win32 (push) Waiting to run
build and test / test-armv7-linux (push) Waiting to run
build and test / test-aarch64-linux (push) Waiting to run
build and test / test-riscv64-linux (push) Waiting to run

While adding some testcases for attribute cleanup I found a
bug in the riscv code. It modifies the sv->c.i in load_symofs.
If a structure contains more then one element only the
first is stored correctly. This only happens on a large
stack frame.
Fixed by saving/restoring sv->c.i.
This commit is contained in:
herman ten brugge 2025-07-17 06:50:15 +02:00
parent 9670d10294
commit 7c23c48a93
3 changed files with 60 additions and 0 deletions

View File

@ -233,6 +233,7 @@ ST_FUNC void load(int r, SValue *sv)
int v = fr & VT_VALMASK;
int rr = is_ireg(r) ? ireg(r) : freg(r);
int fc = sv->c.i;
int save_fc = fc;
int bt = sv->type.t & VT_BTYPE;
int align, size;
if (fr & VT_LVAL) {
@ -370,6 +371,7 @@ ST_FUNC void load(int r, SValue *sv)
EI(0x13, 0, rr, 0, t ^ 1); // addi RR, x0, !t
} else
tcc_error("unimp: load(non-const)");
sv->c.i = save_fc;
}
ST_FUNC void store(int r, SValue *sv)
@ -377,6 +379,7 @@ ST_FUNC void store(int r, SValue *sv)
int fr = sv->r & VT_VALMASK;
int rr = is_ireg(r) ? ireg(r) : freg(r), ptrreg;
int fc = sv->c.i;
int save_fc = fc;
int bt = sv->type.t & VT_BTYPE;
int align, size = type_size(&sv->type, &align);
assert(!is_float(bt) || is_freg(r) || bt == VT_LDOUBLE);
@ -413,6 +416,7 @@ ST_FUNC void store(int r, SValue *sv)
ES(is_freg(r) ? 0x27 : 0x23, // fs... | s...
size == 1 ? 0 : size == 2 ? 1 : size == 4 ? 2 : 3, // ... [wd] | [bhwd]
ptrreg, rr, fc); // RR, fc(base)
sv->c.i = save_fc;
}
static void gcall_or_jmp(int docall)

View File

@ -5,6 +5,8 @@ typedef struct { int a; int b; int c; int d; int e; int f; int g; int h; } tstl;
typedef struct { int a; int b; int c; int d; } tsti;
typedef struct { double a; double b; } tstd;
typedef struct { long double a; } tstld;
typedef struct { int a; double b; } tstm;
typedef struct { float a; float b; float c; float d; } tstf;
void incr_glob_i(int *i)
{
@ -258,6 +260,44 @@ tstld test_cleanup5(void) {
return n;
}
void my_cleanup6(tstm *p) {
printf("%d %g\n", p->a, p->b);
p->a = 90;
p->b = 91.0;
}
tstm test_cleanup6(void) {
tstm __attribute__((cleanup(my_cleanup6))) n;
n.a = 42;
n.b = 43.0;
return n;
}
void my_cleanup7(tstf *p) {
printf("%f %f %f %f\n", p->a, p->b, p->c, p->d);
p->a = 0x90; p->b = 0x91; p->c = 0x92; p->d = 0x93;
}
tstf test_cleanup7(void) {
tstf __attribute__((cleanup(my_cleanup7))) n;
n.a = 42; n.b = 43; n.c = 44; n.d = 45;
return n;
}
void my_cleanup8(int **p) {
**p = 0x90;
}
int test_cleanup8(void) {
int n = 42;
int __attribute__((cleanup(my_cleanup8))) *p = &n;
return n;
}
static void my_cleanupe(int *p) {
*p = 0x90;
}
int main()
{
int i __attribute__ ((__cleanup__(check))) = 0, not_i;
@ -267,6 +307,8 @@ int main()
tsti ti;
tstd td;
tstld tld;
tstm tm;
tstf tf;
{
__attribute__ ((__cleanup__(check_oh_i))) char oh_i = 'o', o = 'a';
@ -299,6 +341,14 @@ int main()
printf("%g %g\n", td.a, td.b);
tld = test_cleanup5();
printf("%Lf\n", tld.a);
tm = test_cleanup6();
printf("%d %g\n", tm.a, tm.b);
tf = test_cleanup7();
printf("%f %f %f %f\n", tf.a, tf.b, tf.c, tf.d);
printf("%d\n", test_cleanup8());
printf("%d\n", ({
int __attribute__ ((cleanup(my_cleanupe))) n = 42;
n; }));
return i;
}

View File

@ -58,6 +58,12 @@ after break
42 43
42.000000
42.000000
42 43
42 43
42.000000 43.000000 44.000000 45.000000
42.000000 43.000000 44.000000 45.000000
42
42
---- 0
---- 1
str: plop