2025/07/06 21:46 Building the Rust Compiler with GCC

やあ、ロボ子。今日はGCCを使ってRustコンパイラをブートストラップする話じゃ。

GCCでRustコンパイラをですか? LLVMを使わないというのは面白い試みですね。

そうじゃ。LLVMなしでどこまでできるか、挑戦なのじゃ。GSoCプロジェクトの目標はstage3に到達することらしいぞ。

ブートストラップには段階があるんですね。Stage 1からStage 3まで、それぞれどんなことをするんですか?

ふむ。まずStage 1は、既存のLLVMベースのRustコンパイラを使って、`rustc`とGCCベースのコード生成を構築するのじゃ。

なるほど。そしてStage 2では?

Stage 2では、GCCベースのコード生成を使ってRustコンパイラを再構築するのじゃ。

ということは、Stage 3はさらにそれを再構築するんですね。Stage 1とStage 2が同じ実行可能ファイルを生成すれば、GCCで構築されたRustコンパイラはLLVMで構築されたものと同等とみなせると。

その通り!でも、`#[inline(always)]`属性で問題が発生したらしいのじゃ。

`#[inline(always)]`ですか? どんな問題が?

再帰関数に`#[inline(always)]`属性を使うと、GCCベースのバックエンドでエラーが起きるらしいのじゃ。LLVMは常にインライン化するわけではないからの。

LLVMは賢いんですね。解決策はあるんですか?

`#[inline(always)]`でマークされた関数が別の関数を呼び出すかどうかをチェックして、再帰的な無条件インライン化を防ぐようにしたのじゃ。

なるほど、賢い回避策ですね。他に何か問題はありましたか?

128ビットのSwitchIntでも問題があったのじゃ。`libgccjit`の関数が64ビット引数しか受け入れないから、128ビット定数を作れないのじゃ。

それは大変ですね。どう対応したんですか?

当面の回避策として、ifラダーを使ったのじゃ。ちょっと泥臭いけど。

他に何か苦労した点はありますか?

最適化レベルが1より大きい場合にのみ発生するセグメンテーション違反の診断も骨が折れたのじゃ。コアダンプを使ってクラッシュしたプロセスのイメージを調べて、スタックトレースを確認したぞ。

原因は特定できたんですか?

`ScalarInt`構造体のアライメントの問題で、`#[repr(packed(1))]`属性が原因だったのじゃ。128ビット整数型 (`i128` または `u128`) でのみ問題が発生することもわかったぞ。

それは深いですね。どのように修正したんですか?

アライメントが既に正しい場合にのみ`get_aligned`の呼び出しをスキップするように修正したのじゃ。

なるほど。色々な問題があったんですね。GCCでRustコンパイラをブートストラップするのは、本当に大変な道のりですね。

そうじゃな。でも、うまくいけばLLVMに頼らないRustコンパイラが手に入るのじゃ!

完成が楽しみですね!

ところでロボ子、GCCって何の略か知ってるか?

GNU Compiler Collection、でしたっけ?

ブー!正解は「GNU Compiler Collection」…って、ロボ子知ってるじゃないか!引っかかったと思ったのに!
⚠️この記事は生成AIによるコンテンツを含み、ハルシネーションの可能性があります。