Skip to content

Commit

Permalink
Merge #787
Browse files Browse the repository at this point in the history
787: feat(interface-types) Implement Interface Types (WIT) r=Hywan a=Hywan

So far, this PR implements a new crate named `wasmer-interface-types`. The goal is to implement the WebAssembly Interface Types (WIT) proposal, https://github.com/WebAssembly/interface-types. Keep in mind the proposal is highly unstable and experimental.

The `wasmer-interface-types` is designed to be _runtime agnostic_, which means that there is no connection between this crate and `wasmer-runtime-core` or `wasmer-runtime` (or any backend crates). The hope is that other runtimes could use `wasmer-interface-types` according to their needs.

The `wasmer-interface-types` is composed of 4 parts:
* AST: [The WIT language, represented as an AST](https://github.com/Hywan/wasmer/blob/feat-interface-types/lib/interface-types/src/ast.rs) (it's not really abstract though),
* Decoders: So far, it contains only [one parser that reads the WIT binary language](https://github.com/Hywan/wasmer/blob/feat-interface-types/lib/interface-types/src/decoders/binary.rs) and produces an AST,
* Encoders: So far, it contains only [one compiler that transforms the AST into "WIT.wat”](https://github.com/Hywan/wasmer/blob/feat-interface-types/lib/interface-types/src/encoders/wat.rs), i.e. the textual representation of an Interface Types AST
* Instructions: WIT defines a new concept called Adapters. An adapter contains a set of instructions. Those instructions are executed when data are bound. So, in more details, this module contains:
  * [`interpreter.rs`](https://github.com/Hywan/wasmer/blob/feat-interface-types/lib/interface-types/src/interpreter/mod.rs), a stack-based interpreter, defined by:
    * A compiler that transforms a set of instructions into a set of _executable_ instructions,
    * A stack,
    * A runtime that holds the “invocation inputs” (arguments of the interpreter), the stack, and the Wasm instance (which holds the exports, the imports, the memories, the tables etc.),
  * [`stack.rs`](https://github.com/Hywan/wasmer/blob/feat-interface-types/lib/interface-types/src/interpreter/stack.rs), a very light and generic stack implementation, exposing only the API required by the interpreter,
  * [`wasm/*.rs`](https://github.com/Hywan/wasmer/blob/feat-interface-types/lib/interface-types/src/interpreter/wasm/structures.rs), a set of enums, types, and traits to represent a Wasm runtime —basically this is the part a runtime should take a look to support the `wasmer-interface-types` crate—.

Progression:

* [x] WIT binary parser,
* [x] WIT.wat compiler,
* [ ] Interpreter:
  * [ ] Wasm runtime traits to represent:
    * [x] Instance,
    * [x] Export,
    * [x] Memory,
    * [x] Import,
    * [ ] Table,
  * [x] Generic stack implementation,
  * [ ] Implemented instructions:
    * [x] `arg.get`,
    * [x] `call`,
    * [x] `call-export`,
    * [x] `read-utf8`,
    * [x] `write-utf8`,
    * [ ] `as-wasm`,
    * [ ] `as-interface`
    * [ ] `table-ref-add`
    * [ ] `table-ref-get`
    * [ ] `call-method`
    * [ ] `make-record`
    * [ ] `get-field`
    * [ ] `const`
    * [ ] `fold-seq`
    * [ ] `add`
    * [ ] `mem-to-seq`
    * [ ] `load`
    * [ ] `seq.new`
    * [ ] `list.push`
    * [ ] `repeat-until`
    * [ ] `seq-to-mem`
    * [ ] `store`
* [ ] Plug `wasmer-interface-types` into `wasmer-runtime-core`

Co-authored-by: Ivan Enderlin <ivan.enderlin@hoa-project.net>
  • Loading branch information
bors[bot] and Hywan authored Feb 13, 2020
2 parents f2d9a49 + c697e68 commit 16245c6
Show file tree
Hide file tree
Showing 22 changed files with 3,868 additions and 120 deletions.
297 changes: 177 additions & 120 deletions Cargo.lock

Large diffs are not rendered by default.

1 change: 1 addition & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,7 @@ members = [
"lib/wasi-tests",
"lib/emscripten-tests",
"lib/middleware-common-tests",
"lib/interface-types",
"examples/parallel",
"examples/plugin-for-example",
"examples/parallel-guest",
Expand Down
11 changes: 11 additions & 0 deletions lib/interface-types/Cargo.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
[package]
name = "wasmer-interface-types"
version = "0.13.1"
description = "WebAssembly Interface Types library for Wasmer"
license = "MIT"
authors = ["The Wasmer Engineering Team <engineering@wasmer.io>"]
repository = "https://github.com/wasmerio/wasmer"
edition = "2018"

[dependencies]
nom = "5.1"
209 changes: 209 additions & 0 deletions lib/interface-types/src/ast.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,209 @@
//! Represents the WIT language as a tree. This is the central
//! representation of the language.

use crate::interpreter::Instruction;
use std::str;

/// Represents the types supported by WIT.
#[derive(PartialEq, Clone, Debug)]
pub enum InterfaceType {
/// An integer.
Int,

/// A float.
Float,

/// Opaque reference.
Any,

/// A string.
String,

/// A sequence.
Seq,

/// A 32-bits integer.
I32,

/// A 64-bits integer.
I64,

/// A 32-bits float.
F32,

/// A 64-bits float.
F64,

/// An `any` reference.
AnyRef,
}

/// Represents the kind of adapter.
#[derive(PartialEq, Debug)]
pub(crate) enum AdapterKind {
/// An adapter defined for an imported function of a WebAssembly instance.
Import,

/// An adapter defined for an exported function of a WebAssembly instance.
Export,

/// A helper function.
HelperFunction,
}

/// Represents an exported function signature.
#[derive(PartialEq, Debug)]
pub struct Export<'input> {
/// The function name.
pub name: &'input str,

/// The function input types.
pub input_types: Vec<InterfaceType>,

/// The function output types.
pub output_types: Vec<InterfaceType>,
}

/// Represents an imported function signature.
#[derive(PartialEq, Debug)]
pub struct Import<'input> {
/// The function namespace.
pub namespace: &'input str,

/// The function name.
pub name: &'input str,

/// The function input types.
pub input_types: Vec<InterfaceType>,

/// The function output types.
pub output_types: Vec<InterfaceType>,
}

/// Represents a structural type.
#[derive(PartialEq, Debug)]
pub struct Type<'input> {
/// The type name.
pub name: &'input str,

/// The field names.
field_names: Vec<&'input str>,

/// The field types.
field_types: Vec<InterfaceType>,
}

impl<'input> Type<'input> {
/// Creates a new `Type`.
///
/// The constructor panics if there is the length of `names` is
/// different than the length of `types`.
pub fn new(type_name: &'input str, names: Vec<&'input str>, types: Vec<InterfaceType>) -> Self {
assert_eq!(
names.len(),
types.len(),
"There must be the same number of field names than field types."
);

Self {
name: type_name,
field_names: names,
field_types: types,
}
}

/// Adds a new field to the type.
pub fn add_field(&mut self, name: &'input str, ty: InterfaceType) {
self.field_names.push(name);
self.field_types.push(ty);
}

/// Returns the field names.
pub fn field_names(&self) -> &Vec<&'input str> {
&self.field_names
}

/// Returns the field types.
pub fn field_types(&self) -> &Vec<InterfaceType> {
&self.field_types
}
}

/// Represents an adapter.
#[derive(PartialEq, Debug)]
pub enum Adapter<'input> {
/// An adapter for an imported function.
Import {
/// The function namespace.
namespace: &'input str,

/// The function name.
name: &'input str,

/// The function input types.
input_types: Vec<InterfaceType>,

/// The function output types.
output_types: Vec<InterfaceType>,

/// The instructions of the adapter.
instructions: Vec<Instruction<'input>>,
},

/// An adapter for an exported function.
Export {
/// The function name.
name: &'input str,

/// The function input types.
input_types: Vec<InterfaceType>,

/// The function output types.
output_types: Vec<InterfaceType>,

/// The instructions of the adapter.
instructions: Vec<Instruction<'input>>,
},

/// An adapter for a helper function.
HelperFunction {
/// The helper name.
name: &'input str,

/// The helper input types.
input_types: Vec<InterfaceType>,

/// The helper output types.
output_types: Vec<InterfaceType>,

/// The instructions of the adapter.
instructions: Vec<Instruction<'input>>,
},
}

/// Represented a forwarded export.
#[derive(PartialEq, Debug)]
pub struct Forward<'input> {
/// The forwarded export name.
pub name: &'input str,
}

/// Represents a set of interfaces, i.e. it entirely describes a WIT
/// definition.
#[derive(PartialEq, Debug)]
pub struct Interfaces<'input> {
/// All the exported functions.
pub exports: Vec<Export<'input>>,

/// All the types.
pub types: Vec<Type<'input>>,

/// All the imported functions.
pub imports: Vec<Import<'input>>,

/// All the adapters.
pub adapters: Vec<Adapter<'input>>,

/// All the forwarded functions.
pub forwards: Vec<Forward<'input>>,
}
Loading

0 comments on commit 16245c6

Please sign in to comment.