80 lines
2.5 KiB
Python
80 lines
2.5 KiB
Python
|
|
"""
|
||
|
|
Call instruction lowering
|
||
|
|
Handles regular function calls (not BoxCall or ExternCall)
|
||
|
|
"""
|
||
|
|
|
||
|
|
import llvmlite.ir as ir
|
||
|
|
from typing import Dict, List, Optional
|
||
|
|
|
||
|
|
def lower_call(
|
||
|
|
builder: ir.IRBuilder,
|
||
|
|
module: ir.Module,
|
||
|
|
func_name: str,
|
||
|
|
args: List[int],
|
||
|
|
dst_vid: Optional[int],
|
||
|
|
vmap: Dict[int, ir.Value],
|
||
|
|
resolver=None
|
||
|
|
) -> None:
|
||
|
|
"""
|
||
|
|
Lower MIR Call instruction
|
||
|
|
|
||
|
|
Args:
|
||
|
|
builder: Current LLVM IR builder
|
||
|
|
module: LLVM module
|
||
|
|
func_name: Function name to call
|
||
|
|
args: List of argument value IDs
|
||
|
|
dst_vid: Optional destination for return value
|
||
|
|
vmap: Value map
|
||
|
|
resolver: Optional resolver for type handling
|
||
|
|
"""
|
||
|
|
# Look up function in module
|
||
|
|
func = None
|
||
|
|
for f in module.functions:
|
||
|
|
if f.name == func_name:
|
||
|
|
func = f
|
||
|
|
break
|
||
|
|
|
||
|
|
if not func:
|
||
|
|
# Function not found - create declaration
|
||
|
|
# Default: i64(i64, ...) signature
|
||
|
|
ret_type = ir.IntType(64)
|
||
|
|
arg_types = [ir.IntType(64)] * len(args)
|
||
|
|
func_type = ir.FunctionType(ret_type, arg_types)
|
||
|
|
func = ir.Function(module, func_type, name=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 expected type
|
||
|
|
if i < len(func.args):
|
||
|
|
expected_type = func.args[i].type
|
||
|
|
else:
|
||
|
|
expected_type = ir.IntType(64)
|
||
|
|
|
||
|
|
if isinstance(expected_type, ir.IntType):
|
||
|
|
arg_val = ir.Constant(expected_type, 0)
|
||
|
|
elif isinstance(expected_type, ir.DoubleType):
|
||
|
|
arg_val = ir.Constant(expected_type, 0.0)
|
||
|
|
else:
|
||
|
|
arg_val = ir.Constant(expected_type, None)
|
||
|
|
|
||
|
|
# Type conversion if needed
|
||
|
|
if i < len(func.args):
|
||
|
|
expected_type = func.args[i].type
|
||
|
|
if hasattr(arg_val, 'type') and arg_val.type != expected_type:
|
||
|
|
if expected_type.is_pointer and isinstance(arg_val.type, ir.IntType):
|
||
|
|
arg_val = builder.inttoptr(arg_val, expected_type)
|
||
|
|
elif isinstance(expected_type, ir.IntType) and arg_val.type.is_pointer:
|
||
|
|
arg_val = builder.ptrtoint(arg_val, expected_type)
|
||
|
|
|
||
|
|
call_args.append(arg_val)
|
||
|
|
|
||
|
|
# Make the call
|
||
|
|
result = builder.call(func, call_args, name=f"call_{func_name}")
|
||
|
|
|
||
|
|
# Store result if needed
|
||
|
|
if dst_vid is not None:
|
||
|
|
vmap[dst_vid] = result
|