2015-04-05 60 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