先日、社内の勉強会で、コンパイラ関連の話を聞いていた際に、LLVM
という単語を初めて聞いた。
とても興味が湧いたので、調べてみることにした。
ちなみに僕は、コンパイラなど使ったことしかないため、かなり遠い道のりになりそう。
関連するサイト

- 作者: 出村成和
- 出版社/メーカー: ソシム
- 発売日: 2014/06/23
- メディア: 単行本(ソフトカバー)
- この商品を含むブログ (1件) を見る
Unofficial Automated Mirror of LLVM
Getting Started with the LLVM System
Getting Started: Building and Running Clang
[LLVM/Clang] LLVM/Clangを知る【はじめに】
コンパイラの仕組み
コンパイラには、主に3つの処理が存在する。
それぞれを、フロントエンド、ミドルエンド、バックエンドである。それぞれの役割を解説する。
フロントエンド
フロントエンドでは、字句解析と構文解析を行う。
字句解析とは、ソースコードを意味のある語句に分解(記号、識別子、予約語など)することで、
構文解析は、字句をプログラミング言語の構文に従って解析(よく用いられるのは、抽象構文木)することである。
そして、最終的に、中間コードを出力する。
ミドルエンド
ミドルエンドでは、フロントエンドから受け取った中間コードを、最適化し、最適化された中間コードを出力する。
最適化には、二つの目的が存在する。
一つは、実行ファイルの実行速度を向上させること、もうひとつは、実行ファイルのサイズを小さくすることである。
最適化の一つの手法として、定数畳み込み
というものがある。
これは、ビルド時に結果が分かっている演算結果を、実行コードに反映することで、実行時の演算量を削減するものだ。
例えば、
const int a = 1, b = 2; int c; c = a + b;
この場合、cはあらかじめ計算される。
よって、上のコードは、この段階で以下のように解釈される。
int c; c = 3;
バックエンド
バックエンドでは、ミドルエンドから渡された中間コードを、様々な処理を経て、最終的にターゲットのコードを出力する。
これは、特定のCPUで実行できる、ネイティブコードが多いが、JavaScriptのソースコードなども出力することができる。
次に、上で述べた、様々な処理
について、追って行く。
ここで行う主な処理は3つである。
一つ目は、実行する命令の選択
である。
例えば、かけ算を行うにしても、かけ算命令を行うのか、あるいは、加算を繰り返すか、など、様々な選択肢が存在する。
それらの中から、実行時に有利になる方法を選択する。
二つ目は、レジスタの割り当て
である。
CPUは、メインメモリとレジスタを利用して、演算を行う。
レジスタは、リソースが有限なため、これをうまく使えるか否かが、演算速度向上の決め手となる。
三つ目は、命令の並び替え
である。
ここでは、CPU命令の並び替えを行う。
対象となるCPUアーキテクチャの特性なども考慮して、高速に実行されるよう並び替えを行う。
LLVM/Clangの特徴
LLVMとは、コンパイラの開発基盤であって、中立的な設計方針である。
特定のプログラミング言語や、CPUアーキテクチャとは独立した設計方針となっている。
また、従来のコンパイラでは、上記のフロントエンド、ミドルエンド、バックエンドの境界が曖昧となっていることが多く、
どれかを拡張した場合、他の部分の修正が必要になることがある。
また、独立しているため、ある言語のコンパイラをLLVMで作る際、フロントエンドのみを開発すれば、あとはもともとあるLLVMw利用することができるようになる。
Clangとは
[LLVM/Clang] LLVM/Clangを知る【はじめに】
macにインストールしてみる
いつまでも理論ばっか垂れ流してても、意味がないので、自分のmacにインストールしてみる。
Getting Started with the LLVM System
Getting Started: Building and Running Clang
これらを参考に、LLVM/Clangをインストールしてみる。
% brew install --HEAD LLVM # To use the bundled libc++ please add the following LDFLAGS: # LDFLAGS="-L/usr/local/opt/LLVM/lib -Wl,-rpath,/usr/local/opt/LLVM/lib" # This formula is keg-only, which means it was not symlinked into /usr/local, # because macOS already provides this software and installing another version in # parallel can cause all kinds of trouble. # If you need to have this software first in your PATH run: # echo 'export PATH="/usr/local/opt/LLVM/bin:$PATH"' >> ~/.zshrc # For compilers to find this software you may need to set: # LDFLAGS: -L/usr/local/opt/LLVM/lib # CPPFLAGS: -I/usr/local/opt/LLVM/include # If you need Python to find bindings for this keg-only formula, run: # echo /usr/local/opt/LLVM/lib/python2.7/site-packages >> /usr/local/lib/python2.7/site-packages/LLVM.pth # mkdir -p /Users/username/.local/lib/python2.7/site-packages # echo 'import site; site.addsitedir("/usr/local/lib/python2.7/site-packages")' >> /Users/username/.local/lib/python2.7/site-packages/homebrew.pth # ==> Summary # 🍺 /usr/local/Cellar/LLVM/HEAD-06ded73: 2,571 files, 1.3GB, built in 32 minutes 14 seconds
keg-only
というワードが出てきた。
【Homebrew】インストールしたパッケージのシンボリックリンクが作成されない場合
こちらのサイトを参考にやってみる。
% brew link LLVM # Warning: LLVM is keg-only and must be linked with --force # Note that doing so can interfere with building software. # If you need to have this software first in your PATH instead consider running: # echo 'export PATH="/usr/local/opt/LLVM/bin:$PATH"' >> ~/.zshrc
% brew link LLVM --force # Linking /usr/local/Cellar/LLVM/HEAD-06ded73... 2596 symlinks created # If you need to have this software first in your PATH instead consider running: # echo 'export PATH="/usr/local/opt/LLVM/bin:$PATH"' >> ~/.zshrc
% which LLVM # LLVM not found
おかしい....
このままいじりすぎると、壊れてしまいそうなので、一旦、macへのインストールは諦めて、先日インストールしたkali linuxに入れてみることにする。