yarv2llvm開発を再開しました

LLVM勉強会でスレッドが並列に動いてないと指摘を受けて、ジャイアントロックをはずした独自ランタイムを作ろうとしています。
http://d.hatena.ne.jp/miura1729/20090323/1237799188
ところが、スレッドを実現するランタイムはかなり大きく、これをLLVMで手書きするのはしんどそうです。clangなんかを使うことも考えたのですが、メンテナンスを考えると大変そうなのでやめました。結局、スレッドのランタイムをRubyで書くことにしました。
当然、ランタイムを書くにはRubyではいじれない構造体の中身をいじる必要があります。
中身をいじるためにRuby FFIのようなAPIを用意することも考えたのですが、yarv2llvmとは相性が悪そうです。FFIを実現するために動的に実行する必要があって、コンパイル時に静的に解析するといったことが全く考慮されていないからです。

このような普通はRubyではいじれない低レベルの操作を可能にするため、unsafeとういうメソッドを作っています。まだ、できていないですがunsafeはこんな感じで使うことを考えています。

def unsafe_sample
  RBASIC = Type::struct([VALUE, VALUE])
  RARRAY = Type::struct([RBASIC, LONG, LONG, P_VALUE])
  P_RARRAY = Type::pointer(RARRAY)
  foo = YARV2LLVM::LLVMLIB::unsafe([:a], P_ARRAY)
  YARV2LLVM::LLVMLIB::safe(foo[0][1])   # 配列の長さ1を得る
end

unsafeは非常に危険なメソッドなのでわざと使いにくくしています。YARV2LLVM::LLVMLIB::unsafe(値, LLVMでの型)とすると、「値」が「LLVMでの型」で示される構造を持っていると定義できます。
unsafeの戻り値はUnsafeオブジェクトで、このオブジェクトは[ ]と[ ]=をメソッドに持ちます。[ ], [ ]=は構造体または配列の要素をアクセスするためのものです。ポインタ型のときは[0]でデリファレンスできます。あと、Unsafeオブジェクトはsafeメソッドを使ってその値に対応するRubyオブジェクトを得ることができます。

Unsafeオブジェクトは内部表現はRubyのオブジェクトとは限らない生データなのでインスタンス変数等に入れるとGCがバグります。そのため、Unsafeオブジェクトは他のオブジェクトと混在しないようにしっかりチェックする必要があります。