llvmの基本となるツールたち 〜llvm 入門 その1〜
http://www.ibm.com/developerworks/jp/opensource/library/os-createcompilerllvm1/
最初なのでとりあえず↑の記事を基本なぞってます。
llvm ってなんなん?
LLVMは(Low Level Virtual Machineの略
LLVMは lightweight language とは関係ない。
LLVMはclang/clang++のバックエンドとしてつかわれている
LLVMはコンパイラーツクール
llvm IR とは?
intermediate representation(中間表現)のこと。 llvm API でくみたてることができる。dump してテキストで表現することも可能。dump したテキスト表現を llvm アセンブリとよんだりするようです。
重要な3つのツール
lli
llvmアセンブリを実行するインタープリタ。その場で JIT して実行。
llvm-gcc
llvm-gcc -S -emit-llvm foo.c
とすると、llvmアセンブリをはいてくれる!
llc
llvmアセンブリをネイティブのアセンブリに変換する。
3つのツールをためす
helloworld.c はこちら。
#include <stdio.h> int main( ) { printf("Hello World!\n"); }
llvmアセンブリを生成!
$ llvm-gcc -S -emit-llvm helloworld.c
helloworld.s ができてた。
; ModuleID = 'helloworld.c' target datalayout = "e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-v64:64:64-v128:128:128-a0:0:64-s0:64:64-f80:128:128-n8:16:32:64" target triple = "x86_64-apple-darwin11.4" @.str = private constant [13 x i8] c"Hello World!\00", align 1 ; <[13 x i8]*> [#uses=1] define i32 @main() nounwind ssp { entry: %retval = alloca i32 ; <i32*> [#uses=1] %"alloca point" = bitcast i32 0 to i32 ; <i32> [#uses=0] %0 = call i32 @puts(i8* getelementptr inbounds ([13 x i8]* @.str, i64 0, i64 0)) nounwind ; <i32> [#uses=0] br label %return return: ; preds = %entry %retval1 = load i32* %retval ; <i32> [#uses=1] ret i32 %retval1 } declare i32 @puts(i8*)
実行してみる。
$ lli helloworld.s Hello World!
そして、ネイティブアセンブラへの変換もためす。
$ llc helloworld.s
helloworld.s.s という名前で x86 asm ができていた。
.section __TEXT,__text,regular,pure_instructions .globl _main .align 4, 0x90 _main: ## @main ## BB#0: ## %entry pushq %rax leaq L_.str(%rip), %rdi callq _puts movl 4(%rsp), %eax popq %rdx ret .section __TEXT,__const L_.str: ## @.str .asciz "Hello World!" .subsections_via_symbols
なるほど動いている様子。
まとめ
llvm のツールをいくつかみてみた。各フェーズごとに途中経過をみれるのがありがたい。