LLVM-C Python bindings with nanobind.
Project description
llvm-nanobind
Python bindings for the LLVM-C API using nanobind.
This project provides a Pythonic interface to LLVM's compiler infrastructure, enabling you to build compilers, analyzers, and code transformation tools in Python.
Current status: Experimental but usable. The bindings target LLVM 21.1.6 and are published as llvm-nanobind on PyPI (import name: llvm). Wheels bundle LLVM and are built/tested in CI for Linux x86_64/aarch64, macOS arm64, and Windows x86_64. The API is still evolving; expect breaking changes until a stable release.
Version numbers track LLVM: 21.1.6.1 means LLVM 21.1.6 plus binding/package revision 1.
Note: This project is 90%+ vibe coded. It is mostly an experiment to see what LLMs can do when you set things up properly.
Installation
Released wheels bundle LLVM for supported platforms, so normal installation is:
pip install llvm-nanobind
python -c "import llvm; print(llvm)"
For source/development builds, see Development.
See llvm-nanobind-example for a simple example project.
Quick Start
import llvm
# Create a simple function that returns 42.
with llvm.create_context() as ctx:
i32 = ctx.types.i32
fn_type = ctx.types.function(i32, [])
with ctx.create_module("example") as mod:
fn = mod.add_function("get_answer", fn_type)
entry = fn.append_basic_block("entry")
with entry.create_builder() as builder:
builder.ret(i32.constant(42))
assert mod.verify(), mod.verification_error
print(mod)
This exact snippet is available as examples/quick_start.py.
Examples
Runnable examples live in examples/ and are covered by tests/test_examples.py.
uv run python examples/quick_start.py
uv run python examples/transform_replace_add.py
More examples worth browsing:
examples/intrinsic_memcpy.py- call an LLVM intrinsic by name withBuilder.intrinsic(...)examples/optimize_module.py- optimize a module with a PassBuilder pipeline stringexamples/optimize_function.py- optimize one function with a function-level PassBuilder pipeline stringexamples/emit_object_assembly.py- emit host object code and assembly from a moduleexamples/jit_add.py- JIT-compile IR, call it through ctypes, and register a Python callbackexamples/instruction_metadata.py- attach custom metadata to an instruction and print the IRexamples/named_metadata.py- create module named metadata and print the IRexamples/metadata_debug_info.py- attach metadata, create debug info, and use debug-location scopesexamples/transform_replace_add.py- simple IR transformation using operands, RAUW, and instruction deletionexamples/bc-stats.py- print per-function instruction histograms from LLVM IRexamples/bc-graphviz.py- emit a GraphViz-style control-flow graph from LLVM IRexamples/bc-profile.py- instrument LLVM IR with profiling hooks
Current capabilities
- Pythonic wrappers for contexts, modules, types, values, functions, basic blocks, builders, metadata, debug info, object files, targets, target machines, and pass builder options
- IR construction, traversal, and transformation helpers: constants, globals, PHI/control flow/memory/cast/cmp instructions, operands, predecessors, RAUW, split blocks, move/clone/erase instructions
- IR and bitcode parsing/writing, lazy bitcode modules, module cloning/linking, diagnostics, attributes, COMDATs, calling conventions, linkage/visibility/storage controls
- Metadata/debug-info APIs including named metadata views, module flag views, instruction/global metadata mappings, DIBuilder recipes, and debug-location scopes
- Target lookup, data layouts,
Module.emit_object(),Module.emit_assembly(), target-machine emission, and PassBuilder pipeline execution viaModule.optimize(),Function.optimize(), andModule.run_passes() - Generic intrinsic calls with
Builder.intrinsic(...)and in-process JIT execution through the LLVM-C ORC LLJIT API - Lifetime/validity guards that turn many use-after-free, disposed-object, null-reference, and wrong-kind mistakes into Python exceptions instead of hard crashes
- Auto-generated typed
.pyistubs for IDEs/type checkers - Golden-master tests, Python regression scripts, examples, and vendored
llvm-c-testlit tests, including CI coverage against installed wheels
Documentation
Type stubs are auto-generated and provide IDE intellisense. After building, find them at:
.venv/lib/python3.*/site-packages/llvm/__init__.pyi
For development documentation, see devdocs/README.md.
Known limitations
- The API is not stable yet; method names and ownership rules may still change.
- Scope follows the LLVM-C API, not the full LLVM C++ API. JIT support is intentionally limited to what is exposed cleanly through LLVM-C ORC LLJIT.
- Docs are currently the README, examples,
devdocs/, and the generated.pyistub; there is no hosted API reference yet. - Prebuilt wheels currently target CPython 3.12+ stable ABI on Linux x86_64/aarch64, macOS arm64/x86_64, and Windows x86_64. Other platforms require a source build.
Development
Setup
Source/development builds need LLVM 21.1.6 available to CMake. The LLVM archives used for packaging are published at LLVMParty/llvm-builds v21.1.6.
From a checkout, download the matching LLVM archive and then run uv sync:
# Choose the archive matching your platform:
# llvm-21.1.6-linux-x86_64.zip
# llvm-21.1.6-linux-aarch64.zip
# llvm-21.1.6-macos-arm64.zip
# llvm-21.1.6-macos-x86_64.zip
# llvm-21.1.6-windows-x86_64.zip
python tools/ci/install_llvm.py \
--version 21.1.6 \
--archive llvm-21.1.6-linux-x86_64.zip \
--dest .llvm \
--prefix-file .llvm-prefix
uv sync --verbose
If you are using your own LLVM install instead, set LLVM_ROOT to its install prefix:
export LLVM_ROOT=/path/to/llvm
uv sync --verbose
If .llvm-prefix already points at another LLVM install, delete it first; CMake may reuse it from a previous configure.
For offline builds:
uv sync --offline --no-build-isolation --verbose
For Windows C++/LSP setup, see the Windows development section below.
Testing
# Main golden-master suite:
# - runs C++ test executables from build/
# - runs paired Python scripts
# - compares Python output against stored C++ behavior
uv run run_tests.py
# Python-only regression scripts in tests/regressions/
uv run run_tests.py --regressions
# Vendored llvm-c-test lit suite against the C test binary
# Rebuilds the vendored C binary before running lit.
uv run run_llvm_c_tests.py
uv run run_llvm_c_tests.py -v
# Vendored llvm-c-test lit suite against the Python implementation
uv run run_llvm_c_tests.py --use-python
# Run the Python llvm-c-test port directly during development
uv run python -m llvm_c_test --targets-list
# Type checking (not a test suite, but commonly run in CI/dev)
uvx ty check
If you want the closest thing to “run everything in this repo”, use:
uv run run_tests.py
uv run run_tests.py --regressions
uv run run_llvm_c_tests.py
uv run run_llvm_c_tests.py --use-python
Python tests here are intended to be executable as standalone scripts
(e.g. uv run tests/test_module.py or uv run tests/regressions/test_const_bytes.py).
They are generally pytest-compatible too, but direct script execution is the
historical/default style used by run_tests.py and for one-off debugging.
pytest is still useful for targeting specific regression files or subsets, but
it is not our complete top-level test entrypoint by itself.
Coverage
# Run with coverage
uv run coverage run run_llvm_c_tests.py --use-python
uv run coverage combine
uv run coverage report --include="llvm_c_test/*"
Windows source builds and C++ IntelliSense
The wheel is the easiest path on Windows. If you need a source/development build, install Visual Studio or Visual Studio Build Tools with the C++ workload, then fetch LLVM and run uv sync:
py -3.12 tools\ci\install_llvm.py `
--version 21.1.6 `
--archive llvm-21.1.6-windows-x86_64.zip `
--dest .llvm `
--prefix-file .llvm-prefix
uv sync --verbose
That command downloads from LLVMParty/llvm-builds v21.1.6, installs into .llvm, and writes .llvm-prefix for CMake.
If you are using your own LLVM install instead:
$env:LLVM_ROOT = "C:\path\to\llvm"
uv sync --verbose
For C++ local development with an LSP, create a local CMakeUserPresets.json at the repository root. CMake gets LLVM from .llvm-prefix created above, or from LLVM_ROOT on first configure. The compiler paths below assume the usual LLVM installer location; adjust them if your clang-cl.exe is elsewhere:
{
"version": 3,
"configurePresets": [
{
"name": "clang-cl",
"displayName": "Ninja with clang-cl",
"generator": "Ninja",
"binaryDir": "${sourceDir}/build",
"cacheVariables": {
"CMAKE_C_COMPILER": "C:/Program Files/LLVM/bin/clang-cl.exe",
"CMAKE_CXX_COMPILER": "C:/Program Files/LLVM/bin/clang-cl.exe",
"CMAKE_EXPORT_COMPILE_COMMANDS": "ON",
"CMAKE_BUILD_TYPE": "RelWithDebInfo"
}
}
],
"buildPresets": [
{
"name": "clang-cl",
"configurePreset": "clang-cl"
}
]
}
Then configure/build with:
cmake --preset clang-cl
cmake --build --preset clang-cl
If you move or replace the LLVM install, delete or regenerate .llvm-prefix from any previous configure.
License
This project is licensed under the MIT License. See LICENSE for details.
LLVM is licensed under the Apache License v2.0 with LLVM Exceptions.
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 Distribution
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 llvm_nanobind-21.1.6.2.tar.gz.
File metadata
- Download URL: llvm_nanobind-21.1.6.2.tar.gz
- Upload date:
- Size: 642.4 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
0d26abcad14829a6d707126c5a1f910bbaac09e7d45bd4efdea6dbe033943887
|
|
| MD5 |
972bf51469ec252eccd147783c83dde0
|
|
| BLAKE2b-256 |
1541488051cca794f8f41cd601426b408a1c8b97a9e6e7629d2c6639a0846ab3
|
Provenance
The following attestation bundles were made for llvm_nanobind-21.1.6.2.tar.gz:
Publisher:
ci.yml on LLVMParty/llvm-nanobind
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
llvm_nanobind-21.1.6.2.tar.gz -
Subject digest:
0d26abcad14829a6d707126c5a1f910bbaac09e7d45bd4efdea6dbe033943887 - Sigstore transparency entry: 1528194924
- Sigstore integration time:
-
Permalink:
LLVMParty/llvm-nanobind@3ceca4002cd42be7f91c7af583800f6934d84499 -
Branch / Tag:
refs/tags/v21.1.6.2 - Owner: https://github.com/LLVMParty
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
ci.yml@3ceca4002cd42be7f91c7af583800f6934d84499 -
Trigger Event:
push
-
Statement type:
File details
Details for the file llvm_nanobind-21.1.6.2-cp312-abi3-win_amd64.whl.
File metadata
- Download URL: llvm_nanobind-21.1.6.2-cp312-abi3-win_amd64.whl
- Upload date:
- Size: 44.1 MB
- Tags: CPython 3.12+, Windows x86-64
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
f02f7a204b453771d504c9b6f5cc09fbed6acdc668036df1e9a4fed811391e54
|
|
| MD5 |
217b90a46657788f18771dfc7193ec5e
|
|
| BLAKE2b-256 |
98f7a8e0cf2d1308bcd2b9ccbd44f791e0abb9b2cb555e504a4e5311b6f7c5c3
|
Provenance
The following attestation bundles were made for llvm_nanobind-21.1.6.2-cp312-abi3-win_amd64.whl:
Publisher:
ci.yml on LLVMParty/llvm-nanobind
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
llvm_nanobind-21.1.6.2-cp312-abi3-win_amd64.whl -
Subject digest:
f02f7a204b453771d504c9b6f5cc09fbed6acdc668036df1e9a4fed811391e54 - Sigstore transparency entry: 1528195460
- Sigstore integration time:
-
Permalink:
LLVMParty/llvm-nanobind@3ceca4002cd42be7f91c7af583800f6934d84499 -
Branch / Tag:
refs/tags/v21.1.6.2 - Owner: https://github.com/LLVMParty
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
ci.yml@3ceca4002cd42be7f91c7af583800f6934d84499 -
Trigger Event:
push
-
Statement type:
File details
Details for the file llvm_nanobind-21.1.6.2-cp312-abi3-manylinux_2_28_x86_64.whl.
File metadata
- Download URL: llvm_nanobind-21.1.6.2-cp312-abi3-manylinux_2_28_x86_64.whl
- Upload date:
- Size: 61.8 MB
- Tags: CPython 3.12+, manylinux: glibc 2.28+ x86-64
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
b40365eba14492ecdeac3030c4a99f8828ddc6d92a3bff76c7b146c39f8203fa
|
|
| MD5 |
0fef7d80bb66017ece8861f3269ba45c
|
|
| BLAKE2b-256 |
26f787f892ec27e0a7c5b4f3d254ffa4c2d6a53edb21dc3bd65f52bd4fd942ce
|
Provenance
The following attestation bundles were made for llvm_nanobind-21.1.6.2-cp312-abi3-manylinux_2_28_x86_64.whl:
Publisher:
ci.yml on LLVMParty/llvm-nanobind
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
llvm_nanobind-21.1.6.2-cp312-abi3-manylinux_2_28_x86_64.whl -
Subject digest:
b40365eba14492ecdeac3030c4a99f8828ddc6d92a3bff76c7b146c39f8203fa - Sigstore transparency entry: 1528195361
- Sigstore integration time:
-
Permalink:
LLVMParty/llvm-nanobind@3ceca4002cd42be7f91c7af583800f6934d84499 -
Branch / Tag:
refs/tags/v21.1.6.2 - Owner: https://github.com/LLVMParty
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
ci.yml@3ceca4002cd42be7f91c7af583800f6934d84499 -
Trigger Event:
push
-
Statement type:
File details
Details for the file llvm_nanobind-21.1.6.2-cp312-abi3-manylinux_2_28_aarch64.whl.
File metadata
- Download URL: llvm_nanobind-21.1.6.2-cp312-abi3-manylinux_2_28_aarch64.whl
- Upload date:
- Size: 58.5 MB
- Tags: CPython 3.12+, manylinux: glibc 2.28+ ARM64
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
5a8f0d85a99d7ec48d5d1c0adacedb524e73c1455d53bafdd00afc232b85224b
|
|
| MD5 |
f743c49d337ae2e6820374ef5c56bd3c
|
|
| BLAKE2b-256 |
d4534a9138f771dfc5c6132b5a6f0957febdb97df8430d34d0011714b6113093
|
Provenance
The following attestation bundles were made for llvm_nanobind-21.1.6.2-cp312-abi3-manylinux_2_28_aarch64.whl:
Publisher:
ci.yml on LLVMParty/llvm-nanobind
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
llvm_nanobind-21.1.6.2-cp312-abi3-manylinux_2_28_aarch64.whl -
Subject digest:
5a8f0d85a99d7ec48d5d1c0adacedb524e73c1455d53bafdd00afc232b85224b - Sigstore transparency entry: 1528195021
- Sigstore integration time:
-
Permalink:
LLVMParty/llvm-nanobind@3ceca4002cd42be7f91c7af583800f6934d84499 -
Branch / Tag:
refs/tags/v21.1.6.2 - Owner: https://github.com/LLVMParty
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
ci.yml@3ceca4002cd42be7f91c7af583800f6934d84499 -
Trigger Event:
push
-
Statement type:
File details
Details for the file llvm_nanobind-21.1.6.2-cp312-abi3-macosx_13_0_x86_64.whl.
File metadata
- Download URL: llvm_nanobind-21.1.6.2-cp312-abi3-macosx_13_0_x86_64.whl
- Upload date:
- Size: 47.0 MB
- Tags: CPython 3.12+, macOS 13.0+ x86-64
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
c7993f2e4e98757de80ee97666cb9bb968adede7f63106d87d7ce381e989d77a
|
|
| MD5 |
2e1d028f75eeca394f1845675797707b
|
|
| BLAKE2b-256 |
43db5afbd5d9703d6bf1b58a211de08d1cc67f4405f547afe4110a035a1ecb95
|
Provenance
The following attestation bundles were made for llvm_nanobind-21.1.6.2-cp312-abi3-macosx_13_0_x86_64.whl:
Publisher:
ci.yml on LLVMParty/llvm-nanobind
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
llvm_nanobind-21.1.6.2-cp312-abi3-macosx_13_0_x86_64.whl -
Subject digest:
c7993f2e4e98757de80ee97666cb9bb968adede7f63106d87d7ce381e989d77a - Sigstore transparency entry: 1528195116
- Sigstore integration time:
-
Permalink:
LLVMParty/llvm-nanobind@3ceca4002cd42be7f91c7af583800f6934d84499 -
Branch / Tag:
refs/tags/v21.1.6.2 - Owner: https://github.com/LLVMParty
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
ci.yml@3ceca4002cd42be7f91c7af583800f6934d84499 -
Trigger Event:
push
-
Statement type:
File details
Details for the file llvm_nanobind-21.1.6.2-cp312-abi3-macosx_13_0_arm64.whl.
File metadata
- Download URL: llvm_nanobind-21.1.6.2-cp312-abi3-macosx_13_0_arm64.whl
- Upload date:
- Size: 44.0 MB
- Tags: CPython 3.12+, macOS 13.0+ ARM64
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
fea0242d4225f1f5b33e8e561f2b9d2f9beb92a405b1183e6d2704647fb73f36
|
|
| MD5 |
da0b7e82e03537e628c4d320c90eaf3e
|
|
| BLAKE2b-256 |
fd8d38e69ac12e3327ed1fc4ede719526c3d699cb1339e8d0475771a48f7aecc
|
Provenance
The following attestation bundles were made for llvm_nanobind-21.1.6.2-cp312-abi3-macosx_13_0_arm64.whl:
Publisher:
ci.yml on LLVMParty/llvm-nanobind
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
llvm_nanobind-21.1.6.2-cp312-abi3-macosx_13_0_arm64.whl -
Subject digest:
fea0242d4225f1f5b33e8e561f2b9d2f9beb92a405b1183e6d2704647fb73f36 - Sigstore transparency entry: 1528195236
- Sigstore integration time:
-
Permalink:
LLVMParty/llvm-nanobind@3ceca4002cd42be7f91c7af583800f6934d84499 -
Branch / Tag:
refs/tags/v21.1.6.2 - Owner: https://github.com/LLVMParty
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
ci.yml@3ceca4002cd42be7f91c7af583800f6934d84499 -
Trigger Event:
push
-
Statement type: