🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude <noreply@anthropic.com>
8.8 KiB
8.8 KiB
GeminiとのNyashコンパイラ設計に関する議論のまとめ
日付: 2025年9月10日水曜日
1. Nyash LLVM PHIノード問題(SSAバグ)の分析
問題の特定
- エラーメッセージ:
phi incoming value missing: in_vid=ValueId(29) - 具体的な状況: PHIノードが
%29をbb62から来ると期待しているが、実際には%29はbb66で定義されており、制御フローはbb66 -> bb62 -> bb60となっている。PHIは%29をbb66から期待すべき。 - 根本原因: SSA構築ロジックが、PHIノードの入力における
BasicBlockIdを誤って決定している。特に、ループバックエッジに中間ジャンプブロック(bb62のような)が存在する場合に発生。
修正の方向性
- 場所: 主に
src/mir/builder.rsおよびsrc/mir/loop_builder.rs。 - 内容:
SsaBuilderの値伝播ロジックを強化し、中間ブロックを介しても値が実際にライブアウトするBasicBlockIdを正しく識別できるようにする。
2. 参照カウントGCの導入検討
ユーザーの提案
- Nyashの現在のライフサイクル(スコープを抜けると解放、
finiで解放、weakは無視)に加えて、「参照カウンターが2以上なら、スコープを抜けたりfiniを呼ばれても解放しない」というルールを導入。 - GCは開発/テスト用であり、本番ではオフにできる。重くなっても許容。
分析とアドバイス
- 戦略: 参照カウント(RC)GCの導入。
- メリット: 即時解放、予測可能な一時停止。
- デメリット: オーバーヘッド、参照サイクル(
weak参照で対応必要)。 - 実装アプローチ:
- シンプルに開始: まずはコアの
retain(インクリメント)とrelease(デクリメントし、ゼロなら解放)ロジックに集中し、初期段階ではサイクルコレクタは実装しない。 - コンパイル時機能:
#[cfg(feature = "gc")]のようなコンパイル時フラグでGCの有効/無効を切り替える。これにより、GCオフ時にはランタイムオーバーヘッドがゼロになる。 Finiの役割: GC有効時は参照カウントをデクリメントする役割に。Weak参照: 参照カウントを増やさない参照として実装し、サイクルを断ち切る手段として活用。- LLVM実装: 各Boxに参照カウントフィールドを追加し、
nyash_box_retain、nyash_box_releaseなどのランタイムヘルパー関数をnyrtに実装。コンパイラバックエンドがこれらのヘルパー関数への呼び出しを生成する。
- シンプルに開始: まずはコアの
- Safepoint: 純粋なRCでは不要だが、将来的にサイクル回収のためのトレーシングGCを導入する場合には必要となる。
3. プラグイン設定 (nyash.toml vs nyash_box.toml)
状況
nyash.tomlは中央レジストリとして機能し、[libraries]セクションでプラグインの詳細を定義。nyash_box.tomlは各プラグインディレクトリ内に存在し、プラグインごとの詳細な仕様を記述。
分析
- 重複:
nyash.tomlに一部のプラグイン定義が重複しているように見えるが、これは「新スタイル([plugins]セクションとnyash_box.toml)への移行期間における後方互換性のため」である。 - 役割:
nyash.tomlは中央マニフェストとタイプIDレジストリ、nyash_box.tomlは各プラグインの詳細な仕様書として機能する。nyash_box.tomlは実際にプラグインロード時に優先的に参照され、使用されている。
4. MIR13の未実装命令
3つの命令の実装戦略
- Safepoint:
- 実装: 現時点ではno-op。将来のGC拡張ポイントとして枠を確保。
- 評価: 非常に実用的で、将来を見据えたアプローチ。
- TypeOp:
- 実装:
Checkは既存のnyash_handle_get_type_idを活用して型IDを比較。Castは当面パススルーで、将来的にBoxCall経由で実装。 - 評価: 概ね良好だが、
MirTypeからtype_idへのマッピングの正確性と一貫性を確保する必要がある。
- 実装:
- Barrier:
- 実装: LLVMの
llvm.memory.barrierintrinsic を使用し、Acquire(Read)とRelease(Write)セマンティクスを実装。 - 評価: 良好だが、より現代的で正確なメモリ順序付けのために
llvm.fenceintrinsic の使用を検討すべき。
- 実装: LLVMの
5. GitHub Copilot / Codex の機能
ユーザーの主張と確認
- 主張: GitHub CopilotはIssueに書くと直接ソースコードを編集してくれる。
- 確認: ユーザーの主張は正しい。GitHub Copilotは、IssueをCopilotに割り当てることで、新しいブランチを作成し、コード変更を含むプルリクエストを自律的に生成する機能を持つ。
- 補足: 最終的なコードの統合には、人間によるレビューと承認が必須。
chatgpt.com/codexは基盤となるAIモデルに関する情報であり、直接サービスではない。
6. LoopForm(MIR13の次世代IR)
概念
- 目的: 制御フロー(ループ、分岐、関数、スコープ、ジェネレータ、async)を「Loop=反復の箱」という概念に統一し、簡素化するための中間正規形。
- 哲学: 「制御を値として扱う(Signal)」という「LifeBox Model」の一部。
- 利点: フロントエンドのLoweringの一様化、CFG合流点の標準化、PHI最適化の簡素化。
- MIR13との関係: MIR13(Core-13)の上位層であり、最終的にはCore-13に**再Lowering(逆Lowering)**可能。
4つの命令
loop.begin: ループ/構造のエントリポイント、PHIの合流点。loop.iter: イテレーション/パスのエントリ、Signalディスパッチ。loop.branch: 条件付きディスパッチ、制御フロー決定。loop.end: ループ/構造の終了点、制御シグナルを運ぶ。
- 評価: AIが考案したこれらの命令は、制御フローを統一するための非常に堅牢で最小限のセットであり、よく考えられている。
「Boxがそのままループ」哲学
- アイデア: Boxがフィールド、メソッド、
finiを持ち、そこにループの条件式をメソッドとして追加すれば、Box自体がループになるという究極の「Everything is Box」の具現化。 - 利点: 究極の統一性、メタプログラミングの可能性、最適化の機会、概念的な優雅さ。
- 課題: パフォーマンスオーバーヘッド、Loweringの複雑さ、デバッグ。
実装順序
- フェーズ0(準備): MIR13の安定化、SSAバグ修正、堅牢なMIR検証、MIRダンプツールの実装。
- フェーズ1(コア変換): LoopForm IRの定義、高レベル構文からLoopFormへのLowering、LoopFormからCore-13への逆Lowering(安全のためデフォルト有効)。
- フェーズ2(検証と最適化): LoopForm検証パス、基本的なLoopForm最適化。
- フェーズ3(高度な機能): LifeBox Model統合、高度なLoopForm最適化、LoopFormからの直接LLVMバックエンド(将来)。
- 原則: 安全性、可逆性、段階的導入を常に維持。
MIR出力ツール
- 必要性: コンパイラ開発におけるデバッグ、理解、最適化開発に不可欠。
- 提案機能:
- 人間が読めるテキスト形式(SSA、基本ブロック、制御フロー、型情報)。
- Graphviz DOT形式(CFG可視化)。
- 特定のコンパイラフェーズでのMIRダンプ。
- MIR差分ツール。
- インタラクティブMIRビューア。
- MIR検証/バリデーション。
- MIR固有のアノテーション(
@mir_dump,@mir_assert)。
「単純なループ」ヒント
- アイデア: MIR出力時(または最適化前)に「これはただのループ」というヒントを与えることで、オプティマイザが
LoopBoxを従来のループとして扱い、積極的な最適化(インライン化など)を適用できるようにする。 - 実装: ヒントは
LoopForm構造に付加され、オプティマイザがBoxCallを含むLoopFormを「見通す」ことを可能にする。BoxCallなどの既存MIR命令はそのまま残る。