diff options
Diffstat (limited to 'gcc/testsuite/gcc.target/i386/20000724-1.c')
-rw-r--r-- | gcc/testsuite/gcc.target/i386/20000724-1.c | 72 |
1 files changed, 72 insertions, 0 deletions
diff --git a/gcc/testsuite/gcc.target/i386/20000724-1.c b/gcc/testsuite/gcc.target/i386/20000724-1.c new file mode 100644 index 000000000..b3be437b5 --- /dev/null +++ b/gcc/testsuite/gcc.target/i386/20000724-1.c @@ -0,0 +1,72 @@ +/* { dg-do run { target *-*-linux* } } */ +/* { dg-require-effective-target ilp32 } */ +/* { dg-options "-O2 -fomit-frame-pointer" } */ + +extern void abort (void); +extern void exit (int); + +struct s { + struct { int a; } a; + int b; + struct { struct { int a; } a; struct t { struct t *a, *b; } b; } c; +}; + +int bar(int (*fn)(void *), void *arg, unsigned long flags) +{ + return 0; +} + +int baz(void *x) +{ + return 0; +} + +void do_check (struct s *) asm ("do_check") __attribute__((regparm(1))); + +void __attribute__((regparm(1))) do_check(struct s *x) +{ + if (x->a.a || x->b || x->c.a.a) + abort(); + if (x->c.b.a != &x->c.b || x->c.b.b != &x->c.b) + abort(); +} + +#define NT "\n\t" + +asm ("\n" +"___checkme:" +NT "pushl %eax; pushl %ebx; pushl %ecx; pushl %edx; pushl %esi; pushl %edi" + +NT "pushl $0; pushl $0; pushl $0; pushl $0; pushl $0" +NT "pushl $0; pushl $0; pushl $0; pushl $0; pushl $0" + +NT "movl %ecx, %eax" +NT "call do_check" + +NT "popl %eax; popl %eax; popl %eax; popl %eax; popl %eax" +NT "popl %eax; popl %eax; popl %eax; popl %eax; popl %eax" + +NT "popl %edi; popl %esi; popl %edx; popl %ecx; popl %ebx; popl %eax" +NT "ret" +); + +extern inline void do_asm(struct s * x) +{ + asm volatile("call ___checkme" : : "c" (x) : "memory"); +} + +int foo(void) +{ + struct s x = { { 0 }, 0, { { 0 }, { &x.c.b, &x.c.b } } }; + bar(baz, &x, 1); + do_asm(&x); + bar(baz, &x, 1); + do_asm(&x); + return 0; +} + +int main() +{ + foo(); + exit(0); +} |