Files
hakorune/docs/development/current/main/investigations/phase-259-block-parameterized-cfg-consult.md

7.2 KiB
Raw Blame History

Phase 259: Block-Parameterized CFG / Join-Explicit CFG — ChatGPT Pro 相談パケット

目的: ChatGPT Pro に「正規化normalizedをどう設計し、小さい強い箱Boxで結び、block-parameterized CFG へ段階移行するか」を相談するためのコピペ用 SSOT を用意する。

更新日: 2025-12-20


1) ChatGPT Pro へ投げる文章(コピペ用)

以下の条件で、段階移行できる設計を提案してください。

コンテキスト

Nyash/Hakorune の JoinIR→MIR 経路で、Jump/continuation/params/edge-args が「暗黙 ABI順序/長さ/役割/識別)」として散在し、パターン追加のたびに merge/optimizer/verify が連鎖で壊れました。最近は SSOT 化と Fail-Fast を進め、JumpArgsLayout を boundary に持たせて推測を排除しましたが、最終的には block-parameterized CFGedge-args を第一級に持つ CFGに収束させたいです。

北極星north star: “Join-Explicit CFG Construction”

ゴール(最終形)

  • Jump/continuation/params/edge-args を第一級explicitとして扱う
  • JoinIR↔MIR 間の暗黙 ABI を消し、変換を「意味解釈」ではなく「写像mapping」に縮退する
  • 長期的には JoinIR を builder DSL に降格できる状態にする(削除は急がない)

制約 / 方針

  • フォールバックより Fail-Fastprod/CI 既定で安全)
  • by-name ハードコード分岐は禁止(特定 Box 名での条件分岐など)
  • 新しい環境変数の増殖は禁止(既存 debug gate の範囲で)
  • 段階導入Stranglerで、差分を小さく・可逆に

質問(回答してほしいこと)

  1. Normalized JoinIR の最小語彙は何がよいか?
    • Jump(args) / Branch(then_args, else_args) / Return / Call のセット
    • cond 付き Jump を禁止し、Branch に寄せるべきか
  2. ABI役割・順序SSOT をどこに置くべきか?
    • JoinAbisig/roles/special conts/aliasを新設するか、JoinModule に持たせるか
    • boundary の join_inputs/host_inputs を Vec 順序のまま段階移行する案(最小差分)と、ParamId→ValueId 束縛にする案(最終形)
  3. block-parameterized CFG 移行の最小ステップを、Phase で刻んで提示してほしい
    • jump_args を BasicBlock メタから terminator operand に埋め込む手順(併存→移行→削除)
    • verify / optimizer / printer / builder への影響の最小化
  4. Box分割は最小でどう切るべきか?
    • “推測禁止” と “Fail-Fast” をどの箱に閉じ込めるか
    • 例: AbiBox, BoundaryContractCheckBox, ExitArgsPlumbingBox, CfgSuccessorSyncBox
  5. **不変条件invariants**と検証地点の設計
    • Normalizer直後 / merge直前 / --verify の各地点で、何を verify するのが最短で強いか

期待する出力(形式)

  • 「いきなり最終形」ではなく、**段階移行1フェーズ=小差分)**のマイルストーンを提示
  • 各フェーズの 受け入れ基準smoke/verify/contractを明文化
  • 新規箱は最小2〜3個から開始で、増やす判断基準も書く

2) リポジトリ現状SSOTメモ

最近の到達点(コミット)

  • 73ddc5f58 feat(joinir): Phase 257 P1.1/P1.2/P1.3Pattern6 SSOT / PHI predecessor verify / LoopHeaderPhi 修正)
  • 23531bf64 feat(joinir): Phase 258 P0index_of_string dynamic needle window scan
  • e4f57ea83 docs: Phase 257-259 SSOT 更新

現在の “意味データが IR 外” の例

  • jump_argsBasicBlock のメタとして存在DCE/verify が追う必要がある)
  • spans が instructions と並行 Vec同期漏れで SPAN MISMATCH が起きる)

3) 最低限のソースコード断片Pro に見せる用)

3.1 BasicBlockjump_args と span の現状)

src/mir/basic_block.rs:45

pub struct BasicBlock {
    pub id: BasicBlockId,
    pub instructions: Vec<MirInstruction>,
    pub instruction_spans: Vec<Span>,
    pub terminator: Option<MirInstruction>,
    pub terminator_span: Option<Span>,
    pub predecessors: BTreeSet<BasicBlockId>,
    pub successors: BTreeSet<BasicBlockId>,
    // ...
    pub jump_args: Option<Vec<ValueId>>, // Phase 246-EX: Jump args metadata
}

3.2 JumpArgsLayout(推測排除の SSOT

src/mir/join_ir/lowering/inline_boundary.rs:107

pub enum JumpArgsLayout {
    CarriersOnly,
    ExprResultPlusCarriers,
}

3.3 Exit args collectionlayout に従うだけ)

src/mir/builder/control_flow/joinir/merge/exit_args_collector.rs:94

pub fn collect(
    &self,
    exit_bindings: &[LoopExitBinding],
    remapped_args: &[ValueId],
    block_id: BasicBlockId,
    strict_exit: bool,
    layout: JumpArgsLayout,
) -> Result<ExitArgsCollectionResult, String>

3.4 DCE が jump_args を use として数える(現状の暫定対応)

src/mir/passes/dce.rs:40

if let Some(args) = &block.jump_args {
    for &u in args {
        used_values.insert(u);
    }
}

4) 相談したい設計上の痛点(要約)

  • jump_args がメタなので、最適化/検証/表示/CFG更新が「忘れると壊れる」になりやすい
  • continuation の識別が ID/名前/legacy alias で揺れると merge が壊れる
  • “順序” が暗黙だと、expr_result と carrier が同一 ValueId のときにズレて誤配線になりやすい
  • spans が並行 Vec だと、パスが1箇所でも同期を忘れると壊れる
  • this/me の表面名と内部 variable_map キーがズレると、Pattern 側で receiver を取り違えやすいSSOT不足
  • Branch が入ると “edge-args の参照点” が曖昧になりやすいthen/else のどちらかだけ見て事故る)

5) 移行の北極星(既存 SSOT へのリンク)

  • North Star: docs/development/current/main/design/join-explicit-cfg-construction.md
  • Phase 256 で露出した契約論点: docs/development/current/main/investigations/phase-256-joinir-contract-questions.md

6) 追加質問receiver SSOT

me receiver の host ValueId を Pattern 側が直接 "me"/"this" で参照しないように、API/Box として封印したい。

  • どの層に置くべきか?(例: joinir/api/receiver.rs
  • Fail-Fast の位置builder で未登録なら即死pattern detect の時点で弾く?)
  • this/me の将来拡張Stage-3/4に耐える最小設計は

7) ChatGPT Pro 追記(設計レビュー観点)

段階移行ロードマップの細部で、次の2点を優先して “迷子防止” を強化したい。

  1. edge-args の参照 API は Branch 前提にする
    • edge_args() 単発は曖昧になりやすい
    • 推奨: out_edges() / edge_args_to(target) のように「edge を列挙」できる形を SSOT にする
  2. terminator operand の edge-args は “意味付き” にする
    • Vec<ValueId> だけだと layoutCarriersOnly / ExprResultPlusCarriers)の推測が残る
    • 最小: EdgeArgs { layout: JumpArgsLayout, values: Vec<ValueId> } を同梱(将来は ContSigId に置換)