On Wed, 2010-12-15 at 03:07 +0100, grischka wrote:
> Henry Kroll wrote:
> > x86_64 fails to copy the second struct passed to va_arg.
> > 
> > static struct myspace {
> >     short int profile;
> > } bob = { 42 };
> > 
> > void badfunc(int eek, ...) {
> >     va_list ack;
> >     int validate;
> >     struct myspace george, bill;
> >     va_start(ack, eek);
> >         bill     = va_arg(ack, struct myspace);
> >         george   = va_arg(ack, struct myspace);
> >         validate = va_arg(ack, int);
> > [...]
> > int main(int argc, char **argv) {
> >     badfunc(0, bob, bob, bob.profile);
> > [...]
> 
> This line from tcc's include/stdarg.h might give a hint:
>      /* XXX: this lacks the support of aggregated types. */                  \
> 
> I have no idea though how such support would look like.
> 
> Btw. on win64 it does not work either.  I must have misunderstood
> something about the structures part of the calling conventions.
> 
> --- grischka
> 
> 
> _______________________________________________
> Tinycc-devel mailing list
> [email protected]
> http://lists.nongnu.org/mailman/listinfo/tinycc-devel

This passes some hurried tests I threw at it, but I'm sure it needs more
type checking. I used the attached test program to generate a map of
ap->overflow_arg_area for various sized structures.

diff --git a/include/stdarg.h b/include/stdarg.h
index b5844d0..7b52d3d 100644
--- a/include/stdarg.h
+++ b/include/stdarg.h
@@ -39,8 +39,11 @@ typedef struct __va_list_struct *va_list;
                  : (ap->overflow_arg_area += 8,                 \
                     ap->overflow_arg_area - 8))                 \
               : (ap->gp_offset < 48                             \
-                 ? (ap->gp_offset += 8,                         \
-                    ap->reg_save_area + ap->gp_offset - 8)      \
+    ? __builtin_types_compatible_p(type, int)                   \
+        ? (ap->gp_offset += 8,                                  \
+           ap->reg_save_area + ap->gp_offset - 8)               \
+        : (ap->overflow_arg_area += (sizeof(type) + 3 & ~3),    \
+           ap->overflow_arg_area - (sizeof(type) + 3 & ~3))     \
                  : (ap->overflow_arg_area += 8,                 \
                     ap->overflow_arg_area - 8))                 \
         ))

#include <stdio.h>
#include <stdarg.h>
#define failed(what) do { \
    printf("%i %s:%d: failure\n",what, __FILE__, __LINE__); \
    errors++; \
} while (0)
static int errors = 0;
static struct myspace {
    long double profile;
};
void badfunc(int eek, ...) {
    va_list ack;
    long int validate, i;
    struct myspace bob, ned, sam;
    va_start(ack, eek);
        printf("Map of ack->overflow_arg_area:\n");
        for (i=0;i<32;i++)
            printf("%i ",*(ack->overflow_arg_area+i));
        printf("\n");
        bob      = va_arg(ack, struct myspace);
        ned      = va_arg(ack, struct myspace);
        sam      = va_arg(ack, struct myspace);
        validate = va_arg(ack, int);
        if (bob.profile   != 1) failed(bob.profile);
        if (ned.profile   != 2) failed(ned.profile);
        if (sam.profile   != 3) failed(sam.profile);
        if (validate      != 4) failed(validate);
    va_end(ack);
}
int main(int argc, char **argv) {
    struct myspace bob = {1};
    struct myspace ned = {2};
    struct myspace sam = {3};
    badfunc(0, bob, ned, sam, 4);
    return errors;
}
_______________________________________________
Tinycc-devel mailing list
[email protected]
http://lists.nongnu.org/mailman/listinfo/tinycc-devel

Reply via email to