feat(joinir): Phase 256 P1.5-P1.7 contracts and naming SSOT
This commit is contained in:
@ -48,7 +48,14 @@
|
||||
## 2025-12-19:Phase 256(StringUtils.split/2 可変 step ループ)🔜
|
||||
|
||||
- Phase 256 README: `docs/development/current/main/phases/phase-256/README.md`
|
||||
- Current first FAIL: `StringUtils.split/2`(Missing caps: `ConstStep` → freeze)
|
||||
- Current first FAIL: `StringUtils.split/2`(`jump_args length mismatch` → `Carrier 'i' has no latch incoming set`)
|
||||
- 状況:
|
||||
- `MirInstruction::Select` の導入は完了、Pattern6(index_of)は PASS 維持。
|
||||
- `ValueId(57)` undefined は根治(原因は `const_1` 未初期化)。
|
||||
- SSA undef(`%49/%67`)は P1.7 で根治(continuation 関数名の SSOT 不一致)。
|
||||
- 残りは Pattern7 の carrier PHI 配線(ExitLine / jump_args 契約)を直す段階。
|
||||
- P1.5-DBG: boundary entry params の契約チェックを追加(VM実行前 fail-fast)。
|
||||
- P1.6: 契約チェックの薄い集約 `run_all_pipeline_checks()` を導入(pipeline の責務を縮退)。
|
||||
|
||||
## 2025-12-19:Phase 254(index_of loop pattern)✅ 完了(Blocked by Phase 255)
|
||||
|
||||
|
||||
@ -0,0 +1,150 @@
|
||||
# Legacy 候補一覧
|
||||
|
||||
Phase 256+ で特定された、将来削除可能な legacy コード候補を記録する。
|
||||
|
||||
---
|
||||
|
||||
## Phase 256 P1.7 で特定された legacy
|
||||
|
||||
### `join_func_name()` (src/mir/join_ir_vm_bridge/mod.rs)
|
||||
|
||||
**状態**: 未使用になった可能性あり(要精査)
|
||||
|
||||
**理由**:
|
||||
- Phase 256 P1.7 で `continuation_func_ids` が `String` ベースに変更
|
||||
- `join_func_name()` による `JoinFuncId → String` 変換が不要になった可能性
|
||||
- JoinFunction の `name` フィールドが直接利用可能
|
||||
|
||||
**残利用箇所**: 11箇所 + 定義1箇所 = 計12箇所
|
||||
|
||||
#### 実利用箇所(10箇所)
|
||||
|
||||
1. **src/mir/join_ir_vm_bridge/runner.rs:55**
|
||||
```rust
|
||||
let entry_name = join_func_name(entry_func);
|
||||
```
|
||||
- 用途: VM実行時のエントリーポイント関数名取得
|
||||
- 状態: 実利用(Phase 27-shortterm S-4.3)
|
||||
|
||||
2. **src/mir/join_ir_vm_bridge/joinir_block_converter.rs:162**
|
||||
```rust
|
||||
let func_name = join_func_name(*func);
|
||||
```
|
||||
- 用途: JoinIR ブロック変換時の関数名取得
|
||||
- 状態: 実利用(Phase 190)
|
||||
|
||||
3. **src/mir/join_ir_vm_bridge/normalized_bridge/direct.rs:94**
|
||||
```rust
|
||||
name: join_func_name(JoinFuncId(func.id.0)),
|
||||
```
|
||||
- 用途: Normalized → MIR 変換時の関数署名生成
|
||||
- 状態: 実利用(Phase 141+)
|
||||
- 条件: `#[cfg(feature = "normalized_dev")]`
|
||||
|
||||
4. **src/mir/join_ir_vm_bridge/normalized_bridge/direct.rs:182**
|
||||
```rust
|
||||
let func_name = join_func_name(JoinFuncId(target.0));
|
||||
```
|
||||
- 用途: Normalized 関数ターゲット名取得
|
||||
- 状態: 実利用(Phase 141+)
|
||||
- 条件: `#[cfg(feature = "normalized_dev")]`
|
||||
|
||||
5. **src/mir/join_ir_vm_bridge/joinir_function_converter.rs:39**
|
||||
```rust
|
||||
.insert(join_func_name(*func_id), mir_func);
|
||||
```
|
||||
- 用途: MIR モジュールへの関数登録
|
||||
- 状態: 実利用(Phase 190)
|
||||
|
||||
6. **src/mir/builder/control_flow/joinir/merge/tail_call_lowering_policy.rs:100**
|
||||
```rust
|
||||
let k_exit_name = join_func_name(JoinFuncId::new(2));
|
||||
```
|
||||
- 用途: テストコード内での k_exit 関数名生成
|
||||
- 状態: テスト専用(`#[cfg(test)]`)
|
||||
|
||||
7. **src/mir/control_tree/normalized_shadow/loop_true_break_once.rs:63**
|
||||
```rust
|
||||
use crate::mir::join_ir_vm_bridge::join_func_name;
|
||||
```
|
||||
- 用途: テストコード内での関数名取得
|
||||
- 状態: テスト専用(`#[cfg(test)]`)
|
||||
|
||||
#### コメント参照箇所(3箇所)
|
||||
|
||||
8. **src/mir/builder/control_flow/joinir/merge/instruction_rewriter.rs**
|
||||
```rust
|
||||
// No need to convert with join_func_name() - use directly
|
||||
```
|
||||
- 用途: コメント(変換不要の説明)
|
||||
- 状態: ドキュメント
|
||||
|
||||
9. **src/mir/join_ir_vm_bridge/meta.rs**
|
||||
```rust
|
||||
// Phase 256 P1.7: Use actual function name instead of join_func_name()
|
||||
// join_func_name() produces "join_func_{id}" but JoinFunction.name contains
|
||||
```
|
||||
- 用途: コメント(Phase 256 P1.7 の設計変更説明)
|
||||
- 状態: ドキュメント
|
||||
|
||||
10. **src/mir/builder/control_flow/joinir/patterns/pattern7_split_scan.rs**
|
||||
```rust
|
||||
// The bridge uses JoinFunction.name as the MirModule function key, not join_func_name(id)
|
||||
```
|
||||
- 用途: コメント(Pattern 7 の設計説明)
|
||||
- 状態: ドキュメント
|
||||
|
||||
#### 定義箇所(1箇所)
|
||||
|
||||
11. **src/mir/join_ir_vm_bridge/mod.rs**
|
||||
```rust
|
||||
pub(crate) fn join_func_name(id: JoinFuncId) -> String {
|
||||
```
|
||||
- 用途: 関数定義
|
||||
- 状態: pub(crate) で公開
|
||||
|
||||
---
|
||||
|
||||
## 推奨アクション
|
||||
|
||||
### 短期(Phase 256 P1.7 スコープ外)
|
||||
- ✅ このドキュメントに記録完了
|
||||
- 実装変更は行わない(記録のみ)
|
||||
|
||||
### 中期(Phase 257+ で検討)
|
||||
1. **段階的移行案**:
|
||||
- Step 1: 新規コードでは `JoinFunction.name` を直接使用
|
||||
- Step 2: 既存の10実利用箇所を段階的に置換
|
||||
- Step 3: テストコード(2箇所)を置換
|
||||
- Step 4: コメント更新(3箇所)
|
||||
- Step 5: `join_func_name()` 削除
|
||||
|
||||
2. **影響範囲**:
|
||||
- Bridge 層: 7箇所(実利用6 + テスト1)
|
||||
- Normalized 層: 2箇所(feature gated)
|
||||
- Control flow builder: 1箇所(テストのみ)
|
||||
- Control tree: 1箇所(テストのみ)
|
||||
|
||||
3. **リスク評価**:
|
||||
- 低: テストコードのみ(2箇所)
|
||||
- 中: Bridge 層の実利用(7箇所)
|
||||
- 高: Normalized 層(feature gated, 現在開発中)
|
||||
|
||||
4. **優先度**: 低(現在問題なし、技術的負債削減として)
|
||||
|
||||
---
|
||||
|
||||
## メンテナンス
|
||||
|
||||
- **作成日**: 2025-12-20
|
||||
- **最終更新**: 2025-12-20
|
||||
- **関連 Phase**: 256 P1.7
|
||||
- **関連コミット**: (Phase 256 P1.7 完了後に記入)
|
||||
|
||||
---
|
||||
|
||||
## 参考リンク
|
||||
|
||||
- Phase 256 P1.7 設計: [phase-256/README.md](../phases/phase-256/README.md)
|
||||
- JoinIR 設計マップ: [design/joinir-design-map.md](../design/joinir-design-map.md)
|
||||
- JoinIR アーキテクチャ: [joinir-architecture-overview.md](../joinir-architecture-overview.md)
|
||||
@ -6,13 +6,28 @@ Related:
|
||||
- Phase 255 完了(loop_invariants 導入、Pattern 6 完成)
|
||||
- Phase 254 完了(Pattern 6 index_of 実装)
|
||||
|
||||
## 失敗詳細
|
||||
## Current Status (SSOT)
|
||||
|
||||
- Current first FAIL: `StringUtils.split/2`(`jump_args length mismatch` → `Carrier 'i' has no latch incoming set`)
|
||||
- Pattern6 は PASS 維持
|
||||
- 直近の完了:
|
||||
- P1.7: SSA undef(`%49/%67`)根治(continuation 関数名の SSOT 不一致)
|
||||
- P1.6: pipeline contract checks を `run_all_pipeline_checks()` に集約
|
||||
- 次の作業: P1.8(Pattern7 の carrier PHI wiring / ExitLine + jump_args 契約の修正)
|
||||
|
||||
---
|
||||
|
||||
## Background (P0 Archive)
|
||||
|
||||
このセクションは初期の失敗詳細とP0設計の記録。現状の作業は上記の Current Status を参照。
|
||||
|
||||
### 失敗詳細
|
||||
|
||||
**テスト**: json_lint_vm (quick profile)
|
||||
**エラー**: `[joinir/freeze] Loop lowering failed: JoinIR does not support this pattern`
|
||||
**関数**: `StringUtils.split/2`
|
||||
|
||||
### エラーメッセージ全体
|
||||
#### エラーメッセージ全体
|
||||
|
||||
```
|
||||
[trace:dev] loop_canonicalizer: Decision: FAIL_FAST
|
||||
@ -25,15 +40,15 @@ Function: StringUtils.split/2
|
||||
Hint: This loop pattern is not supported. All loops must use JoinIR lowering.
|
||||
```
|
||||
|
||||
## 期待される動作
|
||||
### 期待される動作
|
||||
|
||||
`StringUtils.split(s, separator)` が正常にコンパイルされ、文字列分割が動作すること。
|
||||
|
||||
## 実際の動作
|
||||
### 実際の動作
|
||||
|
||||
Loop canonicalizer が `ConstStep` を要求しているが、このループはステップが複雑で定数ではない。
|
||||
|
||||
## 最小再現コード
|
||||
### 最小再現コード
|
||||
|
||||
```nyash
|
||||
split(s, separator) {
|
||||
@ -68,9 +83,9 @@ split(s, separator) {
|
||||
}
|
||||
```
|
||||
|
||||
## 分析
|
||||
### 分析
|
||||
|
||||
### ループ構造
|
||||
#### ループ構造
|
||||
|
||||
1. **条件**: `i <= s.length() - separator.length()`
|
||||
2. **ボディ**:
|
||||
@ -85,7 +100,7 @@ split(s, separator) {
|
||||
- **複数キャリア**: `i`, `start`, `result` を更新
|
||||
- **MethodCall**: `substring()`, `push()`, `length()` を使用
|
||||
|
||||
### Canonicalizer の問題
|
||||
#### Canonicalizer の問題
|
||||
|
||||
```
|
||||
Missing caps: [ConstStep]
|
||||
@ -95,9 +110,9 @@ Missing caps: [ConstStep]
|
||||
- このループは条件分岐で異なるステップ幅を使う
|
||||
- Pattern 2 (balanced_depth_scan) に近いが、可変ステップがネック
|
||||
|
||||
## 実装計画
|
||||
### 実装計画
|
||||
|
||||
### Option A: Pattern 7 - Split/Tokenization Pattern
|
||||
#### Option A: Pattern 7 - Split/Tokenization Pattern
|
||||
|
||||
**新しいパターン追加**:
|
||||
- 可変ステップサポート
|
||||
@ -111,20 +126,20 @@ Missing caps: [ConstStep]
|
||||
- Else: `i = i + 1` (定数ステップ)
|
||||
3. Accumulator への追加操作 (`push` など)
|
||||
|
||||
### Option B: Pattern 2 拡張
|
||||
#### Option B: Pattern 2 拡張
|
||||
|
||||
**既存 Pattern 2 を拡張**:
|
||||
- ConstStep 要件を緩和
|
||||
- If-else で異なるステップ幅を許可
|
||||
- balanced_depth_scan_policy を拡張
|
||||
|
||||
### Option C: Normalization 経路
|
||||
#### Option C: Normalization 経路
|
||||
|
||||
**ループ正規化で対応**:
|
||||
- 可変ステップを定数ステップに変換
|
||||
- Carrier 追加で状態管理
|
||||
|
||||
## 次のステップ
|
||||
### 次のステップ(P0時点の初期計画)
|
||||
|
||||
1. **StepTree 詳細解析**: split ループの完全な AST 構造確認
|
||||
2. **類似パターン調査**: 他の可変ステップループ(indexOf, contains など)
|
||||
@ -133,7 +148,7 @@ Missing caps: [ConstStep]
|
||||
|
||||
---
|
||||
|
||||
## Phase 256 指示書(P0)
|
||||
## Phase 256 指示書(P0 / 完了済み)
|
||||
|
||||
### 目標
|
||||
|
||||
@ -184,3 +199,213 @@ Option A(Pattern 7 新設)を推奨。
|
||||
- Phase 255 で loop_invariants が導入されたが、このケースは invariants 以前の問題(可変ステップ)
|
||||
- Phase 254-256 の流れで Pattern 6 → Pattern 7 の自然な進化が期待される
|
||||
- split/tokenization は一般的なパターンなので、汎用的な解決策が望ましい
|
||||
|
||||
---
|
||||
|
||||
## 進捗(P0/P1)
|
||||
|
||||
### P0: Pattern 7 基本実装(完了)
|
||||
|
||||
- Fixture & smokes(integration):
|
||||
- `apps/tests/phase256_p0_split_min.hako`
|
||||
- `tools/smokes/v2/profiles/integration/apps/phase256_p0_split_vm.sh`
|
||||
- `tools/smokes/v2/profiles/integration/apps/phase256_p0_split_llvm_exe.sh`
|
||||
- Pattern 7:
|
||||
- Detector / Extractor / JoinIR lowerer / MirBuilder 統合まで実装
|
||||
- JoinIR lowerer は可変 step を `JoinInst::Select` で表現
|
||||
|
||||
### P1: Carrier/param 配線の整流(完了)
|
||||
|
||||
- “Carriers-first” の順序を SSOT として固定し、latch incoming 不足を解消
|
||||
- exit bindings を明示的に構築(`i`, `start`)
|
||||
|
||||
### P1.5: JoinIR→MIR 変換の根治(進行中)
|
||||
|
||||
背景:
|
||||
- Pattern 7 は `JoinInst::Select` を使用するが、JoinIR→MIR 変換経路で Select が未対応だったため、
|
||||
“dst が定義されない ValueId” が発生し得る。
|
||||
|
||||
対応(完了):
|
||||
- boundary の伝播を bridge 経路全体へ追加
|
||||
- `MirInstruction::Select` の追加、および JoinIR→MIR 変換 / remap / value collection を実装
|
||||
|
||||
現状(ブロッカー):
|
||||
- integration VM が still FAIL:
|
||||
- `use of undefined value ValueId(57)`(`StringUtils.split/2`)
|
||||
|
||||
#### 追加の事実(2025-12-20)
|
||||
|
||||
- Pattern 6(index_of)回帰: PASS(Select 導入後もインフラは健全)
|
||||
- `ValueId(57)` の正体:
|
||||
- JoinIR `ValueId(1004)` の remap 先(JoinIR→Host の remap は成功している)
|
||||
- `sep_len = sep.length()` のローカル値(loop_step 内で `BoxCall("length")` で定義される想定)
|
||||
- つまり「remap の欠落」ではなく、「定義命令(dst を持つ BoxCall)が MIR に落ちていない/順序が壊れている」問題が濃厚
|
||||
|
||||
#### 次(P1.5 Task 3): sep_len 定義トレース(SSOT)
|
||||
|
||||
目的: `sep_len` の「定義(dst)」が MIR に存在し、かつ use より前に配置されることを確認し、欠落しているなら根治する。
|
||||
|
||||
1) MIR ダンプで「%57 の定義があるか」を確認
|
||||
- `./target/release/hakorune --backend vm --dump-mir --mir-verbose apps/tests/phase256_p0_split_min.hako > /tmp/split.mir`
|
||||
- `rg -n \"\\bValueId\\(57\\)\\b|%57\" /tmp/split.mir`
|
||||
- 期待: `BoxCall` かそれに相当する命令で `dst=%57` が use より前に出る
|
||||
|
||||
2) 定義が無い場合: JoinIR→MIR converter を疑う
|
||||
- `JoinInst::Compute(MirLikeInst::BoxCall { dst: Some(sep_len), method: \"length\", .. })`
|
||||
が `MirInstruction::BoxCall { dst: Some(remapped), .. }` として出力されているかを点検する
|
||||
- もし `dst: None` になっている/命令自体が落ちているなら、converter か value-collector の取りこぼしを修正する
|
||||
|
||||
3) 定義があるが use より後の場合: ブロック内の命令順の生成/マージ規約を疑う
|
||||
- joinir→mir の「生成順」か merge の「挿入位置」がおかしい
|
||||
- 期待: “def-before-use” が各 BasicBlock 内で成立する
|
||||
|
||||
4) 受け入れ基準(P1.5)
|
||||
- `tools/smokes/v2/profiles/integration/apps/phase256_p0_split_vm.sh` が PASS
|
||||
- `tools/smokes/v2/profiles/integration/apps/phase256_p0_split_llvm_exe.sh` が PASS
|
||||
- 既存: `tools/smokes/v2/profiles/integration/apps/phase254_p0_index_of_vm.sh` が PASS 維持
|
||||
|
||||
#### 診断アップデート(2025-12-20)
|
||||
|
||||
`ValueId(57)`(= `sep_len`)について、Step 2 の結果で「Case A」が確定した:
|
||||
|
||||
- JoinIR には定義が存在する:
|
||||
- `JoinInst::Compute(MirLikeInst::BoxCall { dst: Some(sep_len), method: "length", args: [sep] })`
|
||||
- しかし最終 MIR(`--dump-mir`)には `%57 = ...` 相当の def が存在しない(use のみ)
|
||||
- remap 自体は成功している:
|
||||
- JoinIR `ValueId(1004)` → Host `ValueId(57)`
|
||||
|
||||
結論:
|
||||
- 「remap が壊れている」ではなく、
|
||||
**`JoinInst::Compute(MirLikeInst::BoxCall)` が JoinIR→MIR 変換/マージ経路のどこかで落ちている**。
|
||||
|
||||
次の実装タスク(P1.5 Task 3.1):
|
||||
- JoinIR→MIR の中間生成物(bridge 側の MirModule)をダンプして、
|
||||
- `dst: Some(1004)` の `MirInstruction::BoxCall` が生成されているか(生成されていないなら converter バグ)
|
||||
- 生成されているのに最終 MIR から消えるなら merge/DCE バグ
|
||||
を二分探索で確定する。
|
||||
|
||||
#### Task 3.1 結果(2025-12-20)
|
||||
|
||||
`ValueId(57)` undefined は根治できた(def-before-use 不変条件が回復)。
|
||||
|
||||
- 最終原因:
|
||||
- `split_scan_minimal.rs` 内で `const_1`(`JoinValueSpace` のローカル ValueId)が **初期化されないまま** `i + const_1` に使用されていた。
|
||||
- これが remap 後に `ValueId(57)` となり、最終 MIR で「use のみ / def が無い」になっていた。
|
||||
- 修正:
|
||||
- `const_1 = 1` を `JoinInst::Compute(MirLikeInst::Const { .. })` で use より前に挿入。
|
||||
- 付随:
|
||||
- bridge 生成物 MirModule を `/tmp/joinir_bridge_split.mir` へダンプできるようにした(`HAKO_JOINIR_DEBUG=1` ガード)。
|
||||
|
||||
⚠️ 注記:
|
||||
- これにより「ValueId(57) = sep_len」仮説は撤回する。
|
||||
- 以降は、各ローカル ValueId の意味は **bridge dump / join module dump を SSOT** として確定すること。
|
||||
|
||||
#### 次のブロッカー(P1.5 Task 3.2)
|
||||
|
||||
`ValueId(57)` は直ったが、Pattern7(split) はまだ PASS していない。新たに以下が露出:
|
||||
|
||||
- SSA:
|
||||
- `Undefined value %49 used in block bb10`
|
||||
- `Undefined value %67 used in block bb10`
|
||||
- 型:
|
||||
- `unsupported compare Le on BoxRef(ArrayBox) and Integer(...)`
|
||||
|
||||
次のタスク(P1.5 Task 3.2):
|
||||
- まず `--verify` と `--dump-mir` で **%49 / %67 が何の値で、どの命令で定義されるべきか**を確定し、
|
||||
- (A) joinir lowerer が def を吐いていないのか
|
||||
- (B) bridge が落としているのか
|
||||
- (C) merge/optimizer が落としているのか
|
||||
を二分探索する。
|
||||
|
||||
#### 追記(P1.7完了後)
|
||||
|
||||
- SSA undef(`%49/%67`)は P1.7 で根治済み
|
||||
- 現在の first FAIL は carrier PHI 配線へ移動:
|
||||
- `[joinir/exit-line] jump_args length mismatch: expected 3 or 4 but got 5`
|
||||
- `Phase 33-16: Carrier 'i' has no latch incoming set`
|
||||
|
||||
---
|
||||
|
||||
## 進捗(P1.5-DBG)
|
||||
|
||||
### P1.5-DBG: Boundary Entry Parameter Contract Check(完了)
|
||||
|
||||
目的:
|
||||
- `boundary.join_inputs` と JoinIR entry function の `params` の対応(個数/順序/ValueId)を **VM 実行前**に fail-fast で検出する。
|
||||
- これにより、Pattern6 で起きた `loop_invariants` 順序バグ(例: `[s, ch]` ↔ `[ch, s]`)のような問題を「実行時の undef」ではなく「構造エラー」として落とせる。
|
||||
|
||||
実装(SSOT):
|
||||
- `src/mir/builder/control_flow/joinir/merge/contract_checks.rs`
|
||||
- `verify_boundary_entry_params()`(個数/順序/ValueId の検証)
|
||||
- `get_entry_function()`(`join_module.entry` → `"main"` へのフォールバック)
|
||||
- unit tests を追加(正常/順序ミスマッチ/個数ミスマッチ)
|
||||
- `src/mir/builder/control_flow/joinir/patterns/conversion_pipeline.rs`
|
||||
- JoinIR→MIR 変換直前に検証を追加
|
||||
- `is_joinir_debug()` 時にログ出力
|
||||
|
||||
運用:
|
||||
- `HAKO_JOINIR_DEBUG=1` で `[joinir/boundary-contract] ...` を出す(既存トグルのみ、env 追加なし)。
|
||||
|
||||
### P1.6: Pipeline Contract Checks の薄い集約(完了)
|
||||
|
||||
目的:
|
||||
- `conversion_pipeline.rs` から契約チェック呼び出しと debug ログの詳細を排除し、
|
||||
契約チェックの SSOT を `contract_checks.rs` に集約する(dyn trait など過剰な箱化はしない)。
|
||||
|
||||
実装(SSOT):
|
||||
- `src/mir/builder/control_flow/joinir/merge/contract_checks.rs`
|
||||
- `run_all_pipeline_checks()`(薄い集約エントリ)
|
||||
- `debug_log_boundary_contract()` を同ファイルへ移設(`is_joinir_debug()` ガード)
|
||||
- `src/mir/builder/control_flow/joinir/patterns/conversion_pipeline.rs`
|
||||
- `run_all_pipeline_checks()` の 1 呼び出しに縮退
|
||||
|
||||
効果:
|
||||
- pipeline 側の責務を「パイプラインの制御」に戻し、契約チェックは `contract_checks.rs` に閉じ込めた。
|
||||
今後チェック項目を増やす場合も `run_all_pipeline_checks()` に追記するだけで済む。
|
||||
|
||||
---
|
||||
|
||||
## 進捗(P1.7)
|
||||
|
||||
### P1.7: SSA undef(`%49/%67`)根治(完了)
|
||||
|
||||
症状:
|
||||
- `Undefined value %49 used in block bb10`
|
||||
- `Undefined value %67 used in block bb10`
|
||||
|
||||
根本原因:
|
||||
- JoinIR→MIR bridge が `JoinFunction.name` をそのまま MirModule の関数名にしていた(例: `"k_exit"`, `"loop_step"`)
|
||||
- merge 側が `join_func_name(id)`(例: `"join_func_2"`)で関数を探索していた
|
||||
- その結果、continuation 関数が見つからず inline/merge がスキップされ、SSA undef が露出した
|
||||
|
||||
修正方針:
|
||||
- continuation 関数の識別を「関数ID→暗黙変換」に依存させず、MirModule 上の関数名(String)で SSOT 化する
|
||||
|
||||
結果:
|
||||
- `./target/release/hakorune --backend vm --verify apps/tests/phase256_p0_split_min.hako` で SSA undef は消滅
|
||||
|
||||
### リファクタリング方針(P1.6候補 / 先送り推奨)
|
||||
|
||||
現時点(split がまだ FAIL)では、箱化のための箱化で複雑さが増えやすいので、以下を推奨する:
|
||||
|
||||
- ✅ 先にやってよい(低リスク / 価値が高い)
|
||||
- `contract_checks.rs` 内で「チェックの実行順」を `run_all_*()` のような薄い関数にまとめる(dyn trait は不要)
|
||||
- debug ログは既存の仕組み(`is_joinir_debug()` / `DebugOutputBox`)に寄せる(新 logger box を増やさない)
|
||||
- テストの JoinModule 構築は、重複が 3 箇所以上になった時点で共通化
|
||||
|
||||
- ⛔ 先送り(split を PASS してから)
|
||||
- `ContractCheckerBox`(trait object)化:柔軟だが、ここでは過剰になりやすい
|
||||
- `JoinIRDebugLoggerBox` 新設:既存の DebugOutputBox と二重化しやすい
|
||||
- MIR 命令 dst 抽出の広域統一:既存の `MirInstruction` helper との重複が出やすいので要調査の上で
|
||||
|
||||
### 小さな整理(今後の予定 / P1.8以降)
|
||||
|
||||
- JoinIR の関数名は `src/mir/join_ir/lowering/canonical_names.rs` を SSOT とする
|
||||
- `"k_exit"` / `"loop_step"` / `"main"` の直書きは段階的に `canonical_names::*` へ置換
|
||||
- 正規化 shadow の `"join_func_2"` は `canonical_names::K_EXIT_LEGACY` として隔離し、統一は Phase 256 完了後に検討
|
||||
- legacy 掃除候補:
|
||||
- `join_func_name(id)` の利用箇所を棚卸しし、「structured JoinIR では使用禁止 / normalized shadow だけで使用」など境界を明文化
|
||||
|
||||
次(P1.5 Task 3):
|
||||
- `ValueId(57)` が「何の JoinIR 値の remap 結果か」を確定し、定義側(dst)が MIR に落ちているかを追う
|
||||
- 例: `sep_len = sep.length()` の BoxCall dst が収集/変換/順序のどこかで欠けていないか
|
||||
|
||||
Reference in New Issue
Block a user