人生は勉強ブログ

https://github.com/dooooooooinggggg

LLVMについて調べた

先日、社内の勉強会で、コンパイラ関連の話を聞いていた際に、LLVMという単語を初めて聞いた。

とても興味が湧いたので、調べてみることにした。

ちなみに僕は、コンパイラなど使ったことしかないため、かなり遠い道のりになりそう。

関連するサイト

LLVM/Clang実践活用ハンドブック

LLVM/Clang実践活用ハンドブック

公式サイト

LLVM

Clang

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を知る【はじめに】

Clangは、LLVMと共に提供されるコンパイラフロントエンドです。

macにインストールしてみる

いつまでも理論ばっか垂れ流してても、意味がないので、自分のmacにインストールしてみる。

Getting Started with the LLVM System

Getting Started: Building and Running Clang

これらを参考に、LLVM/Clangをインストールしてみる。

mac osでLLVMの環境を構築してみる

% 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に入れてみることにする。