首先通过LLVM bitcode链接器运行GHC的LLVM输出

Cli*_*ton 17 haskell llvm ghc

我希望能够在没有完整函数调用的开销的情况下从Haskell调用LLVM代码.例如:

-- Main.hs --

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

import GHC.Exts(Word(W#))
import GHC.Prim(Word#)

foreign import ccall llvminc :: Word# -> Word#

main = do
  line1 <- getLine
  let !(W# x1) = read line1
  let !r1 = llvminc x1
  print (W# r1)


-- funcs.ll --

define fastcc i64 @llvminc(i64 inreg %x) {
  %r = add i64 %x, 1
  ret i64 %r
}
Run Code Online (Sandbox Code Playgroud)

我可以编译并链接它以通过运行生成一个正常运行的可执行文件

ghc -O2 -fllvm Main.hs funcs.ll
Run Code Online (Sandbox Code Playgroud)

实际上,即使删除-fllvm仍然会导致功能可执行,例如

ghc -O2 Main.hs funcs.ll
Run Code Online (Sandbox Code Playgroud)

这让我强烈怀疑GHC是在使用普通C链接的两种情况下分别链接这些文件.

实际上,当我使用以下方法调查中间输出时:

ghc -O2 -fllvm -keep-s-files Main.hs funcs.ll
Run Code Online (Sandbox Code Playgroud)

我在Main.s中看到以下内容:

callq   suspendThread
movq    %rax, %rbp
movq    %rbx, %rdi
callq   llvminc
movq    %rax, %rbx
movq    %rbp, %rdi
callq   resumeThread
Run Code Online (Sandbox Code Playgroud)

这再次暗示GHC只是要求LLVM单独编译文件,然后将结果发送到系统链接器,而不会内联调用.

相反,我希望GHC将初始LLVM文件(从GHC和用户指定)发送到llvm-link,与系统链接器不同,它只是将多个LLVM bitcode文件合并到一个LLVM bitcode文件中.最好将此结果编译为本机代码对象文件并发送到系统链接器,而不是将多个目标文件发送到系统链接器.

实际上,当我手动尝试此操作时,将.ll人类可读文件组装到LLVM .bcbitcode,llvm-link生成最终的bitcode,然后像这样拆解bitcode:

llvm-as Main.ll
llvm-as funcs.ll
llvm-link funcs.bc Main.bc -o combined.bc
llvm-dis combined.bc
Run Code Online (Sandbox Code Playgroud)

我在生成的LLVM代码中找到了以下内容

%ln59M = add i64 %ln59L, 1
Run Code Online (Sandbox Code Playgroud)

直接调用后读取,没有"调用"或返回.实际的功能仍在LLVM中,但不是必需的.

因此,我尝试通过添加-pgml llvm-link到命令行来指示GHC与LLVM链接器链接,但这种情况非常失败,并且llvm-link丢失了许多关于未知选项的错误.这并不奇怪,因为llvm-link它不是真正的链接器,它只是结合了LLVM文件.

那么,无论如何让GHC通过LLVM链接器发送它的所有中间LLVM文件以启用LLVM级别的模块间优化?

men*_*kgs 1

你尝试过这两件事吗?

1 - 使用alwaysinline 函数属性:http://llvm.org/docs/LangRef.html#function-attributes

2 - 使用 GHC 调用约定(cc 10 而不是 fastcc): http://llvm.org/docs/LangRef.html#calling-conventions

define cc 10 i64 @llvminc(i64 inreg %x) alwaysinline {
  %r = add i64 %x, 1
  ret i64 %r
}
Run Code Online (Sandbox Code Playgroud)