On Fri, Apr 06, 2012 at 12:31:14PM +0200, Joachim Breitner wrote: > Hi, > > Am Donnerstag, den 05.04.2012, 22:18 +0200 schrieb Iustin Pop: > > On Wed, Apr 04, 2012 at 08:15:31PM +0200, Joachim Breitner wrote: > > > Hi, > > > > > > am I understanding the problem correctly: If one calls a variadic C > > > function with libffi, one should use ffi_prep_cif_variadic() instead of > > > ffi_prep_cif(), otherwise bad things may happen. Whether the function is > > > variadic or not might not be known when looking at the source that calls > > > ffi_prep_cif(), e.g. in the implementation of the Haskell Foreign > > > Function Interface. > > > > > > In GHC itself, ffi_prep_cif is called > > > * in ./rts/Adjustor.c when provding Haskell code to C calls; as Haskell > > > functions are never variadic, this is not a problem. > > > * in ./compiler/ghci/LibFFI.hsc in the Haskell function > > > prepForeignCall, called by generateCCall > > > in ./compiler/ghci/ByteCodeGen.lhs. It seems that this is only relevant > > > for ghci. > > > > [-other lists] > > > > Hmm. If ffi_prep_cif is not called by regular (compiled) Haskell code, > > how is such code calling foreign functions? Reading ffi(3), it seems > > that if using ffi_call, one needs to prepare the call either this or > > ffi_prep_cif_variadic, and no way around it. > > > > Apologies if this is obvious to everyone else :) > > Unfortunately, I am not sure. When generating code for a FFI call > ("sin"), the assembly looks like this: > > addq $8,%rsp > movsd 64(%rsp),%xmm0 > subq $8,%rsp > movq %rax,80(%rsp) > movl $1,%eax > call sin > addq $8,%rsp > movq 72(%rsp),%rax > movq %rax,%rdi > subq $8,%rsp > movl $0,%eax > movsd %xmm0,88(%rsp) Argh, assembler, my eyes! :) > so somewhere before, GHC knew the calling convention. I assume it is > just baked in (and hence most likely does not support variadic > arguments). Is it GHC itself, or libffi? If it's hardcoded in GHC, why do binaries use libffi.so? I would look at an ltrace here, would be a bit more helpful. Compiling the example from http://www.haskell.org/haskellwiki/FFI_Introduction, we have: $ ldd ./example … libffi.so.5 => /usr/lib/x86_64-linux-gnu/libffi.so.5 … so for some reason this is needed at runtime. $ ltrace ./example 2>&1 | grep ffi (nothing) I also tried to override the ffi calls via another library: #include <stdio.h> #include <ffi.h> void ffi_call(ffi_cif *cif, void (*fn)(void), void *rvalue, void **avalue) { printf("Hello ffi_call!\n"); } ffi_status ffi_prep_cif(ffi_cif *cif, ffi_abi abi, unsigned int nargs, ffi_type *rtype, ffi_type **atypes) { printf("Hello ffi_prep!\n"); } ffi_type ffi_type_double; ffi_type ffi_type_float; ffi_type ffi_type_pointer; ffi_type ffi_type_sint16; ffi_type ffi_type_sint32; ffi_type ffi_type_sint64; ffi_type ffi_type_sint8; ffi_type ffi_type_uint16; ffi_type ffi_type_uint32; ffi_type ffi_type_uint64; ffi_type ffi_type_uint8; ffi_type ffi_type_void; Compiled this as libffi.so.5, and: $ ldd ./example … libffi.so.5 => ./libffi.so.5 (0x00007f91a38e8000) … (so it uses our own "stub" libffi) and still: $ ./example works correctly. So at this step it does indeed looks like GHC hardcodes the calling convention, and doesn't use libffi itself; I wonder though if it's used for other, more complex foreign imports. > On arm, without the native code generator, GHC generates llvm code: > > %ln1aM = load double* %lc18u > %ln1aN = call ccc double (double)* @sin( double %ln1aM ) nounwind > > so here, LLVM has to know about the calling convention, so not our > problem. Makes sense, yes. thanks! iustin
Attachment:
signature.asc
Description: Digital signature