# CSE Pass Callee フィールド対応修正 - 完了報告 ## 日付 2025-12-05 ## 概要 CSE (Common Subexpression Elimination) パスの `instruction_key()` 関数で `Call` 命令の `callee` フィールドを無視していたバグを修正しました。 ## 問題 ### 根本原因 `src/mir/passes/cse.rs` の `instruction_key()` 関数が `Call` 命令のキー生成時に `callee` フィールドを無視していました: ```rust // 修正前(バグあり) MirInstruction::Call { func, args, .. } => { format!("call_{}_{}", func.as_u32(), args_str) // ← callee フィールドを無視! } ``` ### 影響範囲 これにより、以下のような問題が発生する可能性がありました: 1. **異なるメソッドの誤統合**: ```rust %r1 = call Method { receiver: %obj, method: "upper", ... } () %r2 = call Method { receiver: %obj, method: "lower", ... } () // 両方とも "call__" という同じキー → 誤って統合される可能性 ``` 2. **Global 関数の情報損失**: ```rust %r1 = call Global("print") (%msg) // callee 情報が失われ、func の ValueId だけでキー生成 ``` ## 修正内容 ### コード変更 `src/mir/passes/cse.rs` の `instruction_key()` 関数を修正(行 81-126): ```rust MirInstruction::Call { callee, func, args, .. } => { let args_str = args.iter() .map(|v| v.as_u32().to_string()) .collect::>() .join(","); // callee 情報を含めて正確なキー生成 if let Some(c) = callee { use crate::mir::Callee; match c { Callee::Global(name) => { format!("call_global_{}_{}", name, args_str) } Callee::Method { box_name, method, receiver, .. } => { let recv_str = receiver .map(|r| r.as_u32().to_string()) .unwrap_or_else(|| "static".to_string()); format!("call_method_{}.{}_{}_{}", box_name, method, recv_str, args_str) } Callee::Value(v) => { format!("call_value_{}_{}", v.as_u32(), args_str) } Callee::Extern(name) => { format!("call_extern_{}_{}", name, args_str) } Callee::Constructor { box_type } => { format!("call_ctor_{}_{}", box_type, args_str) } Callee::Closure { .. } => { // Closures are unique by definition format!("call_closure_{}_{}", func.as_u32(), args_str) } } } else { // Legacy path: backward compatibility format!("call_legacy_{}_{}", func.as_u32(), args_str) } } ``` ### キー生成方式 | Callee 種類 | キー形式 | 例 | |------------|---------|-----| | Global | `call_global_{name}_{args}` | `call_global_print_200` | | Method | `call_method_{box}.{method}_{receiver}_{args}` | `call_method_StringBox.upper_100_` | | Value | `call_value_{vid}_{args}` | `call_value_42_200` | | Extern | `call_extern_{name}_{args}` | `call_extern_libc.malloc_1024` | | Constructor | `call_ctor_{box_type}_{args}` | `call_ctor_StringBox_5` | | Closure | `call_closure_{func}_{args}` | `call_closure_99_` | | None (legacy) | `call_legacy_{func}_{args}` | `call_legacy_42_200` | ## テスト結果 ### 単体テスト(standalone) ``` ✅ Test 1: 同じ receiver、異なる method → 異なるキー call_method_StringBox.upper_100_ ≠ call_method_StringBox.lower_100_ ✅ Test 2: 異なる receiver、同じ method → 異なるキー call_method_StringBox.upper_100_ ≠ call_method_StringBox.upper_101_ ✅ Test 3: 完全に同じ呼び出し → 同じキー(CSE が効く) call_method_StringBox.upper_100_ == call_method_StringBox.upper_100_ ✅ Test 4: Global 関数呼び出し → 正しいキー call_global_print_200 ✅ Test 5: Legacy 呼び出し(callee なし)→ 互換性維持 call_legacy_42_200 ``` ### 統合テスト ```bash ✅ apps/tests/loop_if_phi.hako - sum=9(正常) ✅ apps/tests/peek_expr_block.hako - found one(正常) ✅ apps/tests/loop_min_while.hako - 0 1 2(正常) ✅ apps/tests/string_ops_basic.hako - len=5, sub=bcd(正常) ``` ### ビルド結果 ```bash ✅ cargo build --release Compiling nyash-rust v0.1.0 Finished `release` profile [optimized] target(s) in 0.10s ``` ## 達成効果 ### ✅ 正確性向上 - 異なるメソッド呼び出しを正しく区別 - receiver と method の両方を考慮したキー生成 - Global/Extern/Constructor 呼び出しを明確に分離 ### ✅ バグ予防 - 同じ receiver でも異なるメソッドは別のキーに - 異なる receiver でも同じメソッドは別のキーに - callee 情報の完全活用 ### ✅ 後方互換性 - `callee: None` の legacy path で既存コード継続動作 - 段階的移行をサポート ### ✅ パフォーマンス - キー生成コストはわずか(許容範囲) - CSE の効果は維持(正確性向上) ## 技術的洞察 ### Callee 型の重要性 ChatGPT5 Pro が設計した `Callee` enum は、MIR Call 命令の型安全性を大幅に向上させました: 1. **コンパイル時解決**: 関数呼び出しの種類を型で表現 2. **シャドウイング回避**: 実行時文字列解決から脱却 3. **最適化基盤**: CSE などのパスが正確な情報を利用可能 ### CSE での活用 Callee 情報により、CSE パスは以下を正確に判断できます: - 同じメソッド呼び出しの検出(receiver + method) - 異なる呼び出しの区別(Global vs Method vs Extern) - Constructor と Closure の特別扱い ## 関連ドキュメント - [MIR Callee 革新](../architecture/mir-callee-revolution.md) - [Callee 実装ロードマップ](../../private/roadmap2/phases/phase-15/mir-callee-implementation-roadmap.md) - [CSE Pass 修正提案](cse-pass-callee-fix.md) ## 今後の展開 ### 短期(Phase 33) - ✅ CSE Pass の callee 対応完了 - 🔄 他の最適化パスでの callee 活用検討 ### 中期(Phase 34) - 型推論での callee 情報活用 - インライン化での callee 情報利用 ### 長期(Phase 40+) - Callee ベースの高度な最適化 - JIT での callee 情報活用 ## 結論 CSE Pass の callee 対応修正は完全に成功しました。修正は最小限(約50行)で、テストは全て通過し、期待される効果を達成しています。 この修正により、CSE パスは MIR Call 命令の callee 情報を正確に利用し、異なる呼び出しを正しく区別できるようになりました。これは MIR Callee 型革新(Phase 15.5)の重要な実装成果の一つです。 --- **実装者**: Claude Code **レビュー**: 完了 **マージ準備**: Ready ✅