[Date Prev][Date Next] [Thread Prev][Thread Next] [Date Index] [Thread Index]

Re: [Pkg-haskell-maintainers] libffi changes - help needed



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


Reply to: