On 02-Jun-2003, Alastair Reid <[EMAIL PROTECTED]> wrote: > > > The Mercury compiler will generate appropriate glue code to marshal and > > unmarshal values of that type. > > How does it figure out what concrete type to use? Does it use trial > compilations a la autoconf?
No. We don't try to second-guess the C compiler. We just let the C compiler figure it out. The Mercury compiler generates a small amount of glue code in C, and invokes the C compiler on that code. The glue code consists of a wrapper around every foreign function (although if you wanted to optimize things, you might note that this is only really needed for foreign functions whose arguments or result are foreign types). The glue code interface uses only known types such as WORD, so it can be called in a straight-forward manner from the assembly code that the Mercury compiler's assembly-language back-end generates. The glue code for each function calls the function, boxing or unboxing the arguments and/or results if needed, i.e. if they have a foreign type which doesn't fit in a word. This approach of boxing all foreign types has the major advantage that these foreign types can be passed to polymorphically typed Mercury procedures or inserted in polymorphically typed Mercury data structures. Generating a wrapper for every foreign function also means that it is possible to interface to C macros as well as to C functions. In fact, we also allow interfacing with arbitrary C code fragments, not just macros or functions, so you can use this feature to write inline asm, for example. To illustate how the wrappers work, here's what the glue code for a function "foo :: T -> T", where "T" is a foreign type implemented by the C type "CT", could look like: WORD foo_glue(WORD boxed_x) { WORD boxed_y; CT x, y; /* maybe unbox the function's input argument */ x = *(CT *)(sizeof(CT) > sizeof(WORD) ? boxed_x : &boxed_x); /* call the function or macro foo() */ y = foo(x); /* maybe box the function's result */ if (sizeof(CT) > sizeof(WORD)) { boxed_y = (WORD) GC_malloc(sizeof(CT)); *(CT *)boxed_y = y; } else { *(CT *)&boxed_y = y; } return boxed_y; } Note that if compiling to C, such wrappers can be inlined. -- Fergus Henderson <[EMAIL PROTECTED]> | "I have always known that the pursuit The University of Melbourne | of excellence is a lethal habit" WWW: <http://www.cs.mu.oz.au/~fjh> | -- the last words of T. S. Garp. _______________________________________________ FFI mailing list [EMAIL PROTECTED] http://www.haskell.org/mailman/listinfo/ffi