Hachioji.pm 日めくりテックトーク

Compiler::CodeGenerator::LLVMで遊ぼう!

今日は, @goccy54さんが開発されたCompiler::CodeGenerator::LLVMを導入して, ひと通り動かすまでのアレコレをご紹介したいと思います.

LLVMのインストール

Compiler::CodeGenerator::LLVMはLLVM 3.3に依存しているので, まず最初にLLVM 3.3を導入します.
ついでにLLVMを基盤とするコンパイラのClangと, ランタイムライブラリのCompiler RTも入れてしまいましょう.

まず, こちらのページから, Clang source code, LLVM source code, Compiler RT source codeをクリックして, 必要なソースコードをダウンロードします.

$ wget http://llvm.org/releases/3.3/cfe-3.3.src.tar.gz
$ wget http://llvm.org/releases/3.3/compiler-rt-3.3.src.tar.gz
$ wget http://llvm.org/releases/3.3/llvm-3.3.src.tar.gz

それぞれ, cfe-3.3.src.tar.gz, llvm-3.3.src.tar.gz, compiler-rt-3.3.src.tar.gzというファイルがダウンロードできるので, さっさと解凍してしまいます.

$ tar -xf cfe-3.3.src.tar.gz
$ tar -xf llvm-3.3.src.tar.gz
$ tar -xf compiler-rt-3.3.src.tar.gz

解凍してできたllvm-3.3.srcの中の適切な位置に, cfe-3.3.srccompiler-rt-3.3.srcを配置していきます.

$ mv cfe-3.3.src llvm-3.3.src/tools/clang
$ mv compiler-rt-3.3.src llvm-3.3.src/projects/compiler-rt

続いて, llvm-3.3.srcディレクトリに移動して, configureで設定を行います.

$ cd llvm-3.3.src
$ ./configure

問題なくconfigureが終われば, make, make check, make installでビルドして, インストールまで済ませます.
ちなみにconfigureを実行する際, --prefixオプションで任意の場所にLLVMやClangをインストールすることができますが, 手元の環境では何故かうまく動かなかったのでデフォルトでインストールした方が良さそうです.
「sudoで入れるの嫌だなあ...」という方はVagrantとかVirtualBoxとか, そういうのを作ってCompiler::CodeGenerator::LLVM用のVMを建てましょう!

$ make

ちなみに, makeコマンドはmake -jNとすることで, Nコアを使って処理を進めることができます.
ビルドには時間がかかるので, make -j2とかmake -j4とかで高速化しましょう.

$ make check
$ sudo make install

make checkは任意ですが, とりあえずやっておきましょう. 手元の環境では100件ほどFailしますが, おそらく大丈夫... だと思います.
あとはsudo make installを実行すれば, LLVMとClangがインストールされます.

$ which llvm-config
/home/username/local/llvm/bin/llvm-config
$ llvm-config --version
3.3

といった感じで, LLVMとClangが正常にインストールできていることが確認できれば, 準備完了です.

Compiler::CodeGenerator::LLVMのインストール

それではCompiler::CodeGenerator::LLVMをインストールしましょう.

まず依存モジュールの準備です.
Compiler::CodeGenerator::LLVMは, こちらもまたgoccy氏が開発したCompiler::LexerCompiler::Parserに依存しているので, これを入れる必要があります.

$ cpanm Compiler::Lexer Compiler::Parser

どちらもCPANizeされているので, 素直にcpanmでインストールしてもいいですし, GitHubからcloneしてインストールしてもよいでしょう.
ちなみにどちらのモジュールも, Minillaで開発されているのでminil installでインストールできます.

依存モジュールの準備が終われば, いよいよCompiler::CodeGenerator::LLVMのインストールです.
こちらのモジュールは, まだCPANizeされていないので,

$ git clone https://github.com/goccy/p5-Compiler-CodeGenerator-LLVM.git

でcloneしてきてから,

$ cd p5-Compiler-CodeGenerator-LLVM
$ perl Makefile.PL
$ make
$ make test
$ make install

の手順でインストールしていきます.

早速, 試す!

それでは早速, Compiler::CodeGenerator::LLVMで遊んでみましょう.
まずはSynopsisのコードを動かしてみます.

use Compiler::Lexer;
use Compiler::Parser;
use Compiler::CodeGenerator::LLVM;

my $filename = $ARGV[0];
open(my $fh, "<", $filename) or die("$filename is not found.");
my $script = do { local $/; <$fh> };
my $lexer = Compiler::Lexer->new($filename);
my $tokens = $lexer->tokenize($script);
my $parser = Compiler::Parser->new();
my $ast = $parser->parse($tokens);
my $generator = Compiler::CodeGenerator::LLVM->new();    
my $llvm_ir = $generator->generate($ast); # generate LLVM-IR
$generator->debug_run($ast); # execute LLVM-IR with JIT

Synopsisのコードは, 標準入力に与えられたファイル名に書かれているコードからLLVM IRを生成して, それをJITで実行するというスゴイやつです.
テストコードをsynopsis.plみたいな名前で保存して,

use strict;
use warnings;

my @arg = (0, 1, 2, 3, 4);
foreach my $i (@arg) {
    say $i;
}

こんな感じのファイルをsample.plで保存して, $ perl synopsis.pl sample.plてな感じで実行すると...

$ perl synopsis.pl sample.pl
0
1
2
3
4

Wow! 実行できましたね.
個人的には, 内部で生成されたLLVM IRをダンプできれば, いろいろと遊べそうな感じがしますが, 現状そのようなメソッドはないっぽいので, 今後に期待したいと思います.
(時間があれば実装とかチャレンジしてみたい所ですが... XSだしなあ...)

まとめ

YAPC::Asiaにおいて, 注目の的の1つでもあったPerlMotionを支えるgoccy wareの, Compiler::CodeGenerator::LLVMの導入方法をまとめてみました.
このモジュールが完成すれば, PerlでiPhoneアプリが開発できるようになるだけでなく, PerlのコードをLLVM IR経由で各種バイナリに変換したり, C言語に変換したり, CUDAに変換したり... と, いろいろな可能性が期待できるようになります.

今後も, バク報告だけでなく, 出来ればコードをコミットしていく... という方法で, Compiler::CodeGenerator::LLVMやCompiler::Lexer, Compiler::Parserといったgoccy wareをサポートして行けたらいいなあ, と思っています.
これからのCompiler::CodeGenerator::LLVM, 要チェックですね!

なお, 今回この記事を書くにあたり, 作者の@goccy54さんに大変, ものっすごっく, アドバイスとご協力を頂きました.
この場をお借りして御礼申し上げます. 本当にありがとうございました!

created by
papix
created at
last modified at
2013-10-14 23:35
comments powered by Disqus