refactor(joinir): Phase 286C-2.1 Step 1 - Create 3-stage function stubs
- 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<RewritePlan, String> - plan_rewrites(RewritePlan, &mut RewriteContext) -> Result<RewrittenBlocks, String> - 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 <noreply@anthropic.com>
This commit is contained in:
@ -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<ValueId, String>,
|
||||
ctx: &RewriteContext,
|
||||
debug: bool,
|
||||
) -> Result<RewritePlan, String> {
|
||||
// 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<RewrittenBlocks, String> {
|
||||
// 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<MergeResult, String> {
|
||||
// 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<String> (function names)
|
||||
// No need to convert with join_func_name() - use directly
|
||||
let continuation_candidates: BTreeSet<String> = 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,
|
||||
|
||||
Reference in New Issue
Block a user