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

时间:2017-01-08 00:35:53

标签: haskell ghc ffi

这是我之前的问题here的后续内容。我已经能够按Reid Barton's answer获得一些工作,但我注意到核心中__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)

我认为你对'安全"的期望是什么? ffi电话。然而,添加"不安全"不允许使用外部导入字符串(尽管错误消息并不能说明原因):

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. 相同
  3. 为什么似乎不支持foreign import prim unsafe
  4. 假设我理解(1):无论如何我能解决这个问题,既可以有效地返回多个值,又可以避免在(1)中发生任何簿记?
  5. 编辑:查看来自-ddump-asm的程序集,清楚地表明没有发生任何事情(不应该害怕看到程序集),支持Reid Barton&#39的评论如下:

    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对应于haskell xor。所有那些movq确实似乎是一个无赖......但

1 个答案:

答案 0 :(得分:3)

正如Reid Barton所指出的,__pkg_ccall_GC并没有表明任何事情。生成的代码不会执行您在safe FFI调用中看到的簿记。