From 99e59e24e2dc9c83ad886e9ee215003e5ff41bfa Mon Sep 17 00:00:00 2001 From: Moe Charm Date: Wed, 27 Aug 2025 17:58:50 +0900 Subject: [PATCH] LowerCore: stabilize minimal PHI by tracking Phi dst and pushing block param when that ValueId is requested; verified jit_phi_demo returns merged value under cranelift. --- docs/development/current/CURRENT_TASK.md | 3 ++- examples/jit_phi_demo.nyash | 18 ++++++++++++++++++ src/jit/lower/core.rs | 11 ++++++++++- 3 files changed, 30 insertions(+), 2 deletions(-) create mode 100644 examples/jit_phi_demo.nyash diff --git a/docs/development/current/CURRENT_TASK.md b/docs/development/current/CURRENT_TASK.md index 1dc8364d..86a6cfb3 100644 --- a/docs/development/current/CURRENT_TASK.md +++ b/docs/development/current/CURRENT_TASK.md @@ -30,7 +30,8 @@ 3) 10_7: 分岐配線(Cranelift)— 進捗中 - LowerCore: BB整列・マッピング→builderの`prepare_blocks/switch/seal/br_if/jump`呼出 ✅ - CraneliftBuilder: ブロック配列管理、`brif/jump`実装、条件b1/`i64!=0`両対応 ✅ - - 残: 最小PHI(単純ダイアモンド)導入(`NYASH_JIT_PHI_MIN=1`ガード)/ 副作用命令の扱い方針(当面VMへ) + - 最小PHI(単純ダイアモンド)導入(`NYASH_JIT_PHI_MIN=1`ガード)✅ 初期対応 + - 残: 副作用命令の扱い方針(当面VMへ)、CFG可視化の拡張(`NYASH_JIT_DUMP=1`) 備考(制限と次の着手点) - 返り値はi64(VMValue::Integer)に限定。f64はconst最小emit、boolはi64 0/1へ正規化(分岐条件入力に対応) diff --git a/examples/jit_phi_demo.nyash b/examples/jit_phi_demo.nyash new file mode 100644 index 00000000..684982b4 --- /dev/null +++ b/examples/jit_phi_demo.nyash @@ -0,0 +1,18 @@ +// JIT minimal PHI demo (single diamond) +// Enable: NYASH_JIT_EXEC=1 NYASH_JIT_THRESHOLD=1 NYASH_JIT_PHI_MIN=1 + +static box Main { + main() { + local a, b, x + a = 3 + b = 5 + if (a < b) { + x = 10 + } else { + x = 20 + } + // Merge should pick 10 + return x + } +} + diff --git a/src/jit/lower/core.rs b/src/jit/lower/core.rs index 26c8d8bc..da9b83b7 100644 --- a/src/jit/lower/core.rs +++ b/src/jit/lower/core.rs @@ -10,10 +10,12 @@ pub struct LowerCore { known_i64: std::collections::HashMap, /// Parameter index mapping for ValueId param_index: std::collections::HashMap, + /// Track values produced by Phi (for minimal PHI path) + phi_values: std::collections::HashSet, } impl LowerCore { - pub fn new() -> Self { Self { unsupported: 0, covered: 0, known_i64: std::collections::HashMap::new(), param_index: std::collections::HashMap::new() } } + pub fn new() -> Self { Self { unsupported: 0, covered: 0, known_i64: std::collections::HashMap::new(), param_index: std::collections::HashMap::new(), phi_values: std::collections::HashSet::new() } } /// Walk the MIR function and count supported/unsupported instructions. /// In the future, this will build CLIF via Cranelift builders. @@ -48,11 +50,13 @@ impl LowerCore { builder.prepare_signature_i64(func.params.len(), true); builder.begin_function(&func.signature.name); // Iterate blocks in the sorted order to keep indices stable + self.phi_values.clear(); for (idx, bb_id) in bb_ids.iter().enumerate() { let bb = func.blocks.get(bb_id).unwrap(); builder.switch_to_block(idx); for instr in bb.instructions.iter() { self.cover_if_supported(instr); + if let MirInstruction::Phi { dst, .. } = instr { self.phi_values.insert(*dst); } self.try_emit(builder, instr); } if let Some(term) = &bb.terminator { @@ -107,6 +111,11 @@ impl LowerCore { /// Push a value onto the builder stack if it is a known i64 const or a parameter. fn push_value_if_known_or_param(&self, b: &mut dyn IRBuilder, id: &ValueId) { + if self.phi_values.contains(id) { + // Minimal PHI: read current block param + b.push_block_param_i64(); + return; + } if let Some(pidx) = self.param_index.get(id).copied() { b.emit_param_i64(pidx); return;