[GHC] #9352: Allow `State# s` argument/result types in `ccall` FFI imports

GHC ghc-devs at haskell.org
Fri Jul 25 10:27:41 UTC 2014


#9352: Allow `State# s` argument/result types in `ccall` FFI imports
-------------------------------------+-------------------------------------
              Reporter:  hvr         |            Owner:
                  Type:  feature     |           Status:  new
  request                            |        Milestone:  7.10.1
              Priority:  normal      |          Version:  7.8.2
             Component:  Compiler    |         Keywords:
  (Type checker)                     |     Architecture:  Unknown/Multiple
            Resolution:              |       Difficulty:  Unknown
      Operating System:              |       Blocked By:
  Unknown/Multiple                   |  Related Tickets:  #9281
       Type of failure:              |
  None/Unknown                       |
             Test Case:              |
              Blocking:              |
Differential Revisions:              |
-------------------------------------+-------------------------------------

Comment (by simonpj):

 Simon M: looking into the code, I'm quite perplexed.  Have a look at:
 DsCCall.boxResult.  It seems the when we say
 {{{
 foreign import foo :: Int -> Int
 }}}
 we actually generate (in effect) an inline use of `unsafePerformIO`.
 Here's the tidy core:
 {{{
 M.foo :: GHC.Types.Int -> GHC.Types.Int
 [GblId, Arity=1, Caf=NoCafRefs, Str=DmdType]
 M.foo =
   \ (ds_d1A2 :: GHC.Types.Int) ->
     case ds_d1A2 of _ [Occ=Dead] { GHC.Types.I# ds2_d1A4 ->
     case {__pkg_ccall main foo Int#
                       -> State# RealWorld -> (# State# RealWorld, Int#
 #)}_d1A7
            ds2_d1A4 GHC.Prim.realWorld#
     of _ [Occ=Dead] { (# ds3_d1A6, ds4_d1A5 #) ->
     GHC.Types.I# ds4_d1A5 } }
 }}}
 Note that we come up with a `realWorld#` out of thin air and then discard
 it again... that's the `unsafePerformIO` stuff.  Then the code generator
 has to painstakingly discard all that state-passing nonsense, to get back
 to a simple C call to "foo".

 Why do we bother with this?  Why not produce this core:
 {{{
 M.foo :: GHC.Types.Int -> GHC.Types.Int
 M.foo =
   \ (ds_d1A2 :: GHC.Types.Int) ->
     case ds_d1A2 of _ [Occ=Dead] { GHC.Types.I# ds2_d1A4 ->
     case {__pkg_ccall main foo Int# -> Int#}_d1A7
            ds2_d1A4
     of ds4_d1A5 [Occ=Dead] { DEFAULT ->
     GHC.Types.I# ds4_d1A5 } }
 }}}
 Simpler, more direct, and should generate exactly the same code.  At the
 moment the built-in `FCallId` Ids always have an IO-ish type, but I see no
 reason to require that.

 If we did this, then I think the distinction between `boxResult` and
 `resultWrapper` could disappear, leading to a simpler, compositional
 structur.

 Moreover, if we want to accommodate
 {{{
 foreign import foo :: Int -> State# s -> (# State# s, Int #)
 }}}
 which doesn't have an IO-ish type (at least not built with the `IO` type
 constructor), it would seem utterly bizarre to enclose it in the
 `unsafePerformIO` boilerplate as above.

 I think Herbert might be able to act on all this, but first let's check
 that I have not forgotten anything stupid.

 Simon

--
Ticket URL: <http://ghc.haskell.org/trac/ghc/ticket/9352#comment:5>
GHC <http://www.haskell.org/ghc/>
The Glasgow Haskell Compiler


More information about the ghc-tickets mailing list