Cの関数を呼べるようにしました

ランタイムをRubyで書くための準備で、Cの関数を呼べるようにしました。これで後は、動的ロードと外部変数をアクセスできるようにしたらランタイムが書けるんじゃないかなと思います。実装がバグバグなんでバグ取りが山のように残っていますが。

サンプルプログラムです。

def tdefine_external_function
  value = RubyHelpers::VALUE
  int32ty = LLVM::Type::Int32Ty
  type = LLVM::function(value, [int32ty])
  YARV2LLVM::LLVMLIB::define_external_function(:rb_ary_new2, 
                                               'rb_ary_new2', 
                                               type)
  
  siz = YARV2LLVM::LLVMLIB::unsafe(2, int32ty)
  rb_ary_new2(siz)
end

サイズ2の配列を作って返すだけの関数です。ここで、Unsafeオブジェクトと組み合わせて、rb_ary_new2に2という値を渡せられるところが売りです。通常なら2を渡すとrb_ary_new2には5(Fixnumで最下位ビットが1だから)が渡ってしまいます。

こんな感じのコードが出てきます。

define i32 @__stub__tdefine__external__function(i32) {
bb:
	%1 = tail call i32 @rb_ary_new2(i32 2)		; <i32> [#uses=1]
	ret i32 %1
}

本当は、define_external_functionに渡す引数はUnsafeオブジェクトだけにするように、また戻り値は通常のオブジェクトに変換してから使うようにチェックしないといけないです。そうしないと、GCと絡んだとき絶対バグるからです。でも、まだそうなっていないです。