Skip to content

Commit 7c23c48

Browse files
committed
Riscv struct saving
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.
1 parent 9670d10 commit 7c23c48

File tree

3 files changed

+60
-0
lines changed

3 files changed

+60
-0
lines changed

riscv64-gen.c

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -233,6 +233,7 @@ ST_FUNC void load(int r, SValue *sv)
233233
int v = fr & VT_VALMASK;
234234
int rr = is_ireg(r) ? ireg(r) : freg(r);
235235
int fc = sv->c.i;
236+
int save_fc = fc;
236237
int bt = sv->type.t & VT_BTYPE;
237238
int align, size;
238239
if (fr & VT_LVAL) {
@@ -370,13 +371,15 @@ ST_FUNC void load(int r, SValue *sv)
370371
EI(0x13, 0, rr, 0, t ^ 1); // addi RR, x0, !t
371372
} else
372373
tcc_error("unimp: load(non-const)");
374+
sv->c.i = save_fc;
373375
}
374376

375377
ST_FUNC void store(int r, SValue *sv)
376378
{
377379
int fr = sv->r & VT_VALMASK;
378380
int rr = is_ireg(r) ? ireg(r) : freg(r), ptrreg;
379381
int fc = sv->c.i;
382+
int save_fc = fc;
380383
int bt = sv->type.t & VT_BTYPE;
381384
int align, size = type_size(&sv->type, &align);
382385
assert(!is_float(bt) || is_freg(r) || bt == VT_LDOUBLE);
@@ -413,6 +416,7 @@ ST_FUNC void store(int r, SValue *sv)
413416
ES(is_freg(r) ? 0x27 : 0x23, // fs... | s...
414417
size == 1 ? 0 : size == 2 ? 1 : size == 4 ? 2 : 3, // ... [wd] | [bhwd]
415418
ptrreg, rr, fc); // RR, fc(base)
419+
sv->c.i = save_fc;
416420
}
417421

418422
static void gcall_or_jmp(int docall)

tests/tests2/101_cleanup.c

Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,8 @@ typedef struct { int a; int b; int c; int d; int e; int f; int g; int h; } tstl;
55
typedef struct { int a; int b; int c; int d; } tsti;
66
typedef struct { double a; double b; } tstd;
77
typedef struct { long double a; } tstld;
8+
typedef struct { int a; double b; } tstm;
9+
typedef struct { float a; float b; float c; float d; } tstf;
810

911
void incr_glob_i(int *i)
1012
{
@@ -258,6 +260,44 @@ tstld test_cleanup5(void) {
258260
return n;
259261
}
260262

263+
void my_cleanup6(tstm *p) {
264+
printf("%d %g\n", p->a, p->b);
265+
p->a = 90;
266+
p->b = 91.0;
267+
}
268+
269+
tstm test_cleanup6(void) {
270+
tstm __attribute__((cleanup(my_cleanup6))) n;
271+
n.a = 42;
272+
n.b = 43.0;
273+
return n;
274+
}
275+
276+
void my_cleanup7(tstf *p) {
277+
printf("%f %f %f %f\n", p->a, p->b, p->c, p->d);
278+
p->a = 0x90; p->b = 0x91; p->c = 0x92; p->d = 0x93;
279+
}
280+
281+
tstf test_cleanup7(void) {
282+
tstf __attribute__((cleanup(my_cleanup7))) n;
283+
n.a = 42; n.b = 43; n.c = 44; n.d = 45;
284+
return n;
285+
}
286+
287+
void my_cleanup8(int **p) {
288+
**p = 0x90;
289+
}
290+
291+
int test_cleanup8(void) {
292+
int n = 42;
293+
int __attribute__((cleanup(my_cleanup8))) *p = &n;
294+
return n;
295+
}
296+
297+
static void my_cleanupe(int *p) {
298+
*p = 0x90;
299+
}
300+
261301
int main()
262302
{
263303
int i __attribute__ ((__cleanup__(check))) = 0, not_i;
@@ -267,6 +307,8 @@ int main()
267307
tsti ti;
268308
tstd td;
269309
tstld tld;
310+
tstm tm;
311+
tstf tf;
270312

271313
{
272314
__attribute__ ((__cleanup__(check_oh_i))) char oh_i = 'o', o = 'a';
@@ -299,6 +341,14 @@ int main()
299341
printf("%g %g\n", td.a, td.b);
300342
tld = test_cleanup5();
301343
printf("%Lf\n", tld.a);
344+
tm = test_cleanup6();
345+
printf("%d %g\n", tm.a, tm.b);
346+
tf = test_cleanup7();
347+
printf("%f %f %f %f\n", tf.a, tf.b, tf.c, tf.d);
348+
printf("%d\n", test_cleanup8());
349+
printf("%d\n", ({
350+
int __attribute__ ((cleanup(my_cleanupe))) n = 42;
351+
n; }));
302352
return i;
303353
}
304354

tests/tests2/101_cleanup.expect

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -58,6 +58,12 @@ after break
5858
42 43
5959
42.000000
6060
42.000000
61+
42 43
62+
42 43
63+
42.000000 43.000000 44.000000 45.000000
64+
42.000000 43.000000 44.000000 45.000000
65+
42
66+
42
6167
---- 0
6268
---- 1
6369
str: plop

0 commit comments

Comments
 (0)