History

Struct va_arg fix

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

herman ten brugge committed 6 years ago

Commit 4a16beb1 parent 757a9746 files · +99 −40Browse files

Unified · Split

6 files
  1. arm64-gen.c +6 −4
  2. lib/va_list.c +10 −2
  3. riscv64-gen.c +6 −1
  4. tests/bug.c +0 −17
  5. tests/tcctest.c +59 −2
  6. x86_64-gen.c +18 −14
arm64-gen.c+6−4
@@ -1050,10 +1050,12 @@ ST_FUNC void gfunc_call(int nb_args) · 1049 unmodified lines
1050 // value in general-purpose registers1050 // value in general-purpose registers
1051 if ((vtop->type.t & VT_BTYPE) == VT_STRUCT) {1051 if ((vtop->type.t & VT_BTYPE) == VT_STRUCT) {
1052 int align, size = type_size(&vtop->type, &align);1052 int align, size = type_size(&vtop->type, &align);
1053 vtop->type.t = VT_PTR;1053 if (size) {
1054 gaddrof();1054 vtop->type.t = VT_PTR;
1055 gv(RC_R(a[i] / 2));1055 gaddrof();
1056 arm64_ldrs(a[i] / 2, size);1056 gv(RC_R(a[i] / 2));
1057 arm64_ldrs(a[i] / 2, size);
1058 }
1057 }1059 }
1058 else1060 else
1059 gv(RC_R(a[i] / 2));1061 gv(RC_R(a[i] / 2));
lib/va_list.c+10−2
@@ -23,6 +23,8 @@ typedef struct { · 22 unmodified lines
23} __builtin_va_list[1];23} __builtin_va_list[1];
24*/24*/
25 25
26extern void *memcpy(void *dest, const void *src, unsigned long n);
27
26void *__va_arg(__builtin_va_list ap,28void *__va_arg(__builtin_va_list ap,
27 int arg_type,29 int arg_type,
28 int size, int align)30 int size, int align)
@@ -40,9 +42,15 @@ void *__va_arg(__builtin_va_list ap, · 11 unmodified lines
40 case __va_float_reg:42 case __va_float_reg:
41 if (ap->fp_offset < 128 + 48) {43 if (ap->fp_offset < 128 + 48) {
42 ap->fp_offset += 16;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 goto use_overflow_area;54 goto use_overflow_area;
47 55
48 case __va_stack:56 case __va_stack:
riscv64-gen.c+6−1
@@ -552,7 +552,9 @@ ST_FUNC void gfunc_call(int nb_args) · 551 unmodified lines
552 if (!sa && align == 2*XLEN && size <= 2*XLEN)552 if (!sa && align == 2*XLEN && size <= 2*XLEN)
553 areg[0] = (areg[0] + 1) & ~1;553 areg[0] = (areg[0] + 1) & ~1;
554 nregs = prc[0];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 || (prc[1] == RC_FLOAT && areg[1] >= 16)558 || (prc[1] == RC_FLOAT && areg[1] >= 16)
557 || (nregs == 2 && prc[1] == RC_FLOAT && prc[2] == RC_FLOAT559 || (nregs == 2 && prc[1] == RC_FLOAT && prc[2] == RC_FLOAT
558 && areg[1] >= 15)560 && areg[1] >= 15)
@@ -651,6 +653,8 @@ ST_FUNC void gfunc_call(int nb_args) · 92 unmodified lines
651 vrotb(i+1);653 vrotb(i+1);
652 origtype = vtop->type;654 origtype = vtop->type;
653 size = type_size(&vtop->type, &align);655 size = type_size(&vtop->type, &align);
656 if (size == 0)
657 goto done;
654 loadt = vtop->type.t & VT_BTYPE;658 loadt = vtop->type.t & VT_BTYPE;
655 if (loadt == VT_STRUCT) {659 if (loadt == VT_STRUCT) {
656 loadt = (ii >> 12) & VT_BTYPE;660 loadt = (ii >> 12) & VT_BTYPE;
@@ -701,6 +705,7 @@ ST_FUNC void gfunc_call(int nb_args) · 44 unmodified lines
701 EI(0x13, 0, ireg(r2), ireg(vtop->r2), 0); // mv Ra+1, RR2705 EI(0x13, 0, ireg(r2), ireg(vtop->r2), 0); // mv Ra+1, RR2
702 vtop->r2 = r2;706 vtop->r2 = r2;
703 }707 }
708done:
704 vrott(i+1);709 vrott(i+1);
705 }710 }
706 }711 }
tests/bug.c+0−17
@@ -1,21 +1,6 @@
1#include <stdio.h>1#include <stdio.h>
2#include <stdarg.h>2#include <stdarg.h>
3 3
4typedef struct{double x,y;}p;
5
6void 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
19void tst3(void)4void tst3(void)
20{5{
21 /* Should VT_SYM be checked for TOK_builtin_constant_p */6 /* Should VT_SYM be checked for TOK_builtin_constant_p */
@@ -60,7 +45,5 @@ int compile_errors(void) · 38 unmodified lines
60int45int
61main(void)46main(void)
62{47{
63 p v = { 1, 2};
64 tst2(1, v);
65 tst3();48 tst3();
66}49}
tests/tcctest.c+59−2
@@ -2627,18 +2627,34 @@ void vprintf1(const char *fmt, ...) · 2626 unmodified lines
2627struct myspace {2627struct myspace {
2628 short int profile;2628 short int profile;
2629};2629};
2630struct myspace2 {
2631 char a[0];
2632};
2633struct myspace3 {
2634 char a[1];
2635};
2636struct myspace4 {
2637 char a[2];
2638};
2630 2639
2631void stdarg_for_struct(struct myspace bob, ...)2640void stdarg_for_struct(struct myspace bob, ...)
2632{2641{
2633 struct myspace george, bill;2642 struct myspace george, bill;
2643 struct myspace2 alex1;
2644 struct myspace3 alex2;
2645 struct myspace4 alex3;
2634 va_list ap;2646 va_list ap;
2635 short int validate;2647 short int validate;
2636 2648
2637 va_start(ap, bob);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 bill = va_arg(ap, struct myspace);2653 bill = va_arg(ap, struct myspace);
2639 george = va_arg(ap, struct myspace);2654 george = va_arg(ap, struct myspace);
2640 validate = va_arg(ap, int);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 bob.profile, bill.profile, george.profile, validate);2658 bob.profile, bill.profile, george.profile, validate);
2643 va_end(ap);2659 va_end(ap);
2644}2660}
@@ -2664,10 +2680,40 @@ void stdarg_syntax(int n, ...) · 19 unmodified lines
2664 (va_end(ap));2680 (va_end(ap));
2665}2681}
2666 2682
2683typedef struct{
2684 double x,y;
2685} point;
2686point 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
2688static 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
2667void stdarg_test(void)2710void stdarg_test(void)
2668{2711{
2669 LONG_DOUBLE ld = 1234567891234LL;2712 LONG_DOUBLE ld = 1234567891234LL;
2670 struct myspace bob;2713 struct myspace bob;
2714 struct myspace2 bob2;
2715 struct myspace3 bob3;
2716 struct myspace4 bob4;
2671 2717
2672 vprintf1("%d %d %d\n", 1, 2, 3);2718 vprintf1("%d %d %d\n", 1, 2, 3);
2673 vprintf1("%f %d %f\n", 1.0, 2, 3.0);2719 vprintf1("%f %d %f\n", 1.0, 2, 3.0);
@@ -2709,9 +2755,20 @@ void stdarg_test(void) · 35 unmodified lines
2709 42.0, 43.0, ld);2755 42.0, 43.0, ld);
2710 2756
2711 bob.profile = 42;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 stdarg_for_libc("stdarg_for_libc: %s %.2f %d\n", "string", 1.23, 456);2762 stdarg_for_libc("stdarg_for_libc: %s %.2f %d\n", "string", 1.23, 456);
2714 stdarg_syntax(1, 17);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
2717int reltab[3] = { 1, 2, 3 };2774int reltab[3] = { 1, 2, 3 };
x86_64-gen.c+18−14
@@ -1244,6 +1244,7 @@ void gfunc_call(int nb_args) · 1243 unmodified lines
1244 stack_adjust = 0;1244 stack_adjust = 0;
1245 for(i = nb_args - 1; i >= 0; i--) {1245 for(i = nb_args - 1; i >= 0; i--) {
1246 mode = classify_x86_64_arg(&vtop[-i].type, NULL, &size, &align, &reg_count);1246 mode = classify_x86_64_arg(&vtop[-i].type, NULL, &size, &align, &reg_count);
1247 if (size == 0) continue;
1247 if (mode == x86_64_mode_sse && nb_sse_args + reg_count <= 8) {1248 if (mode == x86_64_mode_sse && nb_sse_args + reg_count <= 8) {
1248 nb_sse_args += reg_count;1249 nb_sse_args += reg_count;
1249 onstack[i] = 0;1250 onstack[i] = 0;
@@ -1278,21 +1279,23 @@ void gfunc_call(int nb_args) · 28 unmodified lines
1278 stack_adjust &= 15;1279 stack_adjust &= 15;
1279 for (i = k = 0; i < nb_args;) {1280 for (i = k = 0; i < nb_args;) {
1280 mode = classify_x86_64_arg(&vtop[-i].type, NULL, &size, &align, &reg_count);1281 mode = classify_x86_64_arg(&vtop[-i].type, NULL, &size, &align, &reg_count);
1281 if (!onstack[i + k]) {1282 if (size) {
1282 ++i;1283 if (!onstack[i + k]) {
1283 continue;1284 ++i;
1284 }1285 continue;
1285 /* Possibly adjust stack to align SSE boundary. We're processing1286 }
1286 args from right to left while allocating happens left to right1287 /* Possibly adjust stack to align SSE boundary. We're processing
1287 (stack grows down), so the adjustment needs to happen _after_1288 args from right to left while allocating happens left to right
1288 an argument that requires it. */1289 (stack grows down), so the adjustment needs to happen _after_
1289 if (stack_adjust) {1290 an argument that requires it. */
1290 o(0x50); /* push %rax; aka sub $8,%rsp */1291 if (stack_adjust) {
1291 args_size += 8;1292 o(0x50); /* push %rax; aka sub $8,%rsp */
1292 stack_adjust = 0;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 vrotb(i+1);1300 vrotb(i+1);
1298 1301
@@ -1357,6 +1360,7 @@ void gfunc_call(int nb_args) · 58 unmodified lines
1357 assert(sse_reg <= 8);1360 assert(sse_reg <= 8);
1358 for(i = 0; i < nb_args; i++) {1361 for(i = 0; i < nb_args; i++) {
1359 mode = classify_x86_64_arg(&vtop->type, &type, &size, &align, &reg_count);1362 mode = classify_x86_64_arg(&vtop->type, &type, &size, &align, &reg_count);
1363 if (size == 0) continue;
1360 /* Alter stack entry type so that gv() knows how to treat it */1364 /* Alter stack entry type so that gv() knows how to treat it */
1361 vtop->type = type;1365 vtop->type = type;
1362 if (mode == x86_64_mode_sse) {1366 if (mode == x86_64_mode_sse) {

Keyboard shortcuts

General

Show keyboard shortcuts
?
Focus the current search
/

Issues and pull requests

Open filters
f

Issues, pull requests and Inbox

Select next item
j↓
Select previous item
k↑
Open selected item
Enter
Dismiss filters or clear selection
Esc

Repository code

Go to file
t