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