LLVMとの離婚申請
(github.com/ziglang)- Zigプロジェクトは、メインのzig実行ファイルからLLVM、Clang、LLDライブラリへの依存を完全に取り除くことを目標としている
- 残っている作業は、LLDの削除、LLVM API呼び出しの削除、C/x86/wasm/aarch64バックエンドの進展、Clang依存のサブコマンドとプリプロセッサ使用の削除、
zig arの代替実装などに分かれる - LLVMバックエンドはすでに
.bcファイルを出力できるが、Zigコンパイラは.bcをオブジェクトファイルへコンパイルする機能を持たなくなり、この用途ではClangの別途インストールが必要になる - 期待される効果として、ソースビルドとブートストラップの簡素化、LinuxディストリビューションやHomebrewにおけるLLVM/Clang/LLD関連の問題回避、バイナリサイズの約150 MiB → 5 MiBへの削減が挙げられている
- Zigが独自の最適化パスを実装し、alive2のような研究プロジェクトやIntel、ARM、RISC-Vのチップメーカーからの直接的な貢献を呼び込めるという方向性を打ち出している
Zig実行ファイルから取り除こうとしている依存関係
- このイシューの目標は、ZigプロジェクトからLLVM、Clang、LLDライブラリを完全に取り除くこと
- 残っている接続点は、LLD、LLVM、Clang、
zig arの領域に整理される
LLD関連の残作業
- completely eliminate dependency on LLD #8726: LLD依存を完全に取り除く作業が残っている
LLVM関連の残作業
- LLVMの領域には、LLVM bitcode出力、バックエンドのテスト通過率、LLVM API削除作業が含まれる
- directly output LLVM bitcode rather than using LLVM's IRBuilder API #13265: LLVMのIRBuilder APIの代わりにLLVM bitcodeを直接出力する作業
- Cバックエンドは1742/1792テスト通過、通過率97%の状態
- enable the x86 backend by default for debug builds on x86_64-linux #22257: x86_64-linuxのデバッグビルドでx86バックエンドをデフォルトで有効化する作業
- wasmバックエンドは1611/1765テスト通過、通過率91%の状態
- 100% behavior tests passing for the aarch64 backend #21172: aarch64バックエンドのbehavior testを100%通過させる作業
- ability to create import libs from def files without LLVM #17807: LLVMなしでdefファイルからimport libsを作成する機能
- Avoid LLVM API for setting a module's code model and PIC/PIE levels #21238: モジュールのcode modelとPIC/PIEレベル設定でLLVM APIの使用を避ける作業
- completely eliminate dependency on LLVM library API calls #25492: LLVMライブラリAPI呼び出しへの依存を完全に取り除く作業
Clang関連の残作業
- ZigリポジトリのC++ソースファイルは、ブートストラップ時にclangでビルドされている
- src/windows_sdk.cpp: port to Zig #15657:
src/windows_sdk.cppをZigへ移植する作業
- src/windows_sdk.cpp: port to Zig #15657:
zig cc,zig c++,zig translate-cand other subcommands without a clang/llvm dependency in the compiler binary #20875: コンパイラバイナリ内のclang/llvm依存なしでzig cc、zig c++、zig translate-cおよびその他のサブコマンドを提供する作業- make resinator use aro's preprocessor instead of clang #17752: resinatorがclangの代わりにaroのプリプロセッサを使うようにする作業
- make mingw .def.in file parsing use aro's preprocessor instead of clang #17753: mingwの
.def.inファイル解析でclangの代わりにaroのプリプロセッサを使うようにする作業 - move
@cImportto the build system #20630:@cImportをビルドシステムへ移す作業
zig arと.bcファイル処理の制約
- zig ar: a drop-in llvm-ar replacement #9828:
zig arをllvm-arの代替品にする作業が残っている - LLVMバックエンドはすでに
.bcファイルを出力できるが、Zigコンパイラは.bcファイルをオブジェクトファイルへコンパイルする機能を持たなくなる - このユースケースに対応するには、Clangを別途インストールする必要がある
依存関係の削除で期待される変化
- Zig側のバグがすべてZigプロジェクトの責任範囲に収まる
- コンパイラをソースからビルドしてブートストラップする過程が簡素化され、ホストシステムにはCコンパイラだけあればよくなる
- LinuxディストリビューションやHomebrewのようなパッケージマネージャが、LLVM、Clang、LLDに関連して生じていた問題を扱わなくてよくなる
- Zigコンパイラのバイナリサイズが約150 MiBから5 MiBへ縮小する
- コンパイル速度が桁違いに速くなる可能性がある
- Zigが独自の最適化パスを実装し、コンピューティングの最先端を押し上げられる
- alive2のような研究プロジェクトを呼び込める
- Intel、ARM、RISC-Vのチップメーカーのように、自社CPUでより良いマシンコードを望む利害関係者からの直接的な貢献を促せる
2件のコメント
LLVM ほどの最適化やプラットフォーム対応は可能なのでしょうか..
Hacker Newsのコメント
Andrewはもともと非常に鋭い人物なので、目標として掲げられた以上、チームは最終的にやり遂げそうだと感じる
ただ、LLVMまわりでZigが抱えている難しさをよく知らない立場から見ると、この決定はチームの力をZig本体ではなく、binutilsのような周辺ツールへ振り向けるようにも見える
タイトルだけ見たときはコンパイラを捨てるのかと思ったし、ZigのようなプロジェクトならLLVMを維持して得られるものも多そうに思える
それでも、LLVM内の多くのコードをC++の代わりにZigで書き直す構想はかなりクールで野心的だ。LLVMを作ったLattnerの試みに匹敵するほど野心的だとも言える
ただし、偶然に二次時間計算量になってしまうコードは、ZigもLLVMと同じくらい人気で有用になれば避けにくいだろう
「宇宙ミッションが既存の打ち上げ機を再利用しないなら、そのプロジェクトは打ち上げ機開発プロジェクトとなり、ミッションの中核だと思っていた残りの部分はすべて副次的な仕事になる」という趣旨だった
さらに覚えているのは、「既存の打ち上げ機に合わせて妥協する代わりに、特定のミッション向けの打ち上げ機を作ればもっと安く効率的になると考えるかもしれないが」という前提が添えられていたことだ
Rustの成功の一部もC/C++との似た互換性の上に成り立っている
Zigが同様の能力なしに成功するのは想像しにくく、だからこのマイルストーンをそのまま押し進めないでほしい
GCCがAppleの望むこと、あるいは必要としていたことを許可または実装しようとしなかったからだ
TCCのようにもっと絞り込めば、大半は複数アーキテクチャ向けのコード生成になるはずだ
ここには二つの問題がある。一つはコード生成で、もう一つはブートストラップだ
経験上、コンパイラの最適化パスは書きやすくて楽しい。レジスタ割り当てやSSA形式を理解するには論文を読む必要があるが、IRをさまざまな最適化パスに流して徐々に磨いていくコードは楽しく書ける
LLVMなしでも高品質な最適化パスは作れる。しかしIRを機械語へ線形化する段階は、「
mov [eax+8*ebx], 123」命令をx86-32/64がエンコードするあらゆる方法が好きでもない限り、退屈で地味な作業だバイナリサイズを最適化するなら、あるプラットフォームで「
push eax; push eax; push eax」が「add rsp,12」より短いか測りたいだろうか? これはx86だけの話で、ほとんどの開発者には重要でない非x86アーキテクチャまで掛け合わせると、話ははるかに大きくなるあまり使われないアーキテクチャのコード生成器では、大きなバグが何年も見つからない可能性も非常に高い
二つ目はブートストラップだ。Zigで書かれたZigコンパイラを何でコンパイルするのか? たとえばCで書いた非最適化の最小ZigコンパイラでZigコンパイラをコンパイルすることはできる
しかし非最適化なら、その後でもう一度、最適化されたZigコンパイラでZigコンパイラを再コンパイルしなければならない。解けない問題ではないが、長く複雑なビルド過程は潜在的な貢献者を遠ざける危険がある
ZigがC、ひょっとするとC++までコンパイルできるとあれだけ宣伝しておいて、今度はLLVMを完全に外すというのはかなり過激に見える
よほど多くの人がサポートに参加しない限り、LLVMレベルのプラットフォーム対応に近づける可能性も非常に低そうだ
望む人向けに独自バックエンドを追加する計画は理解できるが、LLVMをそのまま取り除くのは性急に見える
今はチームがフィードバックを集め、影響を受けるユースケースを学び、実現可能性を見極めている段階なので、性急というよりはむしろその反対に近いと思う
一般的なケースでは必要ですらない100MB超のLLVMコピーをバンドルしなければならないのは少し奇妙なので、理にかなっている。開発者ならどうせインストール済みのことも多いだろう
ただし、インストールされたZigがシステムのLLVMバージョンと正しく動作すると保証するのは難しいかもしれない。様子を見る必要がある
https://github.com/ziglang/zig/issues/13265
最近Zigをもう少し読んで、システムパッケージと格闘せずにLLVMでC++を簡単にコンパイルする手段としても試してみた。C/C++からZigへ移れるという点が大きなセールスポイントだった
かなり唐突で予想外だ。プロジェクトにとって合っているのか間違っているのかは分からないが、私の立場からすると本当に脈絡なく感じる
一方で、依存関係を減らそうとする几帳面な姿勢には敬意を払うが、その代償はかなり深刻に見える
C++互換性の喪失は、私の周囲のZigファンが最もよく挙げていた利点を事実上なくすことになる
性能低下も、一時的だとしても、彼らがあわせて挙げていたもう一つの重要点だ
軽く読んでいる人向けに言うと、これは決定事項ではなく提案だ
約4年間、組み込みプロジェクトとライブラリをすべてZigで書いてきたのに、今後は複数のtier 1対応アーキテクチャが単に外されるということか?
言語はあちらのものなので好きにすればいいが、そうするならブランディングもそれに合わせて調整してほしい
おそらくtier 1対応は2つのカテゴリに分かれることになる。内蔵のtier 1対応と、オプションのLLVMバックエンドによるtier 1対応だ
すでにあるアーキテクチャがtier 1対応なら、LLVMバックエンドをオプション依存に変えたからといってその対応が失われる理由はないように見える
Andrewが提案で書いていたように、このやり方はむしろより珍しいアーキテクチャをうまくサポートする道になるかもしれない。面白いプロセッサアーキテクチャ向けのZigバックエンドなら喜んで取り組むが、LLVMには絶対に貢献しない。C++で作業するのは趣味でやるようなことではない
その利点は何だ? 資源の浪費ではないのか?
DLangにはコンパイラが3つある
gdcはGnuコンパイラコレクションのバックエンドベースで、ldcはLLVMバックエンドベース、dmdは私がZortech/Symantec/Digital Mars向けに書いたx86コードジェネレータベースだ
それぞれ長所・短所と対象が異なるが、対応しているD言語は同じだ
全体としてユーザーは選択肢を好み、中には2つ以上を併用する人もいる
それが正しいなら、Zigのアプローチのほうが好みだ
そのおかげで開発中は最速のコンパイラを使い、最終リリースでは最速のランタイムや最小のメモリ使用量を持つコンパイラを使えるので非常に便利だ
また、すべてのコンパイラが従う言語仕様があれば、言語が安定していて下の層で突然壊れないという保証にもなる
もちろん、Zigのようにまだ好きなように変更して、言語をより一貫性があり、きれいで、強力にできる言語にも利点はある。最近はこうした安定性をずっと高く評価するようになった。開発ツールを追いかけ続ける代わりに、ユーザーに実質的な価値を生むことに集中できるからだ
Zigが面白かった主な理由の1つは、C/C++コンパイラの代替としてそのまま差し込めたことだった
Windowsでは、他のどんな代替よりもZigをC/C++コンパイラとしてインストールしやすいと友人たちは言っていた
この提案が受け入れられたら、個人的にはZigの人気はHareや他の極端にニッチな言語並みに落ちると思う
同僚にZigを一度でも試してもらうには、Uberが本番環境で使っているという記事まで送らなければならなかった。既存プロジェクトに即時の価値がなければ、同僚たちは二度考えもしなかっただろう
それでも提案の背景は理解できる。LLVMのコンパイル時間はひどく感じられることがあるし、独自のバイトコードがあれば面白い最適化手法も実装できる。LLVMのバグを扱うのは実質的に手を出しにくい作業で、Juliaエコシステムでもそういうことを見てきた
私の提案に意味があるなら、Zigは1) デバッグビルドでは高速ビルドと高速デバッグのためにカスタムバイトコードを使い、2) リリースビルドでは高速なランタイム性能のためにLLVMを使うのがよいと思う
C/C++クロスコンパイル対応を維持しつつ1)を実現できるなら、たとえばその部分だけLLVMに渡すなら、追加のバックエンドコードを保守しなければならないというトレードオフはあるが、最良の折衷案かもしれない
高水準のJuliaコンパイラ作業とは別のスキルが必要で、バグ修正をアップストリームにマージするのに時間がかかることもある
だが実際には、我々はアップストリームとかなり良好で生産的な関係を維持しており、LLVMをなくすと決めていたら、プロジェクトで達成できたことはずっと少なかっただろう
特にGPU対応やHPC対応、たとえばPPCはLLVMに依存している
なので我々は、Juliaを自分たちのパッチセット/フォークに合わせてビルドすべきだという立場を取り、そのパッチを使っていないJuliaビルドで発生したバグには時間を割かない。特にディストリビューションのビルドでよく起きる
他の言語の非LLVMバックエンド開発を見てきた立場からすると、リンク先の提案からは傲慢さが強く感じられる
書いたのがあの人でなければ、Zig初心者が適当に書いたGitHub issueだと思って流していたはずだ
必要な作業量を過小評価し、LLVMに注がれてきたすべての作業を暗に見下しつつ、「当然うちならもっと安く、速く、良くできる」という自信とマッチョさが文章の端々からにじんでいる。失望した
これまでAndrewの仕事は本当に尊敬してきたので、急いで、あるいは即興で書いたせいでそう読めてしまうことに気づかなかったのだと善意に解釈したい
しかしこの文章は信頼を与えず、提案そのものをもっと開かれた気持ちで見る助けにもならない
Webpackとesbuildがその例だ
LLVMなしで何かを作る適切なタイミングは数年前だった。だが今C++機能を外せば、Zigの終わりになる可能性が高い
段階的に削る代わりに、Zigで独自のC++コンパイラを書く計画を発表しなかったのは驚きだ
18歳の誕生日に始めた個人がC++コンパイラを書けるのかすら確信がない。動くコンパイラを作るだけの残りの人生の時間が十分にあるかどうかも分からない
Zigは世界の新しいCになりたいのであって、世界の新しいC++になりたいわけではあまりない
この提案でも Cクロスコンパイル は引き続きサポートされることが見て取れる
この選択は正しいかもしれない。Cは現在も組み込みの世界で広く使われており、その領域ではLLVMはあまり優れていない
私がZigなら、あらゆるマイクロコントローラを対象にしたいと思うだろうし、それを達成する現実的な道はこれしかない