//! Phase 189: JoinIR ID Remapper - ValueId/BlockId ID空間変換の独立化 //! //! 責務: //! - ValueId/BlockId の ID割り当て //! - JoinIR fragment → host MIR への ID変換 //! - 決定性を重視した実装 use crate::mir::{BasicBlock, BasicBlockId, MirInstruction, ValueId}; use std::collections::BTreeMap; // Phase 222.5-E: HashMap → BTreeMap for determinism /// JoinIR ID space を host MIR ID space に変換する pub struct JoinIrIdRemapper { /// (func_name, old_block_id) → new_block_id のマッピング /// Phase 222.5-E: HashMap → BTreeMap for determinism block_map: BTreeMap<(String, BasicBlockId), BasicBlockId>, /// old_value_id → new_value_id のマッピング /// Phase 222.5-E: HashMap → BTreeMap for determinism value_map: BTreeMap, } impl JoinIrIdRemapper { pub fn new() -> Self { Self { // Phase 222.5-E: HashMap → BTreeMap for determinism block_map: BTreeMap::new(), value_map: BTreeMap::new(), } } /// Block ID mapping を取得 pub fn get_block(&self, func_name: &str, old_id: BasicBlockId) -> Option { self.block_map .get(&(func_name.to_string(), old_id)) .copied() } /// Value ID mapping を取得 pub fn get_value(&self, old_id: ValueId) -> Option { self.value_map.get(&old_id).copied() } /// Block mapping を設定 pub fn set_block(&mut self, func_name: String, old_id: BasicBlockId, new_id: BasicBlockId) { self.block_map.insert((func_name, old_id), new_id); } /// Value mapping を設定 pub fn set_value(&mut self, old_id: ValueId, new_id: ValueId) { self.value_map.insert(old_id, new_id); } /// Block 内の ValueId を収集 pub fn collect_values_in_block(&self, block: &BasicBlock) -> Vec { let mut values = Vec::new(); for inst in &block.instructions { values.extend(self.collect_values_in_instruction(inst)); } if let Some(ref term) = block.terminator { values.extend(self.collect_values_in_instruction(term)); } values } /// 命令内の ValueId を収集 pub fn collect_values_in_instruction(&self, inst: &MirInstruction) -> Vec { use crate::mir::MirInstruction::*; match inst { Const { dst, .. } => vec![*dst], UnaryOp { dst, operand, .. } => vec![*dst, *operand], BinOp { dst, lhs, rhs, .. } => vec![*dst, *lhs, *rhs], Compare { dst, lhs, rhs, .. } => vec![*dst, *lhs, *rhs], Load { dst, ptr } => vec![*dst, *ptr], Store { value, ptr } => vec![*value, *ptr], Call { dst, func, args, .. } => { let mut vals = vec![*func]; if let Some(d) = dst { vals.push(*d); } vals.extend(args.iter().copied()); vals } BoxCall { dst, box_val, args, .. } => { let mut vals = vec![*box_val]; if let Some(d) = dst { vals.push(*d); } vals.extend(args.iter().copied()); vals } PluginInvoke { dst, box_val, args, .. } => { let mut vals = vec![*box_val]; if let Some(d) = dst { vals.push(*d); } vals.extend(args.iter().copied()); vals } Branch { condition, .. } => vec![*condition], Return { value } => value.iter().copied().collect(), Phi { dst, inputs, .. } => { let mut vals = vec![*dst]; vals.extend(inputs.iter().map(|(_, v)| *v)); vals } Copy { dst, src } => vec![*dst, *src], NewBox { dst, args, .. } => { let mut vals = vec![*dst]; vals.extend(args.iter().copied()); vals } NewClosure { dst, captures, me, .. } => { let mut vals = vec![*dst]; vals.extend(captures.iter().map(|(_, v)| *v)); if let Some(m) = me { vals.push(*m); } vals } Print { value, .. } => vec![*value], Debug { value, .. } => vec![*value], DebugLog { values, .. } => values.clone(), Throw { exception, .. } => vec![*exception], Catch { exception_value, .. } => vec![*exception_value], RefNew { dst, box_val } => vec![*dst, *box_val], RefGet { dst, reference, .. } => vec![*dst, *reference], RefSet { reference, value, .. } => vec![*reference, *value], WeakNew { dst, box_val } => vec![*dst, *box_val], WeakLoad { dst, weak_ref } => vec![*dst, *weak_ref], WeakRef { dst, value, .. } => vec![*dst, *value], BarrierRead { ptr } => vec![*ptr], BarrierWrite { ptr } => vec![*ptr], Barrier { ptr, .. } => vec![*ptr], FutureNew { dst, value } => vec![*dst, *value], FutureSet { future, value } => vec![*future, *value], Await { dst, future } => vec![*dst, *future], TypeCheck { dst, value, .. } => vec![*dst, *value], Cast { dst, value, .. } => vec![*dst, *value], TypeOp { dst, value, .. } => vec![*dst, *value], ArrayGet { dst, array, index } => vec![*dst, *array, *index], ArraySet { array, index, value, } => vec![*array, *index, *value], Jump { .. } | Nop | Safepoint => vec![], ExternCall { dst, args, .. } => { let mut vals = Vec::new(); if let Some(d) = dst { vals.push(*d); } vals.extend(args.iter().copied()); vals } } } /// 命令を新しい ID空間にリマップ pub fn remap_instruction(&self, inst: &MirInstruction) -> MirInstruction { use crate::mir::MirInstruction::*; let remap = |v: ValueId| self.value_map.get(&v).copied().unwrap_or(v); match inst { Const { dst, value } => Const { dst: remap(*dst), value: value.clone(), }, UnaryOp { dst, op, operand } => UnaryOp { dst: remap(*dst), op: *op, operand: remap(*operand), }, BinOp { dst, op, lhs, rhs } => BinOp { dst: remap(*dst), op: *op, lhs: remap(*lhs), rhs: remap(*rhs), }, Compare { dst, op, lhs, rhs } => Compare { dst: remap(*dst), op: *op, lhs: remap(*lhs), rhs: remap(*rhs), }, Load { dst, ptr } => Load { dst: remap(*dst), ptr: remap(*ptr), }, Store { value, ptr } => Store { value: remap(*value), ptr: remap(*ptr), }, Call { dst, func, callee, args, effects, } => Call { dst: dst.map(remap), func: remap(*func), callee: callee.clone(), args: args.iter().map(|&a| remap(a)).collect(), effects: *effects, }, BoxCall { dst, box_val, method, method_id, args, effects, } => BoxCall { dst: dst.map(remap), box_val: remap(*box_val), method: method.clone(), method_id: *method_id, args: args.iter().map(|&a| remap(a)).collect(), effects: *effects, }, PluginInvoke { dst, box_val, method, args, effects, } => PluginInvoke { dst: dst.map(remap), box_val: remap(*box_val), method: method.clone(), args: args.iter().map(|&a| remap(a)).collect(), effects: *effects, }, Copy { dst, src } => Copy { dst: remap(*dst), src: remap(*src), }, NewBox { dst, box_type, args, } => NewBox { dst: remap(*dst), box_type: box_type.clone(), args: args.iter().map(|&a| remap(a)).collect(), }, NewClosure { dst, params, body, captures, me, } => NewClosure { dst: remap(*dst), params: params.clone(), body: body.clone(), captures: captures .iter() .map(|(n, v)| (n.clone(), remap(*v))) .collect(), me: me.map(remap), }, Print { value, effects } => Print { value: remap(*value), effects: *effects, }, Debug { value, message } => Debug { value: remap(*value), message: message.clone(), }, DebugLog { message, values } => DebugLog { message: message.clone(), values: values.iter().map(|&v| remap(v)).collect(), }, Throw { exception, effects } => Throw { exception: remap(*exception), effects: *effects, }, Catch { exception_type, exception_value, handler_bb, } => Catch { exception_type: exception_type.clone(), exception_value: remap(*exception_value), handler_bb: *handler_bb, }, RefNew { dst, box_val } => RefNew { dst: remap(*dst), box_val: remap(*box_val), }, RefGet { dst, reference, field, } => RefGet { dst: remap(*dst), reference: remap(*reference), field: field.clone(), }, RefSet { reference, field, value, } => RefSet { reference: remap(*reference), field: field.clone(), value: remap(*value), }, WeakNew { dst, box_val } => WeakNew { dst: remap(*dst), box_val: remap(*box_val), }, WeakLoad { dst, weak_ref } => WeakLoad { dst: remap(*dst), weak_ref: remap(*weak_ref), }, WeakRef { dst, op, value } => WeakRef { dst: remap(*dst), op: *op, value: remap(*value), }, BarrierRead { ptr } => BarrierRead { ptr: remap(*ptr) }, BarrierWrite { ptr } => BarrierWrite { ptr: remap(*ptr) }, Barrier { op, ptr } => Barrier { op: *op, ptr: remap(*ptr), }, FutureNew { dst, value } => FutureNew { dst: remap(*dst), value: remap(*value), }, FutureSet { future, value } => FutureSet { future: remap(*future), value: remap(*value), }, Await { dst, future } => Await { dst: remap(*dst), future: remap(*future), }, TypeCheck { dst, value, expected_type, } => TypeCheck { dst: remap(*dst), value: remap(*value), expected_type: expected_type.clone(), }, Cast { dst, value, target_type, } => Cast { dst: remap(*dst), value: remap(*value), target_type: target_type.clone(), }, TypeOp { dst, op, value, ty } => TypeOp { dst: remap(*dst), op: *op, value: remap(*value), ty: ty.clone(), }, ArrayGet { dst, array, index } => ArrayGet { dst: remap(*dst), array: remap(*array), index: remap(*index), }, ArraySet { array, index, value, } => ArraySet { array: remap(*array), index: remap(*index), value: remap(*value), }, ExternCall { dst, iface_name, method_name, args, effects, } => ExternCall { dst: dst.map(remap), iface_name: iface_name.clone(), method_name: method_name.clone(), args: args.iter().map(|&a| remap(a)).collect(), effects: *effects, }, // Phase 189 FIX: Remap PHI dst and input values (BlockId remapping is done in control_flow.rs) Phi { dst, inputs, type_hint, } => Phi { dst: remap(*dst), inputs: inputs.iter().map(|(bb, val)| (*bb, remap(*val))).collect(), type_hint: type_hint.clone(), }, // Pass through unchanged (Branch/Jump/Return handled separately) Branch { .. } | Jump { .. } | Return { .. } | Nop | Safepoint => inst.clone(), } } /// Value ID をリマップ pub fn remap_value(&self, v: ValueId) -> ValueId { self.value_map.get(&v).copied().unwrap_or(v) } /// Block ID をリマップ #[allow(dead_code)] pub fn remap_block(&self, func_name: &str, b: BasicBlockId) -> BasicBlockId { self.block_map .get(&(func_name.to_string(), b)) .copied() .unwrap_or(b) } } #[cfg(test)] mod tests { use super::*; #[test] fn test_remapper_new() { let remapper = JoinIrIdRemapper::new(); assert_eq!(remapper.get_value(ValueId(0)), None); } #[test] fn test_remapper_set_and_get_value() { let mut remapper = JoinIrIdRemapper::new(); remapper.set_value(ValueId(0), ValueId(10)); assert_eq!(remapper.get_value(ValueId(0)), Some(ValueId(10))); } #[test] fn test_remapper_set_and_get_block() { let mut remapper = JoinIrIdRemapper::new(); remapper.set_block("main".to_string(), BasicBlockId(0), BasicBlockId(100)); assert_eq!( remapper.get_block("main", BasicBlockId(0)), Some(BasicBlockId(100)) ); } #[test] fn test_remap_value() { let mut remapper = JoinIrIdRemapper::new(); remapper.set_value(ValueId(5), ValueId(50)); assert_eq!(remapper.remap_value(ValueId(5)), ValueId(50)); assert_eq!(remapper.remap_value(ValueId(99)), ValueId(99)); // Unmapped returns original } #[test] fn test_collect_values_simple() { let remapper = JoinIrIdRemapper::new(); let inst = MirInstruction::BinOp { dst: ValueId(1), op: crate::mir::types::BinaryOp::Add, lhs: ValueId(2), rhs: ValueId(3), }; let values = remapper.collect_values_in_instruction(&inst); assert_eq!(values, vec![ValueId(1), ValueId(2), ValueId(3)]); } }