From f2458280c1a4ea009454d07eb9567ca928fca604 Mon Sep 17 00:00:00 2001 From: tomoaki Date: Thu, 25 Dec 2025 03:19:06 +0900 Subject: [PATCH] refactor(joinir): Phase 286C-2.1 Step 1 - Create 3-stage function stubs MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Create scan_blocks() stub (Stage 1: Read-only analysis) - Create plan_rewrites() stub (Stage 2: Pure transformation) - Create apply_rewrites() stub (Stage 3: Builder mutation) - Add strategic markers for future extraction (STAGE 1/2/3) - Document future orchestrator structure Function Signatures: - scan_blocks(&MirFunction, &JoinInlineBoundary, &RewriteContext) -> Result - plan_rewrites(RewritePlan, &mut RewriteContext) -> Result - apply_rewrites(&mut MirBuilder, RewrittenBlocks) -> Result<(), String> Benefits: - Borrow checker safety: Sequential calling pattern (no overlapping borrows) - Clear extraction targets: TODO markers identify logic to move - Build stability: Stubs compile successfully, no functionality changes yet - Foundation for incremental refactoring: Steps 2-5 can now proceed safely Strategic Markers: - Line 205: STAGE 1 marker (scan logic) - Line 282: STAGE 2 marker (plan logic) - Line 1355: STAGE 3 marker (apply logic) - Line 1514: Future orchestrator structure Status: - Scaffolding: ✅ Complete (stubs in place) - Extraction: ⏳ Next step (move logic from merge_and_rewrite to stubs) Build: cargo build --release ✅ 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Sonnet 4.5 --- .../joinir/merge/instruction_rewriter.rs | 113 ++++++++++++++++++ 1 file changed, 113 insertions(+) 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 56f8ecae..d55e1945 100644 --- a/src/mir/builder/control_flow/joinir/merge/instruction_rewriter.rs +++ b/src/mir/builder/control_flow/joinir/merge/instruction_rewriter.rs @@ -87,6 +87,73 @@ use super::rewriter::terminator::{apply_remapped_terminator, remap_branch, remap // The module is ready at super::rewriter::exit_collection but full integration // requires careful refactoring due to logging context and flow control. +// Phase 286C-2.1: Import scaffolding data structures for 3-stage pipeline +use super::rewriter::scan_box::{RewritePlan, TailCallRewrite, ReturnConversion, PhiAdjustment, ParameterBinding}; +use super::rewriter::plan_box::RewrittenBlocks; + +/// Stage 1: Scan - Read-only analysis to identify what needs rewriting +/// +/// Scans all blocks and instructions to identify: +/// - Tail calls to convert +/// - Returns to convert to exit jumps +/// - PHI adjustments needed +/// - Parameter bindings to generate +/// +/// This is a READ-ONLY operation - no mutations, just analysis. +fn scan_blocks( + mir_module: &MirModule, + remapper: &JoinIrIdRemapper, + value_to_func_name: &BTreeMap, + ctx: &RewriteContext, + debug: bool, +) -> Result { + // TODO: Extract scan logic from merge_and_rewrite + // For now, return empty plan + Ok(RewritePlan { + tail_calls: Vec::new(), + return_conversions: Vec::new(), + phi_adjustments: Vec::new(), + parameter_bindings: Vec::new(), + }) +} + +/// Stage 2: Plan - Transform plan into concrete rewritten blocks +/// +/// Generates new BasicBlocks based on the scan plan: +/// - Creates parameter binding instructions +/// - Builds PHI input mappings +/// - Prepares block ID remapping tables +/// +/// Updates RewriteContext but does NOT touch MirBuilder. +fn plan_rewrites( + plan: RewritePlan, + ctx: &mut RewriteContext, +) -> Result { + // TODO: Extract plan logic from merge_and_rewrite + // For now, return empty blocks + Ok(RewrittenBlocks { + new_blocks: Vec::new(), + block_replacements: BTreeMap::new(), + phi_inputs: Vec::new(), + carrier_inputs: BTreeMap::new(), + }) +} + +/// Stage 3: Apply - Apply rewritten blocks to MirBuilder +/// +/// Mutates the builder: +/// - Adds new blocks +/// - Replaces modified blocks +/// - Updates function metadata +fn apply_rewrites( + builder: &mut crate::mir::builder::MirBuilder, + blocks: RewrittenBlocks, +) -> Result<(), String> { + // TODO: Extract apply logic from merge_and_rewrite + // For now, do nothing (blocks will be added by existing logic) + Ok(()) +} + /// Phase 4: Merge ALL functions and rewrite instructions /// /// Returns: @@ -119,6 +186,14 @@ pub(super) fn merge_and_rewrite( exit_block_id: BasicBlockId, debug: bool, ) -> Result { + // Phase 286C-2.1: TODO - This will become an orchestrator calling the 3 stages: + // 1. scan_blocks() - Read-only analysis + // 2. plan_rewrites() - Generate rewritten blocks + // 3. apply_rewrites() - Mutate builder + // + // For now, keep existing monolithic logic intact to ensure no behavior changes. + // Future steps will extract logic incrementally into the 3 functions. + let trace = trace::trace(); let verbose = debug || crate::config::env::joinir_dev_enabled(); macro_rules! log { @@ -127,6 +202,14 @@ pub(super) fn merge_and_rewrite( }; } + // ===== STAGE 1: SCAN (Read-only analysis) ===== + // TODO Phase 286C-2.1: Extract to scan_blocks() + // This section should: + // - Build function_entry_map + // - Build skipped_entry_redirects + // - Identify tail calls, returns, PHI adjustments + // - Return RewritePlan describing what to do + // Phase 256 P1.7: continuation_func_ids is now BTreeSet (function names) // No need to convert with join_func_name() - use directly let continuation_candidates: BTreeSet = boundary @@ -196,6 +279,15 @@ pub(super) fn merge_and_rewrite( // The issue was that pre-pass used stale remapper values before Phase 33-21 updates. // Instead, we now generate Copies for non-carrier params in the main block processing loop. + // ===== STAGE 2: PLAN (Generate rewritten blocks) ===== + // TODO Phase 286C-2.1: Extract to plan_rewrites() + // This section should: + // - Process each function and block + // - Generate Copy instructions for parameter bindings + // - Build new BasicBlocks with remapped instructions + // - Prepare PHI inputs and carrier inputs + // - Return RewrittenBlocks ready to apply + // DETERMINISM FIX: Sort functions by name to ensure consistent iteration order if debug { log!( @@ -1260,6 +1352,13 @@ pub(super) fn merge_and_rewrite( new_block.instruction_spans.truncate(inst_count); } + // ===== STAGE 3: APPLY (Mutate builder) ===== + // TODO Phase 286C-2.1: Extract to apply_rewrites() + // This section should: + // - Add new_block to builder + // - Update function metadata + // - Apply span synchronization + // Add block to current function if let Some(ref mut current_func) = builder.scope_ctx.current_function { // Phase 256 P1.10 DEBUG: Log block content before adding (for blocks with multiple instructions) @@ -1412,6 +1511,20 @@ pub(super) fn merge_and_rewrite( } } + // Phase 286C-2.1: Future orchestrator structure (Step 2 onwards): + // + // // Stage 1: Scan - Read-only analysis + // let plan = scan_blocks(mir_module, remapper, value_to_func_name, &ctx, debug)?; + // + // // Stage 2: Plan - Generate rewritten blocks + // let blocks = plan_rewrites(plan, &mut ctx)?; + // + // // Stage 3: Apply - Mutate builder + // apply_rewrites(builder, blocks)?; + // + // // Build final merge result + // Ok(MergeResult { ... }) + Ok(MergeResult { exit_block_id: ctx.exit_block_id, exit_phi_inputs: ctx.exit_phi_inputs,