feat(mir/phi): improve LoopForm parameter detection - track param names

**Problem**: is_parameter() was too simple, checking only ValueId which changes
through copies/PHIs. This caused parameters like 'data' to be misclassified as
carriers, leading to incorrect PHI construction.

**Solution**: Track original parameter names at function entry.

**Changes**:

1. **Added function_param_names field** (builder.rs):
   - HashSet<String> to track original parameter names
   - Populated in lower_static_method_as_function()
   - Cleared and repopulated for each new function

2. **Improved is_parameter()** (loop_builder.rs):
   - Check name against function_param_names instead of ValueId
   - More reliable than checking func.params (ValueIds change)
   - __pin$*$@* variables correctly classified as carriers
   - Added debug logging with NYASH_LOOPFORM_DEBUG

3. **Enhanced debug output** (loopform_builder.rs):
   - Show carrier/pinned classification during prepare_structure()
   - Show variable_map state after emit_header_phis()

**Test Results**:
-  'args' correctly identified as parameter (was working)
-  'data' now correctly identified as parameter (was broken)
-  __pin variables correctly classified as carriers
-  PHI values allocated and variable_map updated correctly
- ⚠️ ValueId undefined errors persist (separate issue)

**Remaining Issue**:
ValueId(10) undefined error suggests PHI visibility problem or VM verification
issue. Needs further investigation of emit_phi_at_block_start() or VM executor.

**Backward Compatibility**:
- Flag OFF: 100% existing behavior preserved (legacy path unchanged)
- Feature-flagged with NYASH_LOOPFORM_PHI_V2=1

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
nyash-codex
2025-11-17 05:24:07 +09:00
parent f85e485195
commit c459135238
6 changed files with 258 additions and 11 deletions

View File

@ -38,7 +38,7 @@ pub struct PinnedVariable {
///
/// Key Innovation: All ValueIds allocated upfront before any MIR emission,
/// eliminating circular dependency issues.
#[derive(Debug, Default)]
#[derive(Debug)]
pub struct LoopFormBuilder {
pub carriers: Vec<CarrierVariable>,
pub pinned: Vec<PinnedVariable>,
@ -77,6 +77,10 @@ impl LoopFormBuilder {
preheader_copy: ops.new_value(), // Allocate NOW
header_phi: ops.new_value(), // Allocate NOW
};
if std::env::var("NYASH_LOOPFORM_DEBUG").is_ok() {
eprintln!("[loopform/prepare] pinned: {} -> init={:?}, copy={:?}, phi={:?}",
name, value, pinned.preheader_copy, pinned.header_phi);
}
self.pinned.push(pinned);
} else {
// Carrier variable (local, modified in loop)
@ -85,8 +89,12 @@ impl LoopFormBuilder {
init_value: value,
preheader_copy: ops.new_value(), // Allocate NOW
header_phi: ops.new_value(), // Allocate NOW
latch_value: ValueId::INVALID, // Will be set during seal
latch_value: ValueId(0), // Will be set during seal (placeholder)
};
if std::env::var("NYASH_LOOPFORM_DEBUG").is_ok() {
eprintln!("[loopform/prepare] carrier: {} -> init={:?}, copy={:?}, phi={:?}",
name, value, carrier.preheader_copy, carrier.header_phi);
}
self.carriers.push(carrier);
}
}