7.2 KiB
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 CFG(edge-args を第一級に持つ CFG)に収束させたいです。
北極星(north star): “Join-Explicit CFG Construction”
ゴール(最終形)
Jump/continuation/params/edge-argsを第一級(explicit)として扱う- JoinIR↔MIR 間の暗黙 ABI を消し、変換を「意味解釈」ではなく「写像(mapping)」に縮退する
- 長期的には JoinIR を builder DSL に降格できる状態にする(削除は急がない)
制約 / 方針
- フォールバックより Fail-Fast(prod/CI 既定で安全)
- by-name ハードコード分岐は禁止(特定 Box 名での条件分岐など)
- 新しい環境変数の増殖は禁止(既存 debug gate の範囲で)
- 段階導入(Strangler)で、差分を小さく・可逆に
質問(回答してほしいこと)
- Normalized JoinIR の最小語彙は何がよいか?
Jump(args)/Branch(then_args, else_args)/Return/Callのセットcond 付き Jumpを禁止し、Branchに寄せるべきか
- ABI(役割・順序)SSOT をどこに置くべきか?
JoinAbi(sig/roles/special conts/alias)を新設するか、JoinModuleに持たせるか- boundary の
join_inputs/host_inputsを Vec 順序のまま段階移行する案(最小差分)と、ParamId→ValueId束縛にする案(最終形)
- block-parameterized CFG 移行の最小ステップを、Phase で刻んで提示してほしい
jump_argsを BasicBlock メタから terminator operand に埋め込む手順(併存→移行→削除)- verify / optimizer / printer / builder への影響の最小化
- 箱(Box)分割は最小でどう切るべきか?
- “推測禁止” と “Fail-Fast” をどの箱に閉じ込めるか
- 例:
AbiBox,BoundaryContractCheckBox,ExitArgsPlumbingBox,CfgSuccessorSyncBox
- **不変条件(invariants)**と検証地点の設計
- Normalizer直後 / merge直前 /
--verifyの各地点で、何を verify するのが最短で強いか
- Normalizer直後 / merge直前 /
期待する出力(形式)
- 「いきなり最終形」ではなく、**段階移行(1フェーズ=小差分)**のマイルストーンを提示
- 各フェーズの 受け入れ基準(smoke/verify/contract)を明文化
- 新規箱は最小(2〜3個から開始)で、増やす判断基準も書く
2) リポジトリ現状(SSOTメモ)
最近の到達点(コミット)
73ddc5f58feat(joinir): Phase 257 P1.1/P1.2/P1.3(Pattern6 SSOT / PHI predecessor verify / LoopHeaderPhi 修正)23531bf64feat(joinir): Phase 258 P0(index_of_string dynamic needle window scan)e4f57ea83docs: Phase 257-259 SSOT 更新
現在の “意味データが IR 外” の例
jump_argsがBasicBlockのメタとして存在(DCE/verify が追う必要がある)- spans が
instructionsと並行 Vec(同期漏れで SPAN MISMATCH が起きる)
3) 最低限のソースコード断片(Pro に見せる用)
3.1 BasicBlock(jump_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 collection(layout に従うだけ)
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点を優先して “迷子防止” を強化したい。
- edge-args の参照 API は Branch 前提にする
edge_args()単発は曖昧になりやすい- 推奨:
out_edges()/edge_args_to(target)のように「edge を列挙」できる形を SSOT にする
- terminator operand の edge-args は “意味付き” にする
Vec<ValueId>だけだと layout(CarriersOnly/ExprResultPlusCarriers)の推測が残る- 最小:
EdgeArgs { layout: JumpArgsLayout, values: Vec<ValueId> }を同梱(将来はContSigIdに置換)