コンテンツにスキップ

LLVM

出典: フリー教科書『ウィキブックス(Wikibooks)』

LLVMハンドブック

[編集]

はじめに

[編集]

LLVMとは

[編集]

LLVMは、コンパイラを開発するためのモジュール化されたフレームワークであり、再利用可能なコンパイラおよびツールチェーンコンポーネントのセットです。LLVMは、最適化、コード生成、リンカなど、コンパイルプロセスの多くの段階で使用されます。

LLVMの歴史と開発コミュニティ

[編集]

LLVMは2000年代初頭にクリス・ラットナーによって設立されました。その後、Apple、Google、Facebookなどの主要企業がLLVMを採用し、開発を支援しています。LLVMプロジェクトはオープンソースであり、世界中の開発者が貢献しています。

かつてBSD系UNIX(FreeBSDやNetBSDなど)では、GCCやbinutilsがコンパイラツールチェインとして使用されていましたが、2000年代に相次いでLLVM/Clangに移行しました。

LLVMプロジェクトの全体構成

[編集]

LLVMプロジェクトは、以下の多くのサブプロジェクトで構成されています。

各サブプロジェクトについては、後続の章で概要を説明し、詳細は専用のハンドブックを参照してください。

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は、様々なツール(clangoptllcなど)を提供しています。例えば、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は、高度にカスタマイズ可能であり、独自の機能や最適化を追加することができます。

外部リンク

[編集]
Wikipedia
Wikipedia
ウィキペディアLLVMの記事があります。