Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

(When) is loadLibraryPermanently needed? #341

Open
jrp2014 opened this issue May 21, 2021 · 2 comments
Open

(When) is loadLibraryPermanently needed? #341

jrp2014 opened this issue May 21, 2021 · 2 comments

Comments

@jrp2014
Copy link

jrp2014 commented May 21, 2021

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]
@jrp2014
Copy link
Author

jrp2014 commented May 22, 2021

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.

@UnkindPartition
Copy link
Contributor

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.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants