2026-02-20 19:48:39 -05:00
2026-05-11 16:45:05 +02:00
2026-02-16 12:50:51 +01:00
2026-05-11 16:45:05 +02:00
2026-05-11 16:45:05 +02:00
2026-05-12 01:49:51 +02:00
2025-12-23 18:03:49 +01:00
2025-11-26 18:55:17 +01:00
2026-05-12 01:49:51 +02:00
2026-05-11 16:45:05 +02:00
2026-02-20 16:47:46 -05:00
2026-02-20 16:47:46 -05:00
2025-12-04 14:09:20 +01:00
2026-05-12 01:49:51 +02:00
2026-05-11 16:45:05 +02:00
2026-05-12 01:49:51 +02:00
2026-05-12 01:49:51 +02:00
2026-05-12 01:49:51 +02:00

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.

Status: Under active development. Core APIs are bound and tested against LLVM's llvm-c-test suite, but the API is not yet stable. Expect breaking changes.

Note: This project is 90%+ vibe coded. It is mostly an experiment to see what LLMs can do when you set things up properly.

Features

  • Comprehensive LLVM-C API coverage (~7300 lines of bindings)
  • Memory-safe: validity tokens prevent use-after-free crashes
  • Type-safe: auto-generated .pyi stubs for IDE support
  • Tested: 25+ lit tests, 15 golden master test pairs

Installation

This package requires LLVM 21+ to be installed. The build will automatically find LLVM if it's in your PATH, or you can specify the path:

export CMAKE_PREFIX_PATH=/path/to/llvm
pip install .

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:
    with ctx.create_module("example") as mod:
        # Create function type: i32 ()
        i32 = ctx.int32_type()
        fn_type = ctx.function_type(i32, [])
        
        # Create function and basic block
        fn = mod.add_function("get_answer", fn_type)
        bb = fn.append_basic_block("entry")
        
        # Build return instruction
        with ctx.create_builder() as builder:
            builder.position_at_end(bb)
            builder.ret(llvm.const_int(i32, 42))
        
        # Print the IR
        print(mod)

Development

Setup

# Configure (first time)
cmake -B build -G Ninja

# Build
cmake --build build

# Or use uv (recommended) - auto-rebuilds as needed
uv sync

# Offline build
uv sync --offline --no-build-isolation --verbose

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/*"

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.

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.

Windows

Download LLVM+Clang:

Merge them together in C:\llvm-21.1.1.

Create CMakeUserPresets.json:

{
    "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",
                "CMAKE_PREFIX_PATH": "d:/llvm-21.1.1"
            }
        }
    ],
    "buildPresets": [
        {
            "name": "clang-cl",
            "configurePreset": "clang-cl"
        }
    ]
}

Create a virtual environment:

uv venv

Activate the virtual environment:

.venv/Scripts/activate

Configure the CMake project (this should find the Python from your venv):

cmake --preset clang-cl

Note: This saves the LLVM prefix to a file called .llvm-prefix, make sure to delete that if you change the LLVM prefix path.

Build the bindings:

cmake --build build

After that works you can build the Python package with uv:

uv sync --verbose
S
Description
Automated archival mirror of github.com/LLVMParty/llvm-nanobind
Readme MIT
1.5 MiB
Languages
C++ 45.1%
Python 32.8%
C 16.3%
HTML 2.6%
LLVM 2.3%
Other 0.9%