2

Renjin (JVM の場合は R) のバイト コード コンパイラに取り組んでおり、中間 3 アドレス コード (TAC) 表現をバイト コードに変換する実験を行っています。私が参照したコンパイラに関する教科書はすべて、コード生成時のレジスタ割り当てについて説明していますが、JVM のようなスタックベースの仮想マシンでコードを生成するためのリソースを見つけることができませんでした。

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

完全な例を次に示します。

元の R コードは次のようになります。

x + sqrt(x * y)

TAC IR:

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

(コンパイル時にプリミティブへの関数呼び出しを常に解決できるとは限らないという事実を少し無視してください)

結果の JVM バイト コードは、(おおまかに) 次のようになります。

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

基本的に、プログラムの先頭で、TAC 命令 2 に到達するまでにスタックの先頭にローカル変数 x が必要になると考えている必要があります。手動で考えることはできますが、これを正しく行うためのアルゴリズムを考えるのに苦労しています。ポインタはありますか?

4

1 に答える 1

3

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

シーケンスは次のようになります。

  1. 基本ブロックを形成する
  2. SSA 変換を実行する
  3. 基本ブロック内で式ツリーを構築する
  4. 前の手順で削除されなかったレジスタにローカル変数を割り当てるために、レジスタ スケジューリング (および phi- 削除を同時に実行) を実行します。
  5. JVMコードを発行する - レジスタは変数に入れられ、式ツリーはスタック操作に自明に展開されます
于 2011-12-08T08:18:55.447 に答える