diff --git a/src/mir/builder/control_flow/joinir/merge/instruction_rewriter.rs b/src/mir/builder/control_flow/joinir/merge/instruction_rewriter.rs index 0bc325bb..dd43a618 100644 --- a/src/mir/builder/control_flow/joinir/merge/instruction_rewriter.rs +++ b/src/mir/builder/control_flow/joinir/merge/instruction_rewriter.rs @@ -13,7 +13,7 @@ use crate::mir::join_ir::lowering::inline_boundary::JoinInlineBoundary; use super::loop_header_phi_info::LoopHeaderPhiInfo; use super::tail_call_classifier::{TailCallKind, classify_tail_call}; use super::merge_result::MergeResult; -use std::collections::HashMap; +use std::collections::BTreeMap; // Phase 222.5-E: HashMap → BTreeMap for determinism /// Phase 179-A: Exit continuation function name (MIR convention) /// This is the standard name for k_exit continuations in JoinIR → MIR lowering @@ -44,8 +44,8 @@ pub(super) fn merge_and_rewrite( builder: &mut crate::mir::builder::MirBuilder, mir_module: &MirModule, remapper: &mut JoinIrIdRemapper, - value_to_func_name: &HashMap, - function_params: &HashMap>, + value_to_func_name: &BTreeMap, // Phase 222.5-E: HashMap → BTreeMap for determinism + function_params: &BTreeMap>, // Phase 222.5-E: HashMap → BTreeMap for determinism boundary: Option<&JoinInlineBoundary>, loop_header_phi_info: &mut LoopHeaderPhiInfo, exit_block_id: BasicBlockId, @@ -68,7 +68,8 @@ pub(super) fn merge_and_rewrite( std::collections::BTreeMap::new(); // Build function_entry_map for Call→Jump conversion - let mut function_entry_map: HashMap = HashMap::new(); + // Phase 222.5-E: HashMap → BTreeMap for determinism + let mut function_entry_map: BTreeMap = BTreeMap::new(); for (func_name, func) in &mir_module.functions { let entry_block_new = remapper .get_block(func_name, func.entry_block) @@ -121,7 +122,8 @@ pub(super) fn merge_and_rewrite( } // Build a local block map for this function (for remap_instruction compatibility) - let mut local_block_map: HashMap = HashMap::new(); + // Phase 222.5-E: HashMap → BTreeMap for determinism + let mut local_block_map: BTreeMap = BTreeMap::new(); for old_block_id in func.blocks.keys() { let new_block_id = remapper .get_block(func_name, *old_block_id) @@ -687,8 +689,9 @@ pub(super) fn merge_and_rewrite( .get_block(entry_func_name, entry_func.entry_block) .ok_or_else(|| format!("Entry block not found for {}", entry_func_name))?; - // Create HashMap from remapper for BoundaryInjector (temporary adapter) - let mut value_map_for_injector = HashMap::new(); + // Create BTreeMap from remapper for BoundaryInjector (temporary adapter) + // Phase 222.5-E: HashMap → BTreeMap for determinism + let mut value_map_for_injector = BTreeMap::new(); // Phase 171-fix: Add join_inputs to value_map for join_in in &boundary.join_inputs { diff --git a/src/mir/builder/control_flow/joinir/merge/value_collector.rs b/src/mir/builder/control_flow/joinir/merge/value_collector.rs index 28548114..8aff5071 100644 --- a/src/mir/builder/control_flow/joinir/merge/value_collector.rs +++ b/src/mir/builder/control_flow/joinir/merge/value_collector.rs @@ -7,7 +7,8 @@ use crate::mir::{MirInstruction, MirModule, ValueId}; use crate::mir::builder::joinir_id_remapper::JoinIrIdRemapper; -use std::collections::{BTreeSet, HashMap}; +use std::collections::BTreeSet; // Phase 222.5-E: HashMap → BTreeMap for determinism +use std::collections::BTreeMap; // Phase 222.5-E: HashMap → BTreeMap for determinism /// Phase 2: Collect all ValueIds used across ALL functions (Phase 189) /// @@ -21,8 +22,8 @@ pub(super) fn collect_values( ) -> Result< ( BTreeSet, - HashMap, - HashMap>, + BTreeMap, // Phase 222.5-E: HashMap → BTreeMap for determinism + BTreeMap>, // Phase 222.5-E: HashMap → BTreeMap for determinism ), String, > { @@ -33,11 +34,13 @@ pub(super) fn collect_values( } let mut used_values: BTreeSet = BTreeSet::new(); - let mut value_to_func_name: HashMap = HashMap::new(); - let mut function_params: HashMap> = HashMap::new(); + // Phase 222.5-E: HashMap → BTreeMap for determinism + let mut value_to_func_name: BTreeMap = BTreeMap::new(); + let mut function_params: BTreeMap> = BTreeMap::new(); // Build function_entry_map for tracking function names - let function_entry_map: HashMap = mir_module + // Phase 222.5-E: HashMap → BTreeMap for determinism + let function_entry_map: BTreeMap = mir_module .functions .keys() .map(|name| (name.clone(), ())) diff --git a/src/mir/builder/joinir_id_remapper.rs b/src/mir/builder/joinir_id_remapper.rs index 1401e727..fce27387 100644 --- a/src/mir/builder/joinir_id_remapper.rs +++ b/src/mir/builder/joinir_id_remapper.rs @@ -5,22 +5,25 @@ //! - JoinIR fragment → host MIR への ID変換 //! - 決定性を重視した実装 -use std::collections::HashMap; +use std::collections::BTreeMap; // Phase 222.5-E: HashMap → BTreeMap for determinism use crate::mir::{BasicBlock, BasicBlockId, MirInstruction, ValueId}; /// JoinIR ID space を host MIR ID space に変換する pub struct JoinIrIdRemapper { /// (func_name, old_block_id) → new_block_id のマッピング - block_map: HashMap<(String, BasicBlockId), BasicBlockId>, + /// Phase 222.5-E: HashMap → BTreeMap for determinism + block_map: BTreeMap<(String, BasicBlockId), BasicBlockId>, /// old_value_id → new_value_id のマッピング - value_map: HashMap, + /// Phase 222.5-E: HashMap → BTreeMap for determinism + value_map: BTreeMap, } impl JoinIrIdRemapper { pub fn new() -> Self { Self { - block_map: HashMap::new(), - value_map: HashMap::new(), + // Phase 222.5-E: HashMap → BTreeMap for determinism + block_map: BTreeMap::new(), + value_map: BTreeMap::new(), } } diff --git a/src/mir/builder/joinir_inline_boundary_injector.rs b/src/mir/builder/joinir_inline_boundary_injector.rs index 308f718b..01903800 100644 --- a/src/mir/builder/joinir_inline_boundary_injector.rs +++ b/src/mir/builder/joinir_inline_boundary_injector.rs @@ -5,7 +5,7 @@ //! - Entry block への Copy instruction 挿入 //! - SSA 値空間の接続 -use std::collections::HashMap; +use std::collections::BTreeMap; // Phase 222.5-E: HashMap → BTreeMap for determinism use crate::mir::{BasicBlockId, MirFunction, MirInstruction, ValueId}; use crate::mir::join_ir::lowering::inline_boundary::JoinInlineBoundary; @@ -49,16 +49,17 @@ impl BoundaryInjector { /// /// # Returns /// - /// Returns a HashMap mapping original ValueIds to their reallocated ValueIds + /// Returns a BTreeMap mapping original ValueIds to their reallocated ValueIds /// (only for condition_bindings that had collisions). + /// Phase 222.5-E: HashMap → BTreeMap for determinism pub fn inject_boundary_copies( func: &mut MirFunction, entry_block_id: BasicBlockId, boundary: &JoinInlineBoundary, - value_map: &HashMap, + value_map: &BTreeMap, // Phase 222.5-E: HashMap → BTreeMap for determinism phi_dst_ids: &std::collections::HashSet, debug: bool, - ) -> Result, String> { + ) -> Result, String> { // Phase 222.5-E: HashMap → BTreeMap for determinism // Phase 33-20: When loop_var_name is set, ALL join_inputs are handled by header PHIs // This includes the loop variable AND all other carriers from exit_bindings. // We skip ALL join_inputs Copy instructions, only condition_bindings remain. @@ -73,7 +74,8 @@ impl BoundaryInjector { let total_inputs = effective_join_inputs + boundary.condition_bindings.len(); if total_inputs == 0 { // No inputs to process, return empty reallocations map - return Ok(HashMap::new()); + // Phase 222.5-E: HashMap → BTreeMap for determinism + return Ok(BTreeMap::new()); } if debug { @@ -98,7 +100,8 @@ impl BoundaryInjector { // Phase 177-3 Option B: First pass - allocate all new ValueIds for PHI collisions // We need to do this BEFORE acquiring the entry_block reference to avoid borrow conflicts - let mut reallocations = HashMap::new(); + // Phase 222.5-E: HashMap → BTreeMap for determinism + let mut reallocations = BTreeMap::new(); for binding in &boundary.condition_bindings { let remapped_join = value_map.get(&binding.join_value).copied().unwrap_or(binding.join_value);