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

Experimental OrcJITv2 support #919

Closed
wants to merge 11 commits into from

Conversation

gmarkall
Copy link
Member

@gmarkall gmarkall commented Mar 15, 2023

For working on OrcJITv2 support.

Current status:

  • Passes tests with LLVM 14.0.6
  • Numba support needs work.
  • MCJIT example ported to LLJIT works.

Current known to-do list:

  • Add documentation.
  • Invalidate modules passed to add_ir_module() since they're not usable after that.
  • Remove the hack to keep a global list of thread safe modules to keep them alive after compilation.
  • Remove abort statements.
  • Provide the resource tracker back to the caller of add_ir_module(), wrapped in something that removes it when it is garbage-collected.

Not todo:

  • Implement an object cache. This will come later.

gmarkall and others added 6 commits March 15, 2023 13:38
This mainly uses LLJIT through the C API. LLJIT has feature parity with
MCJIT, with the following exceptions:

- Creating an `LLJIT` with a target machine in `test_emit_assembly()`
  and `test_emit_object()` seems to result in a segfault for some
  reason. This should have a fairly simple root cause since creating one
  has worked for me in other contexts (e.g. prototyping on RISC-V).
- The object cache and removing a module is not yet implemented.

This shows up as 5 fails in the `TestOrcLLJIT` class, which covers
testing the same functionality as the `TestMCJIT` class.

A version of the binding tutorial that uses LLJIT is also added in
`examples/lljit.py`, which also demonstrates using typed pointers (as
opposed to opaque pointers) in LLVM 14 (and still works in LLVM 15).
Example execution:

```
$ python examples/lljit.py
x[0] = 7.2
fpadd(1.0, 3.5, &x[0]) = 11.7
```

In addition to implementing missing features, the binding code is rather
"prototype-quality" - it needs better error handling, comments, and
documentation.

Fix ownership of target machines use to build LLJIT

No valgrind errors now but not leak free

Dispose of unneeded thread-safe-context

Fix leak of target machine

The target machine is not owned by LLVM so it should be cleaned up by
llvmlite.

At this point, running the unit test suite results in no leaks or
errors.

Use llvm::orc namespace

Some orcjit FFI tidy up

Add comment about DynamicLibrarySearchGenerator

clang-format orcjit.cpp

Simplify creation of an lljit

Remove global definition of symbols

Refactor lljit creation

Move current process symbol lookup to separate function

Also add tests for it

Simplify and comment LLVMPY_LLJITLookup

[WIP] Implementing module removal, presently very leaky

Fix flake8 in orcjit

Fix leak after addind module remove

Update a comment

