Node:VM code generation, Next:, Previous:VM instruction table, Up:Using the generated code



VM code generation

Vmgen generates VM code generation functions in name-gen.i that the front end can call to generate VM code. This is essential for an interpretive system.

For a VM instruction x ( #a b #c -- d ), Vmgen generates a function with the prototype

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

The ctp argument points to a pointer to the next instruction. *ctp is increased by the generation functions; i.e., you should allocate memory for the code to be generated beforehand, and start with *ctp set at the start of this memory area. Before running out of memory, allocate a new area, and generate a VM-level jump to the new area (this overflow handling is not implemented in our examples).

The other arguments correspond to the immediate arguments of the VM instruction (with their appropriate types as defined in the type_prefix declaration.

The following types, variables, and functions are used in name-gen.i:


Inst
The type of the VM instruction; if you use threaded code, this is void *; for switch dispatch this is an integer type.
vm_prim
The VM instruction table (type: Inst *, see VM instruction table).
gen_inst(Inst **ctp, Inst i)
This function compiles the instruction i. Take a look at it in vmgen-ex/peephole.c. It is trivial when you don't want to use superinstructions (just the last two lines of the example function), and slightly more complicated in the example due to its ability to use superinstructions (see Peephole optimization).
genarg_type_prefix(Inst **ctp, type type_prefix)
This compiles an immediate argument of type (as defined in a type-prefix definition). These functions are trivial to define (see vmgen-ex/support.c). You need one of these functions for every type that you use as immediate argument.

In addition to using these functions to generate code, you should call BB_BOUNDARY at every basic block entry point if you ever want to use superinstructions (or if you want to use the profiling supported by Vmgen; but this support is also useful mainly for selecting superinstructions). If you use BB_BOUNDARY, you should also define it (take a look at its definition in vmgen-ex/mini.y).

You do not need to call BB_BOUNDARY after branches, because you will not define superinstructions that contain branches in the middle (and if you did, and it would work, there would be no reason to end the superinstruction at the branch), and because the branches announce themselves to the profiler.