FAIL: tmpdir-gcc.dg-struct-layout-1/t026 c_compat_x_tst.o-c_compat_y_tst.o execute (more specifically, test2495 fails)
Created attachment 10306 [details] testcase Compile and link the three files in the tar with -O0.
works on i686 with 4.1.0 and 4.0.2
4.0.2 seems to fail also, maybe a testsuite bug? Still somebody needs to investigate closer.
Old value = 0 New value = 1 check2495 (arg0={a = 27121, b = {c = {d = true, e = 359101392}}}, arg1=0x5019ec, arg2={a = 30216, b = {c = {d = true, e = 1}}}) at t026_y.min.i:71 71 if (arg2.b.c.e != a2495[2].b.c.e) ++fails; Reduced testcase: void abort(void); struct S2495 { short int a; union{ struct{ _Bool d; int e:31; } c; } b; }; struct S2495 x; void foo(struct S2495 a) __attribute__((noinline)); void foo(struct S2495 a) { if (a.a != x.a) abort(); if (a.b.c.d != x.b.c.d) abort(); if (a.b.c.e != x.b.c.e) abort(); } int main() { x.a = 30216; x.b.c.d = 1; x.b.c.e = 32766; foo(x); return 0; }
Disassembly with the first two checks removed (only the third aborts): foo: .LFB2: subq $24, %rsp #, .LCFI0: movl x+8(%rip), %eax #, tmp62 movl 16(%rsp), %edx #, tmp60 movq %rdi, 8(%rsp) # a, a andl $2147483647, %eax #, tmp62 andl $2147483647, %edx #, tmp60 cmpl %eax, %edx # tmp62, tmp60 jne .L6 #, addq $24, %rsp #, ret .L6: call abort # main: .LFB3: subq $8, %rsp #, .LCFI1: movl x+8(%rip), %eax #, tmp62 movw $30216, x(%rip) #, x.a movb $1, x+4(%rip) #, x.b.c.d movq x(%rip), %rdi # x, x andl $-2147483648, %eax #, tmp62 orl $32766, %eax #, tmp62 movl %eax, x+8(%rip) # tmp62, call foo # xorl %eax, %eax # <result> addq $8, %rsp #, ret it looks like we are confused on where we passed the structure by value. It's in %rdi and %eax, while we think it got passed on stack(!?) in foo. Someone with more x86_64 ABI knowledge has to look into this.
Something is fishy. Iff registers are used for passing then it would have to be %rdi and %rsi (not %rax)! So the high part of this struct (where the bitfield lies) is not passed at all here. Per ABI this whole struct should be passed in registers (it's not larger than two eightbytes, and both eightbytes have class INTEGER (they contain no unaligned fields or other fancy stuff)).
More reduced/simplified: void abort(void); struct S2495 { int a; struct{ int d; int e:31; } c; }; struct S2495 x; void foo(struct S2495 a) __attribute__((noinline)); void foo(struct S2495 a) { if (a.c.e != x.c.e) abort(); } int main() { x.c.e = 32766; foo(x); return 0; }
3.2.3 also gets this wrong the same way. The callee side says the struct comes on the stack. The caller side says the struct goes in via %rdi. Which one is correct?
Here is the rtl which is produced by expanding foo(x): (insn 15 13 16 (set (reg/f:DI 63) (symbol_ref:DI ("x") <var_decl 0x2aaaab15eb00 x>)) -1 (nil) (nil)) (insn 16 15 17 (set (reg:DI 62) (mem/s/c:DI (reg/f:DI 63) [4 x+0 S8 A32])) -1 (nil) (nil)) (insn 17 16 18 (set (reg:DI 5 di) (reg:DI 62)) -1 (nil) (nil)) (call_insn 18 17 0 (call (mem:QI (symbol_ref:DI ("foo") [flags 0x3] <function_decl 0x2aaaab15fb00 foo>) [0 S1 A8]) (const_int 0 [0x0])) -1 (nil) (expr_list:REG_EH_REGION (const_int 0 [0x0]) (nil)) (expr_list:REG_DEP_TRUE (use (reg:DI 5 di)) (nil))) Obviously this is wrong as it only passes one half of the struct.
Testing patch: 2005-12-02 Jan Hubicka <jh@suse.cz> PR target/24969 * i386.c (classify_argument): Properly adjust offset of bitfield for substructures. Index: config/i386/i386.c =================================================================== *** config/i386/i386.c (revision 107909) --- config/i386/i386.c (working copy) *************** classify_argument (enum machine_mode mod *** 2652,2659 **** misaligned integers. */ if (DECL_BIT_FIELD (field)) { ! for (i = int_bit_position (field) / 8 / 8; ! i < (int_bit_position (field) + tree_low_cst (DECL_SIZE (field), 0) + 63) / 8 / 8; i++) classes[i] = --- 2652,2659 ---- misaligned integers. */ if (DECL_BIT_FIELD (field)) { ! for (i = (int_bit_position (field) + (bit_offset % 64)) / 8 / 8; ! i < ((int_bit_position (field) + (bit_offset % 64)) + tree_low_cst (DECL_SIZE (field), 0) + 63) / 8 / 8; i++) classes[i] =
Honza, how went the patch testing?
Subject: Bug 24969 Author: hubicka Date: Thu Dec 15 12:49:10 2005 New Revision: 108573 URL: http://gcc.gnu.org/viewcvs?root=gcc&view=rev&rev=108573 Log: PR target/24969 * i386.c (classify_argument): Properly adjust offset of bitfield for substructures. Modified: trunk/gcc/ChangeLog trunk/gcc/config/i386/i386.c
Subject: Bug 24969 Author: hubicka Date: Thu Dec 15 13:48:22 2005 New Revision: 108577 URL: http://gcc.gnu.org/viewcvs?root=gcc&view=rev&rev=108577 Log: PR target/24969 * i386.c (classify_argument): Properly adjust offset of bitfield for substructures. Modified: branches/gcc-4_1-branch/gcc/ChangeLog branches/gcc-4_1-branch/gcc/config/i386/i386.c
Fixed.
Subject: Bug 24969 Author: hubicka Date: Thu Dec 15 19:04:04 2005 New Revision: 108592 URL: http://gcc.gnu.org/viewcvs?root=gcc&view=rev&rev=108592 Log: PR target/24969 * i386.c (classify_argument): Properly adjust offset of bitfield for substructures. Modified: branches/gcc-4_0-branch/gcc/ChangeLog branches/gcc-4_0-branch/gcc/config/i386/i386.c