8.3 VM code generation

Vmgen は、フロント・エンドが VM コードを生成するために呼び出すことができる VM コード生成関数を name-gen.i に生成します。 これはインタープリター・システム(interpretive system)には不可欠なものです。

VM 命令 ‘x ( #a b #c -- d )’ の場合、 Vmgen は以下のプロトタイプを持つ関数を生成します

void gen_x(Inst **ctp, a_type a, c_type c)

ctp 引数は、 次の命令へのポインターを指します。 *ctp は生成関数によって増加されます。 つまり、 あなたは生成するコード用のメモリを事前に割り当て、 このメモリ領域の先頭に *ctp を設定して開始する必要があります。 メモリが不足する前に、 新しい領域を割り当て、 新しい領域への VM レベルのジャンプを生成します(このオーバーフロー処理は我々の例では実装されていません)。

他の引数は、 VM 命令の直接引数(immediate arguments)に対応します(type_prefix 宣言で定義されている適切な型を使用します)。

以下の型や変数や関数が name-gen.i で使用されます:

Inst

VM 命令のタイプ。 スレッド化コードを使用する場合、 これは void * です。 スイッチ・ディスパッチの場合、 これは整数型です。

vm_prim

VM 命令テーブル (タイプ: Inst * 。 see VM instruction table)。

gen_inst(Inst **ctp, Inst i)

この関数は命令 i をコンパイルします。 vmgen-ex/peephole.c をご覧ください。 スーパー命令(superinstructions)を使用したくない場合(関数例の最後の 2 行のみの場合)は簡単ですが、 この例ではスーパー命令を使用可能なため、 少し複雑になります(see Peephole optimization)。

genarg_type_prefix(Inst **ctp, type type_prefix)

これにより、 (type-prefix 定義で定義されている) type の直接引数(immediate argument)がコンパイルされます。 これらの関数を定義するのは簡単です(vmgen-ex/support.c を参照)。 あなたが直接引数(immediate argument)として使用するタイプごとに、 これらの関数のいずれかが必要です。

これらの関数を使用してコードを生成することに加えて、 スーパー命令(superinstructions)を使用したい場合は(または、 Vmgen でサポートされているプロファイリングを使用したい場合は; ただし、 このサポートは主にスーパー命令の選択にも役立ちます)は、 すべての基本ブロック・エントリ・ポイントで BB_BOUNDARY を呼び出す必要があります。 あなたが BB_BOUNDARY を利用する場合、 あなたは BB_BOUNDARY も定義する必要があります(vmgen-ex/mini.y の定義をご覧ください)。

分岐の後に BB_BOUNDARY を呼び出す必要はありません。 なぜなら、 あなたは途中に分岐を含むスーパー命令を定義することはないでしょう(もしあなたがそうして、 それがうまくいくなら、 分岐でスーパー命令で終了する理由はありません)、 そして、 分岐はプロファイラに自分自身をアナウンスするからです。