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

116 lines
3.4 KiB
Python
Raw Normal View History

"""
NewBox instruction lowering
Handles box creation (new StringBox(), new IntegerBox(), etc.)
"""
import llvmlite.ir as ir
from typing import Dict, List, Optional
def lower_newbox(
builder: ir.IRBuilder,
module: ir.Module,
box_type: str,
args: List[int],
dst_vid: int,
vmap: Dict[int, ir.Value],
resolver=None
) -> None:
"""
Lower MIR NewBox instruction
Creates a new box instance and returns its handle.
Args:
builder: Current LLVM IR builder
module: LLVM module
box_type: Box type name (e.g., "StringBox", "IntegerBox")
args: Constructor arguments
dst_vid: Destination value ID for box handle
vmap: Value map
resolver: Optional resolver for type handling
"""
# Look up or declare the box creation function
create_func_name = f"ny_create_{box_type}"
create_func = None
for f in module.functions:
if f.name == create_func_name:
create_func = f
break
if not create_func:
# Declare box creation function
# Signature depends on box type
i64 = ir.IntType(64)
i8 = ir.IntType(8)
if box_type in ["StringBox", "IntegerBox", "BoolBox"]:
# Built-in boxes - default constructors (no args)
# Real implementation may have optional args
func_type = ir.FunctionType(i64, [])
else:
# Generic box - variable arguments
# For now, assume no args
func_type = ir.FunctionType(i64, [])
create_func = ir.Function(module, func_type, name=create_func_name)
# Prepare arguments
call_args = []
for i, arg_id in enumerate(args):
arg_val = vmap.get(arg_id)
if not arg_val:
# Default based on box type
if box_type == "StringBox":
# Empty string
i8 = ir.IntType(8)
arg_val = ir.Constant(i8.as_pointer(), None)
else:
# Zero
arg_val = ir.Constant(ir.IntType(64), 0)
# Type conversion if needed
if box_type == "StringBox" and hasattr(arg_val, 'type'):
if isinstance(arg_val.type, ir.IntType):
# int to string ptr
i8 = ir.IntType(8)
arg_val = builder.inttoptr(arg_val, i8.as_pointer())
call_args.append(arg_val)
# Create the box
handle = builder.call(create_func, call_args, name=f"new_{box_type}")
# Store handle
vmap[dst_vid] = handle
def lower_newbox_generic(
builder: ir.IRBuilder,
module: ir.Module,
dst_vid: int,
vmap: Dict[int, ir.Value]
) -> None:
"""
Create a generic box with runtime allocation
This is used when box type is not statically known.
"""
# Look up generic allocation function
alloc_func = None
for f in module.functions:
if f.name == "ny_alloc_box":
alloc_func = f
break
if not alloc_func:
# Declare ny_alloc_box(size: i64) -> i64
i64 = ir.IntType(64)
func_type = ir.FunctionType(i64, [i64])
alloc_func = ir.Function(module, func_type, name="ny_alloc_box")
# Default box size (e.g., 64 bytes)
size = ir.Constant(ir.IntType(64), 64)
handle = builder.call(alloc_func, [size], name="new_box")
vmap[dst_vid] = handle