2011-12-08 27 views
2

私はRenjin(R for the JVM)のバイトコードコンパイラで作業しており、中間3アドレスコード(TAC)表現をバイトコードに変換することを試しています。私が参考にしたコンパイラのすべての教科書は、コード生成中にレジスタの割り当てについて議論していますが、JVMのようなスタックベースの仮想マシン上でコード生成のためのリソースを見つけることができませんでした。3つのアドレスコードからJVMバイトコードへのコード生成

単純なTAC命令はバイトコードに変換するのは簡単ですが、一時的なものが含まれていると少し失われます。誰がこれを説明するリソースへのポインタを持っていますか?

x + sqrt(x * y) 

TAC IR:

オリジナルRコードは次のようになります。ここでは

は完全な例である

0: _t2 := primitive<*>(x, y) 
1: _t3 := primitive<sqrt>(_t2) 
2: return primitive<+>(x, _t3) 

(第2のために事実を無視taht私たちがすることはできませんコンパイル時に常に関数呼び出しをプリミティブに解決する)

結果のJVMバイトコードwouこのようなLDの外観(おおよそ)何か:

aload_x 
dup 
aload_y 
invokestatic r/primitives/Ops.multiply(Lr/lang/Vector;Lr/lang/Vector;) 
invokestatic r/primitives/Ops.sqrt(Lr/lang/Vector;) 
invokestatic r/primitives/Ops.plus(Lr/lang/Vector;Lr/lang/Vector;) 
areturn 

基本的には、プログラムの先頭に、私はすでに私は時間によって、スタックの先頭にローカル変数xを必要とするつもりだと考えてする必要があります私は手動でこれを考えることができますが、これを正しく行うためのアルゴリズムを考えるのは難しいです。すべてのポインタ?

答えて

2

3アドレス表現をスタックに変換する方が、3アドレス表現に変換するよりも簡単です。

  1. フォームの基本ブロック
  2. を基本ブロック内
  3. ビルド式ツリーをSSA-変換を実行
  4. レジスタschedulling(とphi-削除を実行します。

    はあなたの順序は次のようにする必要があります同時に)前のステップで削除されていないレジスタのローカル変数を割り当てる

  5. JVMコードを放出する - レジスタは変数に入り、表現木は自明であるスタック操作にxpanded
+0

ワウ!ありがとう、これは私が探していたものです。質問:基本ブロックごとに、または手順全体にわたってSSA変換を実行する必要がありますか?チュートリアル、教科書、その他のリソースへの指針はありますか? – akbertram

+0

SSA変換は、プロシージャ全体で行われます。http://en.wikipedia.org/wiki/Single_static_assignment変数を割り当てる複数の割り当て場所を持つ基本ブロックごとに、支配的な境界線を見つけるだけで済みます。そこにphiノードを挿入してから、冗長なphisを取り除いてください(nb:循環依存関係を持つものもあります)。 –

+0

@akbertram、 'LLVM'はここでインスピレーションの源泉になることができます。それ以降は中間表現を安全にモデル化できます。そこからいくつかの重要な意思決定:あるレジスタを別のレジスタに割り当てることを許さず、レジスタに定数を割り当てることを許さない場合は、常にその代わりに代わりにそのレジスタを置き換えます。 –

関連する問題