Why is there no 'foreign import prim unsafe'?

风流意气都作罢 提交于 2019-12-12 10:36:27

问题


This is a followup to my earlier question here. I've been able to get something working per Reid Barton's answer, but I notice in the core I see __pkg_ccall_GC:

              case {__pkg_ccall_GC hashabler-2.0.0 sipRound_s_x2 Word#
                                          -> Word#
                                          -> Word#
                                          -> Word#
                                          -> (# Word#, Word#, Word#, Word# #)}
                     ww1 ww2 ww3 (xor# ww4 b1)

Which is I think what you'd expect for a "safe" ffi call. Yet adding "unsafe" to the foreign import string is not allowed (though the error messages doesn't say why):

src/Data/Hashabler/SipHash.hs:60:1: error:
    • The safe/unsafe annotation should not be used with `foreign import prim'.
    • When checking declaration:
        foreign import prim unsafe "static sipRound_s_x4" sipRound_s_x4#
          :: Word#
             -> Word# -> Word# -> Word# -> (# Word#, Word#, Word#, Word# #)

My foreign procedure is just a little but of bit-twiddling, so I don't think I want whatever the _GC is giving me. Some relevant bits of GHC source I've looked at, FWIW and background:

compiler/prelude/ForeignCall.hs: only "Risky" omits the "_GC"

data Safety
  = PlaySafe            -- Might invoke Haskell GC, or do a call back, or
                        -- switch threads, etc.  So make sure things are
                        -- tidy before the call. Additionally, in the threaded
                        -- RTS we arrange for the external call to be executed
                        -- by a separate OS thread, i.e., _concurrently_ to the
                        -- execution of other Haskell threads.

  | PlayInterruptible   -- Like PlaySafe, but additionally
                        -- the worker thread running this foreign call may
                        -- be unceremoniously killed, so it must be scheduled
                        -- on an unbound thread.

  | PlayRisky           -- None of the above can happen; the call will return
                        -- without interacting with the runtime system at all
  deriving ( Eq, Show, Data )
        -- Show used just for Show Lex.Token, I think

I also see some foreign import prim unsafe and ... safe in the GHC tree, though I suppose it's dead code. e.g. testsuite/tests/printer/Ppr046.hs.

So my questions are:

  1. What is the difference between code generated from a __pkg_ccall_GC vs a __pkg_ccall in this case (where I'm doing foreign import prim not ccall)? Is it the same as described here?
  2. Why doesn't a foreign import prim unsafe seem to be supported?
  3. Assuming I understand (1): Is there anyway I can work around this, getting both efficient return of multiple values and avoiding whatever bookkeeping is happening in (1)?

EDIT: Looking at the assembly from -ddump-asm makes it clear nothing much is happening (shouldn't have been scared to look at the assembly), support Reid Barton's comment below:

movq %rdi,%rax
movq %r8,%rdi 
xorq %r9,%rdi
movq %rsi,%rcx
movq %rax,%rsi
movq %r14,%rax
movq %rcx,%r14
movq %rbx,%rcx
movq %rax,%rbx
movq %r9,-8(%rbp)
movq %rcx,(%rbp)
addq $-16,%rbp
jmp sipRound_s_x2

The xorq towards the top corresponds to a haskell xor. All those movq do seem to be a bummer though...


回答1:


As Reid Barton points out the __pkg_ccall_GC doesn't indicate anything. The code generated doesn't do the bookkeeping you would see in a safe FFI call.



来源:https://stackoverflow.com/questions/41528208/why-is-there-no-foreign-import-prim-unsafe

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!