Zig 0.17.0 開発アップデート: @bitCast セマンティクス、LLVM バックエンド、およびビルドシステム
Zig 0.17.0 開発アップデート: @bitCast セマンティクス、LLVM バックエンド、およびビルドシステム
Zig は、パフォーマンス、予測可能性、および開発者体験を向上させるために、コアコンパイラとビルドインフラストラクチャを進化させています。主なアップデートには、エンディアンに依存しないようにするための @bitCast の根本的な再定義、LLVM バックエンドにおける任意の幅の整数のより効率的なローリング、および zig build プロセスの大幅なアーキテクチャの再構築が含まれます。
新しいエンディアン非依存の @bitCast セマンティクス
Zig は、メモリ内の生のバイトを再解釈するのではなく、型の論理的なビット表現に基づいて動作するように @bitCast を再定義しました。この変更により、ビットキャストが異なるターゲットアーキテクチャ間で同一の動作を保証し、ターゲットのエンディアンへの依存を排除します。
論理ビットレイアウト
新しいセマンティクスでは、@bitCast をサポートするすべての型は、「論理ビットレイアウト」—すなわち、順序付けられたビットのシーケンスを持ちます。例えば:
- 整数:
u5は、最下位ビットから最上位ビットまで順序付けられた 5 つの論理ビットで構成されます。 - 配列:
[2]u5は、10 個の論理ビット(最初の要素の 5 ビット、その後に 2 番目の要素の 5 ビット)で構成されます。
集約型への影響
最も重要な変更は、配列やベクトルなどの集約型をビットキャストする場合に発生します。以前は、[2]u8 を u16 にビットキャストすると、ビッグエンディアンとリトルエンディアンのターゲットでは異なる値になります。現在、この操作はエンディアンに依存しません。最初の配列要素は常に結果の整数の下位 8 ビットになります。
追加の @bitCast の変更点
- 列挙型 (Enums):
@bitCastは現在、列挙型に対して許可されています。 - ポインタ: ポインタのベクトルへの、またはポインタのベクトルからの
@bitCastは現在禁止されています。
LLVM バックエンドの改善とパフォーマンス
Zig は、LLVM バックエンドが任意のビット幅の整数型(例:u4, i13)を処理する方法を更新し、LLVM のネイティブなビット整数型をメモリに保持することに関連する、最適化の不足や誤コンパイルを回避するようにしました。
整数ローリング (Integer Lowering)
以前は、Zig はこれらの型を LLVM IR のビット整数型に直接ローリングしていました。新しい実装では、SSA 形式の値に対してのみビット整数型を使用し、メモリに保存する際には ABI サイズの型(i8, i16, i32 など)に拡張します。このアプローチは、Clang が C の _BitInt(N) をローリングする方法と一致しており、LLVM 内でのより良いサポートと、より信頼性の高い最適化を保証します。
パフォーマンスの向上
この変更は、すでに、失われた最適化の復元において成功を示しています。Zig コンパイラ自体は約 5% のパフォーマンス向上を実現しており、これは、今後の 0.17.0 リリースにおけるユーザーへの同様のランタイムの利得をもたらすことを示唆しています。
ビルドシステムのアーキテクチャの再構築
zig build の速度を向上させるために、ビルドシステムは「コンフィギュラー (configurer)」プロセスと「メーカー (maker)」プロセスを分離しています。
コンフィギュラーとメーカーの分離
- コンフィギュラー:
build.zigファイルは、デバッグモードで小さなプロセスとしてコンパイルされます。これはメモリ内でビルドグラフを構築し、それをバイナリ構成ファイルにシリアル化します。 - メーカー: 親
zig buildプロセスは、非同期的に「メーカー」プロセスをコンパイルし、リリースモードで実行します。このメーカープロセスは、シリアル化されたビルドグラフを実行します。
新しいアーキテクチャの利点点
コンパイルの削減: 変更があった場合、ビルドシステム全体ではなく、ユーザーの
build.zigロジックのみがコンパイルされます。キャッシュされた構成: 構成が変更されていない場合(例:
-freference-traceのような CLI フラグを追加する場合)、ビルドシステムはbuild.zigロジックの実行を再開することを完全にスキップできます。最適化された実行: ビルドグラフを実行するプロセスは、現在、最適化が有効な状態でコンパイルされます。
ベンチマークでは、単純なコマンドの実行時間が劇的に減少したことが示されています。例えば、zig build -h は 150ms から 14.3ms に減少しました。
その他の注目すべきコンパイラとツールに関するアップデート
ELF リンカーと増分コンパイル
- 新しい ELF リンカー: 新しい ELF リンカー(
-fnew-linkerで有効化)は、LLVM と LLD ライブラリを使用して、セルフホストされた Zig コンパイラをビルドできます。これは x86_64 Linux 上での高速な増分リビルドをサポートしており、一部のリビルド時間を 30ms 程度まで短縮しています。 - LLVM 増分サポート: 増分コンパイルは現在 LLVM バックエンドで動作し、開発者がコンパ列エラーを数秒ではなく数ミリ秒で受け取れるようにします。
型解決の再設計
- コンパイラの内部型解決は、より遅延評価 (lazy) になりました。型が名前空間としてのみ使用され、初期化もされない場合、コンパイラはそれらのフィールドを分析せず、不要な
@compileErrorの発生を防ぎます。 - 依存関係ループのエラーメッセージは、ループが正確にどこから発生しているかを詳細に記述するように再設計されました。
Windows ネイティブ API の優先
- Zig 標準ライブラリは、不要なヒープ・アロケーション、肥大化、および非決定論的な失敗モードを避けるため、Win32 ラッパー (kernel32.dll) よりもネイティブ API (ntdll.dll) を優先する方向に進んでいます。これは、特にエントロピー生成(
bcryptprimitives.dllを避ける)やファイル I/O (NtReadFile/NtWriteFile) の新しい実装において顕著です。
パッケージ管理
- ローカルストレージ: 取得されたパッケージは、プロジェクトローカルの
zig-pkgディレクトリに保存されるため、、オフラインビルドを容易にし、IDE 統合を容易にします。 - プロジェクト・オーバーライド:
--fork=[path]フラグを使用すると、開発者はbuild.zig.zonを変更せずに、迅速なイテレーションのためのローカルソース・チェックアウトで依存関係を一時的にオーバーライドできます。
コミュニティの視点
技術コミュニティの大部分は、これらの詳細な分析を価値のあるものと見ていますが、 @bitCast の新しいセマンティクスについては議論があります。あるユーザーは次のように述べています:
"This is a huge mistake. You would never expect something like bitCast to do this... Why change something so simple and low level to be complicated and high level?"
逆に、他のユーザーは、手動でのビット操作なしでビットパックされたバイナリヘッダーを扱うための、これらの変更の有用性を強調しています。