diff --git a/src/mir/builder/calls/lowering.rs b/src/mir/builder/calls/lowering.rs index 12cd7a64..47988373 100644 --- a/src/mir/builder/calls/lowering.rs +++ b/src/mir/builder/calls/lowering.rs @@ -268,21 +268,42 @@ impl MirBuilder { let mut slot_regs: Vec<(String, Option)> = Vec::new(); if let Some(ref mut f) = self.current_function { - // 📦 Hotfix 6: Use pre-reserved ValueIds instead of generating new ones - // MirFunction::new() already reserved ValueIds 0..N for parameters - // First parameter is always 'me' at ValueId(0) - let me_id = ValueId(0); - f.params.push(me_id); + // 📦 Hotfix 6 改訂版: + // MirFunction::new() が既に 0..N の ValueId を params 用に予約しているので、 + // ここではそれを「上書き使用」するだけにして、push で二重定義しないようにするよ。 + // + // params レイアウト: + // index 0: me (box) + // index 1..: 通常パラメータ + if f.params.is_empty() { + // 安全弁: 何らかの理由で pre-populate されていない場合は従来どおり new する + let me_id = ValueId(0); + f.params.push(me_id); + for i in 0..params.len() { + f.params.push(ValueId((i + 1) as u32)); + } + } + + // me + let me_id = f.params[0]; self.variable_map.insert("me".to_string(), me_id); self.value_origin_newbox.insert(me_id, box_name.to_string()); slot_regs.push(("me".to_string(), None)); - // Then regular parameters at ValueId(1), ValueId(2), ... + // 通常パラメータ for (idx, p) in params.iter().enumerate() { - let pid = ValueId((idx + 1) as u32); - f.params.push(pid); - self.variable_map.insert(p.clone(), pid); - slot_regs.push((p.clone(), None)); + let param_idx = idx + 1; + if param_idx < f.params.len() { + let pid = f.params[param_idx]; + self.variable_map.insert(p.clone(), pid); + slot_regs.push((p.clone(), None)); + } else { + // 念のため足りない場合は新規に確保(互換用) + let pid = f.next_value_id(); + f.params.push(pid); + self.variable_map.insert(p.clone(), pid); + slot_regs.push((p.clone(), None)); + } } } diff --git a/src/mir/builder/calls/unified_emitter.rs b/src/mir/builder/calls/unified_emitter.rs index 62368705..dd216961 100644 --- a/src/mir/builder/calls/unified_emitter.rs +++ b/src/mir/builder/calls/unified_emitter.rs @@ -177,6 +177,14 @@ impl UnifiedCallEmitterBox { let mut args_local: Vec = args; crate::mir::builder::emit_guard::finalize_call_operands(builder, &mut callee, &mut args_local); + // 📦 Hotfix 7: Include receiver in args for Callee::Method + // VM's exec_function_inner expects receiver as the first parameter (ValueId(0)) + // but finalize_call_operands keeps receiver in Callee, not in args. + // We must add it to args_local here so VM can bind it correctly. + if let Callee::Method { receiver: Some(recv), .. } = &callee { + args_local.insert(0, *recv); + } + // Create MirCall instruction using the new module (pure data composition) let mir_call = call_unified::create_mir_call(dst, callee.clone(), args_local.clone());