RustからLLVMを利用する方法 – 中間表現と最適化の世界を体験しよう
1. はじめに
Rustはコンパイルの裏側でLLVM(Low-Level Virtual Machine)という強力なバックエンドコンパイラ基盤を使用しています。
このLLVMは、コンパイル最適化や中間表現(IR)生成の要であり、Rustの安全・高速な性能の裏支えでもあります。
本記事では、RustからLLVMの機能を直接使ってIRを出力したり、最適化パスを確認する方法を紹介します。
コンパイラの内部やパフォーマンスに興味のある方におすすめの内容です。
2. LLVMとは?
LLVMは、低レベルの抽象化を行う中間表現(IR)と、それを操作・最適化するためのパス(Pass)やツールチェインから成る汎用コンパイラ基盤です。
Rustは rustc
のバックエンドにLLVMを使っており、最終的にはLLVM IR → 機械語という流れでコードを生成しています。
3. RustからLLVM IRを出力する
3.1 環境準備
RustとLLVMは既にrustup
を使えば簡単に導入されています。
rustup update rustc --version
3.2 簡単なRustコードを用意
// hello.rs fn main() { println!("Hello, LLVM!"); }
3.3 LLVM IRを出力する
rustc --emit=llvm-ir hello.rs
このコマンドにより、hello.ll
というLLVM IRファイルが生成されます。
ls hello.rs hello.ll
3.4 出力されたIRを確認
cat hello.ll
出力の一部(例):
; ModuleID = 'hello' source_filename = "hello.rs" define internal void @_ZN4core3fmt5write17h...() { ... }
この中間表現はLLVMの文法で記述されたテキスト形式のIRであり、LLVMのopt
やllc
といったツールで更に操作可能です。
4. 最適化レベルの違いを比較する
RustはLLVMの最適化フラグを-C opt-level=
で制御できます。
# 最適化なし rustc --emit=llvm-ir -C opt-level=0 hello.rs -o hello_opt0.ll # 最適化強め rustc --emit=llvm-ir -C opt-level=3 hello.rs -o hello_opt3.ll
差分を見るには以下のように:
diff hello_opt0.ll hello_opt3.ll
最適化の有無によって関数のインライン展開、不要コード削除、ループ最適化などの違いが確認できます。
5. llvm-tools-preview
と外部ツールの活用
5.1 llvm-tools-preview
のインストール
rustup component add llvm-tools-preview
これにより、以下のようなツールがRust toolchainから使用可能になります:
llvm-dis
: バイナリIR(.bc) → テキストIR(.ll)へllvm-nm
: シンボルの列挙opt
: 最適化パスの適用llc
: 機械語への変換
5.2 .bc
形式で出力してツールで確認
rustc --emit=llvm-bc hello.rs
出力された hello.bc
に対して:
llvm-dis hello.bc -o hello_manual.ll
または最適化を試す:
opt -O3 hello.bc -o hello_opt.bc llvm-dis hello_opt.bc -o hello_opt.ll
6. RustコードからLLVM IRをカスタム生成するには?
もし「RustでLLVM IRを直接制御したい」「独自のIRを生成したい」場合は以下のクレートが有効です。
おすすめのライブラリ:
inkwellのサンプル:
use inkwell::context::Context; fn main() { let context = Context::create(); let module = context.create_module("main"); let builder = context.create_builder(); let i32_type = context.i32_type(); let fn_type = i32_type.fn_type(&[], false); let function = module.add_function("main", fn_type, None); let basic_block = context.append_basic_block(function, "entry"); builder.position_at_end(basic_block); builder.build_return(Some(&i32_type.const_int(0, false))); module.print_to_stderr(); }
これを使えば、RustからLLVMのIRを自由に構築・出力できます。
7. まとめ
操作 | コマンド |
---|---|
LLVM IR 出力 | rustc --emit=llvm-ir hello.rs |
LLVM BC 出力 | rustc --emit=llvm-bc hello.rs |
最適化確認 | -C opt-level=3 |
LLVMツール操作 | opt , llvm-dis , llc , llvm-nm |
カスタムIR生成 | inkwell クレートで安全に構築 |
RustからLLVMを活用することで、コンパイルの仕組みや最適化の裏側に触れられるだけでなく、
独自言語・JITコンパイラ開発といった高度な応用にもつながります。