Phase 116 完了ドキュメント化 ## 更新内容 ### Phase 116 README - 背景: LLVM fragile pattern(keep+call merge) - 実装内容: fixture, VM smoke, LLVM EXE smoke - 検証コマンド - 技術的詳細: JoinIR Pattern 1, PHI接続 - Lessons Learned: Box-First原則, Fail-Fast原則 ### 10-Now.md - Phase 116 完了エントリ追加 - 入口: `docs/development/current/main/phases/phase-116/README.md` ### 01-JoinIR-Selfhost-INDEX.md - Phase 116 を JoinIR Phase リストに追加 - 番号の重複を修正(18-27に整理) ## 成果物 ✅ 片側元値保持、片側call結果のmergeパターンをVM/LLVM両方で固定 ✅ output_validator.sh, llvm_exe_runner.sh 活用で統一的なテスト基盤 ✅ 回帰防止: Phase 115 維持確認 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Phase 116: if-only keep+call merge parity
Status: ✅ DONE Date: 2025-12-18
背景
LLVMバックエンドで壊れやすいパターンの固定: 片側が元値保持、片側がcall結果のmerge。
問題のパターン
fn f(x) { return x + 1 }
fn g(flag) {
local v = 10
if flag == 1 { v = f(1) }
// else側は暗黙的にv=10を保持
print(v)
}
g(0) // → 10 (元値保持)
g(1) // → 2 (f(1) = 1+1 = 2)
- then側: call結果でvを更新 (
v = f(1)) - else側: 元の値を保持 (
v = 10) - merge地点: 2つの異なるソース(元値 vs call結果)からのPHI
実装内容
1. テストフィクスチャ
ファイル: apps/tests/phase116_if_only_keep_plus_call_min.hako
最小限のケース:
g(0)→10(元値保持)g(1)→2(call結果)
2. VM smoke test
ファイル: tools/smokes/v2/profiles/integration/apps/phase116_if_only_keep_plus_call_vm.sh
output_validator.shを使用して数値2行10\n2を検証- 実行条件:
NYASH_DISABLE_PLUGINS=1 HAKO_JOINIR_STRICT=1
3. LLVM EXE smoke test
ファイル: tools/smokes/v2/profiles/integration/apps/phase116_if_only_keep_plus_call_llvm_exe.sh
llvm_exe_runner.shを利用(plugin dlopen/cache/build-all SSOT)llvm_exe_build_and_run_numeric_smokeで出力検証(10\n2)
検証コマンド
# VM smoke test
bash tools/smokes/v2/profiles/integration/apps/phase116_if_only_keep_plus_call_vm.sh
# LLVM EXE smoke test
bash tools/smokes/v2/profiles/integration/apps/phase116_if_only_keep_plus_call_llvm_exe.sh
# 回帰テスト (Phase 115)
bash tools/smokes/v2/profiles/integration/apps/phase115_if_only_call_merge_llvm_exe.sh
技術的詳細
JoinIR Pattern
このケースは Pattern 1 (Simple If) として処理される:
entry_block:
v = 10
if flag == 1 goto then_block else exit_block
then_block:
v = f(1)
goto exit_block
exit_block:
v_merged = PHI [v=10 from entry, v=f(1) from then]
print(v_merged)
PHI接続の重要性
- entry → exit: 元値 (
10) を直接伝播 - then → exit: call結果 (
f(1)) を伝播 - PHI: 2つの異なる型のソース(変数 vs call結果)を正しくmerge
LLVM IRでは、これらが適切な型で統一される必要がある。
期待される効果
- LLVM安定性向上: keep+call mergeパターンの回帰を防止
- PHI生成品質: 異なるソースタイプのmerge処理の検証
- パリティ保証: VM/LLVM両方で同じ動作を保証
関連Phase
- Phase 115: if-only call result merge (両側がcall)
- Phase 114: if-only PHI minimal (基本的なPHI)
- Phase 33: Box Theory Modularization (JoinIR architecture)
Lessons Learned
Box-First原則の適用
このPhaseでは、既存の箱化されたコンポーネントを活用:
- ✅
output_validator.shによる出力検証の統一 - ✅
llvm_exe_runner.shによるLLVM実行の標準化 - ✅ テストインフラの再利用(no reinvention)
Fail-Fast原則
- VM/LLVM両方でエラーを即座に検出
HAKO_JOINIR_STRICT=1で厳密な検証を有効化- フォールバック処理なし(エラーは明示的に失敗)
Future Work
- Phase 117+: より複雑なmergeパターン(両側keep、ネストしたcall等)
- 最適化: 元値保持の場合のPHI削減の可能性検討