O0 とデバッグ
計算、定数式、記憶領域、デバッグ対応情報を保存するルールです。
Wave Foundation
保存モデル
O0はデバッグのためにオリジナルtypedIRの計算・変数・制御フローを保存します。未使用の結果と構造的に到達不能なブロックも維持します。検証は誤った IR を診断し、ブロックの削除や操作を簡素化しません。
機械語を生成するために必要な変換は、別々のサブIRで行われます。変換後もオリジナルIDとの対応を維持しなければなりません。 typed IR 保存がすべて IR 演算と機械命令の一対一対応を意味するわけではありません。
O0で行わない変換
| 変換 | O0動作 |
|---|---|
| インライニング | 呼び出しと関数の境界を維持 |
| Tail-call変換 | 一般呼び出し・返還構造を維持 |
| 死んだコードを削除 | 未使用の計算と到達不能なブロックを維持 |
| ランタイム定数の折りたたみ | 元の操作を維持 |
| 共通計算を合わせる | 別々の計算を維持 |
| ローカル変数ストレージスペースの再利用 | 各ストレージスペースを維持 |
| フレームポインタを省略 | フレームポインタを保持 |
| 文字列の自動マージ | 別個の文字列オブジェクトを保持 |
たとえば、2 つの定数を加算するランタイム演算は、結果を使用しなくても加算として残ります。条件が定数の分岐も元の制御フロー構造を維持します。
コンパイル時定数
コンパイル時定数宣言は、typed初期化式と評価結果を一緒に保存します。これは、通常のランタイムコマンドの定数折りたたみとは異なります。
初期化式が1 + 2の宣言には加算式と結果3が一緒に残ります。この例は式の意味を説明し、特定のソース言語の宣言文法ではありません。結果は静的データを構成するときに使用でき、初期化式をランタイム加算に置き換えることはありません。
未使用・到達不可能な宣言も識別できなければなりません。同じ名前の宣言がお互いを隠しても、名前・宣言ID・参照に区分されなければなりません。検証は、誤った参照、依存性循環、誤った型、元の式と一致しない保存結果を拒否します。
到達不可能なソース文
return・break・continue 後の文章も連結されていないブロックに残ります。この文のため、前のterminatorを変更したり、新しい実行パスを作成したりしないでください。到達不可能な文章内の誤った式も診断します。
この保存規則により、元のプログラム構造を調べることができます。 terminator 後の文が実際に実行されるという意味ではありません。
保存されるIRの例
以下は、バリデータを通過したモジュールの現在のプリンタ出力です。未使用の計算、コンパイル時の宣言、リンクされていないブロックが一緒に表示されます。
module {
format_version 2
semantics_version 1
target "x86_64-whale-linux"
datalayout { ptr=64, endian=little }
declare @f0 "preserved": whale () -> void, linkage internal
fn @preserved() -> void, id @f0 {
entry:
%v0: i32 = const i32 1
%v1: i32 = const i32 2
%v2: i32 = add i32 %v0, %v1
%v3: i32 = const_decl "count" add(i32 1, i32 2) => const i32 3
ret void
unreachable.cont:
%v4: i32 = const i32 4
%v5: i32 = const i32 5
%v6: i32 = add i32 %v4, %v5
ret void
}
}
%v2は使用先がなくてもaddのままです。 %v3は別個のconst_declであり、add(i32 1, i32 2)式と評価結果3を一緒に保存します。 unreachable.contには入ってくる幹線がないので、ret voidの後に実行パスを追加せずに%v6加算を確認できます。
検証はこのコマンドとブロックを保存します。この例は、IR構成、検証、出力を示しており、native実行またはDWARF出力が提供されるという意味ではありません。
ソースとスタック情報
デバッグインタフェースは、DWARF5の関数情報、ソース行、デフォルトのローカル変数、呼び出しフレーム情報を使用します。下位表現に変換しても、関数・地域変数情報と元のIR識別子の対応を維持しなければなりません。
AMD64プロファイルはフレームポインタを保持し、redzoneを使用しません。呼び出しフレーム情報はスタック調査に使用され、例外unwindingサポートを意味しません。 trapはデストラクタやunwindingを保証せずに実行を終了します。
DWARF出力とnative実行の提供可否はツールチェーンの概要を参照してください。 O1以上最適化の動作は、このO0参照の範囲外です。