Files
hakorune/docs/development/current/main/design/joinir-design-map.md
nyash-codex d3b3bf5372 feat(mir): Phase 131-11-E - TypeFacts/TypeDemands 分離(SSOT)
## 実装内容

### 1) Rust MIR Builder (ops.rs + lifecycle.rs)
- OperandTypeClass で型分類(String/Integer/Unknown)
- BinOp 型推論: Integer + Unknown → Integer
- lifecycle.rs に repropagate_binop_types() パス追加
  - PHI 型解決後に BinOp 型を再計算

### 2) JSON Emission (mir_json_emit.rs)
- 結果ベースの dst_type 発行に変更
- Integer → "i64", String → {kind: handle, box_type: StringBox}

### 3) Python LLVM Backend (binop.py)
- dst_type を確実な情報として使用
- dst_type != None なら優先して処理

## 結果
-  MIR: PHI/BinOp が Integer として正しく型付け
-  VM: `Result: 3` (正しい出力)
-  JSON: `dst_type: "i64"` を発行
-  LLVM: 別の codegen 問題の可能性あり

## SSOT 設計達成
- TypeFacts(事実): 定義命令から推論
- TypeDemands(要求): 使用箇所の coercion で吸収
- 後方伝播なし: Fail-Fast に統一

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Haiku 4.5 <noreply@anthropic.com>
2025-12-14 18:55:05 +09:00

10 KiB
Raw Blame History

JoinIR Design Map現役の地図

Status: Active
Scope: JoinIR の「Loop/If を JoinIR 化して MIR に統合する」導線検出→shape guard→lower→merge→契約検証
Related:

このドキュメントは Phase ログではなく、「JoinIR を触る人が迷子にならず、どこを直すべきかが一発で分かる」ための設計図(地図)です。
詳細な経緯・作業ログは docs/development/current/main/phases/docs/development/current/main/investigations/ に分離します。


1枚図: レイヤーAST → JoinIR → MIR → Backend

flowchart LR
  A[AST] -->|Frontend lowering| J1[JoinIR (Structured)]
  J1 -->|Normalize / Shape guard| J2[JoinIR (Normalized)]
  J2 -->|JoinIR → MIR bridge| M1[MIR Module]
  M1 -->|Merge into host function| M2[MIR (in builder)]
  M2 --> B[Backend\n(VM / LLVM / Cranelift)]

  subgraph Frontend
    A
    J1
  end

  subgraph JoinIR Core
    J2
  end

  subgraph MIR Builder
    M1
    M2
  end

読み方:

  • 「Loop/If の形が認識されない」: Pattern 検出Feature/Kindと shape guard を見る
  • 「JoinIR は生成できるが統合で壊れる」: MergeValueId/PHI/ExitLine/Boundaryと契約検証を見る
  • 「なぜこのエラータグが出たか」: ErrorTagsSSOTを起点に呼び出し元へ辿る

“箱”の責務マップ(担当境界)