[WIP] Graft MCJIT object cache into LLJIT (doesn't work directly)

Build orcjit binding on OS X

Add support for adding object file to orcjit

Add test adding obj file from filesystem for orcjit

Add YCM conf

Ignore vim swap files
lookup seems to destroy the module:

```
Before lookup
define double @fpadd(double %.1, double %.2, double* %dummy) {
entry:
  %res = fadd double %.1, %.2
  %val = load double, double* %dummy, align 8
  %res2 = fadd double %res, %val
  ret double %res2
}

After lookup
==34605== Invalid read of size 8
==34605==    at 0x723C83E: llvm::ilist_node_base<true>::getNext() const (ilist_node_base.h:43)
==34605==    by 0x723E5E9: llvm::ilist_node_impl<llvm::ilist_detail::node_options<llvm::Function, true, false, void> >::getNext() (ilist_node.h:67)
==34605==    by 0x723DE4A: llvm::ilist_iterator<llvm::ilist_detail::node_options<llvm::Function, true, false, void>, false, false>::operator++() (ilist_iterator.h:157)
==34605==    by 0x723D68D: llvm::simple_ilist<llvm::Function>::begin() (simple_ilist.h:117)
==34605==    by 0x723C9C7: llvm::Module::begin() (Module.h:620)
==34605==    by 0x723D291: LLVMPY_ModuleFunctionsIter (module.cpp:181)
==34605==    by 0x4868A49: ffi_call_unix64 (in /home/gmarkall/mambaforge/envs/numba-llvm14/lib/libffi.so.8.1.0)
==34605==    by 0x4867FE9: ffi_call_int (in /home/gmarkall/mambaforge/envs/numba-llvm14/lib/libffi.so.8.1.0)
==34605==    by 0x5923F6F: UnknownInlinedFun (callproc.c:916)
==34605==    by 0x5923F6F: _ctypes_callproc (callproc.c:1259)
==34605==    by 0x5923529: PyCFuncPtr_call (_ctypes.c:4201)
==34605==    by 0x259B58: UnknownInlinedFun (call.c:305)
==34605==    by 0x259B58: PyObject_Call (call.c:317)
==34605==    by 0x23DFAE: UnknownInlinedFun (ceval.c:5943)
==34605==    by 0x23DFAE: _PyEval_EvalFrameDefault (ceval.c:4277)
==34605==  Address 0x4e1390b0 is 32 bytes inside a block of size 808 free'd
==34605==    at 0x484BB6F: operator delete(void*, unsigned long) (in /usr/libexec/valgrind/vgpreload_memcheck-amd64-linux.so)
==34605==    by 0x85FCDDA: llvm::orc::IRCompileLayer::emit(std::unique_ptr<llvm::orc::MaterializationResponsibility, std::default_delete<llvm::orc::MaterializationResponsibility> >, llvm::orc::ThreadSafeModule) (in /home/gmarkall/numbadev/llvmlite/llvmlite/binding/libllvmlite.so)
==34605==    by 0x85FD40A: llvm::orc::IRTransformLayer::emit(std::unique_ptr<llvm::orc::MaterializationResponsibility, std::default_delete<llvm::orc::MaterializationResponsibility> >, llvm::orc::ThreadSafeModule) (in /home/gmarkall/numbadev/llvmlite/llvmlite/binding/libllvmlite.so)
==34605==    by 0x85FD40A: llvm::orc::IRTransformLayer::emit(std::unique_ptr<llvm::orc::MaterializationResponsibility, std::default_delete<llvm::orc::MaterializationResponsibility> >, llvm::orc::ThreadSafeModule) (in /home/gmarkall/numbadev/llvmlite/llvmlite/binding/libllvmlite.so)
==34605==    by 0x860703A: llvm::orc::BasicIRLayerMaterializationUnit::materialize(std::unique_ptr<llvm::orc::MaterializationResponsibility, std::default_delete<llvm::orc::MaterializationResponsibility> >) (in /home/gmarkall/numbadev/llvmlite/llvmlite/binding/libllvmlite.so)
==34605==    by 0x856CA87: llvm::orc::MaterializationTask::run() (in /home/gmarkall/numbadev/llvmlite/llvmlite/binding/libllvmlite.so)
==34605==    by 0x8546769: void llvm::detail::UniqueFunctionBase<void, std::unique_ptr<llvm::orc::Task, std::default_delete<llvm::orc::Task> > >::CallImpl<void (*)(std::unique_ptr<llvm::orc::Task, std::default_delete<llvm::orc::Task> >)>(void*, std::unique_ptr<llvm::orc::Task, std::default_delete<llvm::orc::Task> >&) (in /home/gmarkall/numbadev/llvmlite/llvmlite/binding/libllvmlite.so)
==34605==    by 0x85487FE: llvm::orc::ExecutionSession::dispatchTask(std::unique_ptr<llvm::orc::Task, std::default_delete<llvm::orc::Task> >) (in /home/gmarkall/numbadev/llvmlite/llvmlite/binding/libllvmlite.so)
==34605==    by 0x85695ED: llvm::orc::ExecutionSession::dispatchOutstandingMUs() (in /home/gmarkall/numbadev/llvmlite/llvmlite/binding/libllvmlite.so)
==34605==    by 0x8570544: llvm::orc::ExecutionSession::OL_completeLookup(std::unique_ptr<llvm::orc::InProgressLookupState, std::default_delete<llvm::orc::InProgressLookupState> >, std::shared_ptr<llvm::orc::AsynchronousSymbolQuery>, std::function<void (llvm::DenseMap<llvm::orc::JITDylib*, llvm::DenseSet<llvm::orc::SymbolStringPtr, llvm::DenseMapInfo<llvm::orc::SymbolStringPtr, void> >, llvm::DenseMapInfo<llvm::orc::JITDylib*, void>, llvm::detail::DenseMapPair<llvm::orc::JITDylib*, llvm::DenseSet<llvm::orc::SymbolStringPtr, llvm::DenseMapInfo<llvm::orc::SymbolStringPtr, void> > > > const&)>) (in /home/gmarkall/numbadev/llvmlite/llvmlite/binding/libllvmlite.so)
==34605==    by 0x8571160: llvm::orc::InProgressFullLookupState::complete(std::unique_ptr<llvm::orc::InProgressLookupState, std::default_delete<llvm::orc::InProgressLookupState> >) (in /home/gmarkall/numbadev/llvmlite/llvmlite/binding/libllvmlite.so)
==34605==    by 0x855871D: llvm::orc::ExecutionSession::OL_applyQueryPhase1(std::unique_ptr<llvm::orc::InProgressLookupState, std::default_delete<llvm::orc::InProgressLookupState> >, llvm::Error) (in /home/gmarkall/numbadev/llvmlite/llvmlite/binding/libllvmlite.so)
==34605==  Block was alloc'd at
==34605==    at 0x4849013: operator new(unsigned long) (in /usr/libexec/valgrind/vgpreload_memcheck-amd64-linux.so)
==34605==    by 0x94AE67F: llvm::parseAssemblyString(llvm::StringRef, llvm::SMDiagnostic&, llvm::LLVMContext&, llvm::SlotMapping*) (in /home/gmarkall/numbadev/llvmlite/llvmlite/binding/libllvmlite.so)
==34605==    by 0x723B84F: LLVMPY_ParseAssembly (assembly.cpp:22)
==34605==    by 0x4868A49: ffi_call_unix64 (in /home/gmarkall/mambaforge/envs/numba-llvm14/lib/libffi.so.8.1.0)
```
This reverts commit 0c6b605.

This hack helped with the Numba tests, but leaks all modules that ever
get compiled, so it's not a good long-term strategy.
These tests were ported from MCJIT, but the initial OrcJIT
implementation won't support object caching. The design of the object
caching API for OrcJIT will likely be different than that of the MCJIT
binding, so these tests test an API that will likely never exist.

@pitrou originally started a discussion about the object cache design
(https://lists.llvm.org/pipermail/llvm-dev/2015-August/089225.html) in
2015 where it was eventually recommended that the ObjectLinkingLayer API
to implement a simple object cache
(https://lists.llvm.org/pipermail/llvm-dev/2016-August/103971.html)
@gmarkall
Copy link
Member Author

This is no longer relevant, closing.

@gmarkall gmarkall closed this Jul 26, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

1 participant