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.
Unified · Split
| @@ -233,6 +233,7 @@ ST_FUNC void load(int r, SValue *sv) · 232 unmodified lines | |||
| 233 | int v = fr & VT_VALMASK; | 233 | int v = fr & VT_VALMASK; |
| 234 | int rr = is_ireg(r) ? ireg(r) : freg(r); | 234 | int rr = is_ireg(r) ? ireg(r) : freg(r); |
| 235 | int fc = sv->c.i; | 235 | int fc = sv->c.i; |
| 236 | int save_fc = fc; | ||
| 236 | int bt = sv->type.t & VT_BTYPE; | 237 | int bt = sv->type.t & VT_BTYPE; |
| 237 | int align, size; | 238 | int align, size; |
| 238 | if (fr & VT_LVAL) { | 239 | if (fr & VT_LVAL) { |
| @@ -370,6 +371,7 @@ ST_FUNC void load(int r, SValue *sv) · 131 unmodified lines | |||
| 370 | EI(0x13, 0, rr, 0, t ^ 1); // addi RR, x0, !t | 371 | EI(0x13, 0, rr, 0, t ^ 1); // addi RR, x0, !t |
| 371 | } else | 372 | } else |
| 372 | tcc_error("unimp: load(non-const)"); | 373 | tcc_error("unimp: load(non-const)"); |
| 374 | sv->c.i = save_fc; | ||
| 373 | } | 375 | } |
| 374 | 376 | ||
| 375 | ST_FUNC void store(int r, SValue *sv) | 377 | ST_FUNC void store(int r, SValue *sv) |
| @@ -377,6 +379,7 @@ ST_FUNC void store(int r, SValue *sv) · 1 unmodified line | |||
| 377 | int fr = sv->r & VT_VALMASK; | 379 | int fr = sv->r & VT_VALMASK; |
| 378 | int rr = is_ireg(r) ? ireg(r) : freg(r), ptrreg; | 380 | int rr = is_ireg(r) ? ireg(r) : freg(r), ptrreg; |
| 379 | int fc = sv->c.i; | 381 | int fc = sv->c.i; |
| 382 | int save_fc = fc; | ||
| 380 | int bt = sv->type.t & VT_BTYPE; | 383 | int bt = sv->type.t & VT_BTYPE; |
| 381 | int align, size = type_size(&sv->type, &align); | 384 | int align, size = type_size(&sv->type, &align); |
| 382 | assert(!is_float(bt) || is_freg(r) || bt == VT_LDOUBLE); | 385 | assert(!is_float(bt) || is_freg(r) || bt == VT_LDOUBLE); |
| @@ -413,6 +416,7 @@ ST_FUNC void store(int r, SValue *sv) · 30 unmodified lines | |||
| 413 | ES(is_freg(r) ? 0x27 : 0x23, // fs... | s... | 416 | ES(is_freg(r) ? 0x27 : 0x23, // fs... | s... |
| 414 | size == 1 ? 0 : size == 2 ? 1 : size == 4 ? 2 : 3, // ... [wd] | [bhwd] | 417 | size == 1 ? 0 : size == 2 ? 1 : size == 4 ? 2 : 3, // ... [wd] | [bhwd] |
| 415 | ptrreg, rr, fc); // RR, fc(base) | 418 | ptrreg, rr, fc); // RR, fc(base) |
| 419 | sv->c.i = save_fc; | ||
| 416 | } | 420 | } |
| 417 | 421 | ||
| 418 | static void gcall_or_jmp(int docall) | 422 | static void gcall_or_jmp(int docall) |
| @@ -5,6 +5,8 @@ typedef struct { int a; int b; int c; int d; int e; int f; int g; int h; } tstl; · 4 unmodified lines | |||
| 5 | typedef struct { int a; int b; int c; int d; } tsti; | 5 | typedef struct { int a; int b; int c; int d; } tsti; |
| 6 | typedef struct { double a; double b; } tstd; | 6 | typedef struct { double a; double b; } tstd; |
| 7 | typedef struct { long double a; } tstld; | 7 | 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; | ||
| 8 | 10 | ||
| 9 | void incr_glob_i(int *i) | 11 | void incr_glob_i(int *i) |
| 10 | { | 12 | { |
| @@ -258,6 +260,44 @@ tstld test_cleanup5(void) { · 247 unmodified lines | |||
| 258 | return n; | 260 | return n; |
| 259 | } | 261 | } |
| 260 | 262 | ||
| 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 | |||
| 261 | int main() | 301 | int main() |
| 262 | { | 302 | { |
| 263 | int i __attribute__ ((__cleanup__(check))) = 0, not_i; | 303 | int i __attribute__ ((__cleanup__(check))) = 0, not_i; |
| @@ -267,6 +307,8 @@ int main() · 3 unmodified lines | |||
| 267 | tsti ti; | 307 | tsti ti; |
| 268 | tstd td; | 308 | tstd td; |
| 269 | tstld tld; | 309 | tstld tld; |
| 310 | tstm tm; | ||
| 311 | tstf tf; | ||
| 270 | 312 | ||
| 271 | { | 313 | { |
| 272 | __attribute__ ((__cleanup__(check_oh_i))) char oh_i = 'o', o = 'a'; | 314 | __attribute__ ((__cleanup__(check_oh_i))) char oh_i = 'o', o = 'a'; |
| @@ -299,6 +341,14 @@ int main() · 26 unmodified lines | |||
| 299 | printf("%g %g\n", td.a, td.b); | 341 | printf("%g %g\n", td.a, td.b); |
| 300 | tld = test_cleanup5(); | 342 | tld = test_cleanup5(); |
| 301 | printf("%Lf\n", tld.a); | 343 | 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; })); | ||
| 302 | return i; | 352 | return i; |
| 303 | } | 353 | } |
| 304 | 354 | ||
| @@ -58,6 +58,12 @@ after break · 57 unmodified lines | |||
| 58 | 42 43 | 58 | 42 43 |
| 59 | 42.000000 | 59 | 42.000000 |
| 60 | 42.000000 | 60 | 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 | ||
| 61 | ---- 0 | 67 | ---- 0 |
| 62 | ---- 1 | 68 | ---- 1 |
| 63 | str: plop | 69 | str: plop |