✨ Python LLVM backend implementation (experimental)
- Created llvmlite-based LLVM backend in src/llvm_py/ - Implemented all MIR14 instructions (const, binop, jump, branch, ret, compare, phi, call, boxcall, externcall, typeop, newbox, safepoint, barrier) - Experimental LoopForm support - ~2000 lines of clean Python code vs complex Rust/inkwell - Useful for PHI/SSA validation and rapid prototyping - Added documentation to CLAUDE.md This was created while waiting for ChatGPT's investigation of BuilderCursor issues.
This commit is contained in:
107
src/llvm_py/instructions/safepoint.py
Normal file
107
src/llvm_py/instructions/safepoint.py
Normal file
@ -0,0 +1,107 @@
|
||||
"""
|
||||
Safepoint instruction lowering
|
||||
GC safepoints where runtime can safely collect garbage
|
||||
"""
|
||||
|
||||
import llvmlite.ir as ir
|
||||
from typing import Dict, List, Optional
|
||||
|
||||
def lower_safepoint(
|
||||
builder: ir.IRBuilder,
|
||||
module: ir.Module,
|
||||
live_values: List[int],
|
||||
vmap: Dict[int, ir.Value],
|
||||
safepoint_id: Optional[int] = None
|
||||
) -> None:
|
||||
"""
|
||||
Lower MIR Safepoint instruction
|
||||
|
||||
Safepoints are places where GC can safely run.
|
||||
Live values must be tracked for potential relocation.
|
||||
|
||||
Args:
|
||||
builder: Current LLVM IR builder
|
||||
module: LLVM module
|
||||
live_values: List of value IDs that are live across safepoint
|
||||
vmap: Value map
|
||||
safepoint_id: Optional safepoint identifier
|
||||
"""
|
||||
# Look up or declare safepoint function
|
||||
safepoint_func = None
|
||||
for f in module.functions:
|
||||
if f.name == "ny_safepoint":
|
||||
safepoint_func = f
|
||||
break
|
||||
|
||||
if not safepoint_func:
|
||||
# Declare ny_safepoint(live_count: i64, live_values: i64*) -> void
|
||||
i64 = ir.IntType(64)
|
||||
void = ir.VoidType()
|
||||
func_type = ir.FunctionType(void, [i64, i64.as_pointer()])
|
||||
safepoint_func = ir.Function(module, func_type, name="ny_safepoint")
|
||||
|
||||
# Prepare live values array
|
||||
i64 = ir.IntType(64)
|
||||
if live_values:
|
||||
# Allocate array for live values
|
||||
array_size = len(live_values)
|
||||
live_array = builder.alloca(i64, size=array_size, name="live_vals")
|
||||
|
||||
# Store each live value
|
||||
for i, vid in enumerate(live_values):
|
||||
val = vmap.get(vid, ir.Constant(i64, 0))
|
||||
|
||||
# Ensure i64 (handles are i64)
|
||||
if hasattr(val, 'type') and val.type.is_pointer:
|
||||
val = builder.ptrtoint(val, i64)
|
||||
|
||||
idx = ir.Constant(ir.IntType(32), i)
|
||||
ptr = builder.gep(live_array, [idx])
|
||||
builder.store(val, ptr)
|
||||
|
||||
# Call safepoint
|
||||
count = ir.Constant(i64, array_size)
|
||||
builder.call(safepoint_func, [count, live_array])
|
||||
|
||||
# After safepoint, reload values (they may have moved)
|
||||
for i, vid in enumerate(live_values):
|
||||
idx = ir.Constant(ir.IntType(32), i)
|
||||
ptr = builder.gep(live_array, [idx])
|
||||
new_val = builder.load(ptr, name=f"reload_{vid}")
|
||||
vmap[vid] = new_val
|
||||
else:
|
||||
# No live values
|
||||
zero = ir.Constant(i64, 0)
|
||||
null = ir.Constant(i64.as_pointer(), None)
|
||||
builder.call(safepoint_func, [zero, null])
|
||||
|
||||
def insert_automatic_safepoint(
|
||||
builder: ir.IRBuilder,
|
||||
module: ir.Module,
|
||||
location: str # "loop_header", "function_call", etc.
|
||||
) -> None:
|
||||
"""
|
||||
Insert automatic safepoint at strategic locations
|
||||
|
||||
Args:
|
||||
builder: Current LLVM IR builder
|
||||
module: LLVM module
|
||||
location: Location type for debugging
|
||||
"""
|
||||
# Simple safepoint without tracking specific values
|
||||
# Runtime will scan stack/registers
|
||||
|
||||
check_func = None
|
||||
for f in module.functions:
|
||||
if f.name == "ny_check_safepoint":
|
||||
check_func = f
|
||||
break
|
||||
|
||||
if not check_func:
|
||||
# Declare ny_check_safepoint() -> void
|
||||
void = ir.VoidType()
|
||||
func_type = ir.FunctionType(void, [])
|
||||
check_func = ir.Function(module, func_type, name="ny_check_safepoint")
|
||||
|
||||
# Insert safepoint check
|
||||
builder.call(check_func, [], name=f"safepoint_{location}")
|
||||
Reference in New Issue
Block a user