lib/va_list.c: - Handle struct {double, double} correctly arm64-gen.c: riscv64-gen.c: x86_64-gen.c: - Allow zero sized structs to work with va_arg tcctest.c: - Add new va_arg test code test/bug.c: - Remove tst2 va_arg test
Unified · Split
| @@ -1050,10 +1050,12 @@ ST_FUNC void gfunc_call(int nb_args) · 1049 unmodified lines | ||
| 1050 | 1050 | // value in general-purpose registers |
| 1051 | 1051 | if ((vtop->type.t & VT_BTYPE) == VT_STRUCT) { |
| 1052 | 1052 | int align, size = type_size(&vtop->type, &align); |
| 1053 | − vtop->type.t = VT_PTR; | |
| 1054 | − gaddrof(); | |
| 1055 | − gv(RC_R(a[i] / 2)); | |
| 1056 | − arm64_ldrs(a[i] / 2, size); | |
| 1053 | + if (size) { | |
| 1054 | + vtop->type.t = VT_PTR; | |
| 1055 | + gaddrof(); | |
| 1056 | + gv(RC_R(a[i] / 2)); | |
| 1057 | + arm64_ldrs(a[i] / 2, size); | |
| 1058 | + } | |
| 1057 | 1059 | } |
| 1058 | 1060 | else |
| 1059 | 1061 | gv(RC_R(a[i] / 2)); |
| @@ -23,6 +23,8 @@ typedef struct { · 22 unmodified lines | ||
| 23 | 23 | } __builtin_va_list[1]; |
| 24 | 24 | */ |
| 25 | 25 | |
| 26 | +extern void *memcpy(void *dest, const void *src, unsigned long n); | |
| 27 | + | |
| 26 | 28 | void *__va_arg(__builtin_va_list ap, |
| 27 | 29 | int arg_type, |
| 28 | 30 | int size, int align) |
| @@ -40,9 +42,15 @@ void *__va_arg(__builtin_va_list ap, · 11 unmodified lines | ||
| 40 | 42 | case __va_float_reg: |
| 41 | 43 | if (ap->fp_offset < 128 + 48) { |
| 42 | 44 | ap->fp_offset += 16; |
| 43 | − return ap->reg_save_area + ap->fp_offset - 16; | |
| 45 | + if (size == 8) | |
| 46 | + return ap->reg_save_area + ap->fp_offset - 16; | |
| 47 | + if (ap->fp_offset < 128 + 48) { | |
| 48 | + memcpy(ap->reg_save_area + ap->fp_offset - 8, | |
| 49 | + ap->reg_save_area + ap->fp_offset, 8); | |
| 50 | + ap->fp_offset += 16; | |
| 51 | + return ap->reg_save_area + ap->fp_offset - 32; | |
| 52 | + } | |
| 44 | 53 | } |
| 45 | − size = 8; | |
| 46 | 54 | goto use_overflow_area; |
| 47 | 55 | |
| 48 | 56 | case __va_stack: |
| @@ -552,7 +552,9 @@ ST_FUNC void gfunc_call(int nb_args) · 551 unmodified lines | ||
| 552 | 552 | if (!sa && align == 2*XLEN && size <= 2*XLEN) |
| 553 | 553 | areg[0] = (areg[0] + 1) & ~1; |
| 554 | 554 | nregs = prc[0]; |
| 555 | − if ((prc[1] == RC_INT && areg[0] >= 8) | |
| 555 | + if (size == 0) | |
| 556 | + info[i] = 0; | |
| 557 | + else if ((prc[1] == RC_INT && areg[0] >= 8) | |
| 556 | 558 | || (prc[1] == RC_FLOAT && areg[1] >= 16) |
| 557 | 559 | || (nregs == 2 && prc[1] == RC_FLOAT && prc[2] == RC_FLOAT |
| 558 | 560 | && areg[1] >= 15) |
| @@ -651,6 +653,8 @@ ST_FUNC void gfunc_call(int nb_args) · 92 unmodified lines | ||
| 651 | 653 | vrotb(i+1); |
| 652 | 654 | origtype = vtop->type; |
| 653 | 655 | size = type_size(&vtop->type, &align); |
| 656 | + if (size == 0) | |
| 657 | + goto done; | |
| 654 | 658 | loadt = vtop->type.t & VT_BTYPE; |
| 655 | 659 | if (loadt == VT_STRUCT) { |
| 656 | 660 | loadt = (ii >> 12) & VT_BTYPE; |
| @@ -701,6 +705,7 @@ ST_FUNC void gfunc_call(int nb_args) · 44 unmodified lines | ||
| 701 | 705 | EI(0x13, 0, ireg(r2), ireg(vtop->r2), 0); // mv Ra+1, RR2 |
| 702 | 706 | vtop->r2 = r2; |
| 703 | 707 | } |
| 708 | +done: | |
| 704 | 709 | vrott(i+1); |
| 705 | 710 | } |
| 706 | 711 | } |
| @@ -1,21 +1,6 @@ | ||
| 1 | 1 | #include <stdio.h> |
| 2 | 2 | #include <stdarg.h> |
| 3 | 3 | |
| 4 | −typedef struct{double x,y;}p; | |
| 5 | − | |
| 6 | −void tst2(int n,...) | |
| 7 | −{ | |
| 8 | − /* va_arg for struct double does not work on some targets */ | |
| 9 | − int i; | |
| 10 | − va_list args; | |
| 11 | − va_start(args,n); | |
| 12 | − for (i = 0; i < n; i++) { | |
| 13 | − p v = va_arg(args,p); | |
| 14 | − if (v.x != 1 || v.y != 2) printf("%g %g\n", v.x, v.y); | |
| 15 | − } | |
| 16 | − va_end(args); | |
| 17 | −} | |
| 18 | − | |
| 19 | 4 | void tst3(void) |
| 20 | 5 | { |
| 21 | 6 | /* Should VT_SYM be checked for TOK_builtin_constant_p */ |
| @@ -60,7 +45,5 @@ int compile_errors(void) · 38 unmodified lines | ||
| 60 | 45 | int |
| 61 | 46 | main(void) |
| 62 | 47 | { |
| 63 | − p v = { 1, 2}; | |
| 64 | − tst2(1, v); | |
| 65 | 48 | tst3(); |
| 66 | 49 | } |
| @@ -2627,18 +2627,34 @@ void vprintf1(const char *fmt, ...) · 2626 unmodified lines | ||
| 2627 | 2627 | struct myspace { |
| 2628 | 2628 | short int profile; |
| 2629 | 2629 | }; |
| 2630 | +struct myspace2 { | |
| 2631 | + char a[0]; | |
| 2632 | +}; | |
| 2633 | +struct myspace3 { | |
| 2634 | + char a[1]; | |
| 2635 | +}; | |
| 2636 | +struct myspace4 { | |
| 2637 | + char a[2]; | |
| 2638 | +}; | |
| 2630 | 2639 | |
| 2631 | 2640 | void stdarg_for_struct(struct myspace bob, ...) |
| 2632 | 2641 | { |
| 2633 | 2642 | struct myspace george, bill; |
| 2643 | + struct myspace2 alex1; | |
| 2644 | + struct myspace3 alex2; | |
| 2645 | + struct myspace4 alex3; | |
| 2634 | 2646 | va_list ap; |
| 2635 | 2647 | short int validate; |
| 2636 | 2648 | |
| 2637 | 2649 | va_start(ap, bob); |
| 2650 | + alex1 = va_arg(ap, struct myspace2); | |
| 2651 | + alex2 = va_arg(ap, struct myspace3); | |
| 2652 | + alex3 = va_arg(ap, struct myspace4); | |
| 2638 | 2653 | bill = va_arg(ap, struct myspace); |
| 2639 | 2654 | george = va_arg(ap, struct myspace); |
| 2640 | 2655 | validate = va_arg(ap, int); |
| 2641 | − printf("stdarg_for_struct: %d %d %d %d\n", | |
| 2656 | + printf("stdarg_for_struct: %d %d %d %d %d %d %d\n", | |
| 2657 | + alex2.a[0], alex3.a[0], alex3.a[1], | |
| 2642 | 2658 | bob.profile, bill.profile, george.profile, validate); |
| 2643 | 2659 | va_end(ap); |
| 2644 | 2660 | } |
| @@ -2664,10 +2680,40 @@ void stdarg_syntax(int n, ...) · 19 unmodified lines | ||
| 2664 | 2680 | (va_end(ap)); |
| 2665 | 2681 | } |
| 2666 | 2682 | |
| 2683 | +typedef struct{ | |
| 2684 | + double x,y; | |
| 2685 | +} point; | |
| 2686 | +point pts[]={{1.0,2.0},{3.0,4.0},{5.0,6.0},{7.0,8.0},{9.0,10.0},{11.0,12.0}}; | |
| 2687 | + | |
| 2688 | +static void stdarg_double_struct(int nargs, int posd,...) | |
| 2689 | +{ | |
| 2690 | + int i; | |
| 2691 | + double d; | |
| 2692 | + point pi; | |
| 2693 | + va_list args; | |
| 2694 | + | |
| 2695 | + printf ("stdarg_double_struct: %d\n", posd); | |
| 2696 | + va_start(args,posd); | |
| 2697 | + for(i = 0; i < nargs; i++) { | |
| 2698 | + if (i == posd) { | |
| 2699 | + d = va_arg (args, double); | |
| 2700 | + printf ("d %d = %g\n", i, d); | |
| 2701 | + } | |
| 2702 | + else { | |
| 2703 | + pi = va_arg (args, point); | |
| 2704 | + printf ("pts[%d] = %g %g\n", i, pi.x, pi.y); | |
| 2705 | + } | |
| 2706 | + } | |
| 2707 | + va_end(args); | |
| 2708 | +} | |
| 2709 | + | |
| 2667 | 2710 | void stdarg_test(void) |
| 2668 | 2711 | { |
| 2669 | 2712 | LONG_DOUBLE ld = 1234567891234LL; |
| 2670 | 2713 | struct myspace bob; |
| 2714 | + struct myspace2 bob2; | |
| 2715 | + struct myspace3 bob3; | |
| 2716 | + struct myspace4 bob4; | |
| 2671 | 2717 | |
| 2672 | 2718 | vprintf1("%d %d %d\n", 1, 2, 3); |
| 2673 | 2719 | vprintf1("%f %d %f\n", 1.0, 2, 3.0); |
| @@ -2709,9 +2755,20 @@ void stdarg_test(void) · 35 unmodified lines | ||
| 2709 | 2755 | 42.0, 43.0, ld); |
| 2710 | 2756 | |
| 2711 | 2757 | bob.profile = 42; |
| 2712 | − stdarg_for_struct(bob, bob, bob, bob.profile); | |
| 2758 | + bob3.a[0] = 1; | |
| 2759 | + bob4.a[0] = 2; | |
| 2760 | + bob4.a[1] = 3; | |
| 2761 | + stdarg_for_struct(bob, bob2, bob3, bob4, bob, bob, bob.profile); | |
| 2713 | 2762 | stdarg_for_libc("stdarg_for_libc: %s %.2f %d\n", "string", 1.23, 456); |
| 2714 | 2763 | stdarg_syntax(1, 17); |
| 2764 | +#ifndef __riscv | |
| 2765 | + stdarg_double_struct(6,-1,pts[0],pts[1],pts[2],pts[3],pts[4],pts[5]); | |
| 2766 | + stdarg_double_struct(7,1,pts[0],-1.0,pts[1],pts[2],pts[3],pts[4],pts[5]); | |
| 2767 | + stdarg_double_struct(7,2,pts[0],pts[1],-1.0,pts[2],pts[3],pts[4],pts[5]); | |
| 2768 | + stdarg_double_struct(7,3,pts[0],pts[1],pts[2],-1.0,pts[3],pts[4],pts[5]); | |
| 2769 | + stdarg_double_struct(7,4,pts[0],pts[1],pts[2],pts[3],-1.0,pts[4],pts[5]); | |
| 2770 | + stdarg_double_struct(7,5,pts[0],pts[1],pts[2],pts[3],pts[4],-1.0,pts[5]); | |
| 2771 | +#endif | |
| 2715 | 2772 | } |
| 2716 | 2773 | |
| 2717 | 2774 | int reltab[3] = { 1, 2, 3 }; |
| @@ -1244,6 +1244,7 @@ void gfunc_call(int nb_args) · 1243 unmodified lines | ||
| 1244 | 1244 | stack_adjust = 0; |
| 1245 | 1245 | for(i = nb_args - 1; i >= 0; i--) { |
| 1246 | 1246 | mode = classify_x86_64_arg(&vtop[-i].type, NULL, &size, &align, ®_count); |
| 1247 | + if (size == 0) continue; | |
| 1247 | 1248 | if (mode == x86_64_mode_sse && nb_sse_args + reg_count <= 8) { |
| 1248 | 1249 | nb_sse_args += reg_count; |
| 1249 | 1250 | onstack[i] = 0; |
| @@ -1278,21 +1279,23 @@ void gfunc_call(int nb_args) · 28 unmodified lines | ||
| 1278 | 1279 | stack_adjust &= 15; |
| 1279 | 1280 | for (i = k = 0; i < nb_args;) { |
| 1280 | 1281 | mode = classify_x86_64_arg(&vtop[-i].type, NULL, &size, &align, ®_count); |
| 1281 | − if (!onstack[i + k]) { | |
| 1282 | − ++i; | |
| 1283 | − continue; | |
| 1284 | − } | |
| 1285 | − /* Possibly adjust stack to align SSE boundary. We're processing | |
| 1286 | − args from right to left while allocating happens left to right | |
| 1287 | − (stack grows down), so the adjustment needs to happen _after_ | |
| 1288 | − an argument that requires it. */ | |
| 1289 | − if (stack_adjust) { | |
| 1290 | − o(0x50); /* push %rax; aka sub $8,%rsp */ | |
| 1291 | − args_size += 8; | |
| 1292 | − stack_adjust = 0; | |
| 1282 | + if (size) { | |
| 1283 | + if (!onstack[i + k]) { | |
| 1284 | + ++i; | |
| 1285 | + continue; | |
| 1286 | + } | |
| 1287 | + /* Possibly adjust stack to align SSE boundary. We're processing | |
| 1288 | + args from right to left while allocating happens left to right | |
| 1289 | + (stack grows down), so the adjustment needs to happen _after_ | |
| 1290 | + an argument that requires it. */ | |
| 1291 | + if (stack_adjust) { | |
| 1292 | + o(0x50); /* push %rax; aka sub $8,%rsp */ | |
| 1293 | + args_size += 8; | |
| 1294 | + stack_adjust = 0; | |
| 1295 | + } | |
| 1296 | + if (onstack[i + k] == 2) | |
| 1297 | + stack_adjust = 1; | |
| 1293 | 1298 | } |
| 1294 | − if (onstack[i + k] == 2) | |
| 1295 | − stack_adjust = 1; | |
| 1296 | 1299 | |
| 1297 | 1300 | vrotb(i+1); |
| 1298 | 1301 | |
| @@ -1357,6 +1360,7 @@ void gfunc_call(int nb_args) · 58 unmodified lines | ||
| 1357 | 1360 | assert(sse_reg <= 8); |
| 1358 | 1361 | for(i = 0; i < nb_args; i++) { |
| 1359 | 1362 | mode = classify_x86_64_arg(&vtop->type, &type, &size, &align, ®_count); |
| 1363 | + if (size == 0) continue; | |
| 1360 | 1364 | /* Alter stack entry type so that gv() knows how to treat it */ |
| 1361 | 1365 | vtop->type = type; |
| 1362 | 1366 | if (mode == x86_64_mode_sse) { |