LLVM
LLVMハンドブック
編集はじめに
編集LLVMとは
編集LLVMは、コンパイラを開発するためのモジュール化されたフレームワークであり、再利用可能なコンパイラおよびツールチェーンコンポーネントのセットです。LLVMは、最適化、コード生成、リンカなど、コンパイルプロセスの多くの段階で使用されます。
LLVMの歴史と開発コミュニティ
編集LLVMは2000年代初頭にクリス・ラットナーによって設立されました。その後、Apple、Google、Facebookなどの主要企業がLLVMを採用し、開発を支援しています。LLVMプロジェクトはオープンソースであり、世界中の開発者が貢献しています。
かつてBSD系UNIX(FreeBSDやNetBSDなど)では、GCCやbinutilsがコンパイラツールチェインとして使用されていましたが、2000年代に相次いでLLVM/Clangに移行しました。
LLVMプロジェクトの全体構成
編集LLVMプロジェクトは、以下の多くのサブプロジェクトで構成されています。
- LLVMコアライブラリ
- Clangと周辺ツール
- compiler-rt
- Polly
- libFuzzer
- LLDB
- LLD (Linker)
- libc++
- OpenMP
- libclc
- libunwind
- MLIR
- BOLT
- Flang
- WebAssemblyサポート
- LLVM libc
各サブプロジェクトについては、後続の章で概要を説明し、詳細は専用のハンドブックを参照してください。
LLVMメインプロジェクト
編集LLVMコアライブラリ
編集LLVMコアライブラリは、コンパイラのフロントエンドからバックエンドまで、すべての段階で使用される基本的なライブラリです。
インストールとビルド
編集LLVMのインストールとビルドは、以下のコマンドで行います。
git clone --depth=1 -b llvmorg-18.1.6 https://github.com/llvm/llvm-project.git cd llvm-project/ cmake -S . -B build/ -DLLVM_ENABLE_PROJECTS="llvm" -DCMAKE_BUILD_TYPE=Release llvm cmake --build build/
基本的な使い方
編集LLVMは、様々なツール(clang
、opt
、llc
など)を提供しています。例えば、C言語のソースコードをコンパイルしてLLVM IRに変換するには、以下のようにします。
clang -S -emit-llvm hello.c -o hello.ll
中間表現(IR)
編集LLVM IRは、LLVMコンパイラフレームワークの中心であり、フロントエンドとバックエンドの間でコードを表現するための形式です。
最適化パス
編集LLVMは、多くの最適化パスを提供しており、これを使用してコードを最適化できます。最適化パスの例として、デッドコード除去やループ最適化があります。
進んだ使い方とカスタマイズ
編集LLVMは、高度にカスタマイズ可能であり、独自の最適化パスやコード生成器を追加することができます。
Clangと周辺ツール
編集Clangの概要
編集Clangは、C、C++、Objective-C、Objective-C++用のLLVMベースのフロントエンドです。高速でモジュール化されており、他のツールやIDEと容易に統合できます。
インストールとビルド
編集Clangのインストールとビルドは、LLVMのビルドと一緒に行われます。
cd llvm-project/ cmake -S . -B build/ -DLLVM_ENABLE_PROJECTS="clang;clang-tools-extra" llvm cmake --build build/
基本的な使い方
編集Clangを使用してC++プログラムをコンパイルするには、以下のようにします。
clang++ hello.cpp -o hello
コンパイルオプションとフラグ
編集Clangは、多くのコンパイルオプションを提供しており、最適化レベルの指定や警告の制御が可能です。
clang++ -march=native -Oz -Weverything -std=c++23 -use-ld=lld hello.cpp -o hello
静的解析ツール
編集Clangには、静的解析ツールが組み込まれており、コードの品質を向上させるために使用できます。
進んだ使い方とカスタマイズ
編集Clangは、プラグインを通じて機能を拡張することができます。また、AST(抽象構文木)を直接操作することも可能です。
compiler-rt
編集compiler-rtの概要
編集compiler-rtは、LLVMとClangに依存するランタイムライブラリ群です。主にサニタイザやプロファイリングツールとして使用されます。
インストールとビルド
編集compiler-rtのインストールとビルドは、LLVMとClangのビルドと一緒に行われます。
cd llvm-project/ cmake -S . -B build/ -DLLVM_ENABLE_PROJECTS="clang;compiler-rt" llvm cmake --build build/
サニタイザ(AddressSanitizer, ThreadSanitizer, UndefinedBehaviorSanitizerなど)
編集compiler-rtには、様々なサニタイザが含まれており、メモリエラーやデータ競合などを検出することができます。
clang -fsanitize=address example.c -o example ./example
プロファイリングツール
編集compiler-rtには、プロファイリングツールも含まれており、パフォーマンスのボトルネックを特定するのに役立ちます。
進んだ使い方とカスタマイズ
編集compiler-rtの機能をカスタマイズすることで、特定のニーズに応じたエラー検出やプロファイリングが可能です。
Polly
編集Pollyの概要
編集Pollyは、LLVMのループ最適化ツールです。ループの並列化やタイル化を行うことで、プログラムの実行速度を向上させます。
インストールとビルド
編集Pollyのインストールとビルドは、LLVMのビルドと一緒に行われます。
cd llvm-project/ cmake -S . -B build/ -DLLVM_ENABLE_PROJECTS="clang;polly" llvm cmake --build build/
基本的な使い方
編集Pollyを使用してコードを最適化するには、clang
の-mllvm
および-polly
オプションを使用します。
clang -O3 -mllvm -polly example.c -o example
ループ最適化
編集Pollyは、ループの依存関係を解析し、並列化やタイル化を行います。これにより、プログラムの実行速度を大幅に向上させることができます。
進んだ使い方とカスタマイズ
編集Pollyの機能をカスタマイズすることで、特定のループ最適化手法を適用することが可能です。
libFuzzer
編集libFuzzerの概要
編集libFuzzerは、LLVMプロジェクトの一部であり、ライブラリ内のバグを検出するためのファジングツールです。入力をランダムに生成し、テスト対象の関数に与えて異常動作を引き起こすことで、バグを発見します。
インストールとビルド
編集libFuzzerのインストールとビルドは、LLVMのビルドと一緒に行われます。
cd llvm-project/ cmake -S . -B build/ -DLLVM_ENABLE_PROJECTS="clang;compiler-rt" llvm cmake --build build/
基本的な使い方
編集libFuzzerを使用するには、ファジング対象の関数を定義し、libFuzzerのAPIを使用してファズテストを実行します。
#include <stdint.h> #include <stddef.h> extern "C" int LLVMFuzzerTestOneInput(const uint8_t *Data, size_t Size) { // ファジング対象のコード return 0; }
コンパイルと実行は以下の通りです。
clang++ -fsanitize=fuzzer example.cpp -o example ./example
進んだ使い方とカスタマイズ
編集libFuzzerは、カスタムの入力生成器やターゲット関数のインストルメンテーションをサポートしており、特定のニーズに合わせてカスタマイズ可能です。
LLDB
編集LLDBの概要
編集LLDBは、LLVMプロジェクトのデバッガであり、高速でモジュール化されたデバッグツールです。C、C++、Objective-Cなどの言語をサポートしています。
インストールとビルド
編集LLDBのインストールとビルドは、LLVMのビルドと一緒に行われます。
cd llvm-project/ cmake -S . -B build/ -DLLVM_ENABLE_PROJECTS="clang;lldb" llvm cmake --build build/
基本的な使い方
編集LLDBを使用してプログラムをデバッグするには、以下のコマンドを使用します。
lldb ./example (lldb) target create "./example" (lldb) run
デバッグテクニック
編集LLDBは、ブレークポイント設定、ステップ実行、変数の検査など、多くのデバッグ機能を提供します。
(lldb) breakpoint set --name main (lldb) step (lldb) print variable_name
進んだ使い方とカスタマイズ
編集LLDBはスクリプトを使用してカスタマイズ可能であり、Pythonスクリプティングをサポートしています。
LLD (Linker)
編集LLDの概要
編集LLDは、LLVMプロジェクトのリンカであり、高速かつ柔軟性に富んだリンキングツールです。ELF、COFF、Mach-Oなど、様々なフォーマットをサポートしています。
インストールとビルド
編集LLDのインストールとビルドは、LLVMのビルドと一緒に行われます。
cd llvm-project/ cmake -S . -B build/ -DLLVM_ENABLE_PROJECTS="clang;lld" llvm cmake --build build/
基本的な使い方
編集LLDを使用してプログラムをリンキングするには、以下のコマンドを使用します。
clang++ -fuse-ld=lld example.o -o example
進んだ使い方とカスタマイズ
編集LLDは、多くのリンキングオプションを提供しており、特定のリンキングシナリオに応じてカスタマイズ可能です。
libc++
編集libc++の概要
編集libc++は、LLVMプロジェクトの一部である標準C++ライブラリです。最新のC++標準に準拠しており、高いパフォーマンスと互換性を提供します。
インストールとビルド
編集libc++のインストールとビルドは、LLVMのビルドと一緒に行われます。
cd llvm-project/ cmake -S . -B build/ -DLLVM_ENABLE_PROJECTS="libcxx;libcxxabi" llvm cmake --build build/
基本的な使い方
編集libc++を使用するには、コンパイル時に指定します。
clang++ -stdlib=libc++ example.cpp -o example
進んだ使い方とカスタマイズ
編集libc++は、高度にカスタマイズ可能であり、独自のアロケータやスレッド管理機能を実装することができます。
OpenMP
編集OpenMPの概要
編集OpenMPは、マルチプラットフォームの並列プログラミングAPIであり、C、C++、Fortranで使用されます。LLVMは、OpenMPのコンパイラサポートを提供しています。
インストールとビルド
編集OpenMPのインストールとビルドは、LLVMのビルドと一緒に行われます。
cd llvm-project/ cmake -S . -B build/ -DLLVM_ENABLE_PROJECTS="clang;openmp" llvm cmake --build build/
基本的な使い方
編集OpenMPを使用して並列プログラムを作成するには、以下のディレクティブを使用します。
#include <omp.h> auto main() -> int { #pragma omp parallel { // 並列化されたコード } return 0; }
コンパイルは以下の通りです。
clang++ -fopenmp example.cpp -o example
進んだ使い方とカスタマイズ
編集OpenMPの高度な機能には、タスク並列性、データ指向の並列性、およびネストされた並列性が含まれます。
libclc
編集libclcの概要
編集libclcは、オープンソースのOpenCL実装であり、LLVMバックエンドを使用してOpenCLカーネルをコンパイルします。
インストールとビルド
編集libclcのインストールとビルドは、以下の手順で行います。
git clone --depth=1 -b llvmorg-18.1.6 https://github.com/llvm/llvm-project.git cd llvm-project/ cmake -S . -B build/ -DLLVM_ENABLE_PROJECTS="libclc" llvm cmake --build build/
基本的な使い方
編集libclcを使用してOpenCLカーネルをコンパイルするには、Clangを使用します。
clang -x cl -cl-std=CL1.2 example.cl -o example.bc
進んだ使い方とカスタマイズ
編集libclcは、特定のデバイス向けのカスタムビルトイン関数を追加するなど、カスタマイズが可能です。
libunwind
編集libunwindの概要
編集libunwindは、スタックトレースを取得し、例外処理のためにコールスタックを巻き戻すためのライブラリです。
インストールとビルド
編集libunwindのインストールとビルドは、LLVMのビルドと一緒に行われます。
cd llvm-project/ cmake -S . -B build/ -DLLVM_ENABLE_PROJECTS="libunwind" llvm cmake --build build/
基本的な使い方
編集libunwindを使用してスタックトレースを取得するには、以下のコードを使用します。
#include <libunwind.h> auto printStackTrace() -> void { unw_cursor_t cursor; unw_context_t context; unw_getcontext(&context); unw_init_local(&cursor, &context); while (unw_step(&cursor) > 0) { unw_word_t offset, pc; unw_get_reg(&cursor, UNW_REG_IP, &pc); printf("0x%lx\n", pc); } }
進んだ使い方とカスタマイズ
編集libunwindは、特定のプラットフォームやアーキテクチャに応じてカスタマイズが可能です。
MLIR
編集MLIRの概要
編集MLIR(Multi-Level Intermediate Representation)は、LLVMプロジェクトの一部であり、ドメイン固有の中間表現を構築するためのフレームワークです。
インストールとビルド
編集MLIRのインストールとビルドは、LLVMのビルドと一緒に行われます。
cd llvm-project/ cmake -S . -B build/ -DLLVM_ENABLE_PROJECTS="mlir" llvm cmake --build build/
基本的な使い方
編集MLIRを使用して中間表現を操作するには、以下のコードを使用します。
#include "mlir/IR/MLIRContext.h" #include "mlir/IR/Module.h" auto main() -> int { mlir::MLIRContext context; auto module = mlir::ModuleOp::create(mlir::UnknownLoc::get(&context)); module.dump(); return 0; }
進んだ使い方とカスタマイズ
編集MLIRは、カスタムのディアレクトやオペレーションを定義することで、特定のドメインに適した中間表現を構築することが可能です。
BOLT
編集BOLTの概要
編集BOLT(Binary Optimization and Layout Tool)は、バイナリの最適化ツールであり、実行時プロファイリングデータを使用してバイナリのパフォーマンスを向上させます。
インストールとビルド
編集BOLTのインストールとビルドは、以下の手順で行います。
git clone --depth=1 -b llvmorg-18.1.6 https://github.com/facebookincubator/BOLT.git cd BOLT cmake -S . -B build/ .. llvm cmake --build build/
基本的な使い方
編集BOLTを使用してバイナリを最適化するには、以下のコマンドを使用します。
perf record -e cycles:u ./example llvm-bolt ./example -o example.bolt --data=perf.data
進んだ使い方とカスタマイズ
編集BOLTは、詳細なプロファイリングデータを収集し、特定のコードパスを最適化することで、さらにパフォーマンスを向上させることができます。
Flang
編集Flangの概要
編集Flangは、LLVMプロジェクトのFortranコンパイラフロントエンドです。FortranコードをLLVM IRに変換し、最適化およびコード生成を行います。
インストールとビルド
編集Flangのインストールとビルドは、LLVMのビルドと一緒に行われます。
cd llvm-project/ cmake -S . -B build/ -DLLVM_ENABLE_PROJECTS="flang" llvm cmake --build build/
基本的な使い方
編集Flangを使用してFortranプログラムをコンパイルするには、以下のコマンドを使用します。
flang hello.f90 -o hello
進んだ使い方とカスタマイズ
編集Flangは、特定の最適化パスやランタイムライブラリのカスタマイズをサポートしています。
WebAssemblyサポート
編集WebAssemblyの概要
編集WebAssembly(Wasm)は、バイナリ命令フォーマットであり、LLVMはWebAssembly向けのバックエンドを提供しています。
インストールとビルド
編集WebAssemblyのインストールとビルドは、LLVMのビルドと一緒に行われます。
cd llvm-project/ cmake -S . -B build/ -DLLVM_ENABLE_PROJECTS="clang;lld" -DLLVM_TARGETS_TO_BUILD="WebAssembly" llvm cmake --build build/
基本的な使い方
編集WebAssembly向けにコードをコンパイルするには、以下のコマンドを使用します。
clang --target=wasm32-unknown-unknown-wasm -O3 -o hello.wasm hello.c
進んだ使い方とカスタマイズ
編集WebAssemblyのバックエンドは、カスタムセクションや特定の最適化オプションをサポートしています。
LLVM libc
編集LLVM libcの概要
編集LLVM libcは、LLVMプロジェクトによって提供される標準Cライブラリです。高い移植性とパフォーマンスを目指しています。
インストールとビルド
編集LLVM libcのインストールとビルドは、以下の手順で行います。
cd llvm-project/ cmake -S . -B build/ -DLLVM_ENABLE_PROJECTS="libc" llvm cmake --build build/
基本的な使い方
編集LLVM libcを使用するには、コンパイル時に指定します。
clang --rtlib=libc hello.c -o hello
進んだ使い方とカスタマイズ
編集LLVM libcは、高度にカスタマイズ可能であり、独自の機能や最適化を追加することができます。