
2026/06/25 23:19
Zig の新しい bitCast セマンティクスと LLVM バックエンドの機能強化
RSS: https://news.ycombinator.com/rss
要約▶
Japanese Translation:
2026年1月から同年6月中旬にかけて、Zigコンパイラはそのバックエンドアーキテクチャにおいて主要な画期的進展を遂げ、信頼性の高いGPUコンパイルと強化されたクロスプラットフォームパフォーマンスを実現することを優先しました。2026年2月下旬には、Windowsで古いカーネルラッパーに代わってネイティブNT APIが採用され、ヒープ配分の削減とCPU使用量の低減を図りました。3月上旬には、型解決の再設計により、コンパイラが無分析された型の処理をより効率的に行う(「遅延処理」)ことが可能になり、段階的コンパイルに関するバグが解消されました。5月/6月に大きく変化したのは、LLVMバックエンドの修正によって非ABI整数型の Lowering 方法が変更された点です(直接のメモリ操作から、ABIサイズに整合する論理的型へ)。これにより最適化が回復し、endianness の処理が改善されました。このアップデートでは、バイト順序ではなく論理的なビット配置に基づく新しい
@bitCast のセマンティクスも導入されました。
2026年6月には、SPIR-V バックエンドでも重要な更新が行われました。機能セット全体に基づいてカプビリティが制御されるようになり、メッシュシェーディング用の呼び出し規約(
spirv_task、spirv_mesh)が追加され、代わりにレガシーなインラインアセンブリヘルパーが削除されました。特に重要なのは、.spv ファイルがオブジェクトファイルとして認識されるようになったことであり、これにより SPIR-V リンカーを介して複数の SPIR-V オブジェクトを単一のモジュールに結合できるようになりました。ユーザー空間でのスタックスイッチングなどの実験的な機能についてはなお堅牢なエラーハンドリングが必要ですが、これらの改良は、先進的目標(具体的には spirv64-vulkan ターゲット)における動作テストのパス率で大幅な増加が確認されるなど、安定したグラフィックプログラミング環境への決定的な進化を示すものです。本文
Zig メインブランチ:2026 年変更点サマリー
本記事は、Zig のメインブランチにおける 2026 年 に関連する最近の変更点を紹介しています。過去の年度(2023-2025 など)の情報については、「Devlog archive」ページをご確認ください。
📅 2026 年 6 月 26 日:SPIR-V バックエンドの進展
著者: Ali Cheraghi
SPIR-V バックエンドには多大な変更が加えられ、過去数週間にわたってより安定した状態に戻されました。主なアップデート内容は以下の通りです。
🆕 新しい型システム対応 (@SpirvType)
- 課題の解決: Zig の標準型システムでは表現できなかった SPIR-V 固有の型に対処しました。
- 導入された機能: 新しい builtin タイプ
が登場し、シェーダー記述における長年のボトルネックを解消します。@SpirvType- 詳細は Issue #20550, #23326, #35461 を参照してください。
// サンプルコード:新しい型の定義例 const Sampler = @SpirvType(.sampler); const Image = @SpirvType(.{ .image = .{ .usage = .{ .sampled = u32 }, .format = .unknown, .dim = .@"2d", .depth = .unknown, .arrayed = false, .multisampled = false, .access = .unknown, } });
🏗️ 呼び出し規約 (Call Conventions) の進化
- Execution Mode の伝搬: ワークグループサイズやフラグメントの起源などの情報は、インラインアセンブラではなく 呼び出し規約 を介して渡されます。
- 旧来の
ヘルパーは廃止されました。std.gpu.executionMode() - SPIR-V アセンブラは
の手動出力を試みても拒否します。OpExecutionMode
- 旧来の
- 新しい呼び出し規約の追加: メッシュシェーディングパイプラインに対応するため、以下の 2 つが追加されました。
spirv_taskspirv_mesh
export fn vert() callconv(.spirv_vertex) void {} export fn frag() callconv(.{ .spirv_fragment = .{ .depth_assumption = .greater } }) void {} export fn task() callconv(.{ .spirv_task = .{ .x = 1, .y = 1, .z = 1 } }) void {} export fn mesh() callconv(.{ .spirv_mesh = .{ .stage_output = .output_lines } }) void {}
⚙️ Capabilities と Extensions の扱い変更
- CPU 機能セット駆動: 以前は適宜(ad hoc)生成されていたCapabilities/Extensionsが、他ターゲット同様 完全な CPU 機能セット に基づいて自動生成されます。
- SPIRV-Headers から依存関係チェーンを抽出し、外部ベンダーの除外処理を実装しています。
- アセンブラからの直接出力拒否が強化されました。
🚀 パフォーマンスと最適化
- マルチスレッド化: コードジェネレーションは現在、他のバックエンド同様 Mir 値を生成し、コンパイラのスレッドプールでスケジューリングされます(以前はシングルスレッド)。
- ISel パスの復活: リファクタリング時に削除されていた以下のパスが復活しました。
: 同等の型指令をマージ。dedup_types
: モジュールからデッドコードを剥離(stripping)。prune_unused
🔗 オブジェクトファイルへのリンク機能
ファイルはオブジェクトファイルとして認識され、複数のソースを組み合わせた単一モジュールの生成が可能になりました。.spv
🐛 品質向上とリネーム
- バグ修正: 多数の既存バグが修正されました。
- テスト増加:
ターゲットでのパス済み振る舞いテスト数は約 10% 増加(現在全体の 49%)。spirv64-vulkan- ※依然として多くのテストがスキップされていますが、改善は続いています。
- パッケージリネーム:
→std.gpu
に改名されました。std.spirv
💡 まとめ: SPIR-V バックエンドは以前より有意義に有用になり、シェーダーや compute カーネルの試みには最適な時期です。バグレポート(Codeberg)が歓迎されます!
📅 2026 年 6 月 25 日:LLVM バックエンド改善と @bitCast の再定義
著者: Matthew Lugg
LLVM バックエンドへの改善を実装した大きなブランチです。言語プロポーザルの実装も包含しています。
📉 Integer Lowering の最適化
- 従来: 任意のビット幅整数型を直接 LLVM IR に降下させていました(Clang と互換性 lacked)。
- 現在: SSA 形式での値操作はそのままに、メモリ保存時は ABI サイズ (
,i8
,i16
など) にゼロ埋めまたは符号拡張する方式へ移行。i32- これにより Clang の
との互換性が保たれ、自明な最適化が失われませんでした。_BitInt(N)
- これにより Clang の
🔄 @bitCast のセマンティクス変更
- 背景: 過去は「メモリのバイトを再解釈する」ことが定義でしたが、時間と共に矛盾が生じていました。整数型とパッキング構造体のサイズ違いでの動作やクラッシュが発生していました。
- 解決策: Jacob Young 氏による言語プロポーザル (#19755) を採用し、論理的なビットレイアウト に基づく新しい定義を実装しました。
- これはセルフホスト x86_64 バックエンドでも既に実装済みでした。
- Legalize パスを活用できるようになり、コンパイルが大幅に簡素化・改善されました。
具体的な挙動変化
- アレイとスカラ: 以前はターゲットのアンデアン性(Big/Little Endian)に影響していましたが、新しいセマンティクスでは エンディアン不可知 で動作します(Little Endian の旧動作に整合)。
- 奇妙な変換の実現: 例として
(6bit) →[2]u3
(6bit) の変換が可能になります。@Vector(3, u2)
test "bitcast [2]u3 to @Vector(3, u2)" { const arr: [2]u3 = .{ 0b001, 0b011 }; const vec: @Vector(3, u2) = @bitCast(arr); // ビットを順次連結し、ブロックに切り取る処理が発生 try expect(vec[0] == 0b01); try expect(vec[1] == 0b10); try expect(vec[2] == 0b01); }
- 補足: ポインターベクトルの
は禁止 (#18936) され、Enum への適用は一部許可されています (#35602)。@bitCast - これらの変更は Zig 0.17.0 リリースノートで正式に説明されます。
⚡ パフォーマンス向上
- 最適化効果: 非 ABI 整数型の降下方法の改善により、コンパイラ自体のパフォーマンスが約 5% 向上 しました。
- これにより 0.17.0 で runtime パフォーマンスの向上も期待できます。
📅 2026 年 5 月 30 日:ELF リンカーの改善
著者: Matthew Lugg
Zig 0.16.0 で debut した新しい ELF リンカーが大幅に強化されました。
🚀 マイルストーン達成
- LLVM および LLD ライブラリとの親和性: 新しいリンカーにより、LLVM を有効にしたセルフホスト Zig コンパイラのビルドが可能になりました。
# 新しいリンカーを用いたコンパイルの例 zig build -Dno-lib -Dnew-linker -Denable-llvm ./zig-out/bin/zig build-exe ~/hello.zig -fllvm -flld
⚡ 高速増分再ビルド (Incremental Rebuilds)
- 外部ライブラリ連携: C ソースコードや外部ライブラリを含め、増分再ビルドが可能になり(x86_64 Linux)、パフォーマンスオーバーヘッドはありません。
- ビルド時間:数秒から 数ミリ秒 へ短縮されました。
🔧 今後の課題と対応
- DWARF デバッグ情報: 現在まだ生成できませんが、これが次の優先事項です。
- 現状でも大量の debug プリンターを用いた状況での即応再ビルドは非常に有効です。
- バージョンについて:
にzig build
を使用可能です。0.17.0 リリースまでお待ちいただくか、最新マスタブランチで試すことを推奨します。-fincremental
📅 2026 年 5 月 26 日:ビルドシステムの再構築
著者: Andrew Kelley
maker プロセスと configurer プロセスを分離する大規模な変更です。ビルドシステム内部の再構築により、zig build の高速化を実現しました。
🏗️ 新しいアーキテクチャ
- configurer:
をデバッグモードで読み込み、メモリ上にビルドグラフを構築し、バイナリ構成ファイルへシリアライズします。build.zig - maker: 構成ファイルを認識し、キャッシュを活用してリリースモードでビルドを実行します。
📈 パフォーマンス改善 (ベンチマーク結果)
zig build --help の実行前後を比較:
| メトリック | 再構築前 (master) | 再構築後 (branch) | 改善率 |
|---|---|---|---|
| Wall Time | 150ms ± 5.52ms | 14.3ms ± 744us | ⚡ -90.4% |
| Peak RSS | 84.8MB ± 275KB | 78.5MB ± 562KB | -7.4% |
| CPU Cycles | 593M ± 4.01M | 24.1M ± 821K | ⚡ -95.9% |
⚠️ Breaking Change の注意点
- API 観点から一部の互換性が失われました。
が廃止され、代わりにrun_cmd.addArgs()
を使用する必要があります。run_cmd.addPassthruArgs()
- ビルドスクリプトからの機能削除により、ビルドシステムのキャッシュ化が可能になりました。
- 対応期間: 0.17.0 リリースまでの間、開発バージョンへの移行が推奨されます。不具合の場合は 0.17.1 で対応予定。
📅 2026 年 4 月 8 日:LLVM による増分コンパイル
著者: Matthew Lugg
LLVM コードジェネレーションバックエンドでの 増分コンパイル (Incremental Compilation) が正式に機能しました。
🚀 効果とメリット
- エラー時の即時フィードバック: コードが変更された際、実際の Zig コンパイラ部分で費やす時間を最小化し、LLVM の.EmitObject 時間の削減ではありません(これは LLVM に依存)。しかし、コンパイルエラーがある場合、LLVM 処理をスキップできるため 秒単位ではなくミリ秒単位 でエラーを検知できます。
- 利用可能: マスタブランチと直近のリリース (0.16.0) で利用可能です。
# 使用例 zig build -fincremental --watch
📊 安定性
- CI 内のすべての増分担テストカバレッジが有効化されています。
- ユーザーから良好なフィードバックを得ており、比較的安定しています。バグ発見時のレポート歓迎です。
📅 2026 年 3 月 10 日:タイプ解決の再設計と言語変更への味付け
著者: Matthew Lugg
約 3 週間かけて 30,000 ライン規模 の PR がマージされました。コンパイラの内部タイプ解決ロジックが大幅に再構築されました。
🆕 ユーザー向け改善点
- フィールドの非参照許容: タイプが名前空間としてのみ使用される場合(初期化されないフィールド)、コンパイルエラーになるのを防ぎました。
// 以前はエラーになったが、現在は動作する const Foo = struct { bad_field: @compileError("..."), const something = 123; // アクセス可能なフィールドのみ参照 }; - 依存ループのエラーメッセージ強化: 循環依存発生時のエラーメッセージが、どの場所で何が問題か詳しく報告します。
error: dependency loop with length 2 repro.zig:1:29: note: type 'repro.Foo' depends on type 'repro.Bar' for field declared here ... note: eliminate any one of these dependencies to break the loop
- 増分コンパイルの劇的改善: 「過度な解析」による無駄な処理が大幅に削減され、インクリメンタルビルドが非常に高速化されました。
- その他:数十件のバグ修正やニッチな言語変更も包含されています(詳細は Codeberg PR を参照)。
📅 2026 年 2 月 13 日:io_uring および Grand Central Dispatch の実装
著者: Andrew Kelley
std.Io.Evented の強化により、以下のような非同期 I/O 実装が加わりました。
- io_uring (Linux)
- Grand Central Dispatch (macOS)
⚠️ 注意:実験的機能
これらはまだ開発段階であり、以下の理由で実験的 (
experimental) と見なされます。
- より良いエラーハンドリングの追加が必要
- ログ出力の整理
- 予期せぬパフォーマンス劣化(IoMode.evented)の診断中
- 一部の関数未実装
- スタックサイズの最適調整が必要
💻 使用サンプル (Evented モード)
// Evented I/O の使用例 var evented: std.Io.Evented = undefined; try evented.init(gpa, .{ .argv0 = .init(init.args), .environ = init.environ, // ... }); const io = evented.io();
I/O 実装はシームレスに差し替え可能であり、標準ライブラリ内部での使用も完了しています。
📅 2026 年 2 月 6 日:パッケージ管理ワークフローの 2 つの改善
著者: Andrew Kelley
依存関係を持つプロジェクトにおける 2 つの大規模な変更が導入されました。
1. ローカルパッケージ保存 (zig-pkg
)
zig-pkg- 取得されたパッケージは、プロジェクトルート内の
ディレクトリにローカルに保存されます(zig-pkg/
で無視推奨)。.gitignore- メリット: オフラインでのビルドや、カスタマイズ(編集)が可能になります。
$ du -sh zig-pkg/* 13M freetype-2.14.1... 5.2M uucode-0.1.0...
2. グローバルキャッシュ強化
- パッケージは
に圧縮された形でグローバルにキャッシュされます。~/.cache/zig/p/- メリット: コンピュータ間でのキャッシュ共有が可能になり、将来的には P2P Torrent 形式の依存ツリーへの進化が期待されます。
$ du -sh ~/.cache/zig/p/* 4.0K opus-0.0.2...tar.gz 120K vaxis-0.5.1...tar.gz
🆕 --fork
フラグの追加
--fork- 機能: 特定のプロジェクトを
の一部として一時的にフォーク(オーバーライド)し、開発環境で使用できます。zig-pkg/- 用途: エコシステム破損時の修復や、独自のソースツリーを安全に検証する際などに有効です。
- 挙動: フラグを指定して利用開始 → 修正完了後 -> フラグを削除すると自動的に正規の依存ツリーに戻ります。
# エコシステム破損時の上書き使用例 zig build --fork=/home/andy/dev/mime
📅 2026 年 2 月 3 日:Win32 API から Native API (NT) への移行推進
著者: Andrew Kelley
Windows 上では、
kernel32.dll のラッパー関数よりも、より直接的で軽量な ntdll.dll などのネイティブ API を優先する方針が強化されています。
🛠️ 具体的な改善例
1. ランダム数生成 (SystemFunction036
→ 直接 NtAPI)
SystemFunction036- 以前:
が動的に読み込まれ、ヒープ割り当てや予期せぬ失敗(エラー 38)が発生していました。bcryptprimitives.dll - 現在:
を直接開き、AES ベースの CSPRNG を初期化して、不必要な DLL ロードを回避しました。"\\Device\\CNG"
2. ファイル I/O (ReadFile
→ NtReadFile
)
ReadFileNtReadFile- 以前: ステータスコードを隠した
戻り値や、エラー取得に別途BOOL
の呼び出しが必要でした。GetLastError - 現在: エラーコードを直接返す
を返し、APC ルーチンによる非同期キャンセルもネイティブに対応できます。NTSTATUS
詳細: Issue "Windows: Prefer the Native API over Win32" をご参照ください。
📅 2026 年 1 月 31 日:zig libc との統合
著者: Andrew Kelley
C libc の関数を Zig スタンダードライブラリラッパーとして提供する
zig libc サブプロジェクトが、Zig コアに統合されました。
🔄 アーキテクチャ変化
- 以前: C ソースファイルが Zig リポジトリ内に多数存在(約 250 ファイル)。
- 現在: これらのファイルは削除され、ZCU (Zig Compilation Unit) と共有するようになりました。
- LTO(リンクタイム最適化)境界を越えた共通のコード复用が可能になりました。
,memcpy
など、多くの関数が標準ライブラリ内ですべて Zig で記述されます。atan2
🚀 メリット
- 独立: サードパーティプロジェクトからの依存関係削減。
- 最適化: コンパイル速度向上、インストールサイズ縮小、静的リンクアプリケーションのバイナリサイズ削減。
- I/O 制御:
と組み合わせることで、io_uring や GCD などへのシームレスな統合が可能になります。std.Io
📢 ビューレポートについて
Zig は現在静的 libc プロバイダとしての役割を担っているため、musl/mingw-w64/wasi-libc に関連する問題が発生した場合は、まず Zig のバグレポートとして提出してください。これによりメンテナンスを負担をかけず、問題解決に寄与します。
2026 年の Zig メインブランチでは、コンパイラ内部の最適化、SPIR-V/GLSL のサポート強化、Windows ネイティブ API への移行、そして開発ワークフロー(ビルド/パッキング)の劇的改善など、幅広い進化が進められています。Happy hacking!