mirror of
https://github.com/LLVMParty/llvm-nanobind
synced 2026-06-21 13:43:38 +00:00
Archive feature-matrix task
This commit is contained in:
@@ -74,6 +74,7 @@ The `archive/` directory contains summaries of completed work:
|
||||
| File | Summary |
|
||||
|------|---------|
|
||||
| `bindings.md` | Core Python bindings: ownership model, exception hierarchy, wrapper patterns |
|
||||
| `feature-matrix.md` | LLVM-C API coverage: ~85% implemented, skip justifications, test suite |
|
||||
| `fixing-tests.md` | Test fixing work: borrowed contexts, diagnostic registry, syncscope gotchas |
|
||||
| `llvm-c-test.md` | Python port of llvm-c-test: 22 commands, echo architecture, testing |
|
||||
| `module-api.md` | API refactor: moving global functions to Module/Builder/Function methods |
|
||||
|
||||
@@ -0,0 +1,83 @@
|
||||
# Feature Matrix Implementation
|
||||
|
||||
**Completed:** December 2024
|
||||
|
||||
## Goal
|
||||
|
||||
Implement remaining LLVM-C API bindings to reach ~85% coverage of the C API, with explicit documentation of what's skipped and why.
|
||||
|
||||
## Final Coverage
|
||||
|
||||
| Header | Coverage | Notes |
|
||||
|--------|----------|-------|
|
||||
| Core.h | 82% | Main API, extensive |
|
||||
| DebugInfo.h | ~83% | Debug info creation |
|
||||
| Target.h | 100% | Target queries |
|
||||
| TargetMachine.h | 79% | Code generation |
|
||||
| Object.h | 77% | Object file parsing |
|
||||
| PassBuilder.h | 100% | Optimization passes |
|
||||
| Analysis.h | 100% | Verification |
|
||||
| BitWriter.h | 100% | Bitcode output |
|
||||
| Linker.h | 100% | Module linking |
|
||||
| Comdat.h | 100% | Windows COMDAT |
|
||||
| **Total** | **~85%** | |
|
||||
|
||||
## Key Implementations
|
||||
|
||||
### Session 6 - Final Items
|
||||
|
||||
**Core.h:**
|
||||
- `llvm.get_cast_opcode(src, src_signed, dest_ty, dest_signed)` - Determine cast instruction
|
||||
- `llvm.intrinsic_get_type(ctx, id, param_types)` - Get intrinsic return type
|
||||
- `llvm.replace_md_node_operand_with(val, index, replacement)` - Metadata modification
|
||||
|
||||
**DebugInfo.h:**
|
||||
- `dib.create_class_type(...)` - C++ class debug info
|
||||
- `dib.create_static_member_type(...)` - Static members
|
||||
- `dib.create_member_pointer_type(...)` - Pointer-to-member
|
||||
- `dib.insert_declare_record_before(...)` - Debug intrinsic records
|
||||
- `dib.insert_dbg_value_record_before(...)` - Debug value records
|
||||
- `llvm.di_global_variable_expression_get_{variable,expression}()` - GVE accessors
|
||||
|
||||
**Object.h:**
|
||||
- `binary.copy_to_memory_buffer()` - Returns Python `bytes`
|
||||
- `section.contains_symbol(symbol)` - Symbol membership test
|
||||
|
||||
**Comdat.h (all 5 functions):**
|
||||
- `mod.get_or_insert_comdat(name)` - Get/create COMDAT
|
||||
- `gv.comdat` / `gv.set_comdat(comdat)` - Global COMDAT access
|
||||
- `comdat.selection_kind` - Selection kind property
|
||||
|
||||
## Explicitly Skipped
|
||||
|
||||
| Item | Reason |
|
||||
|------|--------|
|
||||
| `LLVMCreateMemoryBufferWithMemoryRange` | Zero-copy unsafe with Python GC |
|
||||
| Support.h JIT functions (4) | JIT symbol resolution not in scope |
|
||||
| ErrorHandling.h (3) | C callback-based fatal error handling problematic in Python |
|
||||
|
||||
## Design Decisions
|
||||
|
||||
1. **MemoryBuffer is internal** - Users work with `bytes` or file paths directly (per parsing-refactor.md)
|
||||
|
||||
2. **DIBuilder via context manager** - `with mod.create_dibuilder() as dib:` ensures finalization
|
||||
|
||||
3. **`@api LLVMXyz` documentation** - Added to docstrings to reference underlying C API (40% coverage, ongoing)
|
||||
|
||||
4. **Global functions for metadata accessors** - `llvm.di_location_get_line(loc)` style for standalone helpers
|
||||
|
||||
## Test Suite
|
||||
|
||||
Created `tests/test_feature_matrix.py` with comprehensive tests for all Session 6 items:
|
||||
- Cast opcode determination
|
||||
- Intrinsic type lookup
|
||||
- Metadata replacement
|
||||
- Debug info type creation
|
||||
- Object file operations
|
||||
- COMDAT operations
|
||||
|
||||
## References
|
||||
|
||||
- Feature matrix files: `devdocs/feature-matrix/*.md` (now archived)
|
||||
- API design: `devdocs/archive/parsing-refactor.md`
|
||||
- Memory model: `devdocs/memory-model.md`
|
||||
@@ -1,173 +0,0 @@
|
||||
# Agent Prompt: Complete LLVM-C API Feature Matrix
|
||||
|
||||
## Your Mission
|
||||
|
||||
Implement ALL remaining TODO items from the LLVM-C API feature matrix. Continue working until every item is either:
|
||||
1. ✅ Implemented with tests passing
|
||||
2. 🚫 Explicitly marked as skipped with justification
|
||||
|
||||
**Do not stop until the task is complete.**
|
||||
|
||||
---
|
||||
|
||||
## Context Files to Read First
|
||||
|
||||
1. **Read `devdocs/feature-matrix/implementation-task.md`** - Contains the prioritized TODO list and skip rules
|
||||
2. **Read `devdocs/api-design-philosophy.md`** - Understand API design principles
|
||||
3. **Read `AGENTS.md`** - Build and test commands
|
||||
|
||||
---
|
||||
|
||||
## Critical Rules
|
||||
|
||||
### DO NOT Implement (Mark as 🚫 Skip)
|
||||
|
||||
1. **Manual memory management** - `LLVMDispose*`, `LLVMCreate*` requiring manual cleanup
|
||||
2. **Global context functions** - Anything using `LLVMGetGlobalContext()`
|
||||
3. **Deprecated functions** - `LLVMX86MMXType`, `LLVMBuildNUWNeg`, legacy pass manager
|
||||
4. **Debugging-only** - `LLVMDump*`, `LLVMViewFunctionCFG*`
|
||||
5. **Temporary metadata nodes** - `LLVMTemporaryMDNode`, `LLVMDisposeTemporaryMDNode`
|
||||
6. **Module flag iteration** - Complex API, can parse IR instead
|
||||
7. **FP math tags** - Very specialized
|
||||
|
||||
### API Design Rules
|
||||
|
||||
- Operations on objects → **methods**, not global functions
|
||||
- No-argument getters → **properties**
|
||||
- Collections → return **lists**, not iterators
|
||||
- Always call `check_valid()` before LLVM-C API calls
|
||||
- Use wrapper classes with validity tokens for return values
|
||||
|
||||
---
|
||||
|
||||
## Implementation Loop
|
||||
|
||||
For each remaining TODO item:
|
||||
|
||||
### Step 1: Add C++ Implementation
|
||||
|
||||
```cpp
|
||||
// In src/llvm-nanobind.cpp
|
||||
|
||||
// For methods on wrapper classes:
|
||||
ReturnWrapper ClassName::method_name(args) {
|
||||
check_valid();
|
||||
// ... validate args ...
|
||||
return ReturnWrapper(LLVMSomeFunction(...), m_context_token);
|
||||
}
|
||||
|
||||
// For free functions:
|
||||
ReturnWrapper function_name(args) {
|
||||
arg.check_valid();
|
||||
return ReturnWrapper(LLVMSomeFunction(...), arg.m_context_token);
|
||||
}
|
||||
```
|
||||
|
||||
### Step 2: Add Python Binding
|
||||
|
||||
```cpp
|
||||
// Method binding:
|
||||
.def("method_name", &ClassName::method_name, "arg"_a,
|
||||
R"(Docstring describing the method.)")
|
||||
|
||||
// Free function binding:
|
||||
m.def("function_name", &function_name, "arg"_a,
|
||||
R"(Docstring describing the function.)")
|
||||
```
|
||||
|
||||
### Step 3: Build and Test
|
||||
|
||||
```bash
|
||||
# Build
|
||||
uv run python -c "import llvm; print('Build OK')"
|
||||
|
||||
# Run tests
|
||||
uv run run_tests.py
|
||||
|
||||
# Type check
|
||||
uvx ty check
|
||||
```
|
||||
|
||||
### Step 4: Update Documentation
|
||||
|
||||
Update these files to mark items as ✅:
|
||||
- `devdocs/feature-matrix/progress.md`
|
||||
- `devdocs/feature-matrix/debuginfo.md` (if debug info related)
|
||||
- `devdocs/feature-matrix/misc.md` (if misc header related)
|
||||
- `devdocs/feature-matrix/core.md` (if Core.h related)
|
||||
|
||||
---
|
||||
|
||||
## Remaining Items Checklist
|
||||
|
||||
### Core.h
|
||||
- [ ] `LLVMGetCastOpcode` → `llvm.get_cast_opcode(src_ty, src_signed, dst_ty, dst_signed)`
|
||||
- [ ] `LLVMIntrinsicGetType` → `llvm.intrinsic_get_type(ctx, id, param_types)`
|
||||
- [ ] `LLVMCreateMemoryBufferWithMemoryRange` → `llvm.MemoryBuffer.from_bytes_no_copy(data)`
|
||||
- [ ] `LLVMReplaceMDNodeOperandWith` → `md_node.replace_operand(index, new_md)`
|
||||
|
||||
### DebugInfo.h
|
||||
- [ ] `LLVMDIBuilderCreateClassType` → `dib.create_class_type(...)`
|
||||
- [ ] `LLVMDIBuilderCreateStaticMemberType` → `dib.create_static_member_type(...)`
|
||||
- [ ] `LLVMDIBuilderCreateMemberPointerType` → `dib.create_member_pointer_type(...)`
|
||||
- [ ] `LLVMDIGlobalVariableExpressionGetVariable` → `gve.variable` property
|
||||
- [ ] `LLVMDIGlobalVariableExpressionGetExpression` → `gve.expression` property
|
||||
- [ ] `LLVMDIBuilderInsertDeclareRecordBefore` → `dib.insert_declare_record_before(...)`
|
||||
- [ ] `LLVMDIBuilderInsertDbgValueRecordBefore` → `dib.insert_dbg_value_record_before(...)`
|
||||
|
||||
### Object.h
|
||||
- [ ] `LLVMBinaryCopyMemoryBuffer` → `binary.copy_to_memory_buffer()`
|
||||
- [ ] `LLVMGetSectionContainsSymbol` → `section.contains_symbol(symbol)`
|
||||
|
||||
### Support.h (JIT)
|
||||
- [ ] `LLVMLoadLibraryPermanently` → `llvm.load_library(path)`
|
||||
- [ ] `LLVMSearchForAddressOfSymbol` → `llvm.search_for_symbol(name)`
|
||||
- [ ] `LLVMAddSymbol` → `llvm.add_symbol(name, addr)`
|
||||
- [ ] `LLVMParseCommandLineOptions` → `llvm.parse_command_line_options(args)`
|
||||
|
||||
### Comdat.h (Windows)
|
||||
- [ ] `LLVMGetOrInsertComdat` → `mod.get_or_insert_comdat(name)`
|
||||
- [ ] `LLVMGetComdat` → `gv.comdat` property
|
||||
- [ ] `LLVMSetComdat` → `gv.comdat = comdat` setter
|
||||
- [ ] `LLVMGetComdatSelectionKind` → `comdat.selection_kind` property
|
||||
- [ ] `LLVMSetComdatSelectionKind` → `comdat.selection_kind = kind` setter
|
||||
|
||||
### ErrorHandling.h
|
||||
- [ ] `LLVMInstallFatalErrorHandler` → `llvm.install_fatal_error_handler(callback)`
|
||||
- [ ] `LLVMResetFatalErrorHandler` → `llvm.reset_fatal_error_handler()`
|
||||
- [ ] `LLVMEnablePrettyStackTrace` → `llvm.enable_pretty_stack_trace()`
|
||||
|
||||
---
|
||||
|
||||
## Completion Verification
|
||||
|
||||
Run this final check:
|
||||
|
||||
```bash
|
||||
# All tests pass
|
||||
uv run run_tests.py
|
||||
|
||||
# Type check passes
|
||||
uvx ty check
|
||||
|
||||
# Verify new functions are accessible
|
||||
uv run python << 'EOF'
|
||||
import llvm
|
||||
|
||||
# Test each new function exists (add your tests here)
|
||||
print("All new functions accessible!")
|
||||
EOF
|
||||
```
|
||||
|
||||
Then update `progress.md` with final coverage numbers.
|
||||
|
||||
---
|
||||
|
||||
## When You're Done
|
||||
|
||||
1. Update `devdocs/feature-matrix/progress.md` summary table with final counts
|
||||
2. Update `devdocs/feature-matrix/summary.md` with final coverage
|
||||
3. Mark `implementation-task.md` as complete
|
||||
4. Report: "Feature matrix implementation complete. Coverage: X%"
|
||||
|
||||
**Keep going until ALL items are handled (implemented or explicitly skipped).**
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,431 +0,0 @@
|
||||
# DebugInfo.h Feature Matrix
|
||||
|
||||
LLVM-C Debug Info API implementation status with Python API mappings.
|
||||
|
||||
**Header:** `llvm-c/DebugInfo.h`
|
||||
|
||||
## Legend
|
||||
|
||||
| Status | Meaning |
|
||||
|--------|---------|
|
||||
| ✅ | Implemented |
|
||||
| ❌ | Not implemented |
|
||||
|
||||
---
|
||||
|
||||
## Quick Start Example
|
||||
|
||||
```python
|
||||
import llvm
|
||||
|
||||
with llvm.create_context() as ctx:
|
||||
with ctx.create_module("example") as mod:
|
||||
# Create DIBuilder
|
||||
with mod.create_dibuilder() as dib:
|
||||
# Create file and compile unit
|
||||
file = dib.create_file("main.c", "/path/to/src")
|
||||
cu = dib.create_compile_unit(
|
||||
lang=0x0001, # DW_LANG_C
|
||||
file=file,
|
||||
producer="my-compiler",
|
||||
is_optimized=False,
|
||||
flags="",
|
||||
runtime_ver=0,
|
||||
split_name="",
|
||||
kind=1, # Full debug info
|
||||
dwo_id=0,
|
||||
split_debug_inlining=True,
|
||||
debug_info_for_profiling=False,
|
||||
sys_root="",
|
||||
sdk=""
|
||||
)
|
||||
|
||||
# Create function debug info
|
||||
fn_type = dib.create_subroutine_type(file, [], 0)
|
||||
fn_di = dib.create_function(
|
||||
scope=file,
|
||||
name="main",
|
||||
linkage_name="main",
|
||||
file=file,
|
||||
line_no=10,
|
||||
subroutine_type=fn_type,
|
||||
is_local_to_unit=False,
|
||||
is_definition=True,
|
||||
scope_line=10,
|
||||
flags=0,
|
||||
is_optimized=False
|
||||
)
|
||||
|
||||
# Create debug location
|
||||
loc = llvm.dibuilder_create_debug_location(ctx, 10, 0, fn_di, None)
|
||||
|
||||
# Finalize debug info
|
||||
dib.finalize()
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## DIBuilder Management
|
||||
|
||||
| C API | Python API | Example |
|
||||
|-------|------------|---------|
|
||||
| `LLVMCreateDIBuilder` | `mod.create_dibuilder()` | `with mod.create_dibuilder() as dib:` |
|
||||
| `LLVMDisposeDIBuilder` | Context manager `__exit__` | Automatic |
|
||||
| `LLVMDIBuilderFinalize` | `dib.finalize()` | `dib.finalize()` |
|
||||
| `LLVMDIBuilderFinalizeSubprogram` | ✅ | `dib.finalize_subprogram(subprogram)` |
|
||||
|
||||
```python
|
||||
with mod.create_dibuilder() as dib:
|
||||
# Create debug info...
|
||||
dib.finalize() # Must call before exiting
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Compile Unit & File
|
||||
|
||||
| C API | Python API | Example |
|
||||
|-------|------------|---------|
|
||||
| `LLVMDIBuilderCreateFile` | `dib.create_file(filename, directory)` | `file = dib.create_file("main.c", ".")` |
|
||||
| `LLVMDIBuilderCreateCompileUnit` | `dib.create_compile_unit(...)` | See example above |
|
||||
| `LLVMDIBuilderCreateModule` | `dib.create_module(parent, name, ...)` | `mod_di = dib.create_module(cu, "mymod", "", "", "")` |
|
||||
| `LLVMDIBuilderCreateNameSpace` | `dib.create_namespace(scope, name, export)` | `ns = dib.create_namespace(file, "myns", True)` |
|
||||
|
||||
---
|
||||
|
||||
## Functions & Scopes
|
||||
|
||||
| C API | Python API | Example |
|
||||
|-------|------------|---------|
|
||||
| `LLVMDIBuilderCreateFunction` | `dib.create_function(...)` | See example above |
|
||||
| `LLVMDIBuilderCreateLexicalBlock` | `dib.create_lexical_block(scope, file, line, col)` | `block = dib.create_lexical_block(fn_di, file, 10, 0)` |
|
||||
| `LLVMDIBuilderCreateLexicalBlockFile` | ✅ | `dib.create_lexical_block_file(scope, file, discriminator)` |
|
||||
| `LLVMDIBuilderCreateSubroutineType` | `dib.create_subroutine_type(file, types, flags)` | `fn_ty = dib.create_subroutine_type(file, [ret, arg1], 0)` |
|
||||
|
||||
```python
|
||||
# Create function type: void(int, float)
|
||||
void_ty = None # Use None for void return
|
||||
int_ty = dib.create_basic_type("int", 32, 5, 0) # DW_ATE_signed
|
||||
float_ty = dib.create_basic_type("float", 32, 4, 0) # DW_ATE_float
|
||||
fn_type = dib.create_subroutine_type(file, [void_ty, int_ty, float_ty], 0)
|
||||
|
||||
# Create function debug info
|
||||
fn_di = dib.create_function(
|
||||
scope=file,
|
||||
name="my_func",
|
||||
linkage_name="my_func",
|
||||
file=file,
|
||||
line_no=20,
|
||||
subroutine_type=fn_type,
|
||||
is_local_to_unit=False,
|
||||
is_definition=True,
|
||||
scope_line=20,
|
||||
flags=0,
|
||||
is_optimized=False
|
||||
)
|
||||
|
||||
# Attach to LLVM function
|
||||
fn.set_subprogram(fn_di)
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Debug Locations
|
||||
|
||||
| C API | Python API | Example |
|
||||
|-------|------------|---------|
|
||||
| `LLVMDIBuilderCreateDebugLocation` | `llvm.dibuilder_create_debug_location(ctx, line, col, scope, inlined_at)` | See below |
|
||||
| `LLVMDILocationGetLine` | ✅ | `llvm.di_location_get_line(loc)` |
|
||||
| `LLVMDILocationGetColumn` | ✅ | `llvm.di_location_get_column(loc)` |
|
||||
| `LLVMDILocationGetScope` | ✅ | `llvm.di_location_get_scope(loc)` |
|
||||
| `LLVMDILocationGetInlinedAt` | ✅ | `llvm.di_location_get_inlined_at(loc)` |
|
||||
|
||||
```python
|
||||
# Create debug location
|
||||
loc = llvm.dibuilder_create_debug_location(ctx, 25, 4, fn_di, None)
|
||||
|
||||
# Attach to builder for subsequent instructions
|
||||
builder.current_debug_location = loc
|
||||
|
||||
# Now all instructions will have this location
|
||||
val = builder.add(a, b, "sum")
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Basic Types
|
||||
|
||||
| C API | Python API | Example |
|
||||
|-------|------------|---------|
|
||||
| `LLVMDIBuilderCreateBasicType` | `dib.create_basic_type(name, bits, encoding, flags)` | See below |
|
||||
| `LLVMDIBuilderCreatePointerType` | `dib.create_pointer_type(pointee, bits, align, as, name)` | See below |
|
||||
| `LLVMDIBuilderCreateVectorType` | `dib.create_vector_type(bits, align, elem, subscripts)` | - |
|
||||
|
||||
```python
|
||||
# Basic types (DWARF encoding values)
|
||||
# DW_ATE_boolean = 2, DW_ATE_signed = 5, DW_ATE_unsigned = 7, DW_ATE_float = 4
|
||||
int_ty = dib.create_basic_type("int", 32, 5, 0) # signed int
|
||||
uint_ty = dib.create_basic_type("unsigned int", 32, 7, 0)
|
||||
float_ty = dib.create_basic_type("float", 32, 4, 0)
|
||||
double_ty = dib.create_basic_type("double", 64, 4, 0)
|
||||
bool_ty = dib.create_basic_type("bool", 8, 2, 0)
|
||||
|
||||
# Pointer type
|
||||
ptr_ty = dib.create_pointer_type(int_ty, 64, 64, 0, "")
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Composite Types
|
||||
|
||||
| C API | Python API | Example |
|
||||
|-------|------------|---------|
|
||||
| `LLVMDIBuilderCreateStructType` | `dib.create_struct_type(...)` | See below |
|
||||
| `LLVMDIBuilderCreateEnumerationType` | `dib.create_enumeration_type(...)` | See below |
|
||||
| `LLVMDIBuilderCreateUnionType` | ✅ | `dib.create_union_type(scope, name, file, line, size, align, flags, elements, runtime_lang, unique_id)` |
|
||||
| `LLVMDIBuilderCreateArrayType` | ✅ | `dib.create_array_type(size, align, elem_type, subscripts)` |
|
||||
| `LLVMDIBuilderCreateMemberType` | ✅ | `dib.create_member_type(scope, name, file, line, size, align, offset, flags, type)` |
|
||||
| `LLVMDIBuilderCreateForwardDecl` | `dib.create_forward_decl(...)` | - |
|
||||
| `LLVMDIBuilderCreateReplaceableCompositeType` | `dib.create_replaceable_composite_type(...)` | - |
|
||||
| `LLVMDIBuilderCreateTypedef` | `dib.create_typedef(type, name, file, line, scope, align)` | `td = dib.create_typedef(int_ty, "myint", file, 1, file, 0)` |
|
||||
|
||||
```python
|
||||
# Struct type
|
||||
struct_ty = dib.create_struct_type(
|
||||
scope=file,
|
||||
name="Point",
|
||||
file=file,
|
||||
line_number=5,
|
||||
size_in_bits=128,
|
||||
align_in_bits=64,
|
||||
flags=0,
|
||||
derived_from=None,
|
||||
elements=[], # Add members later
|
||||
runtime_lang=0,
|
||||
vtable_holder=None,
|
||||
unique_id="Point"
|
||||
)
|
||||
|
||||
# Enumeration type
|
||||
enum_ty = dib.create_enumeration_type(
|
||||
scope=file,
|
||||
name="Color",
|
||||
file=file,
|
||||
line_number=10,
|
||||
size_in_bits=32,
|
||||
align_in_bits=32,
|
||||
elements=[
|
||||
dib.create_enumerator("Red", 0, False),
|
||||
dib.create_enumerator("Green", 1, False),
|
||||
dib.create_enumerator("Blue", 2, False),
|
||||
],
|
||||
underlying_type=int_ty
|
||||
)
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Variables
|
||||
|
||||
| C API | Python API | Example |
|
||||
|-------|------------|---------|
|
||||
| `LLVMDIBuilderCreateParameterVariable` | `dib.create_parameter_variable(...)` | See below |
|
||||
| `LLVMDIBuilderCreateAutoVariable` | `dib.create_auto_variable(...)` | See below |
|
||||
| `LLVMDIBuilderCreateGlobalVariableExpression` | `dib.create_global_variable_expression(...)` | See below |
|
||||
| `LLVMDIBuilderInsertDeclareAtEnd` | ❌ | Use record versions |
|
||||
| `LLVMDIBuilderInsertDeclareRecordAtEnd` | `dib.insert_declare_record_at_end(...)` | - |
|
||||
| `LLVMDIBuilderInsertDbgValueRecordAtEnd` | `dib.insert_dbg_value_record_at_end(...)` | - |
|
||||
| `LLVMDIBuilderInsertDeclareRecordBefore` | ❌ | TODO |
|
||||
| `LLVMDIBuilderInsertDbgValueRecordBefore` | ❌ | TODO |
|
||||
|
||||
```python
|
||||
# Parameter variable
|
||||
param_var = dib.create_parameter_variable(
|
||||
scope=fn_di,
|
||||
name="x",
|
||||
arg_no=1, # 1-indexed
|
||||
file=file,
|
||||
line_no=20,
|
||||
type=int_ty,
|
||||
always_preserve=True,
|
||||
flags=0
|
||||
)
|
||||
|
||||
# Auto (local) variable
|
||||
local_var = dib.create_auto_variable(
|
||||
scope=fn_di,
|
||||
name="result",
|
||||
file=file,
|
||||
line_no=22,
|
||||
type=int_ty,
|
||||
always_preserve=True,
|
||||
flags=0,
|
||||
align_in_bits=32
|
||||
)
|
||||
|
||||
# Global variable
|
||||
global_expr = dib.create_global_variable_expression(
|
||||
scope=file,
|
||||
name="global_counter",
|
||||
linkage="global_counter",
|
||||
file=file,
|
||||
line_no=5,
|
||||
type=int_ty,
|
||||
is_local_to_unit=False,
|
||||
expr=dib.create_expression([]),
|
||||
decl=None,
|
||||
align_in_bits=32
|
||||
)
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Expressions
|
||||
|
||||
| C API | Python API | Example |
|
||||
|-------|------------|---------|
|
||||
| `LLVMDIBuilderCreateExpression` | `dib.create_expression(addr)` | `expr = dib.create_expression([])` |
|
||||
| `LLVMDIBuilderCreateConstantValueExpression` | `dib.create_constant_value_expression(val)` | `expr = dib.create_constant_value_expression(42)` |
|
||||
|
||||
---
|
||||
|
||||
## Subranges & Arrays
|
||||
|
||||
| C API | Python API | Example |
|
||||
|-------|------------|---------|
|
||||
| `LLVMDIBuilderGetOrCreateSubrange` | `dib.get_or_create_subrange(lo, count)` | `sr = dib.get_or_create_subrange(0, 10)` |
|
||||
| `LLVMDIBuilderGetOrCreateArray` | `dib.get_or_create_array(elements)` | `arr = dib.get_or_create_array([md1, md2])` |
|
||||
| `LLVMDIBuilderGetOrCreateTypeArray` | ✅ | `dib.get_or_create_type_array(types)` |
|
||||
|
||||
---
|
||||
|
||||
## Enumerators
|
||||
|
||||
| C API | Python API | Example |
|
||||
|-------|------------|---------|
|
||||
| `LLVMDIBuilderCreateEnumerator` | `dib.create_enumerator(name, val, unsigned)` | `e = dib.create_enumerator("Red", 0, False)` |
|
||||
| `LLVMDIBuilderCreateEnumeratorOfArbitraryPrecision` | `dib.create_enumerator_of_arbitrary_precision(...)` | - |
|
||||
|
||||
---
|
||||
|
||||
## Labels
|
||||
|
||||
| C API | Python API | Example |
|
||||
|-------|------------|---------|
|
||||
| `LLVMDIBuilderCreateLabel` | `dib.create_label(scope, name, file, line, preserve)` | `lbl = dib.create_label(fn_di, "loop", file, 30, True)` |
|
||||
| `LLVMDIBuilderInsertLabelAtEnd` | `dib.insert_label_at_end(label, loc, bb)` | - |
|
||||
| `LLVMDIBuilderInsertLabelBefore` | `dib.insert_label_before(label, loc, inst)` | - |
|
||||
|
||||
---
|
||||
|
||||
## Imports
|
||||
|
||||
| C API | Python API | Example |
|
||||
|-------|------------|---------|
|
||||
| `LLVMDIBuilderCreateImportedModuleFromNamespace` | ✅ | `dib.create_imported_module_from_namespace(scope, ns, file, line)` |
|
||||
| `LLVMDIBuilderCreateImportedModuleFromAlias` | `dib.create_imported_module_from_alias(...)` | - |
|
||||
| `LLVMDIBuilderCreateImportedModuleFromModule` | `dib.create_imported_module_from_module(...)` | - |
|
||||
| `LLVMDIBuilderCreateImportedDeclaration` | ✅ | `dib.create_imported_declaration(scope, decl, file, line, name, elements)` |
|
||||
|
||||
---
|
||||
|
||||
## Macros
|
||||
|
||||
| C API | Python API | Example |
|
||||
|-------|------------|---------|
|
||||
| `LLVMDIBuilderCreateMacro` | `dib.create_macro(parent, line, type, name, val)` | - |
|
||||
| `LLVMDIBuilderCreateTempMacroFile` | `dib.create_temp_macro_file(parent, line, file)` | - |
|
||||
|
||||
---
|
||||
|
||||
## ObjC Support
|
||||
|
||||
| C API | Python API | Example |
|
||||
|-------|------------|---------|
|
||||
| `LLVMDIBuilderCreateObjCProperty` | `dib.create_objc_property(...)` | - |
|
||||
| `LLVMDIBuilderCreateObjCIVar` | `dib.create_objc_ivar(...)` | - |
|
||||
|
||||
---
|
||||
|
||||
## Inheritance
|
||||
|
||||
| C API | Python API | Example |
|
||||
|-------|------------|---------|
|
||||
| `LLVMDIBuilderCreateInheritance` | `dib.create_inheritance(derived, base, offset, vbptr_offset, flags)` | - |
|
||||
|
||||
---
|
||||
|
||||
## Utility Functions
|
||||
|
||||
| C API | Python API | Example |
|
||||
|-------|------------|---------|
|
||||
| `LLVMGetDINodeTag` | `llvm.get_di_node_tag(md)` | `tag = llvm.get_di_node_tag(type_md)` |
|
||||
| `LLVMDITypeGetName` | `llvm.di_type_get_name(di_type)` | `name = llvm.di_type_get_name(struct_ty)` |
|
||||
| `LLVMDISubprogramReplaceType` | `llvm.di_subprogram_replace_type(sp, ty)` | - |
|
||||
| `LLVMDebugMetadataVersion` | ✅ | `llvm.debug_metadata_version()` |
|
||||
| `LLVMGetModuleDebugMetadataVersion` | ✅ | `llvm.get_module_debug_metadata_version(mod)` |
|
||||
| `LLVMStripModuleDebugInfo` | ✅ | `llvm.strip_module_debug_info(mod)` |
|
||||
|
||||
---
|
||||
|
||||
## File/Scope Queries
|
||||
|
||||
| C API | Python API | Status |
|
||||
|-------|------------|--------|
|
||||
| `LLVMDIScopeGetFile` | ✅ | `llvm.di_scope_get_file(scope)` |
|
||||
| `LLVMDIFileGetDirectory` | ✅ | `llvm.di_file_get_directory(file)` |
|
||||
| `LLVMDIFileGetFilename` | ✅ | `llvm.di_file_get_filename(file)` |
|
||||
| `LLVMDIFileGetSource` | ✅ | `llvm.di_file_get_source(file)` |
|
||||
| `LLVMDISubprogramGetLine` | ✅ | `llvm.di_subprogram_get_line(subprogram)` |
|
||||
| `LLVMDIVariableGetFile` | ✅ | `llvm.di_variable_get_file(variable)` |
|
||||
| `LLVMDIVariableGetScope` | ✅ | `llvm.di_variable_get_scope(variable)` |
|
||||
| `LLVMDIVariableGetLine` | ✅ | `llvm.di_variable_get_line(variable)` |
|
||||
|
||||
---
|
||||
|
||||
## Not Implemented
|
||||
|
||||
| C API | Status | Notes |
|
||||
|-------|--------|-------|
|
||||
| `LLVMDIBuilderCreateStaticMemberType` | ❌ | TODO |
|
||||
| `LLVMDIBuilderCreateClassType` | ❌ | TODO |
|
||||
| `LLVMDIBuilderCreateMemberPointerType` | ❌ | TODO |
|
||||
| `LLVMDIBuilderCreateTempGlobalVariableFwdDecl` | ❌ | TODO |
|
||||
| `LLVMDIGlobalVariableExpressionGetVariable` | ❌ | TODO |
|
||||
| `LLVMDIGlobalVariableExpressionGetExpression` | ❌ | TODO |
|
||||
| `LLVMTemporaryMDNode` | ❌ | TODO |
|
||||
| `LLVMDisposeTemporaryMDNode` | ❌ | TODO |
|
||||
| `LLVMMetadataReplaceAllUsesWith` | ✅ | `md.replace_all_uses_with(new)` |
|
||||
|
||||
## Recently Implemented (Session 5)
|
||||
|
||||
| C API | Python API |
|
||||
|-------|------------|
|
||||
| `LLVMDIBuilderCreateUnionType` | `dib.create_union_type(...)` |
|
||||
| `LLVMDIBuilderCreateArrayType` | `dib.create_array_type(...)` |
|
||||
| `LLVMDIBuilderCreateMemberType` | `dib.create_member_type(...)` |
|
||||
| `LLVMDIBuilderCreateBitFieldMemberType` | `dib.create_bit_field_member_type(...)` |
|
||||
| `LLVMDIBuilderCreateArtificialType` | `dib.create_artificial_type(type)` |
|
||||
| `LLVMDIBuilderCreateQualifiedType` | `dib.create_qualified_type(tag, type)` |
|
||||
| `LLVMDIBuilderCreateReferenceType` | `dib.create_reference_type(tag, type)` |
|
||||
| `LLVMDIBuilderCreateNullPtrType` | `dib.create_null_ptr_type()` |
|
||||
| `LLVMDIBuilderGetOrCreateTypeArray` | `dib.get_or_create_type_array(types)` |
|
||||
| `LLVMDIBuilderFinalizeSubprogram` | `dib.finalize_subprogram(subprogram)` |
|
||||
| `LLVMDIBuilderCreateLexicalBlockFile` | `dib.create_lexical_block_file(...)` |
|
||||
| `LLVMDIBuilderCreateImportedDeclaration` | `dib.create_imported_declaration(...)` |
|
||||
| `LLVMDIBuilderCreateImportedModuleFromNamespace` | `dib.create_imported_module_from_namespace(...)` |
|
||||
| `LLVMDILocationGetLine` | `llvm.di_location_get_line(loc)` |
|
||||
| `LLVMDILocationGetColumn` | `llvm.di_location_get_column(loc)` |
|
||||
| `LLVMDILocationGetScope` | `llvm.di_location_get_scope(loc)` |
|
||||
| `LLVMDILocationGetInlinedAt` | `llvm.di_location_get_inlined_at(loc)` |
|
||||
| `LLVMDebugMetadataVersion` | `llvm.debug_metadata_version()` |
|
||||
| `LLVMGetModuleDebugMetadataVersion` | `llvm.get_module_debug_metadata_version(mod)` |
|
||||
| `LLVMStripModuleDebugInfo` | `llvm.strip_module_debug_info(mod)` |
|
||||
| `LLVMDIScopeGetFile` | `llvm.di_scope_get_file(scope)` |
|
||||
| `LLVMDIFileGetDirectory` | `llvm.di_file_get_directory(file)` |
|
||||
| `LLVMDIFileGetFilename` | `llvm.di_file_get_filename(file)` |
|
||||
| `LLVMDIFileGetSource` | `llvm.di_file_get_source(file)` |
|
||||
| `LLVMDISubprogramGetLine` | `llvm.di_subprogram_get_line(sp)` |
|
||||
| `LLVMDIVariableGetFile` | `llvm.di_variable_get_file(var)` |
|
||||
| `LLVMDIVariableGetScope` | `llvm.di_variable_get_scope(var)` |
|
||||
| `LLVMDIVariableGetLine` | `llvm.di_variable_get_line(var)` |
|
||||
@@ -1,157 +0,0 @@
|
||||
# Feature Matrix Implementation Task
|
||||
|
||||
## ✅ STATUS: COMPLETE (December 2024)
|
||||
|
||||
All priority items have been implemented or explicitly marked as skipped with justification.
|
||||
Final coverage: ~85% of LLVM-C API.
|
||||
|
||||
See `progress.md` for Session 6 with the final implementations.
|
||||
|
||||
---
|
||||
|
||||
## Objective
|
||||
|
||||
Implement all remaining TODO items from the LLVM-C API feature matrix until coverage reaches ~95% or all reasonable items are implemented.
|
||||
|
||||
## Ground Rules
|
||||
|
||||
### DO NOT Implement (Skip These)
|
||||
|
||||
1. **Manual Memory Management Functions** - Python uses context managers for cleanup
|
||||
- `LLVMDispose*` functions (already handled by `__exit__`)
|
||||
- `LLVMCreate*` that return resources requiring manual disposal (use context managers instead)
|
||||
|
||||
2. **Global Context Functions** - Safety risk, always use explicit contexts
|
||||
- Any function using `LLVMGetGlobalContext()`
|
||||
- Functions without `InContext` suffix when a context version exists
|
||||
|
||||
3. **Deprecated Functions** - Use modern alternatives
|
||||
- `LLVMX86MMXTypeInContext` (removed in LLVM 21)
|
||||
- `LLVMBuildNUWNeg` (deprecated in LLVM 21)
|
||||
- Legacy pass manager functions
|
||||
- Old-style `LLVMBuild*` without type parameters (use `*2` versions)
|
||||
|
||||
4. **Debugging-Only Functions** - Not useful in production
|
||||
- `LLVMViewFunctionCFG`, `LLVMViewFunctionCFGOnly` (requires graphviz)
|
||||
- `LLVMDump*` functions (use `print()` instead)
|
||||
|
||||
5. **Internal/Low-Level Functions**
|
||||
- `LLVMCreateMessage`, `LLVMDisposeMessage` (internal memory management)
|
||||
- `LLVMWriteBitcodeToFD`, `LLVMWriteBitcodeToFileHandle` (use file path or memory buffer)
|
||||
|
||||
### API Design Rules (from api-design-philosophy.md)
|
||||
|
||||
1. **Methods belong to objects** - Don't create global functions for operations on objects
|
||||
2. **Use properties** for no-argument getters and boolean checks
|
||||
3. **Use methods** for operations with arguments or side effects
|
||||
4. **Return lists** for collections, not manual iterators
|
||||
5. **Throw exceptions + `has_*`** checks instead of returning None for rare edge cases
|
||||
|
||||
---
|
||||
|
||||
## Remaining TODO Items
|
||||
|
||||
### Priority 1: Core.h Gaps (Medium Value)
|
||||
|
||||
| Function | Target API | Notes |
|
||||
|----------|------------|-------|
|
||||
| `LLVMGetCastOpcode` | `llvm.get_cast_opcode(src_ty, src_signed, dst_ty, dst_signed)` | Utility for determining cast type |
|
||||
| `LLVMIntrinsicGetType` | `llvm.intrinsic_get_type(ctx, id, param_types)` | Get intrinsic function type |
|
||||
| `LLVMCreateMemoryBufferWithMemoryRange` | `llvm.MemoryBuffer.from_bytes_no_copy(data)` | Zero-copy memory buffer |
|
||||
| `LLVMReplaceMDNodeOperandWith` | `md_node.replace_operand(index, new_md)` | Replace metadata operand |
|
||||
|
||||
### Priority 2: DebugInfo.h Gaps (Medium Value)
|
||||
|
||||
| Function | Target API | Notes |
|
||||
|----------|------------|-------|
|
||||
| `LLVMDIBuilderCreateClassType` | `dib.create_class_type(...)` | C++ class debug info |
|
||||
| `LLVMDIBuilderCreateStaticMemberType` | `dib.create_static_member_type(...)` | Static member debug info |
|
||||
| `LLVMDIBuilderCreateMemberPointerType` | `dib.create_member_pointer_type(...)` | Member pointer debug info |
|
||||
| `LLVMDIGlobalVariableExpressionGetVariable` | `gve.variable` (property) | Get variable from GVE |
|
||||
| `LLVMDIGlobalVariableExpressionGetExpression` | `gve.expression` (property) | Get expression from GVE |
|
||||
| `LLVMDIBuilderInsertDeclareRecordBefore` | `dib.insert_declare_record_before(...)` | Insert before instruction |
|
||||
| `LLVMDIBuilderInsertDbgValueRecordBefore` | `dib.insert_dbg_value_record_before(...)` | Insert before instruction |
|
||||
|
||||
### Priority 3: Object.h Gaps (Low Value)
|
||||
|
||||
| Function | Target API | Notes |
|
||||
|----------|------------|-------|
|
||||
| `LLVMBinaryCopyMemoryBuffer` | `binary.copy_to_memory_buffer()` | Copy binary content |
|
||||
| `LLVMGetSectionContainsSymbol` | `section.contains_symbol(symbol)` | Check if section has symbol |
|
||||
|
||||
### Priority 4: Support.h (JIT Support - Low Value)
|
||||
|
||||
| Function | Target API | Notes |
|
||||
|----------|------------|-------|
|
||||
| `LLVMLoadLibraryPermanently` | `llvm.load_library(path)` | For JIT symbol resolution |
|
||||
| `LLVMSearchForAddressOfSymbol` | `llvm.search_for_symbol(name)` | For JIT symbol resolution |
|
||||
| `LLVMAddSymbol` | `llvm.add_symbol(name, addr)` | For JIT symbol injection |
|
||||
| `LLVMParseCommandLineOptions` | `llvm.parse_command_line_options(args)` | Set LLVM internal flags |
|
||||
|
||||
### Priority 5: Comdat.h (Windows-specific - Low Value)
|
||||
|
||||
| Function | Target API | Notes |
|
||||
|----------|------------|-------|
|
||||
| `LLVMGetOrInsertComdat` | `mod.get_or_insert_comdat(name)` | Get/create COMDAT section |
|
||||
| `LLVMGetComdat` | `gv.comdat` (property) | Get global's COMDAT |
|
||||
| `LLVMSetComdat` | `gv.comdat = comdat` (setter) | Set global's COMDAT |
|
||||
| `LLVMGetComdatSelectionKind` | `comdat.selection_kind` (property) | Get selection kind |
|
||||
| `LLVMSetComdatSelectionKind` | `comdat.selection_kind = kind` (setter) | Set selection kind |
|
||||
|
||||
### Priority 6: ErrorHandling.h (Advanced - Low Value)
|
||||
|
||||
| Function | Target API | Notes |
|
||||
|----------|------------|-------|
|
||||
| `LLVMInstallFatalErrorHandler` | `llvm.install_fatal_error_handler(callback)` | Custom crash handling |
|
||||
| `LLVMResetFatalErrorHandler` | `llvm.reset_fatal_error_handler()` | Reset to default |
|
||||
| `LLVMEnablePrettyStackTrace` | `llvm.enable_pretty_stack_trace()` | Better crash output |
|
||||
|
||||
### Skip These (Mark as 🚫)
|
||||
|
||||
| Function | Reason |
|
||||
|----------|--------|
|
||||
| `LLVMCreateConstantRangeAttribute` | Very rare use case, complex API |
|
||||
| `LLVMCreateMemoryBufferWithSTDIN` | Python has better stdin handling |
|
||||
| `LLVMTemporaryMDNode` / `LLVMDisposeTemporaryMDNode` | Manual memory management |
|
||||
| `LLVMDIBuilderCreateTempGlobalVariableFwdDecl` | Advanced, rarely needed |
|
||||
| Module Flag Iteration (5 functions) | Can parse IR instead, complex API |
|
||||
| FP math tag methods | Very specialized, rarely needed |
|
||||
|
||||
---
|
||||
|
||||
## Implementation Checklist
|
||||
|
||||
For each function:
|
||||
|
||||
1. [ ] Add C++ wrapper method/function to `src/llvm-nanobind.cpp`
|
||||
2. [ ] Add Python bindings with proper docstring
|
||||
3. [ ] Ensure proper validity checking (`check_valid()`)
|
||||
4. [ ] Use appropriate return type (wrapper class with token)
|
||||
5. [ ] Update feature matrix docs to mark as ✅
|
||||
6. [ ] Test the new binding works
|
||||
|
||||
## Verification
|
||||
|
||||
After implementation:
|
||||
|
||||
```bash
|
||||
# Build and import
|
||||
uv run python -c "import llvm; print('OK')"
|
||||
|
||||
# Run tests
|
||||
uv run run_tests.py
|
||||
|
||||
# Type check
|
||||
uvx ty check
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Completion Criteria
|
||||
|
||||
Task is complete when:
|
||||
- All Priority 1-3 items are implemented
|
||||
- Priority 4-6 items are implemented OR explicitly marked as 🚫 with justification
|
||||
- All tests pass
|
||||
- Type checker passes
|
||||
- Feature matrix docs are updated with accurate coverage numbers
|
||||
@@ -1,441 +0,0 @@
|
||||
# Miscellaneous Headers Feature Matrix
|
||||
|
||||
Implementation status for other LLVM-C headers with Python API mappings.
|
||||
|
||||
**Last Updated:** 2024-12-25
|
||||
|
||||
## Legend
|
||||
|
||||
| Status | Meaning |
|
||||
|--------|---------|
|
||||
| ✅ | Implemented |
|
||||
| ❌ | Not implemented |
|
||||
| 🚫 | Intentionally skipped |
|
||||
|
||||
---
|
||||
|
||||
## Analysis.h - Module/Function Verification
|
||||
|
||||
| C API | Status | Python API |
|
||||
|-------|--------|------------|
|
||||
| `LLVMVerifyModule` | ✅ | `mod.verify()` |
|
||||
| `LLVMVerifyFunction` | ✅ | `fn.verify()`, `fn.verify_and_print()` |
|
||||
| `LLVMViewFunctionCFG` | 🚫 | Debugging only, requires graphviz |
|
||||
| `LLVMViewFunctionCFGOnly` | 🚫 | Debugging only, requires graphviz |
|
||||
|
||||
```python
|
||||
# Verify module
|
||||
mod.verify() # Raises exception on error
|
||||
|
||||
# Verify function
|
||||
if not fn.verify():
|
||||
success, msg = fn.verify_and_print()
|
||||
print(f"Function invalid: {msg}")
|
||||
```
|
||||
|
||||
**Coverage:** 2/4 (50%)
|
||||
|
||||
---
|
||||
|
||||
## BitReader.h - Bitcode Reading
|
||||
|
||||
| C API | Status | Python API |
|
||||
|-------|--------|------------|
|
||||
| `LLVMParseBitcode` | 🚫 | Global context |
|
||||
| `LLVMParseBitcode2` | 🚫 | Global context |
|
||||
| `LLVMParseBitcodeInContext` | 🚫 | Deprecated |
|
||||
| `LLVMParseBitcodeInContext2` | ✅ | `ctx.parse_bitcode_from_bytes(data)` |
|
||||
| `LLVMGetBitcodeModuleInContext` | 🚫 | Deprecated |
|
||||
| `LLVMGetBitcodeModuleInContext2` | ✅ | `ctx.parse_bitcode_from_bytes(data, lazy=True)` |
|
||||
| `LLVMGetBitcodeModule` | 🚫 | Global context |
|
||||
| `LLVMGetBitcodeModule2` | ✅ | Via `ctx.parse_bitcode_from_bytes` |
|
||||
|
||||
```python
|
||||
# Parse bitcode from file
|
||||
with ctx.parse_bitcode_from_file("module.bc") as mod:
|
||||
print(mod)
|
||||
|
||||
# Parse bitcode from bytes
|
||||
with open("module.bc", "rb") as f:
|
||||
data = f.read()
|
||||
with ctx.parse_bitcode_from_bytes(data) as mod:
|
||||
print(mod)
|
||||
```
|
||||
|
||||
**Coverage:** 3/8 (37.5%)
|
||||
|
||||
---
|
||||
|
||||
## BitWriter.h - Bitcode Writing
|
||||
|
||||
| C API | Status | Python API |
|
||||
|-------|--------|------------|
|
||||
| `LLVMWriteBitcodeToFile` | ✅ | `mod.write_bitcode_to_file(path)` |
|
||||
| `LLVMWriteBitcodeToMemoryBuffer` | ✅ | `mod.write_bitcode_to_memory_buffer()` → `bytes` |
|
||||
| `LLVMWriteBitcodeToFD` | 🚫 | Low-level file descriptor API |
|
||||
| `LLVMWriteBitcodeToFileHandle` | 🚫 | Deprecated |
|
||||
|
||||
```python
|
||||
# Write bitcode to file
|
||||
mod.write_bitcode_to_file("output.bc")
|
||||
|
||||
# Write bitcode to bytes
|
||||
bc_data = mod.write_bitcode_to_memory_buffer()
|
||||
with open("output.bc", "wb") as f:
|
||||
f.write(bc_data)
|
||||
```
|
||||
|
||||
**Coverage:** 2/4 (50%, 100% of useful APIs)
|
||||
|
||||
---
|
||||
|
||||
## IRReader.h - IR Parsing
|
||||
|
||||
| C API | Status | Python API |
|
||||
|-------|--------|------------|
|
||||
| `LLVMParseIRInContext` | ✅ | `ctx.parse_ir(source, mod_name)` |
|
||||
|
||||
```python
|
||||
ir_source = """
|
||||
define i32 @add(i32 %a, i32 %b) {
|
||||
entry:
|
||||
%sum = add i32 %a, %b
|
||||
ret i32 %sum
|
||||
}
|
||||
"""
|
||||
|
||||
with ctx.parse_ir(ir_source, "my_module") as mod:
|
||||
print(mod)
|
||||
```
|
||||
|
||||
**Coverage:** 1/1 (100%)
|
||||
|
||||
---
|
||||
|
||||
## PassBuilder.h - New Pass Manager
|
||||
|
||||
| C API | Status | Python API |
|
||||
|-------|--------|------------|
|
||||
| `LLVMCreatePassBuilderOptions` | ✅ | `llvm.PassBuilderOptions()` |
|
||||
| `LLVMDisposePassBuilderOptions` | ✅ | Automatic cleanup |
|
||||
| `LLVMPassBuilderOptionsSetVerifyEach` | ✅ | `opts.set_verify_each(bool)` |
|
||||
| `LLVMPassBuilderOptionsSetDebugLogging` | ✅ | `opts.set_debug_logging(bool)` |
|
||||
| `LLVMPassBuilderOptionsSetLoopInterleaving` | ✅ | `opts.set_loop_interleaving(bool)` |
|
||||
| `LLVMPassBuilderOptionsSetLoopVectorization` | ✅ | `opts.set_loop_vectorization(bool)` |
|
||||
| `LLVMPassBuilderOptionsSetSLPVectorization` | ✅ | `opts.set_slp_vectorization(bool)` |
|
||||
| `LLVMPassBuilderOptionsSetLoopUnrolling` | ✅ | `opts.set_loop_unrolling(bool)` |
|
||||
| `LLVMPassBuilderOptionsSetForgetAllSCEVInLoopUnroll` | ✅ | `opts.set_forget_all_scev_in_loop_unroll(bool)` |
|
||||
| `LLVMPassBuilderOptionsSetLicmMssaOptCap` | ✅ | `opts.set_licm_mssa_opt_cap(int)` |
|
||||
| `LLVMPassBuilderOptionsSetLicmMssaNoAccForPromotionCap` | ✅ | `opts.set_licm_mssa_no_acc_for_promotion_cap(int)` |
|
||||
| `LLVMPassBuilderOptionsSetCallGraphProfile` | ✅ | `opts.set_call_graph_profile(bool)` |
|
||||
| `LLVMPassBuilderOptionsSetMergeFunctions` | ✅ | `opts.set_merge_functions(bool)` |
|
||||
| `LLVMPassBuilderOptionsSetInlinerThreshold` | ✅ | `opts.set_inliner_threshold(int)` |
|
||||
| `LLVMRunPasses` | ✅ | `llvm.run_passes(mod, passes, tm, opts)` |
|
||||
|
||||
```python
|
||||
# Create pass builder options
|
||||
opts = llvm.PassBuilderOptions()
|
||||
opts.set_loop_vectorization(True)
|
||||
opts.set_slp_vectorization(True)
|
||||
opts.set_inliner_threshold(250)
|
||||
|
||||
# Run optimization passes
|
||||
llvm.run_passes(mod, "default<O2>", target_machine, opts)
|
||||
|
||||
# Standard optimization levels
|
||||
llvm.run_passes(mod, "default<O0>", tm, opts) # No optimization
|
||||
llvm.run_passes(mod, "default<O1>", tm, opts) # Light optimization
|
||||
llvm.run_passes(mod, "default<O2>", tm, opts) # Standard optimization
|
||||
llvm.run_passes(mod, "default<O3>", tm, opts) # Aggressive optimization
|
||||
llvm.run_passes(mod, "default<Os>", tm, opts) # Size optimization
|
||||
llvm.run_passes(mod, "default<Oz>", tm, opts) # Aggressive size
|
||||
|
||||
# Custom pass pipeline
|
||||
llvm.run_passes(mod, "function(simplifycfg,instcombine)", tm, opts)
|
||||
```
|
||||
|
||||
**Coverage:** 15/15 (100%)
|
||||
|
||||
---
|
||||
|
||||
## Linker.h - Module Linking
|
||||
|
||||
| C API | Status | Python API |
|
||||
|-------|--------|------------|
|
||||
| `LLVMLinkModules2` | ✅ | `mod.link_module(other_mod)` |
|
||||
|
||||
```python
|
||||
# Link modules (other_mod is consumed/destroyed)
|
||||
mod.link_module(other_mod)
|
||||
```
|
||||
|
||||
**Coverage:** 1/1 (100%)
|
||||
|
||||
---
|
||||
|
||||
## Disassembler.h - Instruction Disassembly
|
||||
|
||||
| C API | Status | Python API |
|
||||
|-------|--------|------------|
|
||||
| `LLVMCreateDisasm` | ❌ | Use `LLVMCreateDisasmCPUFeatures` |
|
||||
| `LLVMCreateDisasmCPU` | ❌ | Use `LLVMCreateDisasmCPUFeatures` |
|
||||
| `LLVMCreateDisasmCPUFeatures` | ✅ | `llvm.create_disassembler(triple, cpu, features)` |
|
||||
| `LLVMSetDisasmOptions` | ✅ | `disasm.set_options(options)` |
|
||||
| `LLVMDisasmDispose` | ✅ | Automatic cleanup |
|
||||
| `LLVMDisasmInstruction` | ✅ | `disasm.disassemble(bytes, pc)` |
|
||||
|
||||
```python
|
||||
# Initialize disassembler support
|
||||
llvm.initialize_all_disassemblers()
|
||||
|
||||
# Create disassembler for x86-64
|
||||
disasm = llvm.create_disassembler("x86_64-unknown-linux-gnu", "", "")
|
||||
|
||||
# Disassemble bytes
|
||||
code = bytes([0x48, 0x89, 0xe5]) # mov rbp, rsp
|
||||
text, size = disasm.disassemble(code, 0x1000)
|
||||
print(f"{text} ({size} bytes)")
|
||||
```
|
||||
|
||||
**Coverage:** 3/6 (50%)
|
||||
|
||||
---
|
||||
|
||||
## Object.h - Object File Handling
|
||||
|
||||
| C API | Status | Python API |
|
||||
|-------|--------|------------|
|
||||
| `LLVMCreateBinary` | ✅ | `llvm.create_binary(buf, ctx)` |
|
||||
| `LLVMDisposeBinary` | ✅ | Automatic cleanup |
|
||||
| `LLVMBinaryCopyMemoryBuffer` | ❌ | TODO |
|
||||
| `LLVMBinaryGetType` | ✅ | `binary.type` |
|
||||
| `LLVMObjectFileCopySectionIterator` | ✅ | `binary.sections()` |
|
||||
| `LLVMObjectFileIsSectionIteratorAtEnd` | ✅ | Via iterator |
|
||||
| `LLVMMoveToNextSection` | ✅ | Via iterator |
|
||||
| `LLVMObjectFileCopySymbolIterator` | ✅ | `binary.symbols()` |
|
||||
| `LLVMObjectFileIsSymbolIteratorAtEnd` | ✅ | Via iterator |
|
||||
| `LLVMMoveToNextSymbol` | ✅ | Via iterator |
|
||||
| `LLVMGetSectionName` | ✅ | `section.name` |
|
||||
| `LLVMGetSectionSize` | ✅ | `section.size` |
|
||||
| `LLVMGetSectionContents` | ✅ | `section.contents` |
|
||||
| `LLVMGetSectionAddress` | ✅ | `section.address` |
|
||||
| `LLVMGetSectionContainsSymbol` | ❌ | TODO |
|
||||
| `LLVMGetSymbolName` | ✅ | `symbol.name` |
|
||||
| `LLVMGetSymbolAddress` | ✅ | `symbol.address` |
|
||||
| `LLVMGetSymbolSize` | ✅ | `symbol.size` |
|
||||
| `LLVMGetRelocations` | ✅ | `section.relocations()` |
|
||||
| `LLVMGetRelocationOffset` | ✅ | `reloc.offset` |
|
||||
| `LLVMGetRelocationSymbol` | ✅ | `reloc.symbol` |
|
||||
| `LLVMGetRelocationType` | ✅ | `reloc.type` |
|
||||
| `LLVMGetRelocationTypeName` | ✅ | `reloc.type_name` |
|
||||
| `LLVMGetRelocationValueString` | ✅ | `reloc.value_string` |
|
||||
|
||||
```python
|
||||
# Read object file
|
||||
buf = llvm.MemoryBuffer.from_file("module.o")
|
||||
binary = llvm.create_binary(buf)
|
||||
|
||||
for section in binary.sections():
|
||||
print(f"Section: {section.name}, Size: {section.size}")
|
||||
|
||||
for symbol in binary.symbols():
|
||||
print(f"Symbol: {symbol.name} @ 0x{symbol.address:x}")
|
||||
```
|
||||
|
||||
**Coverage:** 23/31 (74%)
|
||||
|
||||
---
|
||||
|
||||
## Error.h - Error Handling
|
||||
|
||||
| C API | Status | Python API |
|
||||
|-------|--------|------------|
|
||||
| `LLVMGetErrorTypeId` | 🚫 | Errors → Python exceptions |
|
||||
| `LLVMConsumeError` | 🚫 | Automatic in bindings |
|
||||
| `LLVMCantFail` | 🚫 | Not needed in Python |
|
||||
| `LLVMGetErrorMessage` | 🚫 | In exception messages |
|
||||
| `LLVMDisposeErrorMessage` | 🚫 | Automatic |
|
||||
| `LLVMGetStringErrorTypeId` | 🚫 | Not needed |
|
||||
| `LLVMCreateStringError` | 🚫 | Not needed |
|
||||
|
||||
Note: LLVM errors are converted to Python exceptions (`LLVMError`, `LLVMParseError`, `LLVMMemoryError`)
|
||||
|
||||
**Coverage:** N/A (by design)
|
||||
|
||||
---
|
||||
|
||||
## ErrorHandling.h - Fatal Error Handling
|
||||
|
||||
| C API | Status | Python API |
|
||||
|-------|--------|------------|
|
||||
| `LLVMInstallFatalErrorHandler` | ❌ | TODO |
|
||||
| `LLVMResetFatalErrorHandler` | ❌ | TODO |
|
||||
| `LLVMEnablePrettyStackTrace` | ❌ | TODO |
|
||||
|
||||
**Coverage:** 0/3 (0%)
|
||||
|
||||
---
|
||||
|
||||
## Support.h - Miscellaneous Support
|
||||
|
||||
| C API | Status | Python API |
|
||||
|-------|--------|------------|
|
||||
| `LLVMLoadLibraryPermanently` | ❌ | TODO |
|
||||
| `LLVMParseCommandLineOptions` | ❌ | TODO |
|
||||
| `LLVMSearchForAddressOfSymbol` | ❌ | TODO |
|
||||
| `LLVMAddSymbol` | ❌ | TODO |
|
||||
|
||||
**Coverage:** 0/4 (0%)
|
||||
|
||||
---
|
||||
|
||||
## Comdat.h - COMDAT Handling
|
||||
|
||||
| C API | Status | Python API |
|
||||
|-------|--------|------------|
|
||||
| `LLVMGetOrInsertComdat` | ❌ | TODO |
|
||||
| `LLVMGetComdat` | ❌ | TODO |
|
||||
| `LLVMSetComdat` | ❌ | TODO |
|
||||
| `LLVMGetComdatSelectionKind` | ❌ | TODO |
|
||||
| `LLVMSetComdatSelectionKind` | ❌ | TODO |
|
||||
|
||||
**Coverage:** 0/5 (0%)
|
||||
|
||||
---
|
||||
|
||||
## Summary
|
||||
|
||||
| Header | Total | ✅ Impl | 🚫 Skip | ❌ TODO | Coverage |
|
||||
|--------|-------|---------|---------|---------|----------|
|
||||
| Analysis.h | 4 | 2 | 2 | 0 | 50% |
|
||||
| BitReader.h | 8 | 3 | 5 | 0 | 37.5% |
|
||||
| BitWriter.h | 4 | 2 | 2 | 0 | 50% |
|
||||
| IRReader.h | 1 | 1 | 0 | 0 | 100% |
|
||||
| PassBuilder.h | 15 | 15 | 0 | 0 | 100% |
|
||||
| Linker.h | 1 | 1 | 0 | 0 | 100% |
|
||||
| Disassembler.h | 6 | 3 | 0 | 3 | 50% |
|
||||
| Object.h | 31 | 23 | 0 | 8 | 74% |
|
||||
| Error.h | 7 | 0 | 7 | 0 | N/A |
|
||||
| ErrorHandling.h | 3 | 0 | 0 | 3 | 0% |
|
||||
| Support.h | 4 | 0 | 0 | 4 | 0% |
|
||||
| Comdat.h | 5 | 0 | 0 | 5 | 0% |
|
||||
| **Total** | **89** | **50** | **16** | **23** | **73%** |
|
||||
|
||||
---
|
||||
|
||||
## Remaining TODO - Detailed
|
||||
|
||||
### Disassembler.h (2 remaining)
|
||||
| Function | Description | Priority |
|
||||
|----------|-------------|----------|
|
||||
| `LLVMCreateDisasm` | Create basic disassembler | Low - use CPU/features version |
|
||||
| `LLVMCreateDisasmCPU` | Create with CPU | Low - use CPU/features version |
|
||||
|
||||
### Object.h (8 remaining)
|
||||
| Function | Description | Priority |
|
||||
|----------|-------------|----------|
|
||||
| `LLVMBinaryCopyMemoryBuffer` | Copy binary to memory buffer | Low |
|
||||
| `LLVMGetSectionContainsSymbol` | Check if section contains symbol | Medium |
|
||||
| `LLVMDisposeSectionIterator` | Dispose section iterator | Automatic |
|
||||
| `LLVMDisposeSymbolIterator` | Dispose symbol iterator | Automatic |
|
||||
| `LLVMDisposeRelocationIterator` | Dispose reloc iterator | Automatic |
|
||||
| `LLVMMoveToContainingSection` | Move to containing section | Low |
|
||||
| `LLVMGetSectionIndex` | Get section index | Low |
|
||||
| `LLVMGetRelocationAddress` | Get relocation address | Low |
|
||||
|
||||
### ErrorHandling.h (3 remaining)
|
||||
| Function | Description | Priority | Notes |
|
||||
|----------|-------------|----------|-------|
|
||||
| `LLVMInstallFatalErrorHandler` | Install custom fatal error handler | Low | Advanced: custom crash handling |
|
||||
| `LLVMResetFatalErrorHandler` | Reset to default handler | Low | Companion to above |
|
||||
| `LLVMEnablePrettyStackTrace` | Enable pretty stack traces | Low | Debugging only |
|
||||
|
||||
**Use Case:** Handle LLVM fatal errors gracefully instead of crashing. Useful for long-running services.
|
||||
|
||||
### Support.h (4 remaining)
|
||||
| Function | Description | Priority | Notes |
|
||||
|----------|-------------|----------|-------|
|
||||
| `LLVMLoadLibraryPermanently` | Load shared library into process | Low | JIT: load native libs |
|
||||
| `LLVMParseCommandLineOptions` | Parse LLVM command line options | Low | Set LLVM internal flags |
|
||||
| `LLVMSearchForAddressOfSymbol` | Find symbol in loaded libraries | Low | JIT: symbol resolution |
|
||||
| `LLVMAddSymbol` | Add symbol to global symbol table | Low | JIT: symbol injection |
|
||||
|
||||
**Use Case:** JIT symbol resolution. When JIT-compiled code needs to call external functions.
|
||||
|
||||
### Comdat.h (5 remaining)
|
||||
| Function | Description | Priority | Notes |
|
||||
|----------|-------------|----------|-------|
|
||||
| `LLVMGetOrInsertComdat` | Get or create COMDAT section | Low | Windows linking |
|
||||
| `LLVMGetComdat` | Get COMDAT for global | Low | Windows linking |
|
||||
| `LLVMSetComdat` | Set COMDAT for global | Low | Windows linking |
|
||||
| `LLVMGetComdatSelectionKind` | Get COMDAT selection kind | Low | Windows linking |
|
||||
| `LLVMSetComdatSelectionKind` | Set COMDAT selection kind | Low | Windows linking |
|
||||
|
||||
**Use Case:** COMDAT sections control symbol deduplication in Windows COFF object files. Required for proper linking of C++ template instantiations and inline functions on Windows.
|
||||
|
||||
**Proposed API:**
|
||||
```python
|
||||
# Create COMDAT
|
||||
comdat = mod.get_or_insert_comdat("my_section")
|
||||
comdat.selection_kind = llvm.ComdatSelectionKind.Any # or Largest, NoDuplicates, SameSize, ExactMatch
|
||||
|
||||
# Associate with globals
|
||||
fn.comdat = comdat
|
||||
gv.comdat = comdat
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Advanced Features Not Yet Tracked
|
||||
|
||||
### ORC JIT (Orc.h, LLJIT.h, OrcEE.h, LLJITUtils.h)
|
||||
|
||||
Modern JIT compilation infrastructure (~90 functions total):
|
||||
|
||||
| Category | Functions | Description |
|
||||
|----------|-----------|-------------|
|
||||
| ExecutionSession | ~15 | JIT session management |
|
||||
| JITDylib | ~10 | Dynamic library abstraction |
|
||||
| MaterializationUnit | ~8 | Lazy compilation units |
|
||||
| ObjectLayer | ~12 | Object file linking |
|
||||
| IRLayer | ~8 | IR compilation |
|
||||
| LLJIT | ~20 | High-level JIT interface |
|
||||
| LookupState | ~5 | Symbol lookup |
|
||||
| ThreadSafeContext | ~5 | Thread-safe context |
|
||||
|
||||
**Use Case:** JIT compile and execute LLVM IR at runtime. Useful for:
|
||||
- Language interpreters with JIT
|
||||
- Runtime code generation
|
||||
- Dynamic optimization
|
||||
|
||||
**Priority:** Medium - implement if JIT functionality is needed.
|
||||
|
||||
### ExecutionEngine.h (Legacy JIT)
|
||||
|
||||
Legacy JIT interface (~38 functions). **Prefer ORC JIT instead.**
|
||||
|
||||
| Function Group | Count | Notes |
|
||||
|----------------|-------|-------|
|
||||
| Create/Dispose | 8 | Create execution engines |
|
||||
| Run Functions | 6 | Execute JIT code |
|
||||
| Global Access | 8 | Access global variables |
|
||||
| Target Data | 4 | Get target info |
|
||||
| Function Access | 6 | Find/add functions |
|
||||
| Misc | 6 | Other utilities |
|
||||
|
||||
**Status:** Not planned. Use ORC JIT for new code.
|
||||
|
||||
### Remarks.h (Optimization Remarks)
|
||||
|
||||
Optimization diagnostics (~24 functions):
|
||||
|
||||
| Category | Functions | Description |
|
||||
|----------|-----------|-------------|
|
||||
| Parser | 8 | Parse remark files |
|
||||
| Entry | 10 | Access remark entries |
|
||||
| String | 4 | Remark strings |
|
||||
| Debug Location | 2 | Source locations |
|
||||
|
||||
**Use Case:** Analyze optimization decisions for performance tuning.
|
||||
|
||||
**Priority:** Low - specialized debugging use case.
|
||||
@@ -1,123 +0,0 @@
|
||||
# Feature Matrix Plan
|
||||
|
||||
## Goal
|
||||
|
||||
Create and maintain a comprehensive feature matrix that tracks:
|
||||
1. All LLVM-C API functions across all headers
|
||||
2. Implementation status (bound/not bound/partial)
|
||||
3. Python documentation status
|
||||
4. Remarks and notes (limitations, deviations from C API, safety additions)
|
||||
|
||||
## Scope
|
||||
|
||||
### LLVM-C Headers to Track
|
||||
|
||||
| Header | Functions | Priority | Notes |
|
||||
|--------|-----------|----------|-------|
|
||||
| Core.h | ~670 | High | Core IR building - main focus |
|
||||
| DebugInfo.h | ~99 | High | Debug info metadata |
|
||||
| TargetMachine.h | ~37 | High | Code generation |
|
||||
| Object.h | ~37 | Medium | Object file parsing |
|
||||
| Target.h | ~32 | Medium | Target initialization |
|
||||
| ExecutionEngine.h | ~38 | Low | JIT execution (prefer ORC) |
|
||||
| Orc.h | ~68 | Medium | Modern JIT API |
|
||||
| LLJIT.h | ~20 | Medium | High-level ORC wrapper |
|
||||
| Remarks.h | ~24 | Low | Remarks/optimization notes |
|
||||
| Analysis.h | ~4 | High | Module verification |
|
||||
| BitReader.h | ~8 | High | Bitcode reading |
|
||||
| BitWriter.h | ~4 | High | Bitcode writing |
|
||||
| IRReader.h | ~1 | High | IR parsing |
|
||||
| PassBuilder.h | ~17 | High | Optimization passes |
|
||||
| Disassembler.h | ~6 | Medium | Instruction disassembly |
|
||||
| Linker.h | ~1 | Medium | Module linking |
|
||||
| Comdat.h | ~5 | Low | COMDAT handling |
|
||||
| Error.h | ~7 | Medium | Error handling |
|
||||
| ErrorHandling.h | ~3 | Low | Fatal error handlers |
|
||||
| Support.h | ~4 | Low | Misc support functions |
|
||||
| OrcEE.h | ~3 | Low | ORC execution engine bridge |
|
||||
| LLJITUtils.h | ~1 | Low | LLJIT utilities |
|
||||
| blake3.h | ~9 | Skip | Hashing - not LLVM IR related |
|
||||
| lto.h | ~many | Skip | LTO - separate use case |
|
||||
|
||||
**Total: ~1,088 LLVM-C API functions**
|
||||
|
||||
### Currently Included in Bindings
|
||||
|
||||
Based on `#include` directives in `src/llvm-nanobind.cpp`:
|
||||
- ✅ Core.h
|
||||
- ✅ DebugInfo.h
|
||||
- ✅ TargetMachine.h
|
||||
- ✅ Object.h
|
||||
- ✅ Target.h
|
||||
- ✅ Analysis.h
|
||||
- ✅ BitReader.h
|
||||
- ✅ Disassembler.h
|
||||
- ✅ IRReader.h
|
||||
- ❌ BitWriter.h
|
||||
- ❌ ExecutionEngine.h
|
||||
- ❌ Orc.h / LLJIT.h
|
||||
- ❌ PassBuilder.h
|
||||
- ❌ Others...
|
||||
|
||||
## Matrix Structure
|
||||
|
||||
The matrix will be organized by header file, with each function tracked as:
|
||||
|
||||
```markdown
|
||||
| Function | Status | Docs | Remarks |
|
||||
|----------|--------|------|---------|
|
||||
| LLVMFunctionName | ✅/⚠️/❌ | ✅/❌ | Notes about deviations |
|
||||
```
|
||||
|
||||
Status legend:
|
||||
- ✅ Fully implemented
|
||||
- ⚠️ Partial (some parameters not exposed, or wrapped differently)
|
||||
- ❌ Not implemented
|
||||
- 🚫 Intentionally skipped (deprecated, unsafe, etc.)
|
||||
|
||||
## Phases
|
||||
|
||||
### Phase 1: Core.h Inventory
|
||||
Extract all 670 functions from Core.h and track implementation status.
|
||||
Group by functionality (Context, Module, Types, Values, Instructions, Builder, etc.)
|
||||
|
||||
### Phase 2: Other High-Priority Headers
|
||||
- Analysis.h
|
||||
- BitReader.h / BitWriter.h
|
||||
- IRReader.h
|
||||
- DebugInfo.h
|
||||
- Target.h / TargetMachine.h
|
||||
- PassBuilder.h
|
||||
|
||||
### Phase 3: Medium-Priority Headers
|
||||
- Object.h
|
||||
- Disassembler.h
|
||||
- Orc.h / LLJIT.h
|
||||
- Error.h
|
||||
- Linker.h
|
||||
|
||||
### Phase 4: Low-Priority Headers
|
||||
- Remaining headers
|
||||
|
||||
## Output Files
|
||||
|
||||
- `devdocs/feature-matrix/core.md` - Core.h functions
|
||||
- `devdocs/feature-matrix/debuginfo.md` - DebugInfo.h functions
|
||||
- `devdocs/feature-matrix/target.md` - Target.h + TargetMachine.h functions
|
||||
- `devdocs/feature-matrix/jit.md` - ExecutionEngine, Orc, LLJIT functions
|
||||
- `devdocs/feature-matrix/misc.md` - All other headers
|
||||
- `devdocs/feature-matrix/summary.md` - Overall coverage statistics
|
||||
|
||||
## Automation Considerations
|
||||
|
||||
To keep the matrix maintainable:
|
||||
1. Consider scripts to extract function names from headers
|
||||
2. Consider scripts to check which functions are called in bindings
|
||||
3. Update matrix when new bindings are added
|
||||
|
||||
## Testing Strategy
|
||||
|
||||
The matrix itself doesn't need tests, but it should inform:
|
||||
- Which APIs need test coverage
|
||||
- Which APIs are safe to use in production
|
||||
- Which APIs have known limitations
|
||||
@@ -1,452 +0,0 @@
|
||||
# Feature Matrix Progress
|
||||
|
||||
## Current Status
|
||||
|
||||
**Phase:** Feature Matrix Complete ✅
|
||||
|
||||
**Overall Coverage:** ~85% of LLVM-C API
|
||||
|
||||
All priority items are now implemented or explicitly skipped. Remaining items are deprecated, internal, or have better alternatives.
|
||||
|
||||
---
|
||||
|
||||
## Summary Statistics (Updated December 2024 - Final)
|
||||
|
||||
| Header | Total | ✅ Impl | 🚫 Skip | ❌ TODO | Coverage |
|
||||
|--------|-------|---------|---------|---------|----------|
|
||||
| Core.h | 640 | **475** | 48 | 117 | **82%** |
|
||||
| DebugInfo.h | 99 | **~82** | 0 | ~17 | **~83%** |
|
||||
| Target.h | 22 | **22** | 0 | 0 | **100%** |
|
||||
| TargetMachine.h | 29 | **14** | 9 | 6 | **79%** |
|
||||
| Object.h | 31 | **24** | 0 | 7 | **77%** |
|
||||
| Analysis.h | 4 | **2** | 2 | 0 | **100%** |
|
||||
| BitReader.h | 8 | 3 | 5 | 0 | 37.5% |
|
||||
| BitWriter.h | 4 | **2** | 2 | 0 | **100%** |
|
||||
| IRReader.h | 1 | 1 | 0 | 0 | 100% |
|
||||
| PassBuilder.h | 15 | **15** | 0 | 0 | **100%** |
|
||||
| Disassembler.h | 6 | **4** | 0 | 2 | **67%** |
|
||||
| Linker.h | 1 | **1** | 0 | 0 | **100%** |
|
||||
| Comdat.h | 5 | **5** | 0 | 0 | **100%** |
|
||||
| Support.h | 4 | 0 | **4** | 0 | **100%** |
|
||||
| ErrorHandling.h | 3 | 0 | **3** | 0 | **100%** |
|
||||
| **Total** | **~872** | **~650** | **~73** | **~149** | **~85%** |
|
||||
|
||||
---
|
||||
|
||||
## Recently Implemented (December 2024)
|
||||
|
||||
### Session 1 - Core Workflows
|
||||
|
||||
#### BitWriter.h - COMPLETE ✅
|
||||
- `LLVMWriteBitcodeToFile` → `mod.write_bitcode_to_file(path)`
|
||||
- `LLVMWriteBitcodeToMemoryBuffer` → `mod.write_bitcode_to_memory_buffer()`
|
||||
|
||||
#### PassBuilder.h - COMPLETE ✅
|
||||
All 15 functions implemented including all optimization options.
|
||||
|
||||
#### Target.h - COMPLETE ✅
|
||||
All 22 functions including host queries, initialization, and target data.
|
||||
|
||||
#### TargetMachine.h - 79%
|
||||
Core code generation fully working. Only TargetMachineOptions builder API missing (not needed).
|
||||
|
||||
#### Linker.h - COMPLETE ✅
|
||||
- `LLVMLinkModules2` → `mod.link_module(src_mod)`
|
||||
|
||||
#### Analysis.h - COMPLETE ✅
|
||||
- Module and function verification implemented.
|
||||
|
||||
### Session 2 - Additional APIs
|
||||
|
||||
#### Module Flags
|
||||
- `LLVMAddModuleFlag` → `mod.add_module_flag(behavior, key, val)`
|
||||
- `LLVMGetModuleFlag` → `mod.get_module_flag(key)`
|
||||
- `LLVMModuleFlagBehavior` enum → `llvm.ModuleFlagBehavior`
|
||||
|
||||
#### String Attributes
|
||||
- `LLVMCreateStringAttribute` → `ctx.create_string_attribute(key, val)`
|
||||
- `LLVMGetStringAttributeKind` → `attr.string_kind`
|
||||
- `LLVMGetStringAttributeValue` → `attr.string_value`
|
||||
- `LLVMIsEnumAttribute` → `attr.is_enum_attribute`
|
||||
- `LLVMIsStringAttribute` → `attr.is_string_attribute`
|
||||
- `LLVMIsTypeAttribute` → `attr.is_type_attribute`
|
||||
|
||||
#### Type Queries
|
||||
- `LLVMIsLiteralStruct` → `ty.is_literal_struct`
|
||||
|
||||
#### Value Manipulation
|
||||
- `LLVMSetOperand` → `val.set_operand(index, new_val)`
|
||||
|
||||
#### Constant Creation from Strings
|
||||
- `LLVMConstIntOfStringAndSize` → `ty.constant_from_string(text, radix)`
|
||||
- `LLVMConstRealOfStringAndSize` → `ty.real_constant_from_string(text)`
|
||||
|
||||
#### Disassembler Options
|
||||
- `LLVMSetDisasmOptions` → `disasm.set_options(options)`
|
||||
- Disassembler option constants (`DisasmOption_*`)
|
||||
|
||||
#### Builder Instructions
|
||||
- `LLVMBuildAddrSpaceCast` → `b.addr_space_cast(val, ty, name)`
|
||||
- `LLVMBuildFence` → `b.fence(ordering, single_thread, name)`
|
||||
|
||||
### Session 3 - Low Priority Items (December 2024)
|
||||
|
||||
#### Global IFunc Management
|
||||
- `LLVMEraseGlobalIFunc` → `val.erase_from_parent_ifunc()`
|
||||
- `LLVMRemoveGlobalIFunc` → `val.remove_from_parent_ifunc()`
|
||||
|
||||
#### DLL Storage Class
|
||||
- `LLVMGetDLLStorageClass` → `val.dll_storage_class` (getter)
|
||||
- `LLVMSetDLLStorageClass` → `val.dll_storage_class = ...` (setter)
|
||||
- `LLVMDLLStorageClass` enum → `llvm.DLLStorageClass`
|
||||
|
||||
#### Sync Scope
|
||||
- `LLVMGetSyncScopeID` → `ctx.get_sync_scope_id(name)`
|
||||
|
||||
### Session 4 - Medium Priority Items (December 2024)
|
||||
|
||||
#### Type Attributes
|
||||
- `LLVMCreateTypeAttribute` → `ctx.create_type_attribute(kind_id, type)`
|
||||
- `LLVMGetTypeAttributeValue` → `attr.type_value`
|
||||
|
||||
#### Metadata Kind ID
|
||||
- `LLVMGetMDKindIDInContext` → `ctx.get_md_kind_id(name)`
|
||||
|
||||
#### Attribute Management
|
||||
- `LLVMGetAttributesAtIndex` → `fn.get_attributes(idx)`
|
||||
- `LLVMGetStringAttributeAtIndex` → `fn.get_string_attribute(idx, key)`
|
||||
- `LLVMRemoveEnumAttributeAtIndex` → `fn.remove_enum_attribute(idx, kind)`
|
||||
- `LLVMRemoveStringAttributeAtIndex` → `fn.remove_string_attribute(idx, key)`
|
||||
- `LLVMAddTargetDependentFunctionAttr` → `fn.add_target_attribute(key, value)`
|
||||
|
||||
#### Builder Position Control
|
||||
- `LLVMPositionBuilder` → `b.position_at(bb, inst)`
|
||||
- `LLVMClearInsertionPosition` → `b.clear_insertion_position()`
|
||||
|
||||
#### Additional Builder Instructions
|
||||
- `LLVMBuildExactUDiv` → `b.exact_udiv(lhs, rhs, name)`
|
||||
- `LLVMBuildIndirectBr` → `b.indirect_br(addr, num_dests)`
|
||||
- `LLVMAddDestination` → `ibr.add_destination(bb)`
|
||||
- `LLVMBuildAtomicRMW` → `b.atomic_rmw(op, ptr, val, ordering, single_thread)`
|
||||
- `LLVMBuildAtomicCmpXchg` → `b.atomic_cmpxchg(ptr, cmp, new, succ_ord, fail_ord, single_thread)`
|
||||
|
||||
#### Convenience Cast Builders
|
||||
- `LLVMBuildZExtOrBitCast` → `b.zext_or_bitcast(val, ty, name)`
|
||||
- `LLVMBuildSExtOrBitCast` → `b.sext_or_bitcast(val, ty, name)`
|
||||
- `LLVMBuildTruncOrBitCast` → `b.trunc_or_bitcast(val, ty, name)`
|
||||
- `LLVMBuildCast` → `b.cast(op, val, ty, name)`
|
||||
- `LLVMBuildPointerCast` → `b.pointer_cast(val, ty, name)`
|
||||
- `LLVMBuildFPCast` → `b.fp_cast(val, ty, name)`
|
||||
|
||||
### Session 5 - DebugInfo.h Extensions (December 2024)
|
||||
|
||||
#### DIBuilder Type Creation - NEW ✅
|
||||
- `LLVMDIBuilderFinalizeSubprogram` → `dib.finalize_subprogram(subprogram)`
|
||||
- `LLVMDIBuilderCreateMemberType` → `dib.create_member_type(scope, name, file, line, size, align, offset, flags, type)`
|
||||
- `LLVMDIBuilderCreateUnionType` → `dib.create_union_type(scope, name, file, line, size, align, flags, elements, runtime_lang, unique_id)`
|
||||
- `LLVMDIBuilderCreateArrayType` → `dib.create_array_type(size, align, elem_type, subscripts)`
|
||||
- `LLVMDIBuilderCreateQualifiedType` → `dib.create_qualified_type(tag, type)` (const/volatile)
|
||||
- `LLVMDIBuilderCreateReferenceType` → `dib.create_reference_type(tag, type)`
|
||||
- `LLVMDIBuilderCreateNullPtrType` → `dib.create_null_ptr_type()`
|
||||
- `LLVMDIBuilderCreateBitFieldMemberType` → `dib.create_bit_field_member_type(...)`
|
||||
- `LLVMDIBuilderCreateArtificialType` → `dib.create_artificial_type(type)`
|
||||
- `LLVMDIBuilderGetOrCreateTypeArray` → `dib.get_or_create_type_array(types)`
|
||||
- `LLVMDIBuilderCreateLexicalBlockFile` → `dib.create_lexical_block_file(scope, file, discriminator)`
|
||||
- `LLVMDIBuilderCreateImportedDeclaration` → `dib.create_imported_declaration(scope, decl, file, line, name, elements)`
|
||||
- `LLVMDIBuilderCreateImportedModuleFromNamespace` → `dib.create_imported_module_from_namespace(scope, ns, file, line)`
|
||||
|
||||
#### DILocation Accessors - NEW ✅
|
||||
- `LLVMDILocationGetLine` → `llvm.di_location_get_line(loc)`
|
||||
- `LLVMDILocationGetColumn` → `llvm.di_location_get_column(loc)`
|
||||
- `LLVMDILocationGetScope` → `llvm.di_location_get_scope(loc)`
|
||||
- `LLVMDILocationGetInlinedAt` → `llvm.di_location_get_inlined_at(loc)`
|
||||
|
||||
#### Debug Metadata Version - NEW ✅
|
||||
- `LLVMDebugMetadataVersion` → `llvm.debug_metadata_version()`
|
||||
- `LLVMGetModuleDebugMetadataVersion` → `llvm.get_module_debug_metadata_version(mod)`
|
||||
- `LLVMStripModuleDebugInfo` → `llvm.strip_module_debug_info(mod)`
|
||||
|
||||
#### DI File/Scope/Variable Accessors - NEW ✅
|
||||
- `LLVMDIScopeGetFile` → `llvm.di_scope_get_file(scope)`
|
||||
- `LLVMDIFileGetDirectory` → `llvm.di_file_get_directory(file)`
|
||||
- `LLVMDIFileGetFilename` → `llvm.di_file_get_filename(file)`
|
||||
- `LLVMDIFileGetSource` → `llvm.di_file_get_source(file)`
|
||||
- `LLVMDISubprogramGetLine` → `llvm.di_subprogram_get_line(subprogram)`
|
||||
- `LLVMDIVariableGetFile` → `llvm.di_variable_get_file(variable)`
|
||||
- `LLVMDIVariableGetScope` → `llvm.di_variable_get_scope(variable)`
|
||||
- `LLVMDIVariableGetLine` → `llvm.di_variable_get_line(variable)`
|
||||
|
||||
#### Core.h Extensions - NEW ✅
|
||||
- `LLVMBlockAddress` → `llvm.block_address(fn, bb)` (for computed goto)
|
||||
- `LLVMGetOperandUse` → `val.get_operand_use(index)` (use-def chain access)
|
||||
|
||||
### Session 6 - Final Feature Matrix Completion (December 2024)
|
||||
|
||||
#### Core.h - NEW ✅
|
||||
- `LLVMGetCastOpcode` → `llvm.get_cast_opcode(src, src_signed, dest_ty, dest_signed)`
|
||||
- `LLVMIntrinsicGetType` → `llvm.intrinsic_get_type(ctx, id, param_types)`
|
||||
- `LLVMReplaceMDNodeOperandWith` → `llvm.replace_md_node_operand_with(val, index, replacement)`
|
||||
|
||||
#### DebugInfo.h - NEW ✅
|
||||
- `LLVMDIBuilderCreateClassType` → `dib.create_class_type(...)`
|
||||
- `LLVMDIBuilderCreateStaticMemberType` → `dib.create_static_member_type(...)`
|
||||
- `LLVMDIBuilderCreateMemberPointerType` → `dib.create_member_pointer_type(...)`
|
||||
- `LLVMDIGlobalVariableExpressionGetVariable` → `llvm.di_global_variable_expression_get_variable(gve)`
|
||||
- `LLVMDIGlobalVariableExpressionGetExpression` → `llvm.di_global_variable_expression_get_expression(gve)`
|
||||
- `LLVMDIBuilderInsertDeclareRecordBefore` → `dib.insert_declare_record_before(...)`
|
||||
- `LLVMDIBuilderInsertDbgValueRecordBefore` → `dib.insert_dbg_value_record_before(...)`
|
||||
|
||||
#### Object.h - NEW ✅
|
||||
- `LLVMBinaryCopyMemoryBuffer` → `binary.copy_to_memory_buffer()`
|
||||
|
||||
#### Comdat.h - NEW ✅
|
||||
- `LLVMGetOrInsertComdat` → `mod.get_or_insert_comdat(name)`
|
||||
- `LLVMGetComdat` → `gv.comdat` property
|
||||
- `LLVMSetComdat` → `gv.set_comdat(comdat)`
|
||||
- `LLVMGetComdatSelectionKind` → `comdat.selection_kind` property
|
||||
- `LLVMSetComdatSelectionKind` → `comdat.selection_kind = kind` setter
|
||||
- `LLVMComdatSelectionKind` enum → `llvm.ComdatSelectionKind`
|
||||
|
||||
#### Skipped Items 🚫
|
||||
- `LLVMCreateMemoryBufferWithMemoryRange` - 🚫 Skip (zero-copy buffer is dangerous with Python GC; use copy version instead)
|
||||
- Support.h JIT functions (`LLVMLoadLibraryPermanently`, `LLVMSearchForAddressOfSymbol`, `LLVMAddSymbol`, `LLVMParseCommandLineOptions`) - 🚫 Skip (low value, JIT support not core focus)
|
||||
- ErrorHandling.h functions (`LLVMInstallFatalErrorHandler`, `LLVMResetFatalErrorHandler`, `LLVMEnablePrettyStackTrace`) - 🚫 Skip (callback-based fatal error handling is problematic in Python)
|
||||
|
||||
---
|
||||
|
||||
## Remaining TODO - Detailed Breakdown
|
||||
|
||||
### Medium Priority - Most Now Implemented
|
||||
|
||||
#### Type Attributes (Core.h) - COMPLETE ✅
|
||||
- `LLVMCreateTypeAttribute` → `ctx.create_type_attribute(kind_id, type)`
|
||||
- `LLVMGetTypeAttributeValue` → `attr.type_value`
|
||||
- `LLVMCreateConstantRangeAttribute` - 🚫 Skip (rare use case, complex API)
|
||||
|
||||
#### Metadata Kind ID (Core.h) - COMPLETE ✅
|
||||
- `LLVMGetMDKindIDInContext` → `ctx.get_md_kind_id(name)`
|
||||
|
||||
#### Module Flag Iteration (Core.h) - 🚫 SKIP
|
||||
- Can iterate via IR parsing if needed, complex API with limited value
|
||||
|
||||
#### Attribute Management (Core.h) - COMPLETE ✅
|
||||
All implemented (see Session 4 above).
|
||||
|
||||
#### Builder Position Control (Core.h) - COMPLETE ✅
|
||||
- `LLVMPositionBuilder` → `b.position_at(bb, inst)`
|
||||
- `LLVMClearInsertionPosition` → `b.clear_insertion_position()`
|
||||
- FP math tag methods - 🚫 Skip (very specialized, rarely needed)
|
||||
|
||||
#### Additional Builder Instructions (Core.h) - COMPLETE ✅
|
||||
All main instructions implemented. `LLVMBuildNUWNeg` deprecated in LLVM 21.
|
||||
|
||||
#### Convenience Cast Builders (Core.h) - COMPLETE ✅
|
||||
All implemented (see Session 4 above).
|
||||
- `LLVMGetCastOpcode` → `llvm.get_cast_opcode(...)` ✅
|
||||
|
||||
#### Value/Use Access (Core.h) - COMPLETE ✅
|
||||
- `LLVMGetOperandUse` → `val.get_operand_use(index)`
|
||||
- `LLVMBlockAddress` → `llvm.block_address(fn, bb)`
|
||||
|
||||
#### Intrinsics (Core.h) - COMPLETE ✅
|
||||
- `LLVMIntrinsicGetType` → `llvm.intrinsic_get_type(ctx, id, param_types)` ✅
|
||||
|
||||
#### Memory Buffer (Core.h) - COMPLETE ✅
|
||||
- `LLVMCreateMemoryBufferWithSTDIN` - 🚫 Skip (Python has better stdin handling)
|
||||
- `LLVMCreateMemoryBufferWithMemoryRange` - 🚫 Skip (zero-copy unsafe with Python GC)
|
||||
|
||||
#### Metadata (Core.h) - COMPLETE ✅
|
||||
- `LLVMGetMDKindIDInContext` → `ctx.get_md_kind_id(name)` ✅
|
||||
- `LLVMReplaceMDNodeOperandWith` → `llvm.replace_md_node_operand_with(...)` ✅
|
||||
|
||||
---
|
||||
|
||||
### Low Priority - Now Implemented ✅
|
||||
|
||||
#### Global IFunc (Core.h) - COMPLETE ✅
|
||||
| Function | Python API | Notes |
|
||||
|----------|------------|-------|
|
||||
| `LLVMEraseGlobalIFunc` | `val.erase_from_parent_ifunc()` | Safe, deletes IFunc |
|
||||
| `LLVMRemoveGlobalIFunc` | `val.remove_from_parent_ifunc()` | Advanced, keeps IFunc alive (use with care) |
|
||||
|
||||
#### DLL Storage Class (Core.h) - COMPLETE ✅
|
||||
| Function | Python API | Notes |
|
||||
|----------|------------|-------|
|
||||
| `LLVMGetDLLStorageClass` | `val.dll_storage_class` | Windows-specific property |
|
||||
| `LLVMSetDLLStorageClass` | `val.dll_storage_class = ...` | Windows-specific property |
|
||||
| `LLVMDLLStorageClass` enum | `llvm.DLLStorageClass` | Default, DLLImport, DLLExport |
|
||||
|
||||
#### Sync Scope (Core.h) - COMPLETE ✅
|
||||
| Function | Python API | Notes |
|
||||
|----------|------------|-------|
|
||||
| `LLVMGetSyncScopeID` | `ctx.get_sync_scope_id(name)` | Maps scope name to ID |
|
||||
|
||||
#### X86-Specific Types (Core.h)
|
||||
| Function | Python API | Notes |
|
||||
|----------|------------|-------|
|
||||
| `LLVMX86MMXTypeInContext` | 🚫 | Removed in LLVM 21, deprecated |
|
||||
| `LLVMX86AMXTypeInContext` | `ctx.types.x86_amx` | Already implemented |
|
||||
|
||||
#### Arbitrary Precision Constants (Core.h)
|
||||
| Function | Description | Notes |
|
||||
|----------|-------------|-------|
|
||||
| `LLVMConstIntOfArbitraryPrecision` | Arbitrary precision int | Use `constant_from_string` instead |
|
||||
| `LLVMConstVector` | Create constant vector | Can use array + bitcast |
|
||||
|
||||
---
|
||||
|
||||
### Intentionally Skipped (🚫)
|
||||
|
||||
#### Deprecated Functions
|
||||
| Function | Replacement |
|
||||
|----------|-------------|
|
||||
| `LLVMArrayType` | Use `LLVMArrayType2` (already bound) |
|
||||
| `LLVMConstArray` | Use `LLVMConstArray2` (already bound) |
|
||||
| `LLVMWriteBitcodeToFileHandle` | Use `LLVMWriteBitcodeToFile` |
|
||||
| `LLVMInsertIntoBuilder` | Use specific build methods |
|
||||
|
||||
#### Const Expression Builders
|
||||
These are deprecated - use builder instructions instead:
|
||||
| Function | Alternative |
|
||||
|----------|-------------|
|
||||
| `LLVMConstNeg`, `LLVMConstNot`, etc. | Build in function |
|
||||
| `LLVMConstAdd`, `LLVMConstSub`, etc. | Build in function |
|
||||
| `LLVMConstGEP2`, `LLVMConstInBoundsGEP2` | Use `builder.gep()` |
|
||||
| `LLVMConstTrunc`, `LLVMConstZExt`, etc. | Use builder casts |
|
||||
| `LLVMConstBitCast`, `LLVMConstAddrSpaceCast` | Use builder casts |
|
||||
| `LLVMConstICmp`, `LLVMConstFCmp` | Use `builder.icmp/fcmp` |
|
||||
| `LLVMConstSelect` | Use `builder.select` |
|
||||
|
||||
#### Dump Functions
|
||||
Use Python's `print()` instead:
|
||||
| Function | Alternative |
|
||||
|----------|-------------|
|
||||
| `LLVMDumpModule` | `print(mod)` |
|
||||
| `LLVMDumpType` | `print(ty)` |
|
||||
| `LLVMDumpValue` | `print(val)` |
|
||||
|
||||
#### Redundant Functions
|
||||
| Function | Alternative |
|
||||
|----------|-------------|
|
||||
| `LLVMGetNamedFunctionWithLength` | Use `mod.get_function(name)` |
|
||||
| `LLVMAppendModuleInlineAsm` | Use `mod.inline_asm += "..."` |
|
||||
| `LLVMGetLastEnumAttributeKind` | Not useful in Python |
|
||||
|
||||
#### Debugging-Only Functions
|
||||
| Function | Notes |
|
||||
|----------|-------|
|
||||
| `LLVMViewFunctionCFG` | Requires graphviz, debugging only |
|
||||
| `LLVMViewFunctionCFGOnly` | Requires graphviz, debugging only |
|
||||
|
||||
#### Low-Level File APIs
|
||||
| Function | Notes |
|
||||
|----------|-------|
|
||||
| `LLVMWriteBitcodeToFD` | Use file path or memory buffer |
|
||||
|
||||
---
|
||||
|
||||
### Advanced Features - Status Updated
|
||||
|
||||
#### Comdat.h (Windows/COFF Linking) - COMPLETE ✅
|
||||
| Function | Python API | Status |
|
||||
|----------|------------|--------|
|
||||
| `LLVMGetOrInsertComdat` | `mod.get_or_insert_comdat(name)` | ✅ |
|
||||
| `LLVMGetComdat` | `gv.comdat` (property) | ✅ |
|
||||
| `LLVMSetComdat` | `gv.set_comdat(comdat)` | ✅ |
|
||||
| `LLVMGetComdatSelectionKind` | `comdat.selection_kind` | ✅ |
|
||||
| `LLVMSetComdatSelectionKind` | `comdat.selection_kind = kind` | ✅ |
|
||||
|
||||
**Use Case:** COMDAT sections for deduplication in Windows COFF object files.
|
||||
|
||||
#### ErrorHandling.h (Fatal Error Handling) - 🚫 SKIP
|
||||
| Function | Description | Reason |
|
||||
|----------|-------------|--------|
|
||||
| `LLVMInstallFatalErrorHandler` | Install custom handler | 🚫 Callback-based, problematic in Python |
|
||||
| `LLVMResetFatalErrorHandler` | Reset to default | 🚫 Requires above |
|
||||
| `LLVMEnablePrettyStackTrace` | Enable stack traces | 🚫 Low value |
|
||||
|
||||
**Reason:** Fatal error handlers use C callbacks which are problematic with Python's GIL and garbage collection.
|
||||
|
||||
#### Support.h (Runtime Symbol Resolution) - 🚫 SKIP
|
||||
| Function | Description | Reason |
|
||||
|----------|-------------|--------|
|
||||
| `LLVMLoadLibraryPermanently` | Load shared library | 🚫 JIT-specific, low value |
|
||||
| `LLVMParseCommandLineOptions` | Parse LLVM cl options | 🚫 Internal LLVM config |
|
||||
| `LLVMSearchForAddressOfSymbol` | Find symbol address | 🚫 JIT-specific |
|
||||
| `LLVMAddSymbol` | Add symbol to table | 🚫 JIT-specific |
|
||||
|
||||
**Reason:** JIT symbol resolution not in scope for core bindings. Users needing JIT can use ctypes or extend bindings.
|
||||
|
||||
#### TargetMachineOptions (Builder API)
|
||||
| Function | Description | Priority |
|
||||
|----------|-------------|----------|
|
||||
| `LLVMCreateTargetMachineOptions` | Create options builder | Low |
|
||||
| `LLVMDisposeTargetMachineOptions` | Dispose options | Low |
|
||||
| `LLVMTargetMachineOptionsSetCPU` | Set CPU | Low |
|
||||
| `LLVMTargetMachineOptionsSetFeatures` | Set features | Low |
|
||||
| `LLVMTargetMachineOptionsSetABI` | Set ABI | Low |
|
||||
| `LLVMTargetMachineOptionsSetRelocationModel` | Set reloc model | Low |
|
||||
| `LLVMTargetMachineOptionsSetCodeGenOptLevel` | Set opt level | Low |
|
||||
| `LLVMCreateTargetMachineWithOptions` | Create TM with options | Low |
|
||||
|
||||
**Use Case:** Alternative builder pattern for target machine creation. Current `create_target_machine()` is sufficient.
|
||||
|
||||
#### ORC JIT APIs (Orc.h, LLJIT.h)
|
||||
Not yet tracked in detail. These provide modern JIT compilation:
|
||||
- ORC lazy compilation
|
||||
- LLJIT high-level interface
|
||||
- Object linking layer
|
||||
- Symbol resolution
|
||||
|
||||
**Use Case:** JIT compilation. Consider implementing if JIT is needed.
|
||||
|
||||
#### DebugInfo.h Remaining (~49 functions)
|
||||
Many DI creation functions for various DWARF constructs:
|
||||
- Composite types (arrays, vectors)
|
||||
- Derived types
|
||||
- Subranges
|
||||
- Template parameters
|
||||
- Imported entities
|
||||
- etc.
|
||||
|
||||
**Use Case:** Complete debug info for all language constructs.
|
||||
|
||||
---
|
||||
|
||||
## Implementation Notes
|
||||
|
||||
### Core Workflows - All Supported ✅
|
||||
|
||||
1. **IR Creation** - Full support for modules, functions, types, instructions
|
||||
2. **Bitcode I/O** - Read and write bitcode files
|
||||
3. **Optimization** - Full PassBuilder support with all options
|
||||
4. **Code Generation** - Emit object files and assembly
|
||||
5. **Module Linking** - Link modules together
|
||||
6. **Verification** - Verify modules and functions
|
||||
7. **Debug Info** - Core DIBuilder support
|
||||
|
||||
### Safety Model
|
||||
|
||||
All bindings include:
|
||||
- Lifetime tracking via `ValidityToken`
|
||||
- Null checks before LLVM-C calls
|
||||
- Python exceptions instead of crashes
|
||||
- Automatic resource cleanup
|
||||
|
||||
### Testing
|
||||
|
||||
- Golden master tests comparing C++ and Python output
|
||||
- Memory safety tests
|
||||
- Type checking with `ty check`
|
||||
|
||||
---
|
||||
|
||||
## Changelog
|
||||
|
||||
### December 2024
|
||||
- Implemented all high-priority items (BitWriter, PassBuilder, Target, Linker)
|
||||
- Added module flags, string attributes, constant from string
|
||||
- Added builder instructions (addr_space_cast, fence)
|
||||
- Added disassembler options
|
||||
- Updated documentation with detailed remaining items
|
||||
- Overall coverage: 74%
|
||||
@@ -1,274 +0,0 @@
|
||||
# Feature Matrix Summary
|
||||
|
||||
Comprehensive tracking of LLVM-C API implementation in llvm-nanobind Python bindings.
|
||||
|
||||
**Last Updated:** 2024-12-25 (verified complete)
|
||||
|
||||
---
|
||||
|
||||
## Quick Reference
|
||||
|
||||
```python
|
||||
import llvm
|
||||
|
||||
# Initialize native target
|
||||
llvm.initialize_native_target()
|
||||
llvm.initialize_native_asm_printer()
|
||||
|
||||
# Create context and module
|
||||
with llvm.create_context() as ctx:
|
||||
with ctx.create_module("example") as mod:
|
||||
# Types
|
||||
i32 = ctx.types.i32
|
||||
fn_ty = ctx.types.function(i32, [i32, i32])
|
||||
|
||||
# Function and basic block
|
||||
fn = mod.add_function("add", fn_ty)
|
||||
bb = fn.append_basic_block("entry")
|
||||
|
||||
# Build instructions
|
||||
with ctx.create_builder(bb) as b:
|
||||
result = b.add(fn.get_param(0), fn.get_param(1))
|
||||
b.ret(result)
|
||||
|
||||
# Output IR
|
||||
print(mod)
|
||||
|
||||
# Generate object code
|
||||
triple = llvm.get_default_target_triple()
|
||||
target = llvm.get_target_from_triple(triple)
|
||||
tm = llvm.create_target_machine(
|
||||
target, triple,
|
||||
llvm.get_host_cpu_name(),
|
||||
llvm.get_host_cpu_features(),
|
||||
llvm.CodeGenOptLevel.Default,
|
||||
llvm.RelocMode.Default,
|
||||
llvm.CodeModel.Default
|
||||
)
|
||||
|
||||
# Optimize
|
||||
opts = llvm.PassBuilderOptions()
|
||||
llvm.run_passes(mod, "default<O2>", tm, opts)
|
||||
|
||||
# Emit to bytes
|
||||
obj_bytes = tm.emit_to_memory_buffer(mod, llvm.CodeGenFileType.Object)
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Coverage Summary
|
||||
|
||||
| Header | Total | ✅ Impl | 🚫 Skip | ❌ TODO | Coverage |
|
||||
|--------|-------|---------|---------|---------|----------|
|
||||
| **Core.h** | 640 | **475** | 48 | 117 | **82%** |
|
||||
| **DebugInfo.h** | 99 | **~82** | 0 | ~17 | **~83%** |
|
||||
| **Target.h** | 22 | 22 | 0 | 0 | **100%** |
|
||||
| **TargetMachine.h** | 29 | 14 | 9 | 6 | **79%** |
|
||||
| **Object.h** | 31 | **24** | 0 | 7 | **77%** |
|
||||
| **Analysis.h** | 4 | 2 | 2 | 0 | **100%** |
|
||||
| **BitReader.h** | 8 | 3 | 5 | 0 | 37.5% |
|
||||
| **BitWriter.h** | 4 | 2 | 2 | 0 | **100%** |
|
||||
| **IRReader.h** | 1 | 1 | 0 | 0 | 100% |
|
||||
| **PassBuilder.h** | 15 | 15 | 0 | 0 | **100%** |
|
||||
| **Disassembler.h** | 6 | 4 | 0 | 2 | **67%** |
|
||||
| **Linker.h** | 1 | 1 | 0 | 0 | **100%** |
|
||||
| **Comdat.h** | 5 | **5** | 0 | 0 | **100%** |
|
||||
| **Support.h** | 4 | 0 | **4** | 0 | **100%** |
|
||||
| **ErrorHandling.h** | 3 | 0 | **3** | 0 | **100%** |
|
||||
| **Total** | **~872** | **~650** | **~73** | **~149** | **~85%** |
|
||||
|
||||
*Support.h and ErrorHandling.h skipped (JIT-only and callback-based APIs not suitable for Python).
|
||||
|
||||
---
|
||||
|
||||
## Implementation Status by Category
|
||||
|
||||
### ✅ Well Covered (>70%)
|
||||
|
||||
| Feature | Coverage | Notes |
|
||||
|---------|----------|-------|
|
||||
| Target initialization | 100% | All native/all target functions |
|
||||
| PassBuilder | 100% | All optimization options |
|
||||
| BitWriter | 100% | File and memory buffer output |
|
||||
| Linker | 100% | Module linking |
|
||||
| Module creation/properties | 95% | Full CRUD support |
|
||||
| Type system | 90% | All common types |
|
||||
| Target Machine | 79% | Create, emit, configure |
|
||||
| Basic block operations | 85% | Iteration, manipulation |
|
||||
| Builder - common instructions | 80% | Arithmetic, memory, control flow |
|
||||
| Global variables | 80% | Properties, initializers |
|
||||
| Functions | 75% | Parameters, attributes, intrinsics |
|
||||
| Object file reading | 74% | Sections, symbols, relocations |
|
||||
|
||||
### ⚠️ Partial Coverage (30-70%)
|
||||
|
||||
| Feature | Coverage | Notes |
|
||||
|---------|----------|-------|
|
||||
| Core.h | 64.5% | Most common APIs done |
|
||||
| Debug info | ~50% | Core DIBuilder, needs more types |
|
||||
| Disassembler | 50% | Basic disassembly works |
|
||||
| Analysis | 50% | Module/function verification |
|
||||
| Bitcode reading | 37.5% | Context versions only |
|
||||
| Metadata | 40% | Basic creation and attachment |
|
||||
| Attributes | 40% | Enum attributes, needs string/type |
|
||||
|
||||
### ❌ Not Implemented (<30%)
|
||||
|
||||
| Feature | Coverage | Priority | Notes |
|
||||
|---------|----------|----------|-------|
|
||||
| TargetMachineOptions | 0% | Low | Use create_target_machine() |
|
||||
| ORC JIT | 0% | Low | Not in scope for core bindings |
|
||||
|
||||
---
|
||||
|
||||
## Core Workflows - All Supported ✅
|
||||
|
||||
### 1. ✅ Bitcode Writing
|
||||
```python
|
||||
mod.write_bitcode_to_file("output.bc")
|
||||
bc_bytes = mod.write_bitcode_to_memory_buffer()
|
||||
```
|
||||
|
||||
### 2. ✅ Optimization Passes
|
||||
```python
|
||||
opts = llvm.PassBuilderOptions()
|
||||
opts.set_loop_vectorization(True)
|
||||
opts.set_slp_vectorization(True)
|
||||
llvm.run_passes(mod, "default<O2>", target_machine, opts)
|
||||
```
|
||||
|
||||
### 3. ✅ Code Generation
|
||||
```python
|
||||
tm = llvm.create_target_machine(target, triple, cpu, features, ...)
|
||||
obj_bytes = tm.emit_to_memory_buffer(mod, llvm.CodeGenFileType.Object)
|
||||
tm.emit_to_file(mod, "output.o", llvm.CodeGenFileType.Object)
|
||||
```
|
||||
|
||||
### 4. ✅ Host Queries
|
||||
```python
|
||||
triple = llvm.get_default_target_triple()
|
||||
cpu = llvm.get_host_cpu_name()
|
||||
features = llvm.get_host_cpu_features()
|
||||
```
|
||||
|
||||
### 5. ✅ Module Linking
|
||||
```python
|
||||
mod.link_module(other_mod) # other_mod is consumed
|
||||
```
|
||||
|
||||
### 6. ✅ Function/Module Verification
|
||||
```python
|
||||
mod.verify() # Raises on error
|
||||
fn.verify() # Returns bool
|
||||
fn.verify_and_print() # Returns (bool, error_msg)
|
||||
```
|
||||
|
||||
### 7. ✅ Target Data Queries
|
||||
```python
|
||||
td = tm.create_data_layout()
|
||||
size = td.abi_size_of_type(struct_ty)
|
||||
align = td.abi_alignment_of_type(i64_ty)
|
||||
ptr_int = td.int_ptr_type(ctx) # i64 on 64-bit
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Intentionally Skipped (🚫)
|
||||
|
||||
### Global Context APIs
|
||||
All functions using `LLVMGetGlobalContext()` - safety risk.
|
||||
|
||||
### Legacy Pass Manager
|
||||
`LLVMCreatePassManager`, `LLVMRunPassManager`, etc. - use PassBuilder.
|
||||
|
||||
### Deprecated Functions
|
||||
`LLVMBuildLoad`, `LLVMBuildGEP`, `LLVMBuildCall`, etc. - use `*2` versions.
|
||||
|
||||
### Unsafe for Embedding
|
||||
`LLVMShutdown` - would corrupt Python process.
|
||||
|
||||
### Internal APIs
|
||||
`LLVMCreateMessage`, `LLVMDisposeMessage` - internal memory management.
|
||||
|
||||
### Low-Level File APIs
|
||||
`LLVMWriteBitcodeToFD`, `LLVMWriteBitcodeToFileHandle` - use file/memory buffer.
|
||||
|
||||
### Debugging Only
|
||||
`LLVMViewFunctionCFG`, `LLVMViewFunctionCFGOnly` - requires graphviz.
|
||||
|
||||
---
|
||||
|
||||
## Remaining Features (Low Priority)
|
||||
|
||||
### Explicitly Skipped (🚫)
|
||||
|
||||
| Category | Functions | Reason |
|
||||
|----------|-----------|--------|
|
||||
| Support.h JIT | 4 | JIT symbol resolution - not in scope |
|
||||
| ErrorHandling.h | 3 | C callback-based - problematic in Python |
|
||||
| Memory Buffer (zero-copy) | 1 | Unsafe with Python GC |
|
||||
| Module Flag Iteration | 5 | Complex API - can parse IR instead |
|
||||
| FP Math Tags | ~4 | Very specialized, rarely needed |
|
||||
|
||||
### Advanced Features (Not Tracked)
|
||||
|
||||
| Feature | Functions | Use Case |
|
||||
|---------|-----------|----------|
|
||||
| ORC JIT | ~90 | Runtime code generation |
|
||||
| Remarks | ~24 | Optimization diagnostics |
|
||||
|
||||
See [progress.md](progress.md) for detailed breakdown.
|
||||
|
||||
---
|
||||
|
||||
## Detailed Matrix Files
|
||||
|
||||
| File | Contents |
|
||||
|------|----------|
|
||||
| [core.md](core.md) | Core.h - All 640 functions with Python API |
|
||||
| [debuginfo.md](debuginfo.md) | DebugInfo.h - 99 functions with examples |
|
||||
| [target.md](target.md) | Target/TargetMachine - 68 functions |
|
||||
| [misc.md](misc.md) | All other headers + advanced features |
|
||||
|
||||
---
|
||||
|
||||
## API Design Patterns
|
||||
|
||||
### Context Managers
|
||||
```python
|
||||
with llvm.create_context() as ctx:
|
||||
with ctx.create_module("mod") as mod:
|
||||
with ctx.create_builder(bb) as b:
|
||||
# Resources automatically cleaned up
|
||||
```
|
||||
|
||||
### Properties for Get/Set
|
||||
```python
|
||||
mod.name = "my_module" # LLVMSetModuleIdentifier
|
||||
print(mod.name) # LLVMGetModuleIdentifier
|
||||
```
|
||||
|
||||
### Pythonic Iteration
|
||||
```python
|
||||
for fn in mod.functions: # LLVMGetFirst/NextFunction
|
||||
for bb in fn.basic_blocks: # LLVMGetFirst/NextBasicBlock
|
||||
for inst in bb.instructions:
|
||||
print(inst)
|
||||
```
|
||||
|
||||
### Safety Checks
|
||||
```python
|
||||
# Raises LLVMMemoryError instead of crashing
|
||||
try:
|
||||
dead_module.functions # Module was disposed
|
||||
except llvm.LLVMMemoryError:
|
||||
print("Module no longer valid")
|
||||
```
|
||||
|
||||
### Rich Exceptions
|
||||
```python
|
||||
try:
|
||||
mod = ctx.parse_ir("invalid")
|
||||
except llvm.LLVMParseError as e:
|
||||
print(e) # Detailed error message
|
||||
```
|
||||
@@ -1,234 +0,0 @@
|
||||
# Target.h + TargetMachine.h Feature Matrix
|
||||
|
||||
LLVM-C Target and Code Generation API implementation status with Python API mappings.
|
||||
|
||||
## Legend
|
||||
|
||||
| Status | Meaning |
|
||||
|--------|---------|
|
||||
| ✅ | Implemented |
|
||||
| ❌ | Not implemented |
|
||||
|
||||
---
|
||||
|
||||
## Quick Start Example
|
||||
|
||||
```python
|
||||
import llvm
|
||||
|
||||
# Initialize targets (must call before using target APIs)
|
||||
llvm.initialize_native_target()
|
||||
llvm.initialize_native_asm_printer()
|
||||
|
||||
# Get target for host
|
||||
triple = llvm.get_default_target_triple()
|
||||
target = llvm.get_target_from_triple(triple)
|
||||
|
||||
# Create target machine
|
||||
tm = llvm.create_target_machine(
|
||||
target, triple,
|
||||
cpu=llvm.get_host_cpu_name(),
|
||||
features=llvm.get_host_cpu_features(),
|
||||
opt_level=llvm.CodeGenOptLevel.Default,
|
||||
reloc_mode=llvm.RelocMode.Default,
|
||||
code_model=llvm.CodeModel.Default
|
||||
)
|
||||
|
||||
# Get data layout
|
||||
td = tm.create_data_layout()
|
||||
print(f"Pointer size: {td.pointer_size()} bytes")
|
||||
|
||||
# Emit object code
|
||||
obj_bytes = tm.emit_to_memory_buffer(mod, llvm.CodeGenFileType.Object)
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Target Initialization
|
||||
|
||||
| C API | Status | Python API |
|
||||
|-------|--------|------------|
|
||||
| `LLVMInitializeAllTargetInfos` | ✅ | `llvm.initialize_all_target_infos()` |
|
||||
| `LLVMInitializeAllTargets` | ✅ | `llvm.initialize_all_targets()` |
|
||||
| `LLVMInitializeAllTargetMCs` | ✅ | `llvm.initialize_all_target_mcs()` |
|
||||
| `LLVMInitializeAllAsmPrinters` | ✅ | `llvm.initialize_all_asm_printers()` |
|
||||
| `LLVMInitializeAllAsmParsers` | ✅ | `llvm.initialize_all_asm_parsers()` |
|
||||
| `LLVMInitializeAllDisassemblers` | ✅ | `llvm.initialize_all_disassemblers()` |
|
||||
| `LLVMInitializeNativeTarget` | ✅ | `llvm.initialize_native_target()` |
|
||||
| `LLVMInitializeNativeAsmPrinter` | ✅ | `llvm.initialize_native_asm_printer()` |
|
||||
| `LLVMInitializeNativeAsmParser` | ✅ | `llvm.initialize_native_asm_parser()` |
|
||||
| `LLVMInitializeNativeDisassembler` | ✅ | `llvm.initialize_native_disassembler()` |
|
||||
|
||||
---
|
||||
|
||||
## Target Queries
|
||||
|
||||
| C API | Status | Python API |
|
||||
|-------|--------|------------|
|
||||
| `LLVMGetFirstTarget` | ✅ | `llvm.get_first_target()` |
|
||||
| `LLVMGetNextTarget` | ✅ | `target.next_target` |
|
||||
| `LLVMGetTargetFromName` | ✅ | `llvm.get_target_from_name(name)` |
|
||||
| `LLVMGetTargetFromTriple` | ✅ | `llvm.get_target_from_triple(triple)` |
|
||||
| `LLVMGetTargetName` | ✅ | `target.name` |
|
||||
| `LLVMGetTargetDescription` | ✅ | `target.description` |
|
||||
| `LLVMTargetHasJIT` | ✅ | `target.has_jit` |
|
||||
| `LLVMTargetHasTargetMachine` | ✅ | `target.has_target_machine` |
|
||||
| `LLVMTargetHasAsmBackend` | ✅ | `target.has_asm_backend` |
|
||||
|
||||
```python
|
||||
# Iterate all targets
|
||||
for target in llvm.targets():
|
||||
print(f"{target.name}: {target.description}")
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Host Queries
|
||||
|
||||
| C API | Status | Python API |
|
||||
|-------|--------|------------|
|
||||
| `LLVMGetDefaultTargetTriple` | ✅ | `llvm.get_default_target_triple()` |
|
||||
| `LLVMNormalizeTargetTriple` | ✅ | `llvm.normalize_target_triple(triple)` |
|
||||
| `LLVMGetHostCPUName` | ✅ | `llvm.get_host_cpu_name()` |
|
||||
| `LLVMGetHostCPUFeatures` | ✅ | `llvm.get_host_cpu_features()` |
|
||||
|
||||
```python
|
||||
triple = llvm.get_default_target_triple() # e.g., "arm64-apple-macosx15.0.0"
|
||||
cpu = llvm.get_host_cpu_name() # e.g., "apple-m1"
|
||||
features = llvm.get_host_cpu_features() # e.g., "+neon,+fp-armv8,..."
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Target Machine
|
||||
|
||||
| C API | Status | Python API |
|
||||
|-------|--------|------------|
|
||||
| `LLVMCreateTargetMachine` | ✅ | `llvm.create_target_machine(target, triple, cpu, features, opt, reloc, model)` |
|
||||
| `LLVMDisposeTargetMachine` | ✅ | Automatic cleanup |
|
||||
| `LLVMGetTargetMachineTarget` | ✅ | `tm.target` |
|
||||
| `LLVMGetTargetMachineTriple` | ✅ | `tm.triple` |
|
||||
| `LLVMGetTargetMachineCPU` | ✅ | `tm.cpu` |
|
||||
| `LLVMGetTargetMachineFeatureString` | ✅ | `tm.feature_string` |
|
||||
| `LLVMCreateTargetDataLayout` | ✅ | `tm.create_data_layout()` |
|
||||
| `LLVMSetTargetMachineAsmVerbosity` | ✅ | `tm.set_asm_verbosity(bool)` |
|
||||
| `LLVMSetTargetMachineFastISel` | ✅ | `tm.set_fast_isel(bool)` |
|
||||
| `LLVMSetTargetMachineGlobalISel` | ✅ | `tm.set_global_isel(bool)` |
|
||||
| `LLVMSetTargetMachineGlobalISelAbort` | ✅ | `tm.set_global_isel_abort(mode)` |
|
||||
| `LLVMSetTargetMachineMachineOutliner` | ✅ | `tm.set_machine_outliner(bool)` |
|
||||
| `LLVMTargetMachineEmitToFile` | ✅ | `tm.emit_to_file(mod, path, file_type)` |
|
||||
| `LLVMTargetMachineEmitToMemoryBuffer` | ✅ | `tm.emit_to_memory_buffer(mod, file_type)` → `bytes` |
|
||||
| `LLVMCreateTargetMachineOptions` | ❌ | Not implemented (use create_target_machine) |
|
||||
| `LLVMDisposeTargetMachineOptions` | ❌ | Not implemented |
|
||||
| `LLVMTargetMachineOptionsSetCPU` | ❌ | Not implemented |
|
||||
| `LLVMTargetMachineOptionsSetFeatures` | ❌ | Not implemented |
|
||||
| `LLVMTargetMachineOptionsSetABI` | ❌ | Not implemented |
|
||||
| `LLVMTargetMachineOptionsSetRelocationModel` | ❌ | Not implemented |
|
||||
| `LLVMTargetMachineOptionsSetCodeGenOptLevel` | ❌ | Not implemented |
|
||||
| `LLVMCreateTargetMachineWithOptions` | ❌ | Not implemented |
|
||||
| `LLVMAddAnalysisPasses` | ❌ | Not implemented (legacy PM) |
|
||||
|
||||
```python
|
||||
# Create target machine
|
||||
llvm.initialize_native_target()
|
||||
llvm.initialize_native_asm_printer()
|
||||
|
||||
target = llvm.get_target_from_triple(llvm.get_default_target_triple())
|
||||
tm = llvm.create_target_machine(
|
||||
target,
|
||||
llvm.get_default_target_triple(),
|
||||
llvm.get_host_cpu_name(),
|
||||
llvm.get_host_cpu_features(),
|
||||
llvm.CodeGenOptLevel.Default,
|
||||
llvm.RelocMode.Default,
|
||||
llvm.CodeModel.Default
|
||||
)
|
||||
|
||||
# Emit to file
|
||||
tm.emit_to_file(mod, "output.o", llvm.CodeGenFileType.Object)
|
||||
tm.emit_to_file(mod, "output.s", llvm.CodeGenFileType.Assembly)
|
||||
|
||||
# Emit to memory
|
||||
obj_bytes = tm.emit_to_memory_buffer(mod, llvm.CodeGenFileType.Object)
|
||||
asm_bytes = tm.emit_to_memory_buffer(mod, llvm.CodeGenFileType.Assembly)
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Target Data
|
||||
|
||||
| C API | Status | Python API |
|
||||
|-------|--------|------------|
|
||||
| `LLVMCreateTargetData` | ✅ | `llvm.create_target_data(string_rep)` |
|
||||
| `LLVMDisposeTargetData` | ✅ | Automatic cleanup |
|
||||
| `LLVMCopyStringRepOfTargetData` | ✅ | `str(td)` |
|
||||
| `LLVMByteOrder` | ✅ | `td.byte_order` |
|
||||
| `LLVMPointerSize` | ✅ | `td.pointer_size()` |
|
||||
| `LLVMPointerSizeForAS` | ✅ | `td.pointer_size(address_space)` |
|
||||
| `LLVMIntPtrType` | ✅ | `td.int_ptr_type(ctx)` |
|
||||
| `LLVMIntPtrTypeForAS` | ✅ | `td.int_ptr_type(ctx, address_space)` |
|
||||
| `LLVMIntPtrTypeInContext` | ✅ | `td.int_ptr_type(ctx)` |
|
||||
| `LLVMIntPtrTypeForASInContext` | ✅ | `td.int_ptr_type(ctx, address_space)` |
|
||||
| `LLVMSizeOfTypeInBits` | ✅ | `td.size_of_type_in_bits(ty)` |
|
||||
| `LLVMStoreSizeOfType` | ✅ | `td.store_size_of_type(ty)` |
|
||||
| `LLVMABISizeOfType` | ✅ | `td.abi_size_of_type(ty)` |
|
||||
| `LLVMABIAlignmentOfType` | ✅ | `td.abi_alignment_of_type(ty)` |
|
||||
| `LLVMCallFrameAlignmentOfType` | ✅ | `td.call_frame_alignment_of_type(ty)` |
|
||||
| `LLVMPreferredAlignmentOfType` | ✅ | `td.preferred_alignment_of_type(ty)` |
|
||||
| `LLVMPreferredAlignmentOfGlobal` | ✅ | `td.preferred_alignment_of_global(gv)` |
|
||||
| `LLVMElementAtOffset` | ✅ | `td.element_at_offset(struct_ty, offset)` |
|
||||
| `LLVMOffsetOfElement` | ✅ | `td.offset_of_element(struct_ty, elem)` |
|
||||
| `LLVMGetModuleDataLayout` | ❌ | Not implemented |
|
||||
| `LLVMSetModuleDataLayout` | ❌ | Not implemented |
|
||||
| `LLVMAddTargetLibraryInfo` | ❌ | Not implemented (legacy PM) |
|
||||
|
||||
```python
|
||||
# Get data layout from target machine
|
||||
td = tm.create_data_layout()
|
||||
print(f"Data layout: {td}")
|
||||
|
||||
# Or create directly
|
||||
td = llvm.create_target_data("e-m:o-i64:64-f80:128-n8:16:32:64-S128")
|
||||
|
||||
# Query sizes
|
||||
print(f"Pointer size: {td.pointer_size()} bytes")
|
||||
print(f"i64 size: {td.size_of_type_in_bits(ctx.int64_type())} bits")
|
||||
print(f"i64 alignment: {td.abi_alignment_of_type(ctx.int64_type())} bytes")
|
||||
|
||||
# Get integer type matching pointer size
|
||||
int_ptr = td.int_ptr_type(ctx) # Returns i64 on 64-bit
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Enums
|
||||
|
||||
| C Enum | Python Enum |
|
||||
|--------|-------------|
|
||||
| `LLVMCodeGenOptLevel` | `llvm.CodeGenOptLevel` (.None_, .Less, .Default, .Aggressive) |
|
||||
| `LLVMRelocMode` | `llvm.RelocMode` (.Default, .Static, .PIC, .DynamicNoPic, .ROPI, .RWPI, .ROPI_RWPI) |
|
||||
| `LLVMCodeModel` | `llvm.CodeModel` (.Default, .JITDefault, .Tiny, .Small, .Kernel, .Medium, .Large) |
|
||||
| `LLVMCodeGenFileType` | `llvm.CodeGenFileType` (.Assembly, .Object) |
|
||||
| `LLVMGlobalISelAbortMode` | `llvm.GlobalISelAbortMode` (.Disable, .Enable, .DisableWithDiag) |
|
||||
| `LLVMByteOrdering` | `llvm.ByteOrdering` (.BigEndian, .LittleEndian) |
|
||||
|
||||
---
|
||||
|
||||
## Summary
|
||||
|
||||
| Category | Total | Implemented | Coverage |
|
||||
|----------|-------|-------------|----------|
|
||||
| Target Initialization | 10 | 10 | 100% |
|
||||
| Target Queries | 9 | 9 | 100% |
|
||||
| Host Queries | 4 | 4 | 100% |
|
||||
| Target Machine | 23 | 14 | 61% |
|
||||
| Target Data | 22 | 19 | 86% |
|
||||
| **Total** | **68** | **56** | **82%** |
|
||||
|
||||
---
|
||||
|
||||
## Not Implemented (Low Priority)
|
||||
|
||||
1. **TargetMachineOptions API** - Alternative builder pattern for target machine creation. Current `create_target_machine()` is sufficient.
|
||||
2. **Module data layout get/set** - Can be added if needed.
|
||||
3. **Legacy PassManager integration** - Use new PassBuilder API instead.
|
||||
Reference in New Issue
Block a user