国外进口对LLVM的调用

Cli*_*ton 5 haskell ffi llvm ghc llvm-ir

我正在尝试使用这篇文章中的想法调用一个用LLVM编写的外来导入文章,但我只是继续得到段错误.这就是我目前所拥有的.

在哈斯克尔

{-# LANGUAGE GHCForeignImportPrim #-}
{-# LANGUAGE MagicHash, UnboxedTuples #-}
{-# LANGUAGE ForeignFunctionInterface, UnliftedFFITypes #-}

import GHC.Prim

foreign import prim "primllvm" primllvm :: Word# -> Word# -> (# Word#, Word# #)
Run Code Online (Sandbox Code Playgroud)

并在.ll文件中

define cc10 void @primllvm(i64* %baseReg, i64* %sp, i64* %hp, i64* %buffer, i64 %length, i64 %r3, i64 %r4, i64 %r5, i64 %r6, i64* %spLim, float %f1, float %f2, float %f3, float %f4, double %d1, double %d2)
{
  %fp = bitcast i64* %sp to void(i64*, i64*, i64*, i64*, i64, i64, i64, i64, i64, i64*, float, float, float, float, double, double)*
  tail call cc10 void %fp(i64* %baseReg, i64* %sp, i64* %hp, i64* %buffer, i64 %length, i64 %r3, i64 %r4, i64 %r5, i64 %r6, i64* %spLim, float %f1, float %f2, float %f3, float %f4, double %d1, double %d2) noreturn;
  ret void
}
Run Code Online (Sandbox Code Playgroud)

从理论上讲,我认为这应该只是将它作为一个元组返回,但就像我说的那样,它只是段错误.任何帮助让这项工作受到赞赏.

Cac*_*tus 2

我发现您的代码有两个问题:

  1. 虽然你的签名表明你在 Haskell 端传递了两个Word#参数,但在 LLC 端你有i64* %bufferi64 %length(注意类型%buffer是指针类型!)。

  2. : 中还有一层间接寻址spsp指向堆栈,堆栈顶部是延续指针。您的代码似乎尝试将堆栈指针解释为函数指针本身。

我不知道 LLVM,我只是通过查看您链接的博客文章、了解 GHC 并尝试将其拼凑在一起;所以我最终不得不求助于查看clang的输出,因此可能有一种更有效的方法来处理#2,但无论如何,这里有一个可以工作并实现两个 64 位数字交换的版本:

define cc10 void @primllvm(i64* %baseReg, i64* %sp, i64* %hp,
                           i64 %x, i64 %y, i64 %r3, i64 %r4, i64 %r5, i64 %r6,
                           i64* %spLim,
                           float %f1, float %f2, float %f3, float %f4,
                           double %d1, double %d2)
{
  %1 = getelementptr inbounds i64* %sp, i64 0
  %2 = load i64* %1, align 8
  %cont = inttoptr i64 %2 to void (i64*, i64*, i64*,
                                   i64, i64, i64, i64, i64, i64,
                                   i64*,
                                   float, float, float, float,
                                   double, double)*

  tail call cc10 void %cont(i64* %baseReg, i64* %sp, i64* %hp,
                            i64 %y, i64 %x, i64 %r3, i64 %r4, i64 %r5, i64 %r6,
                            i64* %spLim,
                            float %f1, float %f2, float %f3, float %f4,
                            double %d1, double %d2) noreturn
  ret void
}
Run Code Online (Sandbox Code Playgroud)

用于测试的 Haskell 代码:

{-# LANGUAGE GHCForeignImportPrim #-}
{-# LANGUAGE MagicHash, UnboxedTuples, BangPatterns  #-}
{-# LANGUAGE ForeignFunctionInterface, UnliftedFFITypes #-}

import GHC.Prim
import GHC.Word

foreign import prim "primllvm" primllvm :: Word# -> Word# -> (# Word#, Word# #)

main :: IO ()
main = do
  let !(W# w1) = 12
      !(W# w2) = 34
      !(# w1', w2' #) = primllvm w1 w2
      x = W# w1'
      y = W# w2'
  print (x, y)
Run Code Online (Sandbox Code Playgroud)

建筑:

llc -filetype=obj -o Define.o Define.ll
ghc --make Use.hs Define.o
Run Code Online (Sandbox Code Playgroud)