mirror of
https://github.com/LLVMParty/llvm-nanobind
synced 2026-06-21 13:43:38 +00:00
5.7 KiB
5.7 KiB
API UX Cleanup Progress
Status
Implemented and tested the active UX work:
- generic intrinsic helper,
- explicit module optimization helper,
- object/assembly emission convenience,
- JIT through LLVM-C ORC LLJIT,
- metadata/debug-info cleanup.
Implemented APIs
Phase 1: Generic intrinsic helper
- Added
Builder.intrinsic(name, args, *, overloaded_types=..., name_hint=""). - Added no-overload form
Builder.intrinsic(name, args, *, name_hint=""). - Internally looks up the intrinsic ID by name.
- Uses
overloaded_typesas LLVM's overload-disambiguation type list. - Raises a clear error for unknown intrinsic names.
- Raises a clear error when an overloaded intrinsic needs
overloaded_types. - Keeps existing lower-level intrinsic APIs public.
- Tests cover non-overloaded, overloaded, and memory intrinsics.
Phase 2: Module optimization helper
- Added
Module.optimize(pipeline, *, target_machine=None, options=None). - Uses LLVM PassBuilder pipeline strings directly.
- Mutates the module in place.
- Includes the failed pipeline string in error messages.
- Keeps existing lower-level pass APIs public.
- Fixed optional pass options by creating a default
PassBuilderOptionsinternally when none is provided. - Tests cover success and failure paths.
Phase 3: Object/assembly emission convenience
- Added
TargetMachine.host(...). - Added
Module.emit_object(*, target_machine=None). - Added
Module.emit_assembly(*, target_machine=None). - If
target_machineis omitted, creates a host target machine internally. - Emission methods do not run optimization passes.
- Keeps
TargetMachine.emit_to_memory_bufferpublic. - Tests cover object, assembly, host target, explicit target machine, and BinaryManager parsing.
Phase 4: JIT through LLVM-C
- Inspected available LLVM-C headers and chose ORC LLJIT C API.
- Added
llvm.JIT.host()context manager. - Implemented module ownership transfer for
jit.add_module(mod). jit.add_module(mod)invalidates the PythonModulewrapper on success.- Added
jit.lookup(name) -> int. - Added
jit.ctypes_function(...)callable wrapper. jit.ctypes_function(...)keeps the JIT object alive while the returned callable wrapper is alive.- Added
jit.add_symbol(...)for integer addresses and ctypes callbacks. - ctypes callback objects are pinned while the JIT is alive and released on dispose.
- Unsupported host target/JIT setup raises
LLVMError; tests skip target-dependent checks cleanly when unavailable.
Phase 5: Metadata/debug-info cleanup
- Added
Value.metadatamapping view by metadata kind name. - Added
Metadata.kind,is_string,is_node,is_value,string,operands, andvalueaccessors. - Stubbed
Metadata.valuewithNotImplementedErrorbecause LLVM-C cannot unwrap ValueAsMetadata to Value. - Added
MetadataMap.copy_to(target, include_debug_location=False)so transforms can copy arbitrary attached metadata without exposing kind IDs. - Added support for detached instruction metadata by deriving the context from the value type.
- Added
Module.named_metadatamapping/list view. - Added
NamedMetadataMap.keys()and iteration. - Added
Module.module_flagsview. - Added
Context.debug_location(...). - Added
Builder.debug_location(...)context manager. - Added DIBuilder recipes:
file,compile_unit,function,local_variable. - Removed redundant public low-level metadata APIs: raw metadata kind lookup, raw
Value.set_metadata, publicValueMetadataEntries, publicNamedMDNode,Metadata.as_value, raw named-metadata methods, and raw module-flag methods. - Removed redundant DIBuilder aliases covered by recipes:
create_file,create_compile_unit. - Kept advanced DIBuilder
create_*methods where the recipes do not provide full coverage.
Tests added
tests/regressions/test_api_ux_cleanup.pytests/regressions/test_metadata_ux_cleanup.py
Coverage:
- non-overloaded intrinsic call,
- overloaded floating-point intrinsic call,
- memory intrinsic call,
- unknown intrinsic error,
- missing overload types error,
- module optimization success and invalid-pipeline failure,
- optimization with target machine,
- object and assembly emission,
- emitted object opens with
BinaryManager, - JIT integer function lookup and ctypes call,
- module invalidation after JIT transfer,
- missing JIT symbol error,
- JIT ctypes callable keeps the JIT alive,
- JIT callback symbol registration and callback lifetime pinning.
Documentation and examples updated
README.mdcurrent capabilities, known limitations, and example links.devdocs/api-reference.mdhigh-level UX helper examples.devdocs/api-ux-cleanup/plan.mdremains the task design reference.examples/intrinsic_memcpy.pyshowsBuilder.intrinsic(...).examples/optimize_module.pyshowsModule.optimize(...).examples/emit_object_assembly.pyshowsTargetMachine.host(),emit_object(), andemit_assembly().examples/jit_add.pyshowsJIT.host(),add_module(),lookupviactypes_function(), andadd_symbol().
Validation performed
cmake --build build
uv run tests/regressions/test_api_ux_cleanup.py
uv run pytest tests/regressions/test_api_ux_cleanup.py -q
uv run tests/regressions/test_metadata_ux_cleanup.py
uv run pytest tests/regressions/test_metadata_ux_cleanup.py tests/test_examples.py -q
uv run run_tests.py --regressions
uv run run_tests.py
uv run run_llvm_c_tests.py --use-python
uvx ty check
All commands passed.