为什么没有"外国进口不安全"?

jbe*_*man 10 haskell ffi ghc

这是一个后续我先前的问题在这里.我已经能够根据里德巴顿的答案得到一些工作,但我注意到核心我看到了__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)
Run Code Online (Sandbox Code Playgroud)

我认为你对"安全"ffi电话的期望是什么.然而,不允许在外部导入字符串中添加"unsafe"(尽管错误消息没有说明原因):

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# #)
Run Code Online (Sandbox Code Playgroud)

我的外国程序只是一点点,但有点笨拙,所以我不认为我想要的_GC是什么.我看过GHC源的一些相关内容,FWIW和背景:

compiler/prelude/ForeignCall.hs:只有"Risky"省略了"_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
Run Code Online (Sandbox Code Playgroud)

我也看到了一些foreign import prim unsafe... safe在GHC树,但我想这是死代码.例如testsuite/tests/printer/Ppr046.hs.

所以我的问题是:

  1. 是什么从生成的代码之间的差异__pkg_ccall_GCVS一个__pkg_ccall(在那里我做在这种情况下foreign import prim没有ccall)?它和这里描述的相同吗?
  2. 为什么似乎不foreign import prim unsafe支持?
  3. 假设我理解(1):无论如何我能解决这个问题,既可以有效地返回多个值,又可以避免在(1)中发生任何簿记?

编辑:从集会看,-ddump-asm明确没有什么事情发生(不应该害怕看到集会),支持雷德巴顿的评论如下:

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
Run Code Online (Sandbox Code Playgroud)

xorq接近顶部对应于一个Haskell xor.所有这些movq看起来似乎都是一个无赖......

jbe*_*man 3

正如里德·巴顿(Reid Barton)指出的那样,这__pkg_ccall_GC并不表明任何事情。生成的代码不会执行您在safeFFI 调用中看到的簿记操作。