use std::collections::HashMap; use inkwell::{values::BasicValueEnum as BVE, AddressSpace}; use crate::backend::llvm::context::CodegenContext; use crate::mir::ValueId; /// Handle getField/setField; returns true if handled. use super::super::builder_cursor::BuilderCursor; pub(super) fn try_handle_field_method<'ctx, 'b>( codegen: &CodegenContext<'ctx>, cursor: &mut BuilderCursor<'ctx, 'b>, cur_bid: crate::mir::BasicBlockId, vmap: &mut HashMap>, dst: &Option, method: &str, args: &[ValueId], recv_h: inkwell::values::IntValue<'ctx>, resolver: &mut super::super::Resolver<'ctx>, bb_map: &std::collections::HashMap>, preds: &std::collections::HashMap>, block_end_values: &std::collections::HashMap>>, ) -> Result { let i64t = codegen.context.i64_type(); match method { "getField" => { if args.len() != 1 { return Err("getField expects 1 arg (name)".to_string()); } let name_p = resolver .resolve_ptr(codegen, cursor, cur_bid, args[0], bb_map, preds, block_end_values, vmap)?; let i8p = codegen.context.ptr_type(AddressSpace::from(0)); let fnty = i64t.fn_type(&[i64t.into(), i8p.into()], false); let callee = codegen .module .get_function("nyash.instance.get_field_h") .unwrap_or_else(|| codegen.module.add_function("nyash.instance.get_field_h", fnty, None)); let call = cursor .emit_instr(cur_bid, |b| b.build_call(callee, &[recv_h.into(), name_p.into()], "getField")) .map_err(|e| e.to_string())?; if let Some(d) = dst { let rv = call .try_as_basic_value() .left() .ok_or("get_field returned void".to_string())?; let h = if let BVE::IntValue(iv) = rv { iv } else { return Err("get_field ret expected i64".to_string()); }; let pty = codegen.context.ptr_type(AddressSpace::from(0)); let ptr = codegen .builder .build_int_to_ptr(h, pty, "gf_handle_to_ptr") .map_err(|e| e.to_string())?; vmap.insert(*d, ptr.into()); } Ok(true) } "setField" => { if args.len() != 2 { return Err("setField expects 2 args (name, value)".to_string()); } let name_p = resolver .resolve_ptr(codegen, cursor, cur_bid, args[0], bb_map, preds, block_end_values, vmap)?; let val_h = resolver .resolve_i64(codegen, cursor, cur_bid, args[1], bb_map, preds, block_end_values, vmap)?; let i8p = codegen.context.ptr_type(AddressSpace::from(0)); let fnty = i64t.fn_type(&[i64t.into(), i8p.into(), i64t.into()], false); let callee = codegen .module .get_function("nyash.instance.set_field_h") .unwrap_or_else(|| codegen.module.add_function("nyash.instance.set_field_h", fnty, None)); let _ = cursor .emit_instr(cur_bid, |b| b.build_call(callee, &[recv_h.into(), name_p.into(), val_h.into()], "setField")) .map_err(|e| e.to_string())?; Ok(true) } _ => Ok(false), } }