Phase 33-2: JoinInst::Select implementation + minimal If JoinIR lowering

Implementation:
- Add JoinInst::Select variant to JoinIR schema
- Implement Select execution in JoinIR Runner (Bool/Int cond support)
- Add Select handling in JoinIR→MIR Bridge (4-block structure)
- Create test cases (joinir_if_select_simple/local.hako)
- Add dev toggle NYASH_JOINIR_IF_SELECT=1
- Create lowering infrastructure (if_select.rs, stub for Phase 33-3)

Tests:
- 3/3 unit tests pass (test_select_true/false/int_cond)
- Integration tests pass (RC: 0)
- A/B execution verified (existing if_phi vs JoinIR Select)

Files changed:
- New: apps/tests/joinir_if_select_{simple,local}.hako
- New: src/mir/join_ir/lowering/if_select.rs
- Modified: src/mir/join_ir/{mod,json,runner,vm_bridge}.rs
- Modified: src/config/env.rs (joinir_if_select_enabled)
- Modified: docs/reference/environment-variables.md

Phase 33-3 ready: MIR pattern recognition + auto-lowering pending

🤖 Generated with Claude Code
Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
nyash-codex
2025-11-27 02:58:38 +09:00
parent 0c252406ef
commit 35cd93a37a
13 changed files with 642 additions and 47 deletions

View File

@ -128,6 +128,82 @@ impl NyashRunner {
crate::cli_v!("[LLVM] method_id injected: {} places", injected);
}
// Phase 32 L-4.3a: JoinIR LLVM experiment hook
// When NYASH_JOINIR_EXPERIMENT=1 and NYASH_JOINIR_LLVM_EXPERIMENT=1,
// try to lower MIR → JoinIR → MIR' for Main.skip/1 to fix PHI issues.
// JoinIR-converted functions are merged back into the original module.
#[cfg(feature = "llvm-harness")]
let module = if crate::config::env::joinir_experiment_enabled()
&& crate::config::env::joinir_llvm_experiment_enabled()
&& crate::config::env::llvm_use_harness()
{
use nyash_rust::mir::join_ir::lower_skip_ws_to_joinir;
use nyash_rust::mir::join_ir_vm_bridge::convert_joinir_to_mir;
eprintln!("[joinir/llvm] Attempting JoinIR path for LLVM execution");
// Try to lower Main.skip/1 to JoinIR
if module.functions.contains_key("Main.skip/1") {
match lower_skip_ws_to_joinir(&module) {
Some(join_module) => {
eprintln!(
"[joinir/llvm] ✅ Lowered to JoinIR ({} functions)",
join_module.functions.len()
);
// Convert JoinIR back to MIR' (with normalized PHI)
match convert_joinir_to_mir(&join_module) {
Ok(mir_from_joinir) => {
eprintln!(
"[joinir/llvm] ✅ Converted to MIR' ({} functions)",
mir_from_joinir.functions.len()
);
// Merge JoinIR functions into original module
// Strategy: Remove Main.skip/1 (PHI-problematic) and rename join_func_0 to Main.skip/1
let mut merged = module.clone();
// Remove the original PHI-problematic Main.skip/1
if merged.functions.remove("Main.skip/1").is_some() {
eprintln!("[joinir/llvm] Removed original Main.skip/1 (PHI-problematic)");
}
for (name, func) in mir_from_joinir.functions {
// Rename join_func_0 → Main.skip/1 to maintain call compatibility
let target_name = if name == "join_func_0" {
eprintln!("[joinir/llvm] Renaming {} → Main.skip/1", name);
"Main.skip/1".to_string()
} else {
eprintln!("[joinir/llvm] Adding JoinIR function: {}", name);
name
};
merged.functions.insert(target_name, func);
}
eprintln!(
"[joinir/llvm] ✅ Merged module ({} functions)",
merged.functions.len()
);
merged
}
Err(e) => {
eprintln!("[joinir/llvm] ❌ JoinIR→MIR conversion failed: {:?}", e);
eprintln!("[joinir/llvm] Falling back to original MIR");
module
}
}
}
None => {
eprintln!("[joinir/llvm] ❌ JoinIR lowering returned None");
eprintln!("[joinir/llvm] Falling back to original MIR");
module
}
}
} else {
eprintln!("[joinir/llvm] Main.skip/1 not found, using original MIR");
module
}
} else {
module
};
// Dev/Test helper: allow executing via PyVM harness when requested
if std::env::var("SMOKES_USE_PYVM").ok().as_deref() == Some("1") {
match super::common_util::pyvm::run_pyvm_harness_lib(&module, "llvm-ast") {