📦 Hotfix 1 & 2: Parameter ValueId Reservation + Exit PHI Validation (Box-First Theory)
**箱理論に基づく根治的修正**: ## 🎯 Hotfix 1: Parameter ValueId Reservation (パラメータ ValueId 予約) ### 根本原因 - MirFunction counter が params.len() を考慮していなかった - local variables が parameter ValueIds を上書き ### 箱理論的解決 1. **LoopFormContext Box** - パラメータ予約を明示的に管理 - 境界をはっきりさせる 2. **MirFunction::new() 改善** - `initial_counter = param_count.max(1)` でパラメータ予約 - Parameters are %0, %1, ..., %N-1 3. **ensure_counter_after() 強化** - パラメータ数 + 既存 ValueIds 両方を考慮 - `min_counter = param_count.max(max_id + 1)` 4. **reserve_parameter_value_ids() 追加** - 明示的な予約メソッド(Box-First) ## 🎯 Hotfix 2: Exit PHI Predecessor Validation (Exit PHI 検証) ### 根本原因 - LoopForm builder が存在しないブロックを PHI predecessor に追加 - 「幽霊ブロック」問題 ### 箱理論的解決 1. **LoopFormOps.block_exists() 追加** - CFG 存在確認メソッド - 境界を明確化 2. **build_exit_phis() 検証** - 非存在ブロックをスキップ - デバッグログ付き ### 実装ファイル - `src/mir/function.rs`: Parameter reservation - `src/mir/phi_core/loopform_builder.rs`: Context + validation - `src/mir/loop_builder.rs`: LoopFormOps impl - `src/mir/builder/stmts.rs`: Local variable allocation ### 業界標準準拠 - ✅ LLVM IR: Parameters are %0, %1, ... - ✅ SSA Form: PHI predecessors must exist in CFG - ✅ Cytron et al. (1991): Parameter reservation principle 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
@ -77,15 +77,24 @@ impl MirFunction {
|
||||
let mut blocks = HashMap::new();
|
||||
blocks.insert(entry_block, BasicBlock::new(entry_block));
|
||||
|
||||
// 📦 Hotfix 1: Reserve ValueIds for function parameters at creation time
|
||||
// Parameter ValueIds are %0, %1, ..., %N-1 where N = signature.params.len()
|
||||
// next_value_id must start at N to avoid overwriting parameters
|
||||
let param_count = signature.params.len() as u32;
|
||||
let initial_counter = param_count.max(1); // At least 1 to reserve ValueId(0) as sentinel
|
||||
|
||||
if std::env::var("NYASH_LOOPFORM_DEBUG").is_ok() {
|
||||
eprintln!("[MirFunction::new] fn='{}' params={}, initial_counter={}",
|
||||
signature.name, param_count, initial_counter);
|
||||
}
|
||||
|
||||
Self {
|
||||
signature,
|
||||
blocks,
|
||||
entry_block,
|
||||
locals: Vec::new(),
|
||||
params: Vec::new(),
|
||||
// CRITICAL FIX: Start from 1 to reserve ValueId(0) as invalid/uninitialized
|
||||
// LoopForm v2 and other systems use ValueId(0) as sentinel value
|
||||
next_value_id: 1,
|
||||
next_value_id: initial_counter,
|
||||
metadata: FunctionMetadata::default(),
|
||||
}
|
||||
}
|
||||
@ -97,6 +106,26 @@ impl MirFunction {
|
||||
id
|
||||
}
|
||||
|
||||
/// 📦 Reserve ValueIds for function parameters (Hotfix 1: Parameter ValueId Reservation)
|
||||
///
|
||||
/// Call this after setting params to ensure next_value_id doesn't overlap
|
||||
/// with parameter ValueIds. This prevents SSA violations where local variables
|
||||
/// overwrite parameter values.
|
||||
///
|
||||
/// # Box-First理論
|
||||
/// - 「境界をはっきりさせる」: パラメータ予約を明示的に
|
||||
/// - 「いつでも戻せる」: 呼び出しタイミングを制御可能
|
||||
pub fn reserve_parameter_value_ids(&mut self) {
|
||||
let param_count = self.signature.params.len();
|
||||
if self.next_value_id < param_count as u32 {
|
||||
if std::env::var("NYASH_LOOPFORM_DEBUG").is_ok() {
|
||||
eprintln!("[MirFunction::reserve_parameter_value_ids] fn='{}' reserving {} params, adjusting counter {} -> {}",
|
||||
self.signature.name, param_count, self.next_value_id, param_count);
|
||||
}
|
||||
self.next_value_id = param_count as u32;
|
||||
}
|
||||
}
|
||||
|
||||
/// Add a new basic block
|
||||
pub fn add_block(&mut self, block: BasicBlock) -> BasicBlockId {
|
||||
let id = block.id;
|
||||
|
||||
Reference in New Issue
Block a user