Sto seguendo Stephen Diehl's excellent LLVM Haskell tutorial su una macchina Linux Mint (Linux Mint 17 Qiana, GHC 7.8.4, llvm 3.4).JIT Haskell llvm-general: chiama al volo una funzione C. Il tutorial di Stephen Diehl
Ho clonato il repository github del progetto e sono riuscito a creare l'esempio di ogni capitolo utilizzando lo Makefile
incluso.
Nel capitolo 4 tutorial ci presenta un compilatore 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()
Poi il tutorial estende il linguaggio per la scrittura di codice C per implementare le operazioni.
/* 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;
}
Il makefile costruisce il progetto eseguendo:
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
Ma quando provo a chiamare putchard()
ottengo un errore:
LLVM ERROR: Program used external function 'putchard' which could not be resolved!
mi manca qualcosa qui?
Ho visto persone che hanno un problema simile con la versione C++ originale del tutorial. Solitamente lo risolvono aggiungendo un comando flag al comando gcc (-rdynamic
) che dovrebbe far sì che il linker aggiunga tutti i simboli, non solo quelli usati, alla tabella dei simboli dinamici. Sospetto che ghc stia strappando putchard()
dal file eseguibile.
Quando seguo esattamente gli stessi passaggi su OS X I, tutto funziona correttamente e posso chiamare putchard()
senza problemi.
Cosa sta succedendo?
Ho appena provato a eseguire il progetto su Centos 7 e ha funzionato. Deve esserci qualcosa di sbagliato nella mia macchina Mint.
L'aggiunta di '' -optl -rdynamic'' all'invocazione di ghc risolve il problema? Puoi eseguire '' nm chapter4 | grep putchard'' e incollare l'output risultante nella domanda? –
Stephen, avevo provato ad aggiungere '-optl -rdynamic' ma non funzionava. Sfortunatamente l'output di 'nm chapter4 | grep putchard' è nullo. Sembra che ghc stia ignorando 'cbits.so'. Su OS X l'eseguibile non verrà nemmeno eseguito se non trova 'cbits.so'. Su Linux non fa la differenza. Forse c'è un modo per collegarsi con ld invece di ghc? Qual è stata la tua configurazione quando hai scritto il tutorial? – esato1981
Ho testato il codice su entrambi Ubuntu e Arch Linux. Le persone hanno riferito di eseguirlo su tutti i principali sistemi operativi. Forse c'era un bug del linker upstream in GHC che è un po 'troppo zelante nel rimuovere simboli che non appaiono nella fonte Haskell. Hai provato su 7.6 o 7.10? –