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