[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
bug#13342: [PARTIALLY SOLVED] bug#13342: Errors trying to build Guile 2.
From: |
Mark H Weaver |
Subject: |
bug#13342: [PARTIALLY SOLVED] bug#13342: Errors trying to build Guile 2.0.7 |
Date: |
Sun, 27 Jan 2013 20:46:22 -0500 |
User-agent: |
Gnus/5.13 (Gnus v5.13) Emacs/24.2 (gnu/linux) |
Hi Ludovic,
Thanks for looking into this! I think I understand the problem now.
address@hidden (Ludovic Courtès) writes:
> Consider this example:
>
> #include <stdint.h>
>
> int64_t
> test_sum (int8_t a, int64_t b)
> {
> return a + b;
> }
>
> When compiled with GCC 4.6, the assembly is:
>
> test_sum:
> .LFB0:
> .cfi_startproc
> movsbq %dil, %rdi
> leaq (%rdi,%rsi), %rax
> ret
> .cfi_endproc
>
> With Clang 3.1, it is:
>
> test_sum: # @test_sum
> .cfi_startproc
> # BB#0:
> movslq %edi, %rax
> addq %rsi, %rax
> ret
>
> The ‘movsbq’ emitted by GCC arranges to keep only the 8 LSBs. Clang
> does no such thing, thus keeping all the bits of the first operand in
> the addition.
This is the key revelation, although I've reached a different conclusion
about where the bug is.
> I looked at Section 3.2.3 (“Parameter Passing”) of the SysV ABI x86_64
> PS but couldn’t find any evidence as to what the correct behavior is.
I read the same section, and although it is not as clear as I'd prefer,
my interpretation is that the caller is responsible for sign-extending
signed chars to ints. This is also consistent with something I vaguely
remember reading in K&R long ago, namely that 'char' and 'short'
arguments are coerced to 'int' before making a function call.
Clang strictly requires callers to sign-extend, whereas GCC is tolerant
of callers who fail to do so. IMO, both behaviors are permitted by the
ABI.
The problem is that libffi does *not* sign-extend arguments passed in
registers when making calls, which is IMO a bug that has gone (mostly)
unnoticed because of the tolerance and ubiquity of GCC.
> However, on the caller side, both compilers emit the same code. This
> program:
>
> #include <stdint.h>
>
> extern int64_t test_sum (int8_t a, int64_t b);
>
> int64_t
> foo (void)
> {
> return test_sum (-1, 123132);
> }
>
> leads to the following assembly with both compilers:
>
> foo: # @foo
> .cfi_startproc
> movl $-1, %edi
> movl $123132, %esi # imm = 0x1E0FC
> jmp test_sum # TAILCALL
>
> (And as we’ve seen, libffi does the same.)
No, libffi does *not* do the same. Take a look at the relevant code:
https://github.com/atgreen/libffi/blob/master/src/x86/ffi64.c#L488
As you can see in lines 487 and 488, arguments passed in registers are
never sign-extended, but rather zero-extended. The register values are
then copied whole in the darwin-specific assembly stub:
https://github.com/atgreen/libffi/blob/master/src/x86/darwin64.S#L61
Interestingly, arguments passed on the stack *are* sign-extended:
https://github.com/atgreen/libffi/blob/master/src/x86/darwin64.S#L120
* * * * *
In summary, I think this is a bug in libffi.
Note that it has already been reported that the libffi testsuite shows
many failures on OS X Lion, and the failures appear to be related to
this precise issue:
http://sourceware.org/ml/libffi-discuss/2012/msg00162.html
The libffi maintainer wrote "I'm going to chalk this up to compiler
bugs", based on his observation that the tests worked properly when
compiled with -O0. I think it's time to raise this issue again on the
libffi-discuss mailing list.
In any case, it's certainly not a bug in Guile. The bug is either in
LLVM/Clang or libffi, depending on how one chooses to interpret the
x86-64 API.
Regards,
Mark
- bug#13342: Errors trying to build Guile 2.0.7, Peter Teeson, 2013/01/02
- bug#13342: Errors trying to build Guile 2.0.7, Ludovic Courtès, 2013/01/03
- Message not available
- bug#13342: Errors trying to build Guile 2.0.7, Peter Teeson, 2013/01/04
- bug#13342: Errors trying to build Guile 2.0.7, Peter Teeson, 2013/01/03
- bug#13342: Errors trying to build Guile 2.0.7, Ludovic Courtès, 2013/01/04
- Message not available
- bug#13342: [PARTIALLY SOLVED] bug#13342: Errors trying to build Guile 2.0.7, Peter Teeson, 2013/01/08
- bug#13342: [PARTIALLY SOLVED] bug#13342: Errors trying to build Guile 2.0.7, Ludovic Courtès, 2013/01/27
- bug#13342: [PARTIALLY SOLVED] bug#13342: Errors trying to build Guile 2.0.7, Peter Teeson, 2013/01/27
- bug#13342: [PARTIALLY SOLVED] bug#13342: Errors trying to build Guile 2.0.7,
Mark H Weaver <=
- bug#13342: [PARTIALLY SOLVED] bug#13342: Errors trying to build Guile 2.0.7, Peter Teeson, 2013/01/27
- bug#13342: [PARTIALLY SOLVED] bug#13342: Errors trying to build Guile 2.0.7, Ludovic Courtès, 2013/01/28
- bug#13342: [PARTIALLY SOLVED] bug#13342: Errors trying to build Guile 2.0.7, Peter Teeson, 2013/01/28
- bug#13342: [PARTIALLY SOLVED] bug#13342: Errors trying to build Guile 2.0.7, Ludovic Courtès, 2013/01/28
bug#13342: Errors trying to build Guile 2.0.7 [PARTIALLY SOLVED], Peter Teeson, 2013/01/08
bug#13342: Errors trying to build Guile 2.0.7, Mark H Weaver, 2013/01/30
bug#13342: closed (Re: bug#13342: Errors trying to build Guile 2.0.7) , bug#13386: closed (Re: bug#13342: Errors trying to build Guile 2.0.7), Peter Teeson, 2013/01/30