x86-64 psABI says: --- When a value of type _Bool is passed in a register or on the stack, the upper 63 bits of the eightbyte shall be zero. --- However, gcc generates: [hjl@gnu-6 tmp]$ cat b.c _Bool myfunction(char val) { return val; } [hjl@gnu-6 tmp]$ gcc -O2 -S b.c [hjl@gnu-6 tmp]$ cat b.s .file "b.c" .text .p2align 4,,15 .globl myfunction .type myfunction, @function myfunction: .LFB0: .cfi_startproc testb %dil, %dil setne %al ret .cfi_endproc .LFE0: .size myfunction, .-myfunction Icc generates: movsbq %dil, %rax #3.10 movl $1, %edx #3.10 testl %eax, %eax #3.10 cmovne %edx, %eax #3.10 ret #3.10
For what it's worth, gcc 3.4.6 generates a clear on the output register, and therefore complies with the written ABI.
(In reply to comment #1) > For what it's worth, gcc 3.4.6 generates a clear on the output register, and > therefore complies with the written ABI. > That is true. However, gcc 3.4.6 does: [hjl@gnu-26 pr42324]$ cat b1.c _Bool myfunction(char val); int foo (char v) { return myfunction (v); } [hjl@gnu-26 pr42324]$ gcc -O2 -S b1.c [hjl@gnu-26 pr42324]$ cat b1.s .file "b1.c" .text .p2align 4,,15 .globl foo .type foo, @function foo: .LFB2: subq $8, %rsp .LCFI0: movsbl %dil,%edi call myfunction addq $8, %rsp movzbl %al, %eax ret It assumes that _Bool is returned in AL. Gcc 3.4.6 generates: [hjl@gnu-26 pr42324]$ cat b2.c void foo (char, char, char, char, char, char, char, _Bool); void myfunction(char val) { foo (val, val, val, val, val, val, val, val); } [hjl@gnu-26 pr42324]$ gcc -O2 -S b2.c [hjl@gnu-26 pr42324]$ cat b2.s .file "b2.c" .text .p2align 4,,15 .globl myfunction .type myfunction, @function myfunction: .LFB2: movsbl %dil,%r10d subq $24, %rsp .LCFI0: xorl %eax, %eax testb %dil, %dil movl %r10d, %r9d movl %r10d, %r8d setne %al movl %r10d, %ecx movl %r10d, %edx movl %r10d, %esi movl %r10d, %edi movl %eax, 8(%rsp) movl %r10d, (%rsp) call foo addq $24, %rsp ret The upper 32bits of _Bool on stack aren't zeroed.
Gcc 4.1/4.2 generate: xorl %eax, %eax testb %dil, %dil setne %al ret
We have 3 options: 1. Keep the psABI ASIS and fix gcc. But zero out upper 32bits of 64bits for _Bool on stack doesn't make any sense. 2. Remove that paragraph in the psABI and keep gcc ASIS. It will make _Bool consistent independent of if it is used for function parameters. Both gcc and icc always treat _Bool as char even if it is returned from a function. It may break compatibilities among x86-64 compilers. But we have such problems anyway for gcc 4.3 and 4.4. 3. Changes the psABI to zero out 1-31bits. When _Bool is returned from function, upper 63bits will be zeroed out due to x86-64 architecture. But on stack, we only need to zero out 1-31bits. Even if we do this, we still can't treat _Bool as long long when returned from a function since it will break with object files compiled with gcc 4.3/4.4.
The ABI says "is passed", not "is returned". The frontend did return-value promotion until I disabled that (see endless discussions and libffi fixes at that point). So where is a _Bool passed in a registed or on the stack in your testcases? I see the _Bool on stack is properly extended to 32bits. That the ABI requires 64bits here for _Bool seems odd - does it require that for char and int, too? There is an invalid dup for the return value promotion btw.
(In reply to comment #5) > The ABI says "is passed", not "is returned". The frontend did return-value > promotion until I disabled that (see endless discussions and libffi fixes > at that point). > > So where is a _Bool passed in a registed or on the stack in your testcases? Please see b2.c in comment #2. > I see the _Bool on stack is properly extended to 32bits. That the ABI > requires 64bits here for _Bool seems odd - does it require that for > char and int, too? > That is very odd. I think the psABI should be changed to --- When a value of type _Bool is passed in a registeror on the stack, the bits1-31 of the eightbyte shall be zero. --- and leave the upper 32bits undefined.
Another testcase: [hjl@gnu-26 pr42324]$ cat b3.c void foo (unsigned long, unsigned int, unsigned long, unsigned int, unsigned int, unsigned int, unsigned int, unsigned long, unsigned int); void bar (_Bool v1, _Bool v2, unsigned char v3, unsigned char v4, unsigned char v5, unsigned char v6, unsigned char v7, _Bool v8) { foo (v1, v2, v3, v4, v5, v6, v7, v8, v8); } [hjl@gnu-26 pr42324]$ /usr/gcc-4.4/bin/gcc -O2 b3.c -S [hjl@gnu-26 pr42324]$ cat b3.s .file "b3.c" .text .p2align 4,,15 .globl bar .type bar, @function bar: .LFB2: subq $24, %rsp .LCFI0: movzbl %cl, %ecx movzbl %dl, %edx movzbl 40(%rsp), %r10d movzbl %sil, %esi movzbl %dil, %edi movzbl %r9b, %r9d movzbl %r8b, %r8d movzbl %r10b, %eax movq %r10, 8(%rsp) movl %eax, 16(%rsp) movzbl 32(%rsp), %eax movl %eax, (%rsp) call foo addq $24, %rsp ret icc 11.1 generates: .globl bar bar: # parameter 1: %edi # parameter 2: %esi # parameter 3: %edx # parameter 4: %ecx # parameter 5: %r8d # parameter 6: %r9d # parameter 7: 48 + %rsp # parameter 8: 56 + %rsp ..B1.1: # Preds ..B1.0 ..___tag_value_bar.1: #8.1 subq $40, %rsp #8.1 ..___tag_value_bar.2: # movzbl 48(%rsp), %eax #9.32 movzbl 56(%rsp), %r10d #9.36 movl %eax, (%rsp) #9.32 movzbl %dil, %edi #8.1 movq %r10, 8(%rsp) #9.36 movl %r10d, 16(%rsp) #9.40 movzbl %sil, %esi #9.12 movzbl %dl, %edx #8.1 movzbl %cl, %ecx #9.20 movzbl %r8b, %r8d #9.24 movzbl %r9b, %r9d #9.28 call foo #9.3 # LOE rbx rbp r12 r13 r14 r15 ..B1.2: # Preds ..B1.1 addq $40, %rsp #10.1 ..___tag_value_bar.3: # ret #10.1 So both gcc and icc treat _Bool parameters in register and on stack as 1 byte. I think we should just drop --- When a value of type _Bool is passed in a register or on the stack, the upper 63 bits of the eightbyte shall be zero. --- from psABI since it isn't really followed/used at all.
Both icc and gcc generate: [hjl@gnu-26 pr42324]$ cat b4.c extern unsigned int bartmp; void foo(_Bool bar) { bartmp = bar; } [hjl@gnu-26 pr42324]$ objdump -dw b4.o b4.o: file format elf64-x86-64 Disassembly of section .text: 0000000000000000 <foo>: 0: 40 0f b6 ff movzbl %dil,%edi 4: 89 3d 00 00 00 00 mov %edi,0x0(%rip) # a <foo+0xa> a: c3 retq [hjl@gnu-26 pr42324]$
Created attachment 19268 [details] Source and object files These are sources and object files generated by gcc 4.4, icc 11.1 and Sun Studio 12 Update 1 at -O. The results are 1. All compilers access _Bool as one byte when reading function return and function parameters. 2. icc 11.1 and Sun Studio 12 Update 1 clear bits 1-63 when writing function return and function parameters. 3. Gcc 4.4 clears bits 1-7 when writing function return. 4. Gcc 4.4 clears bits 1-31 when writing function parameters.
This is what I got from Sun: Solaris x86-64 compiler does not support this x86-64 psABI requirement for _Bool : "When a value of type _Bool is passed in a register or on the stack, the upper 63 bits of the eightbyte shall be zero" Solaris x86-64 compiler processes it like char or byte. i.e. When a value of type _Bool is passed in a register or on the stack, the bits1-31 of the eightbyte shall be zero and upper 32bits should be left undefined. Thus current behavior of Sun compiler is that which described by option 2. i.e. following solution looks the best from the point of view of Solaris x86-64 compiler : "2. Remove that paragraph in the psABI and keep gcc ASIS. It will make _Bool consistent independent of if it is used for function parameters. Both gcc and icc always treat _Bool as char even if it is returned from a function. It may break compatibilities among x86-64 compilers. But we have such problems anyway for gcc 4.3 and 4.4. "
Rather makes the choice a no-brainer, doesn't it...
The ABI (http://www.x86-64.org/documentation/abi.pdf) now contains this language: -------------------- When a value of type \code{_Bool} is returned or passed in a register or on the stack, bit 0 contains the truth value and bits 1 to 7 shall be zero. -------------------- Hence, fixed by adjusting the document :)
Subject: Re: Gcc doesn't follow x86-64 psABI on _Bool On Wed, 13 Jan 2010, matz at gcc dot gnu dot org wrote: > The ABI (http://www.x86-64.org/documentation/abi.pdf) now contains this > language: Any chance you could give this ABI meaningful version numbers (i.e., change the version number when changing the document)? There have by now been several different versions all claiming to be version 0.99, with dates varying by more than two years.
Yeah, I started to use micro version numbers, but I can't write to the html file on that webserver, only to the subdirectory containing the PDFs. See http://www.x86-64.org/documentation/ for a listing. The current ABI is abi-0.99.4.pdf. I now encode this also into the document itself.
We have Google groups for gABI and i386 psABI. Should I create an x86-64 psABI group?
We have a mailing list already, I don't think we need another one.