Files
hakorune/src/llvm_py/instructions/safepoint.py

107 lines
3.4 KiB
Python
Raw Normal View History

"""
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}")