pub trait Bindgen {
type Operand;
fn emit(
&mut self,
inst: &Instruction<'_>,
operands: &mut Vec<Self::Operand>,
results: &mut Vec<Self::Operand>
);
fn allocate_space(&mut self, slot: usize, ty: &NamedType);
fn push_block(&mut self);
fn finish_block(&mut self, operand: Option<Self::Operand>);
}
Expand description
Trait for language implementors to use to generate glue code between native WebAssembly signatures and interface types signatures.
This is used as an implementation detail in interpreting the ABI between interface types and wasm types. Eventually this will be driven by interface types adapters themselves, but for now the ABI of a function dictates what instructions are fed in.
Types implementing Bindgen
are incrementally fed Instruction
values to
generate code for. Instructions operate like a stack machine where each
instruction has a list of inputs and a list of outputs (provided by the
emit
function).
Associated Types
Required methods
Emit code to implement the given instruction.
Each operand is given in operands
and can be popped off if ownership
is required. It’s guaranteed that operands
has the appropriate length
for the inst
given, as specified with Instruction
.
Each result variable should be pushed onto results
. This function must
push the appropriate number of results or binding generation will panic.
fn allocate_space(&mut self, slot: usize, ty: &NamedType)
fn allocate_space(&mut self, slot: usize, ty: &NamedType)
Allocates temporary space in linear memory indexed by slot
with enough
space to store ty
.
This is called when calling some wasm functions where a return pointer is needed.
fn push_block(&mut self)
fn push_block(&mut self)
Enters a new block of code to generate code for.
This is currently exclusively used for constructing variants. When a variant is constructed a block here will be pushed for each case of a variant, generating the code necessary to translate a variant case.
Blocks are completed with finish_block
below. It’s expected that emit
will always push code (if necessary) into the “current block”, which is
updated by calling this method and finish_block
below.
fn finish_block(&mut self, operand: Option<Self::Operand>)
fn finish_block(&mut self, operand: Option<Self::Operand>)
Indicates to the code generator that a block is completed, and the
operand
specified was the resulting value of the block.
This method will be used to compute the value of each arm of lifting a
variant. The operand
will be None
if the variant case didn’t
actually have any type associated with it. Otherwise it will be Some
as the last value remaining on the stack representing the value
associated with a variant’s case
.
It’s expected that this will resume code generation in the previous
block before push_block
was called. This must also save the results
of the current block internally for instructions like ResultLift
to
use later.