[LLVM超入門] [C++] LLVMを利用してLLVM IRを生成してみる

#First
みなさんこんにちは。[あきっち](https://twitter.com/akicchi1234)です。
いきなりですが**LLVM**、知っていますか？もちろんみなさんならご存じですよね。
そうです。**コンパイラ基盤**です。
最近のプログラミング言語ではよく採用されているようで、とっても優秀らしいです。
私たちも流れに乗ってやってみましょう！！

#前提条件など
C++が多少かける
CMakeのやり方がわかる
includeディレクトリが適切に設定できる
リンクエラーしてもめげない心


#筆者の環境
Windows 10 Home
i7 7700HQ
RAM 16GB
Visual Studio 2019 Community

#環境構築など
この方が書いてくださっている　[LLVMに実行可能コードの生成をまかせたい](https://qiita.com/k2ymg/items/653c5b22b74a091be604)がとってもわかりやすいです。

#LLVM IR
LLVMには中間表現(IR)があり、任意のフロントエンドがIRにすることであとはLLVMに実行ファイルの生成と最適化を任せることが出来ます。例としてCでHello World!を出力するコードと、それに対応するLLVM IRを載せます。

###C言語

```Hello.c
#include <stdio.h>
int main() {
 printf("Hello world");
 return 0;
}
```
###LLVM IR

```Hello.ll
; Function Attrs: noinline nounwind optnone uwtable
define dso_local i32 @main() #0 {
  %1 = alloca i32, align 4
  store i32 0, i32* %1, align 4
  %2 = call i32 (i8*, ...) @printf(i8* getelementptr inbounds ([12 x i8], [12 x i8]* @"??_C@_0M@KIBDPGDE@Hello?5world?$AA@", i32 0, i32 0))
  ret i32 0
}
```

...うーん。よくわかりませんね。
allocaとかstoreはCとかアセンブリ触ってれば分かると思いますがgetelementptrがよくわかりません。
この記事ではその解説はしませんので各自調べてください。

#LLVM IR Builder入門!
さて、ついてにやってきました！**LLVM IR Builder**というIRをBuildするやつを使って書いてみましょう！
Hello world!は標準出力の関係で少しややこしくなるので今回は簡単な足し算をしてみます。

まずは加算をやってみましょう！

```Add.cpp
#include "llvm/IR/IRBuilder.h"

using namespace llvm;

LLVMContext context;
IRBuilder<> builder(context);
Module llvm_module("Example", context);

int main() {
	//	戻り値を設定する。Int32(i32)を返す。
	FunctionType* return_type = FunctionType::get(builder.getInt32Ty(), false);
	//　"main"という名で関数を生成する。llvm_moduleを忘れないように。
	Function* fn = Function::Create(return_type, Function::ExternalLinkage, "main", llvm_module);
	//　ブロックを生成して挿入ポイントをそこに変える。
	BasicBlock* bb = BasicBlock::Create(context, "entry", fn);
	builder.SetInsertPoint(bb);
	
	//i32で1, 2をそれぞれ生成する。
	Value* x = builder.getInt32(1);
	Value* y = builder.getInt32(2);
	//x, yをaddしてみる。
	Value* result = builder.CreateAdd(x, y, "result");
	//addの結果を返すreturnを生成する。
	builder.CreateRet(result);

	//IRをダンプする
	llvm_module.dump();
	return 0;
}
```

おっと。`FunctionType`、`Function`や`BasicBlock`が登場してきました。これらはなんでしょうか？
一つずつみていきましょう。
Functionの宣言をのぞいてみると、

```cpp
Function *Function::Create(FunctionType *Ty, LinkageTypes Linkage,
                           const Twine &N, Module &M);
```
となっています。
うーん...。`*Ty`はなんだ？
ということで`FunctionType`をのぞいてみます。

```cpp
FunctionType *FunctionType::get(Type *Result, bool isVarArg);
```
おぉ...なるほど`Type`型の`*Result`があります。つまりこれは戻り値ということですね。
main関数は`i32`を返したいので`builder.getInt32Ty()`とし、`isVarArg`は`false`とします。(`isVarArg`は可変長引数です)

```cpp
FunctionType* return_type = FunctionType::get(builder.getInt32Ty(), false);
```
とします。
`FunctionType`ができたので次に`Function`をしてみます。

```cpp
Function* fn = Function::Create(return_type, Function::ExternalLinkage, "main", llvm_module);
```
これは簡単ですね。
次に、`BasicBlock`が出てきました。`BasicBlock`はIRの挿入位置を作るもので、とても便利なものです。CとかC++でいうラベルです。

```cpp
BasicBlock* bb = BasicBlock::Create(context, "entry", fn);
builder.SetInsertPoint(bb);
```
**"entry"**という名の`BasicBlock`を作成して、挿入ポイントを作った`BasicBlock`に変えています。
さて、準備がすべて整いました！ということでさっそく加算をやってみます。

IRで数値を扱うにはどうしたらいいでしょうか？IRには`Value`というそれっぽいものがあります。これを使って数値を作ります。

```cpp
//i32で1, 2をそれぞれ生成する。
Value* x = builder.getInt32(1);
Value* y = builder.getInt32(2);
```

とりあえず32ビット整数で数値1と2を作成してみました。

これを加算してみます。

```cpp
Value* result = builder.CreateAdd(x, y, "result");
```
これでできましたね！加算の結果は`result`に格納します。
そして加算の結果を`return`します。

```cpp
builder.CreateRet(result);
```
簡単です。戻り値の型と違う型を返そうとするとエラーになりますのでご注意くださいね。
さいごに生成されたIRを眺めるためにダンプします。

```cpp
llvm_module.dump();
```
cppで`return 0;`も忘れずに。

ビルドして実行してみます。

```llvm
; ModuleID = 'Example'
source_filename = "Example"

define i32 @main() {
entry:
  ret i32 3
}
```
これで動きました。ちゃんと定数畳み込みもしてくれてます。うれしいですね。

#Last
好評だったら続編も作ってみようかと思います。
私自身もLLVM初心者ですので間違っていたら随時修正します。

LLVMはとっても素晴らしいコンパイラインフラストラクチャです。ぜひやってみてください。