Extension to the FFI to allow macro expansions to be avoided
Fergus Henderson
fjh007 at galois.com
Thu Apr 15 21:14:12 EDT 2004
On 15-Apr-2004, Sven Panne <Sven.Panne at aedion.de> 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, at 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.
More information about the FFI
mailing list