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
10501050 // value in general-purpose registers
10511051 if ((vtop->type.t & VT_BTYPE) == VT_STRUCT) {
10521052 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+ }
10571059 }
10581060 else
10591061 gv(RC_R(a[i] / 2));
lib/va_list.c+10−2
@@ -23,6 +23,8 @@ typedef struct { · 22 unmodified lines
2323 } __builtin_va_list[1];
2424 */
2525
26+extern void *memcpy(void *dest, const void *src, unsigned long n);
27+
2628 void *__va_arg(__builtin_va_list ap,
2729 int arg_type,
2830 int size, int align)
@@ -40,9 +42,15 @@ void *__va_arg(__builtin_va_list ap, · 11 unmodified lines
4042 case __va_float_reg:
4143 if (ap->fp_offset < 128 + 48) {
4244 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+ }
4453 }
45− size = 8;
4654 goto use_overflow_area;
4755
4856 case __va_stack:
riscv64-gen.c+6−1
@@ -552,7 +552,9 @@ ST_FUNC void gfunc_call(int nb_args) · 551 unmodified lines
552552 if (!sa && align == 2*XLEN && size <= 2*XLEN)
553553 areg[0] = (areg[0] + 1) & ~1;
554554 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)
556558 || (prc[1] == RC_FLOAT && areg[1] >= 16)
557559 || (nregs == 2 && prc[1] == RC_FLOAT && prc[2] == RC_FLOAT
558560 && areg[1] >= 15)
@@ -651,6 +653,8 @@ ST_FUNC void gfunc_call(int nb_args) · 92 unmodified lines
651653 vrotb(i+1);
652654 origtype = vtop->type;
653655 size = type_size(&vtop->type, &align);
656+ if (size == 0)
657+ goto done;
654658 loadt = vtop->type.t & VT_BTYPE;
655659 if (loadt == VT_STRUCT) {
656660 loadt = (ii >> 12) & VT_BTYPE;
@@ -701,6 +705,7 @@ ST_FUNC void gfunc_call(int nb_args) · 44 unmodified lines
701705 EI(0x13, 0, ireg(r2), ireg(vtop->r2), 0); // mv Ra+1, RR2
702706 vtop->r2 = r2;
703707 }
708+done:
704709 vrott(i+1);
705710 }
706711 }
tests/bug.c+0−17
@@ -1,21 +1,6 @@
11 #include <stdio.h>
22 #include <stdarg.h>
33
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−
194 void tst3(void)
205 {
216 /* Should VT_SYM be checked for TOK_builtin_constant_p */
@@ -60,7 +45,5 @@ int compile_errors(void) · 38 unmodified lines
6045 int
6146 main(void)
6247 {
63− p v = { 1, 2};
64− tst2(1, v);
6548 tst3();
6649 }
tests/tcctest.c+59−2
@@ -2627,18 +2627,34 @@ void vprintf1(const char *fmt, ...) · 2626 unmodified lines
26272627 struct myspace {
26282628 short int profile;
26292629 };
2630+struct myspace2 {
2631+ char a[0];
2632+};
2633+struct myspace3 {
2634+ char a[1];
2635+};
2636+struct myspace4 {
2637+ char a[2];
2638+};
26302639
26312640 void stdarg_for_struct(struct myspace bob, ...)
26322641 {
26332642 struct myspace george, bill;
2643+ struct myspace2 alex1;
2644+ struct myspace3 alex2;
2645+ struct myspace4 alex3;
26342646 va_list ap;
26352647 short int validate;
26362648
26372649 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);
26382653 bill = va_arg(ap, struct myspace);
26392654 george = va_arg(ap, struct myspace);
26402655 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],
26422658 bob.profile, bill.profile, george.profile, validate);
26432659 va_end(ap);
26442660 }
@@ -2664,10 +2680,40 @@ void stdarg_syntax(int n, ...) · 19 unmodified lines
26642680 (va_end(ap));
26652681 }
26662682
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+
26672710 void stdarg_test(void)
26682711 {
26692712 LONG_DOUBLE ld = 1234567891234LL;
26702713 struct myspace bob;
2714+ struct myspace2 bob2;
2715+ struct myspace3 bob3;
2716+ struct myspace4 bob4;
26712717
26722718 vprintf1("%d %d %d\n", 1, 2, 3);
26732719 vprintf1("%f %d %f\n", 1.0, 2, 3.0);
@@ -2709,9 +2755,20 @@ void stdarg_test(void) · 35 unmodified lines
27092755 42.0, 43.0, ld);
27102756
27112757 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);
27132762 stdarg_for_libc("stdarg_for_libc: %s %.2f %d\n", "string", 1.23, 456);
27142763 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
27152772 }
27162773
27172774 int reltab[3] = { 1, 2, 3 };
x86_64-gen.c+18−14
@@ -1244,6 +1244,7 @@ void gfunc_call(int nb_args) · 1243 unmodified lines
12441244 stack_adjust = 0;
12451245 for(i = nb_args - 1; i >= 0; i--) {
12461246 mode = classify_x86_64_arg(&vtop[-i].type, NULL, &size, &align, &reg_count);
1247+ if (size == 0) continue;
12471248 if (mode == x86_64_mode_sse && nb_sse_args + reg_count <= 8) {
12481249 nb_sse_args += reg_count;
12491250 onstack[i] = 0;
@@ -1278,21 +1279,23 @@ void gfunc_call(int nb_args) · 28 unmodified lines
12781279 stack_adjust &= 15;
12791280 for (i = k = 0; i < nb_args;) {
12801281 mode = classify_x86_64_arg(&vtop[-i].type, NULL, &size, &align, &reg_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;
12931298 }
1294− if (onstack[i + k] == 2)
1295− stack_adjust = 1;
12961299
12971300 vrotb(i+1);
12981301
@@ -1357,6 +1360,7 @@ void gfunc_call(int nb_args) · 58 unmodified lines
13571360 assert(sse_reg <= 8);
13581361 for(i = 0; i < nb_args; i++) {
13591362 mode = classify_x86_64_arg(&vtop->type, &type, &size, &align, &reg_count);
1363+ if (size == 0) continue;
13601364 /* Alter stack entry type so that gv() knows how to treat it */
13611365 vtop->type = type;
13621366 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