2015-04-05 59 views
5

我在Linux Mint框(Linux Mint 17 Qiana,GHC 7.8.4,llvm 3.4)上关注Stephen Diehl's excellent LLVM Haskell tutorialHaskell llvm-general JIT:即时调用C函数。 Stephen Diehl的教程

我克隆了项目的github回购,并且能够通过使用包含的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() 

然后教程扩展了编写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; 
} 

生成文件通过运行生成项目:

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 

但是,当我尝试调用putchard()我得到一个错误:

LLVM ERROR: Program used external function 'putchard' which could not be resolved! 

我失去了一些东西在这里?

我见过有人遇到与本教程的原始C++版本类似的问题。他们通常通过向gcc build命令(-rdynamic)添加一个标志来解决这个问题,该命令可以使链接器将所有符号(不仅是已使用的符号)添加到动态符号表中。我怀疑ghc是从可执行文件中剥离putchard()

当我按照完全相同的步骤在OS X上,我一切正常,我可以打电话putchard()没有问题。

发生了什么事?

我刚刚尝试在Centos 7上运行该项目,它工作。我的造币机器肯定有问题。

+0

是否将''-optl -rdynamic''添加到ghc的调用中修复了问题?你可以运行'nm chapter4 | grep putchard''并将结果输出粘贴到问题中? – 2015-04-06 22:39:01

+0

斯蒂芬,我曾尝试添加'-optl -rdynamic',但它没有工作。不幸的是,输出到'nm chapter4 | grep putchard'为null。看起来ghc忽略了'cbits.so'。在OS X上,如果可执行文件没有找到'cbits.so',它甚至不会运行。在Linux上它没有什么区别。也许有一种方法可以链接到ld而不是ghc?写这篇教程时你的设置是什么? – esato1981 2015-04-07 04:34:33

+0

我已经测试了Ubuntu和Arch Linux上的代码。尽管如此,人们已经报告说它在每个主要操作系统上运行它。也许GHC上游存在一个链接器错误,在剥离不出现在Haskell源代码中的符号时有些过分热情。你在7.6或7.10上试过了吗? – 2015-04-08 23:32:12

回答

1

也许GHC在链接和剥离符号过程中有点过分了?您是否可以使用FFI在Main.hs中手动添加引用,然后重新编译。

{-# LANGUAGE ForeignFunctionInterface #-} 

import Foreign.C.Types 

foreign import ccall safe "putchard" putchard 
    :: CDouble -> CDouble 
+0

我会被诅咒!这个解决方案*做了*工作(在Main.hs中手动添加一个引用)。在尝试之前,我尝试了使用GHC 7.6和GHC 7.8。我试图使用'ld.gold'来代替'ld.ld',但没有一个能够工作。 – esato1981 2015-04-09 05:22:05