Load TVM-FFI exported object files using LLVM ORC JIT v2
Project description
TVM-FFI OrcJIT
A Python package that enables dynamic loading of compiled object files (.o)
using LLVM ORC JIT v2, providing a flexible JIT execution environment for
TVM-FFI exported functions.
Features
- JIT Execution: Load and execute compiled object files at runtime using LLVM's ORC JIT v2
- Multiple Libraries: Create separate dynamic libraries with independent symbol namespaces
- Incremental Loading: Add multiple object files to the same library incrementally
- Symbol Isolation: Different libraries can define the same symbol without conflicts
- Init/Fini Support: Handles static constructors/destructors across ELF (
.init_array/.ctors), Mach-O (__mod_init_func), and COFF (.CRT$XC*/.CRT$XT*) - Cross-Platform: Linux (x86_64, aarch64), macOS (arm64), Windows (AMD64)
- Multi-Compiler: Tested with LLVM Clang, GCC, Apple Clang, MSVC, and clang-cl
- TVM-FFI Integration: Seamlessly works with TVM-FFI's stable C ABI
- Python API: Simple Pythonic interface for JIT compilation and execution
Supported Platforms and Compilers
Object files compiled with any of the following compiler/platform combinations can be loaded and executed by the ORC JIT:
| Platform | Compilers | C | C++ |
|---|---|---|---|
| Linux (x86_64, aarch64) | LLVM Clang, GCC | yes | yes |
| macOS (arm64) | LLVM Clang, Apple Clang | yes | yes |
| Windows (AMD64) | LLVM Clang, MSVC, clang-cl | yes | no |
Windows is C-only across all compilers. C++ objects compiled with
TVM_FFI_DLL_EXPORT_TYPED_FUNC use try/catch (via TVM_FFI_SAFE_CALL_BEGIN/END),
which requires Itanium exception ABI symbols (__cxa_begin_catch,
__gxx_personality_v0, etc.) that the MSVC-built host process cannot provide.
Pure C objects using the TVMFFISafeCallType ABI work on all platforms.
Installation
Install from PyPI
pip install apache-tvm-ffi apache-tvm_ffi_orcjit
Build from Source
Prerequisites
- Python 3.10+, CMake 3.20+, C++17 compiler
- LLVM 22+ development libraries (
llvmdev,llvm-config) - Static
zlibandzstdlibraries (in the same prefix as LLVM)
Install LLVM via conda-forge
The easiest way to get all dependencies is via conda-forge:
conda create -p /opt/llvm -c conda-forge \
llvmdev=22.1.0 clangdev=22.1.0 compiler-rt=22.1.0 zlib zstd-static -y
export LLVM_PREFIX=/opt/llvm
On Windows:
conda create -p C:\opt\llvm -c conda-forge llvmdev=22.1.0 zlib zstd-static -y
set LLVM_PREFIX=C:\opt\llvm
Build and install
git clone --recursive https://github.com/apache/tvm-ffi.git
cd tvm-ffi
# Install tvm-ffi first
pip install -e .
# Build and install the orcjit addon
cd addons/tvm_ffi_orcjit
pip install -e .
The LLVM_PREFIX environment variable tells CMake where to find LLVM. If
LLVM is installed in a conda env or a standard system path, CMake can
auto-discover it and LLVM_PREFIX is not needed.
Usage
Basic Example
from tvm_ffi_orcjit import ExecutionSession
# Create an execution session
session = ExecutionSession()
# Create a dynamic library
lib = session.create_library()
# Load an object file
lib.add("example.o")
# Get and call a function
add_func = lib.get_function("add")
result = add_func(1, 2)
print(f"Result: {result}") # Output: Result: 3
Multiple Libraries with Symbol Isolation
session = ExecutionSession()
lib1 = session.create_library("lib1")
lib2 = session.create_library("lib2")
lib1.add("implementation_v1.o")
lib2.add("implementation_v2.o")
add_v1 = lib1.get_function("add")
add_v2 = lib2.get_function("add")
print(add_v1(5, 3)) # Uses implementation from lib1
print(add_v2(5, 3)) # Uses implementation from lib2
Cross-Library Linking
session = ExecutionSession()
base_lib = session.create_library("base")
base_lib.add("math_ops.o")
caller_lib = session.create_library("caller")
caller_lib.set_link_order(base_lib) # Can resolve symbols from base_lib
caller_lib.add("caller.o")
result = caller_lib.get_function("call_math")(10, 20)
Writing Functions for OrcJIT
C++ (Linux/macOS)
#include <tvm/ffi/function.h>
TVM_FFI_DLL_EXPORT_TYPED_FUNC(add, [](int a, int b) {
return a + b;
});
Compile: clang++ -std=c++17 -fPIC -O2 -c -o example.o example.cc
Pure C (all platforms including Windows)
#include <tvm/ffi/c_api.h>
TVM_FFI_DLL_EXPORT int __tvm_ffi_add(
void* self, const TVMFFIAny* args, int32_t num_args, TVMFFIAny* result) {
result->type_index = kTVMFFIInt;
result->v_int64 = args[0].v_int64 + args[1].v_int64;
return 0;
}
Compile: clang -O2 -c -o example.o example.c
How It Works
- LLJIT: Built on LLVM's ORC JIT v2 with
ObjectLinkingLayer(JITLink) for all platforms. - InitFiniPlugin: Custom
ObjectLinkingLayer::Pluginthat collects function pointers from init/fini sections (ELF.init_array/.ctors/.fini_array/.dtors, Mach-O__mod_init_func/__mod_term_func, COFF.CRT$XC*/.CRT$XT*) and runs them in priority order at symbol lookup / library teardown. - DLL Import Stubs (Windows): Custom
DefinitionGeneratorthat resolves host process symbols from all loaded DLLs and creates__imp_*pointer stubs in JIT memory, keeping all fixups within PCRel32 range. - SEH Stripping (Windows):
ObjectTransformLayerstrips.pdata/.xdatarelocations from COFF objects before JITLink graph building, working around a JITLink limitation with COMDAT section symbols.
Please refers to ORCJIT_PRIMER.md to learn more about object file, linking, llvm orcjit v2, and how the addon works.
Project Structure
tvm_ffi_orcjit/
├── CMakeLists.txt # Build configuration
├── pyproject.toml # Python package metadata
├── src/ffi/
│ ├── orcjit_session.cc # ExecutionSession (LLJIT setup, plugins)
│ ├── orcjit_session.h
│ ├── orcjit_dylib.cc # DynamicLibrary (object loading, symbol lookup)
│ ├── orcjit_dylib.h
│ └── orcjit_utils.h # LLVM error handling utilities
├── python/tvm_ffi_orcjit/
│ ├── __init__.py # Module exports and library loading
│ ├── session.py # Python ExecutionSession wrapper
│ └── dylib.py # Python DynamicLibrary wrapper
├── tests/ # See tests/README.md
└── examples/quick-start/ # Complete example with CMake
CI
Runs on Linux (x86_64, aarch64), macOS (arm64), Windows (AMD64) via
cibuildwheel. Each platform builds test objects with multiple compilers
and runs the full test suite. See .github/workflows/tvm_ffi_orcjit.yml.
Troubleshooting
"Cannot find global function" error
The shared library wasn't loaded. Reinstall: pip install --force-reinstall apache-tvm_ffi_orcjit
"Duplicate definition of symbol" error
Use separate libraries for different implementations of the same symbol.
"Symbol not found" error
Ensure functions are exported with TVM-FFI macros (TVM_FFI_DLL_EXPORT_TYPED_FUNC
for C++, or __tvm_ffi_ prefix for C).
Relocation errors on Windows
MSVC/clang-cl objects must be compiled with /GS- to disable buffer security
checks (__security_cookie) which are CRT symbols the JIT cannot resolve.
LLVM version mismatch
The package requires LLVM 22+. Set LLVM_PREFIX to the LLVM install prefix:
export LLVM_PREFIX=/path/to/llvm
License
Apache License 2.0
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distributions
Built Distributions
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file apache_tvm_ffi_orcjit-0.1.0-py3-none-win_amd64.whl.
File metadata
- Download URL: apache_tvm_ffi_orcjit-0.1.0-py3-none-win_amd64.whl
- Upload date:
- Size: 12.5 MB
- Tags: Python 3, Windows x86-64
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.7
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
8ef9a49ae9a4660c0e1555ae6526a3f9b89ad3adfaa14010b9520946f4c56800
|
|
| MD5 |
699dda3c0235f849ef32ebb98fa82992
|
|
| BLAKE2b-256 |
c886cc2ba70db1bc6f53e2eb8854ad4f12ff52c8f764f82c7fbe2db919d77346
|
Provenance
The following attestation bundles were made for apache_tvm_ffi_orcjit-0.1.0-py3-none-win_amd64.whl:
Publisher:
publish_orcjit_wheel.yml on apache/tvm-ffi
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
apache_tvm_ffi_orcjit-0.1.0-py3-none-win_amd64.whl -
Subject digest:
8ef9a49ae9a4660c0e1555ae6526a3f9b89ad3adfaa14010b9520946f4c56800 - Sigstore transparency entry: 1756245858
- Sigstore integration time:
-
Permalink:
apache/tvm-ffi@59da4c0b82af0d499dae34bd89ef010f64d3ff45 -
Branch / Tag:
refs/heads/main - Owner: https://github.com/apache
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish_orcjit_wheel.yml@59da4c0b82af0d499dae34bd89ef010f64d3ff45 -
Trigger Event:
workflow_dispatch
-
Statement type:
File details
Details for the file apache_tvm_ffi_orcjit-0.1.0-py3-none-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl.
File metadata
- Download URL: apache_tvm_ffi_orcjit-0.1.0-py3-none-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl
- Upload date:
- Size: 23.4 MB
- Tags: Python 3, manylinux: glibc 2.27+ x86-64, manylinux: glibc 2.28+ x86-64
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.7
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
ce3ac5c06ee1d500615bf0b4b22ff536b2ddee28f538c0001c81132452cd50be
|
|
| MD5 |
fd6e8a7f3be7b886707232dbe7cea535
|
|
| BLAKE2b-256 |
17d3e9523c16cf0081fe2f2d130af0be5f384f5109e226372929d507c6397671
|
Provenance
The following attestation bundles were made for apache_tvm_ffi_orcjit-0.1.0-py3-none-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl:
Publisher:
publish_orcjit_wheel.yml on apache/tvm-ffi
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
apache_tvm_ffi_orcjit-0.1.0-py3-none-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl -
Subject digest:
ce3ac5c06ee1d500615bf0b4b22ff536b2ddee28f538c0001c81132452cd50be - Sigstore transparency entry: 1756245851
- Sigstore integration time:
-
Permalink:
apache/tvm-ffi@59da4c0b82af0d499dae34bd89ef010f64d3ff45 -
Branch / Tag:
refs/heads/main - Owner: https://github.com/apache
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish_orcjit_wheel.yml@59da4c0b82af0d499dae34bd89ef010f64d3ff45 -
Trigger Event:
workflow_dispatch
-
Statement type:
File details
Details for the file apache_tvm_ffi_orcjit-0.1.0-py3-none-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl.
File metadata
- Download URL: apache_tvm_ffi_orcjit-0.1.0-py3-none-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl
- Upload date:
- Size: 22.3 MB
- Tags: Python 3, manylinux: glibc 2.27+ ARM64, manylinux: glibc 2.28+ ARM64
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.7
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
f64f172b5e8d77a9dc8abd6cedf4a63b7a28a974ddc8cee6268b1cb810dad87b
|
|
| MD5 |
d0259ca1ddf66cb9bdbdb74d8bbb6466
|
|
| BLAKE2b-256 |
d77fa22fd8665e2bcd7af31094b99e5cedfedbc3d7a0e90a3b3acda9d5f36de6
|
Provenance
The following attestation bundles were made for apache_tvm_ffi_orcjit-0.1.0-py3-none-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl:
Publisher:
publish_orcjit_wheel.yml on apache/tvm-ffi
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
apache_tvm_ffi_orcjit-0.1.0-py3-none-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl -
Subject digest:
f64f172b5e8d77a9dc8abd6cedf4a63b7a28a974ddc8cee6268b1cb810dad87b - Sigstore transparency entry: 1756245863
- Sigstore integration time:
-
Permalink:
apache/tvm-ffi@59da4c0b82af0d499dae34bd89ef010f64d3ff45 -
Branch / Tag:
refs/heads/main - Owner: https://github.com/apache
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish_orcjit_wheel.yml@59da4c0b82af0d499dae34bd89ef010f64d3ff45 -
Trigger Event:
workflow_dispatch
-
Statement type:
File details
Details for the file apache_tvm_ffi_orcjit-0.1.0-py3-none-macosx_11_0_arm64.whl.
File metadata
- Download URL: apache_tvm_ffi_orcjit-0.1.0-py3-none-macosx_11_0_arm64.whl
- Upload date:
- Size: 14.9 MB
- Tags: Python 3, macOS 11.0+ ARM64
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.7
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
1caf8a3b0a74cebba23d6e89652256f38181fa85aedfd19c3dae05d3f17f427c
|
|
| MD5 |
e066d6b1822d61d41d21eea525d852d5
|
|
| BLAKE2b-256 |
14e6a02bd0a656150f38583ffb8b9b8fb1f360fe6e26c7979b293ca8b5b72c81
|
Provenance
The following attestation bundles were made for apache_tvm_ffi_orcjit-0.1.0-py3-none-macosx_11_0_arm64.whl:
Publisher:
publish_orcjit_wheel.yml on apache/tvm-ffi
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
apache_tvm_ffi_orcjit-0.1.0-py3-none-macosx_11_0_arm64.whl -
Subject digest:
1caf8a3b0a74cebba23d6e89652256f38181fa85aedfd19c3dae05d3f17f427c - Sigstore transparency entry: 1756245844
- Sigstore integration time:
-
Permalink:
apache/tvm-ffi@59da4c0b82af0d499dae34bd89ef010f64d3ff45 -
Branch / Tag:
refs/heads/main - Owner: https://github.com/apache
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish_orcjit_wheel.yml@59da4c0b82af0d499dae34bd89ef010f64d3ff45 -
Trigger Event:
workflow_dispatch
-
Statement type: