为什么没有'foreign import prim unsafe'?

Why is there no 'foreign import prim unsafe'?

这是我之前的问题 . I've been able to get something working per 的后续问题,但我注意到在核心中我看到 __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)

我认为这是您对 "safe" 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# #)

我的国外程序只是一点点,但有点麻烦,所以我不认为我想要 _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

我还在 GHC 树中看到了一些 foreign import prim unsafe... safe,尽管我认为它们是死代码。例如testsuite/tests/printer/Ppr046.hs.

所以我的问题是:

  1. 在这种情况下,从 __pkg_ccall_GC 生成的代码与从 __pkg_ccall 生成的代码有什么区别(我做的是 foreign import prim 而不是 ccall)?和描述的一样吗here?
  2. 为什么 foreign import prim unsafe 似乎不受支持?
  3. 假设我理解 (1):无论如何我都可以解决这个问题,同时获得多个值的高效 return 并避免 (1) 中发生的任何簿记?

编辑:从 -ddump-asm 查看程序集清楚地表明没有发生任何事情(不应该害怕查看程序集),支持 Reid Barton 的评论如下:

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

往上的xorq对应一个haskellxor。不过,所有这些 movq 似乎确实令人失望...

正如 Reid Barton 指出的那样,__pkg_ccall_GC 没有任何意义。生成的代码不会执行您在 safe FFI 调用中看到的簿记。