領域 役割(何を決めるか) 主な入口/箱SSOT寄り 主な出力 Fail-Fast典型
Pattern検出 ループ形を分類し、どの lowerer に渡すか決める src/mir/builder/control_flow/joinir/patterns/router.rs, src/mir/builder/control_flow/joinir/patterns/ast_feature_extractor.rs, src/mir/loop_pattern_detection/mod.rs LoopPatternKind / Pattern 選択 「分類不能」→ 明示的に Errサイレントな非JoinIR退避は禁止
shape guard 「この shape なら lower/merge 契約が成立する」を保証する src/mir/join_ir/normalized/shape_guard.rs, src/mir/builder/control_flow/joinir/patterns/*_validator.rs shape OK / 詳細診断 shape 不一致を握りつぶさず Err
lowering JoinIRStructured/Normalizedを生成する src/mir/join_ir/lowering/mod.rs, src/mir/builder/control_flow/joinir/patterns/pattern*_*.rs JoinModule 未対応の構造は error_tags::freeze(...) 等で Err
merge JoinIR→MIR 変換後、ホスト関数に統合する src/mir/builder/control_flow/joinir/patterns/conversion_pipeline.rs, src/mir/builder/control_flow/joinir/merge/mod.rs ホスト MIR のブロック/ValueId 更新 ValueId 競合、ExitLine 未接続、PHI 破綻を Err
ExitMeta 「出口でどの carrier をどの host slot に戻すか」のメタ src/mir/join_ir/lowering/carrier_info.rs, src/mir/builder/control_flow/joinir/merge/exit_line/meta_collector.rs ExitMeta / exit_bindings carrier 不整合(不足/過剰)を Err
CarrierInit carrier 初期化の SSOTFromHost/Const/LoopLocal src/mir/builder/control_flow/joinir/merge/carrier_init_builder.rs, src/mir/join_ir/lowering/carrier_info.rs 初期値 ValueId 初期化経路の分岐が散らばらないSSOT を使う)
ErrorTags エラータグ整形の SSOT検索性・一貫性 src/mir/join_ir/lowering/error_tags.rs 文字列タグ 文字列ハードコードを避け、タグを一元化

注:

  • Pattern 検出は「関数名 by-name 分岐」に依存しない(構造で決める)。必要なら dev/診断限定のガードに閉じ込める。
  • shape guard は「OK なら後工程が前提にできる契約」を固定する場所で、曖昧な許容をしない。

入口(コード側のエントリポイント)

Loopbuilder 側の導線)

JoinIRIR/正規化/ブリッジ)

共通(診断とタグ)


不変条件Fail-Fast

JoinIR を触るときは、次を破ったら「即エラーで止める」前提で設計・実装する。

形状shape

  • Pattern は「認識できる shape だけ」を通し、曖昧な許容をしない。
  • 形状が合わないときは Ok(None) で静かに進めない非JoinIRへの退避を作らない
    • 例外: 明確な “routing” で「別 JoinIR 経路」を選ぶのは可(同一層内での選択)。

ValueId / PHI / Boundary の世界

  • JoinIR 内部JoinValueSpace 等)と host MIR builder の ValueId を混ぜない。
  • Boundary は JoinIR↔host の橋渡し契約:
    • join_inputshost_inputs の対応が明示される
    • Exit 側は “carrier 名” をキーにして reconnection されるExitMeta/exit_bindings
  • PHI は「誰が確保するか」を固定し、衝突を許さないPHI dst の予約・再利用禁止)。

ExitLine 契約

  • ExitLine は「出口へ集約する」ための契約であり、未接続の経路を残さない。
  • carrier/slot の不足・余剰・不整合は error_tags::exit_line_contract(...) 等で即エラーにする。

追加手順チェックリスト(新しいループ形を飲み込む最小手順)

「新しいループ形」を JoinIR で扱えるようにするときの最小手順。

  1. Fixture を追加(再現可能に固定)
    • apps/tests/ または apps/smokes/ に最小の .hako を追加(対象形が一目で分かるもの)
  2. Pattern/feature を追加(検出)
    • src/mir/builder/control_flow/joinir/patterns/ast_feature_extractor.rs(必要なら feature 抽出を拡張)
    • src/mir/loop_pattern_detection/(分類/補助解析が必要ならここに追加)
  3. shape guard を追加(契約の固定)
    • 形状・前提条件を validator として分離し、失敗は Err にする
  4. lower を追加JoinIR を生成)
    • 既存 pattern のコピーではなく、「今回の shape が要求する最小構成」にする
    • エラーは src/mir/join_ir/lowering/error_tags.rs を使いタグを固定する
  5. merge/ExitLine を接続(契約が満たされるように)
    • carrier/ExitMeta/Boundary が揃っているか確認する
  6. Tests を追加(仕様固定)
    • unit: pattern/validator/merge の局所テスト
    • smoke: tools/smokes/v2/ の profile に軽いケースを追加quick を重くしない)
  7. Docs を更新(地図を更新)
    • docs/development/current/main/loop_pattern_space.md(パターン空間に追記が必要なら)
    • docs/development/current/main/joinir-architecture-overview.md(箱/契約が増えたなら)
    • 本ファイル(入口・責務マップの更新)