[GHC] #8281: The impossible happened: primRepToFFIType

GHC ghc-devs at haskell.org
Wed Oct 23 14:01:20 UTC 2013


#8281: The impossible happened: primRepToFFIType
---------------------------------------+-----------------------------------
        Reporter:  tibbe               |            Owner:
            Type:  bug                 |           Status:  new
        Priority:  normal              |        Milestone:
       Component:  Compiler            |          Version:  7.6.2
      Resolution:                      |         Keywords:
Operating System:  Unknown/Multiple    |     Architecture:
 Type of failure:  Compile-time crash  |  Unknown/Multiple
       Test Case:                      |       Difficulty:  Unknown
        Blocking:                      |       Blocked By:
                                       |  Related Tickets:
---------------------------------------+-----------------------------------

Comment (by simonpj):

 Summary: I think we have a plan but there are niggly details.  Help needed
 from Simon M.

 Replying to [comment:3 simonmar]:
 > We used to use `UnliftedFFITypes` quite a lot in the IO library in the
 base package, but I just looked and we use it very little now (only for
 `ThreadId#`).  It does have a brief entry in the flags reference in the
 user's guide, but no proper documentation.  As far as I recall we didn't
 intend it to be an advertised feature, so I'm not sure why it appears in
 the docs at all.

 I don't mind it being advertised as dangerous, but whoever ''is'' using it
 needs to know what the spec it.  If the spec isn't in the user manual it
 should be on the wiki.  But in the user manual is better (more findable,
 more robust), surrounded with caveats perhaps.

 Ditto `foreign import prim`.  This does have a
 [http://www.haskell.org/ghc/docs/latest/html/users_guide/ffi.html#ffi-prim
 user manual entry (8.1.3)], but it refers to an unspecified place in the
 wiki.  I believe that the intended documentation is
 [http://ghc.haskell.org/trac/ghc/wiki/Commentary/PrimOps here], but again
 I'd prefer the docs to be in the user manual; then it stays with that
 particular version of the compiler.

 > What I would like to do is get rid of `UnliftedFFITypes` and use
 `foreign import prim` instead.  The example above is a good use for
 `foreign import prim`, and indeed we should change `GHC.Conc.Sync` to do
 it that way (where the example above was copy/pasted from, incidentally).

 Why is `foreign import prim` better?  The documentation (such as it is)
 says nothing about how things are marshaled, or what types are legal.
 Perhaps all types are legal and are passed without any sort of conversion
 or marshaling.  (Eg a `MutableByteArray#` would be passed as a pointer to
 the array object, not a pointer to the data payload of the object, as
 happens with `foreign import unsafe`.

 Is `foreign import prim` by-construction unsafe?  That is, it does not
 generate any save/restore for STG registers etc, and the Cmm code should
 never block or cause GC.  It's just a "fat machine instruction".  Is that
 right? What if you say `foreign import prim safe`?

 Presumably to make `GHC.Conc.Sync` use `foreign import prim` we'd need to
 call a function (with a different name) defined in some `.cmm` file, not
 `rts_getThreadId` defined in `Threads.c`?



 >
 > But there are some places where `UnliftedFFITypes` is really useful,
 e.g.:
 >
 > {{{
 > foreign import ccall unsafe "memcpy"
 >     memcpy_freeze :: MutableByteArray# s -> MutableByteArray# s -> CSize
 >            -> IO (Ptr a)
 > }}}
 >
 > from the `array` package.  To do this with `foreign import prim` would
 mean another function call.

 Not only that, but presumably it is also sometimes convenient to pass an
 `Int#` because that is what is in your hand, rather than box it up only
 for the FFI to unbox it?

 And it's fine to use `Int#` as an argument to a safe foreign call.  But
 this is plain wrong:
 {{{
 foreign import ccall safe f :: ByteArray# -> IO Int
 }}}
 It should only work for unsafe. Or are you suggesting that it should be
 accepted, but may fail badly at runtime if the `ByteArray#` is not pinned,
 which is not statically checkable?


 You propose:

 >  - disallow passing boxed-but-unlifted types to safe foreign calls,
 except for arrays.  This error would also trigger in GHCi for an unsafe
 call, because GHCi compiles unsafe calls as safe calls.  Hence the above
 code would be rejected by GHCi, but accepted by GHC.

 Alternatives:
  * Disallow passing boxed-but-unlifted types to safe foreign calls
 altogether.  If you want to do that, use `foreign import prim` (which is
 by-construction unsafe).
  * Disallow passing boxed-but-unlifted types to safe foreign calls, except
 for arrays (on the grounds that arrays may be pinned).

 You suggest the latter, but I'd prefer the former, because it's more
 clear-cut.   Moreover the above only covers safe foreign calls.  I think
 the rules for `unsafe` foreign calls should be the same as `foreign import
 prim`.  Do you agree?


 >  - document `UnliftedFFITypes`, and explain the pitfalls: not fully
 supported by GHCi, and be careful passing arrays to `safe` calls (they
 must be pinned).

 Yes.  And document `foreign import prim` better.

 Plus
  - Use `foreign import prim` for `rts_getThreadId` in `GHC.Conc.Sync`

 I'd really like to get this squared away.  Simon M: it might be quicker
 for you to just do this than to explain to me how to do it.  Or perhaps
 you can answer all my stupid questions and someone else can do it.

 Thanks

 Simon

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


More information about the ghc-tickets mailing list