llvm-hs
llvm-hs copied to clipboard
(When) is loadLibraryPermanently needed?
The following code from arith in llvm-hs-examples (llvm-hs-12) works fine (either with or without the commented out JIT.loadLibraryPermanently Nothing on linux., when there are external symbols. Is there some guidance on when that call is actually needed?
-- | JIT-compile the given 'Expr'ession and use the resulting function.
withSimpleJIT ::
NFData a =>
Expr ->
-- | what to do with the generated function
((Double -> Double) -> a) ->
IO a
withSimpleJIT expr doFun = do
putStrLn "*** Codegen ***"
printCodegen expr
JIT.withContext $ \context -> -- (>>) (JIT.loadLibraryPermanently Nothing) $
JIT.withModuleFromAST context (codegen expr) $ \mod' ->
JIT.withHostTargetMachine Reloc.PIC CodeModel.Default CodeGenOpt.Default $ \tm ->
JIT.withExecutionSession $ \es -> do
let dylibName = "myDylib"
dylib <- JIT.createJITDylib es dylibName
JIT.withClonedThreadSafeModule mod' $ \tsm -> do
objectLayer <- JIT.createRTDyldObjectLinkingLayer es
compileLayer <- JIT.createIRCompileLayer es objectLayer tm
JIT.addDynamicLibrarySearchGeneratorForCurrentProcess compileLayer dylib
JIT.addModule tsm dylib compileLayer
asm <- JIT.moduleLLVMAssembly mod'
printExpr expr
printIR asm
optimized <- PM.withPassManager passes $ flip PM.runPassManager mod'
when optimized $ putStrLn "*** Optimized ***"
optasm <- JIT.moduleLLVMAssembly mod'
printIR optasm
sym <- JIT.lookupSymbol es compileLayer dylib "f"
case sym of
Left (JIT.JITSymbolError err) -> do
print err
error "Execution aborted"
Right (JIT.JITSymbol fnAddr _) -> do
let fn = mkDoubleFun . castPtrToFunPtr $ wordPtrToPtr fnAddr
liftIO (putStrLn "*** Result ***\n")
evaluate $ force (doFun fn)
The same code segfaults on macos on the last line (with or without the call to loadLibraryPermenently), because the pointer to fn seems to be invalid, but that is a different issue.
Here's some output from a run
; ModuleID = 'arith.ll'
declare external ccc double @llvm.sin.f64(double)
declare external ccc double @llvm.sqrt.f64(double)
define external ccc double @f(double %x_0) {
%x_1 = fmul double 3.141593e0, %x_0
%x_2 = fdiv double %x_1, 2.000000e0
%x_3 = call ccc double @llvm.sin.f64(double %x_2)
%x_4 = call ccc double @llvm.sqrt.f64(double %x_0)
%x_5 = fadd double 1.000000e0, %x_4
%x_6 = call ccc double @llvm.sqrt.f64(double %x_0)
%x_7 = fadd double 1.000000e0, %x_6
%x_8 = fmul double %x_5, %x_7
%x_9 = fmul double %x_3, %x_8
ret double %x_9
}
*** Expression ***
\x -> sin(3.141592653589793 * x / 2.0) * (1.0 + sqrt(x)) * (1.0 + sqrt(x))
*** LLVM IR ***
; ModuleID = 'arith.ll'
source_filename = "<string>"
declare double @llvm.sin.f64(double)
declare double @llvm.sqrt.f64(double)
define double @f(double %x_0) {
%x_1 = fmul double 0x400921FB54442D18, %x_0
%x_2 = fdiv double %x_1, 2.000000e+00
%x_3 = call double @llvm.sin.f64(double %x_2)
%x_4 = call double @llvm.sqrt.f64(double %x_0)
%x_5 = fadd double 1.000000e+00, %x_4
%x_6 = call double @llvm.sqrt.f64(double %x_0)
%x_7 = fadd double 1.000000e+00, %x_6
%x_8 = fmul double %x_5, %x_7
%x_9 = fmul double %x_3, %x_8
ret double %x_9
}
*** Optimized ***
*** LLVM IR ***
; ModuleID = 'arith.ll'
source_filename = "<string>"
declare double @llvm.sin.f64(double)
declare double @llvm.sqrt.f64(double)
define double @f(double %x_0) local_unnamed_addr {
%x_1 = fmul double %x_0, 0x400921FB54442D18
%x_2 = fmul double %x_1, 5.000000e-01
%x_3 = tail call double @llvm.sin.f64(double %x_2)
%x_4 = tail call double @llvm.sqrt.f64(double %x_0)
%x_5 = fadd double %x_4, 1.000000e+00
%x_6 = tail call double @llvm.sqrt.f64(double %x_0)
%x_7 = fadd double %x_6, 1.000000e+00
%x_8 = fmul double %x_5, %x_7
%x_9 = fmul double %x_3, %x_8
ret double %x_9
}
*** Result ***
results match
[0.0,4.0,7.137764622384033e-16,-7.464101615137754,-2.204364238465236e-15,10.47213595499958,4.3716141420356565e-15,-13.291502622129181,-7.179787856884051e-15,16.0,1.0608230609850833e-14]
Looking more closely, I see that loadLibraryPermanently produces a success/failure Bool. In the case above, it actually returns false (so it failed to load the process symbols, yet the result of the process succeeds). This still leaves the question of when loadLibraryPermanently is neeeded.
I think addDynamicLibrarySearchGeneratorForCurrentProcess might be doing more or less the same thing in your case as loadLibraryPermanently. Try (a) removing both calls and (b) removing addDynamicLibrarySearchGeneratorForCurrentProcess but leaving loadLibraryPermanently and see if that confirms my hypothesis.
Also,
In the case above, it actually returns false (so it failed to load the process symbols, yet the result of the process succeeds).
Though this does not seem to be documented anywhere, loadLibraryPermanently returns True on failure; see the definition
of static bool LoadLibraryPermanently in llvm/include/llvm/Support/DynamicLibrary.h.