On 15-Apr-2004, Sven Panne <[EMAIL PROTECTED]> wrote:
> Fergus Henderson wrote:
> >I'd rather fix GHC so that interfacing with C macros works with ghc -fasm.
> >The equivalent works fine with the Mercury implementation ("mmc --target 
> >asm"
> >generates assembler for the Mercury code and C stubs for the FFI glue),
> >so it's clearly possible.
> 
> How does Mercury handle something like the "broken" macros we discussed 
> recently in its different back-ends?

The macros, of course, are not broken; it the handling of them by Hugs/GHC
and/or the Haskell FFI that is broken :)

In Mercury, it would look like this:

        :- module ffi_example.
        :- interface.
        :- import_module io.
        :- type window.
        :- pred wstandend(window::in, io::di, io::uo) is det.

        :- implementation.
        :- pragma foreign_decl("C", "#include <curses.h>").
        :- pragma foreign_type("C", window, "WINDOW *").
        :- pragma import(wstandend(in,di,uo), [will_not_call_mercury],
                "wstandend").

When using the "--target asm" option, which tells the Mercury compiler to
compile directly to assembler, the Mercury compiler will generate some
C glue code to handle the FFI interfacing pragmas.  The glue code calls
the wstandend() macro with a variable of type "WINDOW *" as its argument:

        #include "mercury.h"
        #include <curses.h>

        void ffi_example__wstandend_3_p_0(void *ffi_example__Arg1_1) {
        {
                WINDOW * Arg1;

                MR_MAYBE_UNBOX_FOREIGN_TYPE(WINDOW *, ffi_example__Arg1_1,
                        Arg1);
                wstandend(Arg1);
        }

The macro MR_MAYBE_UNBOX_FOREIGN_TYPE converts from "void *" to "WINDOW *".
If sizeof(void *) == sizeof(WINDOW *), as is the case on most
architectures, the macro will end up just doing an assignment;
but if the C type is one that doesn't fit in a void *, it will get boxed
when passed from C to Mercury and unboxed when passed from Mercury to C.

This generated C glue code will be compiled with a C compiler.

Then for any Mercury code which calls the "wstandend" Mercury procedure,
we will generate assembler code which calls the C function in our generated
glue code.

For example, if you have

        :- pred foo(window::in, io::di, io::uo) is det.
        foo(W) --> wstandend(W).

then the Mercury compiler will generate the following assembly code:
        
        .globl ffi_example__foo_3_p_0
                .type   ffi_example__foo_3_p_0,@function
        ffi_example__foo_3_p_0:
                jmp     ffi_example__wstandend_3_p_0
        .Lfe5:
                .size   ffi_example__foo_3_p_0,.Lfe5-ffi_example__foo_3_p_0

-- 
Fergus J. Henderson                 |  "I have always known that the pursuit
Galois Connections, Inc.            |  of excellence is a lethal habit"
Phone: +1 503 626 6616              |     -- the last words of T. S. Garp.
_______________________________________________
FFI mailing list
[EMAIL PROTECTED]
http://www.haskell.org/mailman/listinfo/ffi

Reply via email to