[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