[jhc] foreign import "wrapper"

John Meacham john at repetae.net
Mon Jul 16 17:37:34 EDT 2007

On Sun, Jul 15, 2007 at 01:01:58PM -0400, Samuel Bronson wrote:
> On IRC, you (JohnMeacham) (what -- there is someone else who reads
> this list?) said something about region inference and foreign import
> "wrapper". It just occured to me earlier today that you probably can't
> do much of that at all. You can basically do as much as you can do for
> a StablePtr. I remind you that the C functions made by a wrapper stub
> can be passed to C code and held there indefinately, just like a
> StablePtr, and can only be deallocated when the Haskell program calls
> freeHaskellFunPtr on them.

Yes, the region inference algorithm would have to do an 'escape
analysis' to deterime which references escape the current frame.
luckily, this is already inherent to the analysis, data stored in
stableptrs or foreign wrapper imports will be noticed at this point.

> We also talked about how a nice way to implement these wrapper stubs,
> by generating tiny thunks that would redirect calls to an evaluation
> routine after adding the closure to be called as an additional
> argument. (Actually, I suppose the evaluation routine would need a
> wrapper, like a foreign export does...). What I'm not sure about is
> how to refer to the address of the (wrapper around the) evaluation
> routine in the code for the "wrapper stub" (the function that is
> actually declared by the 'foreign import "wrapper"' declaration).

here is what I am thinking

foreign import wrapper mkFoo :: (Int -> Int) -> IO (FunPtr (Int -> Int))

will create the following:

> -- this just translates a haskell function into an unboxed version.
> -- nothing tricky here.
> unboxMkFoo :: (Int -> Int) -> (Int__ -> Int__)
> unboxMkFoo fn = \x -> unbox (fn (box x))
> -- psuedo-import of real C function, note we take a function as
> -- an argument, which is not legal haskell, but is fine, we will
> -- just expect the C function to take a pointer to a haskell heap
> -- object.
> foreign import ccall c_mkFoo :: (Int__ -> Int__) -> IO Addr__
> -- this is the final user visible mkFoo function
> mkFoo fn =  c_mkFoo (unboxMkFoo fn)
> -- and generate a c_mkFoo as follows
> HsFunPtr c_mkFoo(node_t *n) {
>         char *code = asm ("push n; call apply_int_int");
>         return (HsFunPtr)code;
> } 

I hope this is clear, I used some constructs in ways that arn't legal
haskell, but are expressible in core and grin so the meaning should be
clear. you should call the appropriate 'apply' routine, but these are
already generated, if you need to use a special calling convention (like
passing the node in a register) then another stub might be needed rather
than calling apply directly.


John Meacham - ⑆repetae.net⑆john⑈

More information about the jhc mailing list