Hatena::Groupllvm

LLVMメモ (with MacRuby)

2009-07-22

macrubyc つかって LLVM IR (.ll) 出すまで

01:07

$ svn co http://svn.macosforge.org/repository/ruby/MacRuby/branches/experimental/

とかして、READMEに従ってLLVMもろともビルド&インストール。(とりあえず、r2044付近を使用してます)

macrubyc が MacRubyコンパイラで、.oおよびa.out形式(x86_64)ができる。が、そこはまず置いておいて、macrubycコマンドを改造(もちろん、別スクリプトにするでも良いかな)して、.bcなどの中間ファイルを消さないようにしてみる。

具体的には、macrubyc の

app = Compiler.new(ARGV)
begin
  app.run
ensure
  app.cleanup
end

の app.cleanup をコメントアウト

ほいでもって、macrubyc -c test.rb すると、 $TMPDIR に test.bc ができるので、

$ llvm-dis test.bc

とかすると、IR(.ll)がとれる。たとえば

p 1+2

を macrubyc して出てくるIRは、

; ModuleID = 'test.bc'
internal global i8* null		; <i8**>:0 [#uses=1]
internal global i8* null		; <i8**>:1 [#uses=2]
@redefined = internal constant i1 false		; <i1*> [#uses=0]
internal global i8* null		; <i8**>:2 [#uses=2]
internal global i8* null		; <i8**>:3 [#uses=3]
internal constant [3 x i8] c"+:\00"		; <[3 x i8]*>:4 [#uses=1]
internal constant [3 x i8] c"p:\00"		; <[3 x i8]*>:5 [#uses=1]

define i64 @MREP_test(i64 %self, i8* %sel) {
MainBlock:
	%0 = tail call i8* @sel_registerName(i8* getelementptr ([3 x i8]* @5, i32 0, i32 0))		; <i8*> [#uses=1]
	volatile store i8* %0, i8** @3
	%1 = tail call i8* @sel_registerName(i8* getelementptr ([3 x i8]* @4, i32 0, i32 0))		; <i8*> [#uses=1]
	volatile store i8* %1, i8** @1
	%2 = load i8** @3		; <i8*> [#uses=1]
	%3 = tail call i8* @rb_vm_get_method_cache(i8* %2)		; <i8*> [#uses=1]
	volatile store i8* %3, i8** @2
	%4 = load i8** @1		; <i8*> [#uses=1]
	%5 = tail call i8* @rb_vm_get_method_cache(i8* %4)		; <i8*> [#uses=1]
	volatile store i8* %5, i8** @0
	%6 = load i8** @2		; <i8*> [#uses=1]
	%7 = load i8** @3		; <i8*> [#uses=1]
	%8 = tail call i64 (i8*, i64, i8*, i8*, i8, i32, ...)* @rb_vm_dispatch(i8* %6, i64 %self, i8* %7, i8* null, i8 0, i32 1, i64 13)		; <i64> [#uses=1]
	ret i64 %8
}

declare i64 @rb_vm_dispatch(i8*, i64, i8*, i8*, i8, i32, ...)

declare i8* @rb_vm_get_method_cache(i8*)

declare i8* @rb_vm_get_constant_cache(i8*)

declare i8* @sel_registerName(i8*)

declare i8* @rb_global_entry(i64)

declare i64 @rb_intern(i8*)

declare i64 @objc_getClass(i8*)

なかんじ。がんばって読むと、

  • test.rb ファイルをコンパイルすると、最上位階層が MREP_test という名前の関数(Block?)になる
  • sel_registerName, rb_vm_get_method_cache, rb_vm_dispatch の 3つの関数が呼び出されてる
  • rb_vm_dispatch がおそらく p: セレクタで p を評価しようとしているコードっぽく見えるが、その引数の即値が13 (Ruby処理系のVALUEでいうところの、Fixnumで3) と入っている

とかが分かる。

さらに、これは

a = 1
b = a
b += 2
p b

コンパイルしても同じ。どこのオプティマイザがこんなに利口なのか(ソースぜんぜん読んでないので)不明ですが、かなり期待できる予感。

はじめまして

00:58

ここは MacRuby 0.5 (LLVM backend) の解析の軌跡になるはずです。LLVM初心者。