raw foregin imports - new backend for jhc: ghc

John Meacham john at repetae.net
Tue Nov 14 02:30:43 EST 2006

I am working on a new backend for jhc. haskell! well, ghc haskell to be
exact. jhc can now compile things with the -fvia-ghc flag and it will
pass the optimized program off to ghc for the final compilation.

For the most part I use none of the ghc runtime libraries facilities or
machinery, all IO is handled via jhc's libraries built upon the FFI so I
can ignore ghc's primitives but there are a few cases I am finding a
little tricky.

IO was pretty easy, I just mapped my World__ type to State# RealWorld,
and it all just seems to work. 

but I am still having a couple issues:

I am having trouble with a couple foreign imports that I think
should work:

here is one:

> type World__ = State# RealWorld
> main = IO $ \w -> case  getchar w of
>     (# w', ch #) -> (# w', () #)
> foreign import ccall unsafe getchar :: World__ -> (# World__, Int# #) 

which produces a 

ghc-6.6: panic! (the 'impossible' happened)
  (GHC version 6.6 for i386-unknown-linux):
    (# main:Main.World__{tc rpT}, base:GHC.Base.Int{(w) tc 3J} #)

the other is 

where 'global_argc' is a C symbol.

> foreign import ccall "&global_argc" argc :: Addr#

I can work around the second trivially, but can't figure out a pleasing
way around the first.

the other area that is causing trouble is with the numerical primitives,
where ghc and jhc differ quite widely on what they do, in jhc, you add
new primitives by adding a line to data/primitives.txt like so

> Data.Int.Int8, int8_t, int, INT8_MAX, INT8_MIN
> Data.Int.Int16, int16_t, int, INT16_MAX, INT16_MIN
> ...                                     
> Data.Float.Float128, __float128, float, ....

every numeric haskell type maps directly to a C type, the compiler
treats them as completely opaque otherwise.

The end result being that optimized jhc core has a lot of primitive
types, and to compile via ghc I need to somehow, portably, map them to
ghc primitives, and provide all the peek,poke, etc operations such that
they behave correctly as if the underlying c type were being used

at the moment, I am flattening everything to Int#, which is not very
ideal (but oddly enough, doesn't seem to cause an issue for most
programs I have tried) and would like to find something better. Any idea
what the shortest path might be to getting things to work? 

Is there a way to control the C type used to pass values when
importing foreign functions in an unboxed manner, ghc seems to have a
dearth of primitive integer types, condensing everything down to Int#,
so how do I say 'this Int# is actually a C uint16_t' in a foreign
import? if that makes sense..

in the meantime. I have one hell of a haskell obfcusiator: 

check out this translation of 

> putStrLn "Hello, World!"

-fvia-ghc translation:

standard C translation via Grin:

the main (and only) function's c translation extracted:

> void 
> _amain(void)
> {
>         node_t* v1;
>         node_t* v2;
>         node_t* v3;
>         node_t* v4;
>         node_t* v5;
>         HsChar v6;
>         wchar_t v7;
>         v1 = c24;
>         goto f922;
>         /* [p1] */
>         f922: 0;
>             v2 = v1;
>             if (CJhc__Basics___x3a == v2->any.tag) {
>                 v3 = v2->sCJhc__Basics___x3a.a1;
>                 v4 = v2->sCJhc__Basics___x3a.a2;
>                 v5 = v3;
>                 v6 = v5->sCChar_h.a1;
>                 v7 = ((wchar_t)v6);
>                 (void)putwchar((wchar_t)v7);
>                 v1 = v4;
>                 goto f922;
>             } else {
>                 return (void)putwchar((wchar_t)10);
>             }
> }  


John Meacham - ⑆repetae.net⑆john⑈

More information about the Glasgow-haskell-users mailing list