BT

最新技術を追い求めるデベロッパのための情報コミュニティ

寄稿

Topics

地域を選ぶ

InfoQ ホームページ ニュース LLVMおよびRubyの総まとめ:llvmruby、yarv2llvmおよびregexpllvm、Rubinius

LLVMおよびRubyの総まとめ:llvmruby、yarv2llvmおよびregexpllvm、Rubinius

LLVMには「VM」という文字が含まれているが、実際にはコンパイラバックエンドを構築するためのフレームワークである。要するに、命令セット(即座に 表示)およびコードを最適化し、多くのプラットフォーム(x86、ARMなど...)向けのネイティブコードを生成するバックエンドを装備している。現実 世界での使用例の1つは、AppleのOpenGL JIT(リンク)である。

Llvmruby(リンク)(llvmruby GitHubリポジトリ)(リンク)はTom Bagby氏によるプロジェクトである。RubyバインディングをLLVMに提供する。Llvmrubyは、適切にRubyに統合される。たとえば、このコードは追加命令を追加する(codeblockは命令のビルダーである)。

codeblock.bin_op(Instruction::Add, 41.llvm, 1.llvm)

LlvmrubyはObjectを開き、llvmを追加し、LLVMが取り扱うことができる値に変換する。

READMEのインストラクションに従えば(LLVMを取得し、コンパイルし、llvmrubyをコンパイルする)、たとえばirbを使った試みを始めら れる。以下にサンプルセッションを示す(llvmrubyプロジェクトのサンプルから抽出したコードのスニペットつき)。

# Set up LLVM
>> require 'llvm'
=> true
>> include LLVM
=> Object
>> m = LLVM::Module.new("test_module")
=> ; ModuleID = 'test_module'
# Create a function type - the second argument is the method signature,
# ie. the return type and the types of the arguments
# In this case, there are no return values or arguments
>> type = Type::function(MACHINE_WORD, [])
=> #
>> f = m.get_or_insert_function("test", type)
=>
declare i32 @test()
# Create an LLVMBuilder object which allows to call methods and
# generate instructions
>> builder = f.create_block.builder
=> #
# Create an Add instruction - note how it's possible to pass regular Ruby Fixnums
>> ret = builder.bin_op(Instruction::Add, 41.llvm, 1.llvm)
=> #
>> fcode = builder.return(ret)
=> #
>> ExecutionEngine.get(m);
=> true
# Finally: execute the generated code
>> ExecutionEngine.run_autoconvert(f)
=> 42


LLVMの使用について詳しくは、LLVM Tutorialが単純な言語など向けのJITの実装方法を示している(リンク)


llvmrubyを使用したさらに規模の大きな例をMiura Hideki氏(リンク)が提供している。

  • regexpllvm(リンク):正規表現をLLVMコードに変換する。
  • yarv2llvm(リンク):Ruby 1.9の命令コードを受け取り(正式なRuby 1.9 VMとなるまでは1.9 VMはYARVと呼ばれた)、そしてLLVMに変換する。_why's Unholy(Ruby 1.9命令コードをPython VM命令コードに変換)(リンク)またはHotRuby(Ruby 1.9命令コード向けJavascriptインタープリター)(リンク)のような同様のプロジェクトの歩みをたどる。こうしたプロジェクトとは異なり、 llvmrubyはRuby 1.9 VMと緊密に統合し、興味深い可能性を提供している。Regexpllvmは、コードの実行を高速化する1つの方法を示している。つまり、DSLを LLVM命令コードにコンパイルする。他のシステムは、このアプローチを使用している。JavaのXSLT implementationがXSLTスタイルシートをJVMバイトコードにコンパイルする(リンク)
    別の可能性:Rubyコードホットスポットをコンパイルする。そのとき、Rubyコードがパフォーマンスの障害になると判明した場合、実際的なソリュー ションはCでそれを再び書き込むことである(理想主義者は、Ruby VMのパフォーマンスが上押し上げられるのを待つことである)。llvmrubyでは、他の選択肢もある。RubyコードをLLVMにコンパイルすること である。つまり、yarv2llvmをブースターとして使用する。そうは言っても、これが必要なパフォーマンスの改善を提供するかどうかは、コード次第で ある。


Llvmrubyは、C++に関わることなくLLVMでの試みを可能にし、またirbを使用し漸進的におこなうことを可能にする。A useful property, eg. 便利なプロパティ、Rubiniusへのコントリビューターが考えのプロトタイプを製造する(プロジェクトはLLVMを使用する計画)。Rubinius チームは、C++でVMを再書き込みし、内部のクリーンアップで忙しくしている。この作業は、現在GitリポジトリのRubiniusのCPPブランチで おこなわれており、外部ライブラリとしてLLVMを含む(リンク)。C++ブランチは、まもなくマスターブランチに変化する。最近のTwittersによると、 Rubiniusは新たなC++ VMで多くのRubyコードを実行する機能を回復した。. Eric Hodel氏が今週、以下のように述べた(リンク)

Rubiniusの新たなvmは、クラッシュすることなくコアスペックを実行することができる。


Evan Phoenix氏は、以下のように報告した(リンク)

IRBは再び新たなRubinius C++ VMの下、動作する。


RubyでLLVMをどう使用するか?

この記事に星をつける

おすすめ度
スタイル

BT