我正在关注Stephen Diehl在Linux Mint盒子上的优秀LLVM Haskell教程(Linux Mint 17 Qiana,GHC 7.8.4,llvm 3.4).
我克隆了项目的github repo,我能够通过使用包含来构建每个章节的示例Makefile.
在第4章中,本教程为我们提供了一个JIT编译器:
import qualified LLVM.General.ExecutionEngine as EE
jit :: Context -> (EE.MCJIT -> IO a) -> IO a
jit c = EE.withMCJIT c optlevel model ptrelim fastins
where
optlevel = Just 2 -- optimization level
model = Nothing -- code model ( Default )
ptrelim = Nothing -- frame pointer elimination
fastins = Nothing -- fast instruction selection
runJIT :: AST.Module -> IO (Either String ())
runJIT mod = do
...
jit context $ \executionEngine ->
...
EE.withModuleInEngine executionEngine m $ \ee -> do
mainfn <- EE.getFunction ee (AST.Name "main")
case mainfn of
Just fn -> do
res <- run fn
putStrLn $ "Evaluated to: " ++ show res
Nothing -> return ()
Run Code Online (Sandbox Code Playgroud)
然后,本教程通过编写C代码来实现操作来扩展语言.
/* cbits
$ gcc -fPIC -shared cbits.c -o cbits.so
$ clang -fPIC -shared cbits.c -o cbits.so
*/
#include "stdio.h"
// putchard - putchar that takes a double and returns 0.
double putchard(double X) {
putchar((char)X);
fflush(stdout);
return 0;
}
Run Code Online (Sandbox Code Playgroud)
makefile通过运行来构建项目:
gcc -fPIC -shared src/chapter4/cbits.c -o src/chapter4/cbits.so
ghc -no-user-package-db -package-db .cabal-sandbox/*-packages.conf.d src/chapter4/cbits.so --make src/chapter4/*.hs -o chapter4
Run Code Online (Sandbox Code Playgroud)
但是当我试着打电话时putchard()我得到一个错误:
LLVM ERROR: Program used external function 'putchard' which could not be resolved!
Run Code Online (Sandbox Code Playgroud)
我在这里错过了什么吗?
我见过人们对本教程的原始C++版本有类似的问题.它们通常通过向gcc build命令(-rdynamic)添加一个标志来解决它,该命令应该使链接器将所有符号(不仅仅是已使用的符号表)添加到动态符号表中.我怀疑ghc正在putchard()从可执行文件中删除.
当我在OS XI上执行完全相同的步骤时,一切正常,我可以putchard()毫无问题地打电话.
发生了什么?
我刚尝试在Centos 7上运行该项目并且它有效.我的Mint机器肯定有问题.
也许 GHC 在链接和删除符号时有点过于热心?能否使用FFI中手动添加引用Main.hs,然后重新编译。
{-# LANGUAGE ForeignFunctionInterface #-}
import Foreign.C.Types
foreign import ccall safe "putchard" putchard
:: CDouble -> CDouble
Run Code Online (Sandbox Code Playgroud)