Node:VM code generation, Next:Peephole optimization, Previous:VM instruction table, Up:Using the generated code
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
void *
; for switch dispatch this is an integer type.
vm_prim
Inst *
, see VM instruction table).
gen_inst(Inst **ctp, Inst i)
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)
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.