Skip to content

Commit

Permalink
Function references
Browse files Browse the repository at this point in the history
This patch implements (most parts of) the frontend for the function
references proposal (currently we have not implemented initialised
locals). Moreover, the crates shrink, smith, and mutate have yet to
made compatible with the new features --- once the changeset has been
approved we can adjust those crates.

Boardly, the implementation of function references follows the
proposed spec closely, and as such, this patch introduces some
important changes to both the type structure and the validation
algorithm.

The structure of `ValType` is no longer a flat, instead, it contains a
new constructor `Ref(RefType)` which is parameterised by `RefType`,
which is a new struct type. This type is itself parameterised by a
`HeapType`, which is a new enumeration type. In addition, `ValType` is
extended with the constructor `Bot` to represent the special value
bottom type. It is special in the sense that it can only appear during
validation as there is not surface syntax for it (this is in
accordance with the spec). Concretely, the `ValType`, `RefType`, and
`HeapType` are now defined as follows.

```rust
pub enum ValType {
    /// The value type is i32.
    I32,
    /// The value type is i64.
    I64,
    /// The value type is f32.
    F32,
    /// The value type is f64.
    F64,
    /// The value type is v128.
    V128,
    /// The value type is a reference. Which type of reference is decided by
    /// RefType. This is a change in syntax from the function references proposal,
    /// which now provides FuncRef and ExternRef as sugar for the generic ref
    /// construct.
    Ref(RefType),
    /// Special bottom type.
    Bot,
}

pub struct RefType {
    /// Whether it's nullable
    pub nullable: bool,
    /// The relevant heap type
    pub heap_type: HeapType,
}

pub enum HeapType {
    /// It seems by example that u32s are directly used for arbitrary indexes,
    /// but maybe a higher-level structure like TypeRef is relevant here?
    Index(u32),
    /// From reference types
    Func,
    /// From reference types
    Extern,
    /// Special bottom heap type
    Bot,
}
```

The validation algorithm has been adapted to follow that of the
pseudocode algorithm in the appendix of the spec. We have made a few
administrative changes such as plumbing an instance of
`WasmModuleResources` around, because whenever a reference type has
heap type `Index(i)` we need to look up the defined type at index
`i`. The interface of `WasmModuleResources` has been extended with the
following new methods.

```rust
fn type_index_of_function(&self, func_idx: u32) -> Option<u32>;
fn matches(&self, t1: ValType, t2: ValType) -> bool;
fn check_value_type(
    &self,
    t: ValType,
    features: &WasmFeatures,
    offset: usize
) -> Result<(), BinaryReaderError>;
```

These methods are used during validation:

 * `type_index_of_function` is necessary to obtain the result type of `RefFunc`
 * `matches` implements the subtyping relation on types; it is used in
   both operand validation and in element validation. It may need to
   peek into context to retrieve function types.
 * `check_value_type` is again used all over and needs to be shared. It now
    needs access to the context because a value type with an invalid heap index
    (depending on the number of types in the context) is not valid

The validation procedure has obviously been extended with the new
instructions; the only previous instruction whose validation needed to
be updated is `Select`.

The validation helper methods has changed too.

```rust
fn pop_operand(
    &mut self,
    expected: Option<ValType>,
    resources: &impl WasmModuleResources,
) -> OperatorValidatorResult<ValType>

fn pop_ref(
    &mut self,
    resources: &impl WasmModuleResources,
) -> OperatorValidatorResult<RefType>
```

Comments and feedback are most welcome --- we have tried to follow the
structure of the code base to the best of our abilities, however, we
are not completely sure we have put the shared logic
(e.g. `type_index_of_function`, `matches`, and `check_value_type`) in
the right places. Also, help with getting the crates skrink, smith,
and mutate up to date would be much appreciated.

Additionally, we have another patch that makes wasmtime compile and
pass the testsuite (without function references) with our modified
wasm-tools (c.f. effect-handlers/wasmtime#3).

Co-authored-by: Daniel Hillerström <[email protected]>
Co-authored-by: cosine <[email protected]>
  • Loading branch information
dhil and CosineP committed Aug 3, 2022
1 parent b70721d commit 653ea36
Showing 0 changed files with 0 additions and 0 deletions.

0 comments on commit 653ea36

Please sign in to comment.