I am following Stephen Diehl's excellent LLVM Haskell tutorial on a Linux Mint box (Linux Mint 17 Qiana, GHC 7.8.4, llvm 3.4).
I cloned the project's github repo and I was able to build each chapter's example by using the included Makefile
.
In chapter 4 the tutorial presents us a JIT compiler:
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 ()
Then the tutorial extends the language by writing C code to implement operations.
/* 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;
}
The makefile builds the project by running:
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
But when I try to call putchard()
I get an error:
LLVM ERROR: Program used external function 'putchard' which could not be resolved!
Am I missing something here?
I've seen people having a similar issue with the original C++ version of the tutorial. They usually solve it by adding a flag to gcc build command (-rdynamic
) which is supposed to make the linker add all symbols, no only used ones, to the dynamic symbol table. I suspect ghc is stripping putchard()
from the executable file.
When I follow the exact same steps on OS X I everything works fine and I can call putchard()
without a problem.
What's happening?
I just tried running the project on Centos 7 and it worked. There must be something wrong with my Mint machine.
Perhaps GHC is being a bit overzealous during linking and stripping out the symbol? Can you manually add a reference using the FFI in Main.hs
and then recompile.
{-# LANGUAGE ForeignFunctionInterface #-}
import Foreign.C.Types
foreign import ccall safe "putchard" putchard
:: CDouble -> CDouble
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With