raw foregin imports - new backend for jhc: ghc

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): resultWrapper (# 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 directly. 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: http://repetae.net/computer/jhc/stuff/HelloWorld_code.hs standard C translation via Grin: http://repetae.net/computer/jhc/stuff/HelloWorld_code.c 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 -- John Meacham - ⑆repetae.net⑆john⑈

John Sorry for slow reply . It's been a busy week. | 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): | resultWrapper | (# main:Main.World__{tc rpT}, base:GHC.Base.Int{(w) tc 3J} #)# The crash is definitely a bug. The user manual does not claim to allow unboxed tuples in the return type for a foreign call; so GHC should reject the program politely. You might ask "well, couldn't the above program be accepted?". Perhaps so... but why do you want it. You should find that if you say foreign import ccall unsafe getchar :: IO Int and then do { I# x <- getchar; ...} then no boxing occurs. So maybe this new feature isn't reqd. Let us know | the other is | | where 'global_argc' is a C symbol. | | > foreign import ccall "&global_argc" argc :: Addr# What's the problem here? Your mail looks garbled. Concerning primitive types, Ian will respond in a few days. We're not sure we understand what you want! Simon

On Fri, Nov 17, 2006 at 05:12:23PM +0000, Simon Peyton-Jones wrote:
The crash is definitely a bug. The user manual does not claim to allow unboxed tuples in the return type for a foreign call; so GHC should reject the program politely.
You might ask "well, couldn't the above program be accepted?". Perhaps so... but why do you want it. You should find that if you say foreign import ccall unsafe getchar :: IO Int and then do { I# x <- getchar; ...} then no boxing occurs. So maybe this new feature isn't reqd. Let us know
okay, I was hoping that ghc would see that I am giving it the unboxed version right out and not try to unbox/rebox things itself. I thought I saw this in the standard libraries, but looking through it again, the cases I was looking at were actually primitives and not foreign imports. so this isn't a bug. I will do the boxing myself, which is fine, it would be nice to run ghc without its optimizer and still not get the superfluous boxing to get a true test of just how our back-ends compare, but for that kind of control perhaps I will need to spit out ghc external core anyway.
| the other is | | where 'global_argc' is a C symbol. | | > foreign import ccall "&global_argc" argc :: Addr#
What's the problem here? Your mail looks garbled.
yes. sorry about that. I started out asking one question, then decided to give some background that led to another one.
Concerning primitive types, Ian will respond in a few days. We're not sure we understand what you want!
At the moment, I don't think I need anything, I was just misreading certain features. the ghc backend seems to be working fine with the following caveats: * all integral types (even Integer) are flattened to Int#. * ghc -O on my generated programs crashes with the following: ghc-6.6: panic! (the 'impossible' happened) (GHC version 6.6 for i386-unknown-linux): primRepHint:VoidRep http://repetae.net/john/computer/jhc/stuff/HelloWorld_code.hs has this behavior when compiled with ghc -O on another note I have gotten these crashes also, but have been unable to recreate them: jhc: internal error: stg_ap_p_ret (GHC version 6.6 for x86_64_unknown_linux) Please report this as a GHC bug: http://www.haskell.org/ghc/reportabug ghc-6.6: panic! (the 'impossible' happened) (GHC version 6.6 for i386-unknown-linux): hptRules FastMutInt [(Atom, False), (Binary, False), (C.FFI, False), (Doc.DocLike, False), (Doc.PPrint, False), (FastMutInt, False), (FrontEnd.SrcLoc, False), (FrontEnd.Tc.Kind, False), (GenUtil, False), (HsSyn, False), (Name.Name, False), (Name.Names, False), (Name.Prim, False), (Name.VConsts, False), (PackedString, False), (Support.CanType, False), (Support.Unparse, False), (Util.VarName, False)] John -- John Meacham - ⑆repetae.net⑆john⑈

Hi John, On Mon, Nov 27, 2006 at 08:26:34PM -0800, John Meacham wrote:
At the moment, I don't think I need anything, I was just misreading certain features. the ghc backend seems to be working fine with the following caveats:
* all integral types (even Integer) are flattened to Int#.
I'm not sure I follow this - if I do foreign import ccall "static foo.h foo" foo :: Integer -> Integer then GHC tells me Unacceptable argument type in foreign declaration: Integer Unacceptable result type in foreign declaration: Integer Can you explain what you are doing that makes Integer get flattened, please?
* ghc -O on my generated programs crashes with the following:
ghc-6.6: panic! (the 'impossible' happened) (GHC version 6.6 for i386-unknown-linux): primRepHint:VoidRep
Another bug, thanks! Again, this isn't something we claim should work, but it should definitely either work or give a nice error message. I've filed it in trac: #1037. Thanks Ian

On Mon, Dec 04, 2006 at 11:55:26AM +0000, Ian Lynagh wrote:
Can you explain what you are doing that makes Integer get flattened, please?
oh, I meant that was a limitation of my backend, not ghc. jhc has primitive types for all possible c types, like uint32_t and uint16_t etc are distinct unboxed types. ghc seems to work mostly by boxing Int# and doing the appropriate bit narrowing in the library. My current solution is just to map all primitive types to Int#. even though it gives incorrect results it seems to work well enough for testing the back end. I am not sure what my long term solution will be, probably to auto-generate some ghc code to simulate all the appropriate primitives the jhc front end expects to exist. John -- John Meacham - ⑆repetae.net⑆john⑈
participants (3)
-
Ian Lynagh
-
John Meacham
-
Simon Peyton-Jones