From 9db622796d10caf7dfe2b480032e8aeac2e41c6a Mon Sep 17 00:00:00 2001 From: Alex Crichton Date: Tue, 19 Apr 2022 08:58:13 -0700 Subject: [PATCH] Drop support for old-style `*.witx` files I today started looking at updating this project to the new draft of the canonical ABI specified at WebAssembly/component-model#23 and while there's quite a few changes that need to happen the first thing that struck me was that maintaining all of the support for old-style witx files is pretty onerous. Especially the ABI-calculating code has lots of special cases for various witx constructs and the Preview1 ABI, and I wasn't really sure how to update this in many situations. Overall the original purpose of the witx support was to prove out that it's possible to support both the old witx abi and the new canonical ABI in the same generator. The canonical ABI has changed significantly in the meantime however and this doesn't necessarily make sense to do any more. I think it would be best now to reevaluate at the point when WASI is ready to switch to the component model what to do with the old witx support. I no longer think that "build it in here" is the obvious option. As this diff shows there's quite a bit of weight to carry the old witx abis as this commit clocks in at nearly 7000 lines removed. The specifics being dropped here are: * Parsing support for `*.witx` * Support for `Pointer` and `ConstPointer` * Support for `WitxInstruction` * Support for push/pull buffers The push/pull buffer feature was never actually fully implemented, even for Rust hosts they only kind-of worked. Most other generators never even implemented support for them. Additionally support for other `*.witx` constructs was somewhat spotty at best with very few tests. My hope is that there are no existing users of this support. If there are then I think it's best to re-evaluate how best to solve the scenario on-hand. --- Cargo.lock | 14 +- Cargo.toml | 2 +- crates/gen-c/Cargo.toml | 3 - crates/gen-c/src/lib.rs | 150 +--- crates/gen-core/Cargo.toml | 3 - crates/gen-core/src/lib.rs | 112 +-- crates/gen-js/Cargo.toml | 3 - crates/gen-js/src/lib.rs | 229 +---- crates/gen-markdown/src/lib.rs | 68 +- crates/gen-rust-wasm/Cargo.toml | 3 - crates/gen-rust-wasm/src/lib.rs | 279 +----- crates/gen-rust-wasm/tests/codegen.rs | 1 - crates/gen-rust/src/lib.rs | 115 +-- crates/gen-spidermonkey/src/lib.rs | 70 +- crates/gen-wasmtime-py/Cargo.toml | 3 - crates/gen-wasmtime-py/src/lib.rs | 161 +--- crates/gen-wasmtime/Cargo.toml | 3 - crates/gen-wasmtime/src/lib.rs | 372 +------- crates/gen-wasmtime/tests/codegen.rs | 1 - crates/parser/Cargo.toml | 4 - crates/parser/src/abi.rs | 844 +++--------------- crates/parser/src/ast.rs | 305 ------- crates/parser/src/ast/lex.rs | 6 - crates/parser/src/ast/resolve.rs | 56 +- crates/parser/src/lib.rs | 42 +- crates/parser/src/sizealign.rs | 12 +- crates/parser/tests/all.rs | 8 - crates/parser/tests/ui/parse-fail/cycle6.wit | 3 - .../tests/ui/parse-fail/cycle6.wit.result | 5 - crates/parser/tests/ui/parse-fail/cycle7.wit | 3 - .../tests/ui/parse-fail/cycle7.wit.result | 5 - crates/parser/tests/ui/types.wit | 2 - crates/parser/tests/ui/types.wit.result | 44 +- crates/parser/tests/ui/wasi-http.wit | 4 +- crates/parser/tests/ui/wasi-http.wit.result | 8 +- crates/rust-wasm-impl/Cargo.toml | 3 - crates/rust-wasm/Cargo.toml | 3 - crates/rust-wasm/src/exports.rs | 239 ----- crates/rust-wasm/src/imports.rs | 105 --- crates/rust-wasm/src/lib.rs | 2 - crates/test-helpers/Cargo.toml | 3 +- crates/test-helpers/src/lib.rs | 10 - crates/test-rust-wasm/Cargo.toml | 6 +- crates/test-rust-wasm/src/bin/buffers.rs | 3 - crates/wasmlink/Cargo.toml | 2 +- crates/wasmlink/src/adapter/call.rs | 6 - crates/wasmlink/src/module.rs | 3 +- crates/wasmlink/src/resources.rs | 3 +- crates/wasmtime-impl/Cargo.toml | 1 - crates/wasmtime/Cargo.toml | 3 - crates/wasmtime/src/exports.rs | 90 -- crates/wasmtime/src/imports.rs | 415 --------- crates/wasmtime/src/lib.rs | 12 - crates/wit-bindgen-demo/Cargo.toml | 2 +- crates/wit-component/src/decoding.rs | 5 +- crates/wit-component/src/encoding.rs | 23 +- crates/wit-component/src/printing.rs | 10 - tests/codegen/legacy.witx | 68 -- tests/codegen/wasi-next/wasi-next.wit | 411 --------- tests/codegen/wasi-next/wasi-types.wit | 562 ------------ .../wasi_snapshot_preview1/typenames.witx | 751 ---------------- .../wasi-snapshot-preview1.witx | 507 ----------- tests/runtime/buffers/exports.wit | 46 - tests/runtime/buffers/host.py | 91 -- tests/runtime/buffers/host.rs | 194 ---- tests/runtime/buffers/host.ts | 77 -- tests/runtime/buffers/imports.wit | 36 - tests/runtime/buffers/wasm.c | 132 --- tests/runtime/buffers/wasm.rs | 205 ----- 69 files changed, 231 insertions(+), 6741 deletions(-) delete mode 100644 crates/parser/tests/ui/parse-fail/cycle6.wit delete mode 100644 crates/parser/tests/ui/parse-fail/cycle6.wit.result delete mode 100644 crates/parser/tests/ui/parse-fail/cycle7.wit delete mode 100644 crates/parser/tests/ui/parse-fail/cycle7.wit.result delete mode 100644 crates/rust-wasm/src/exports.rs delete mode 100644 crates/rust-wasm/src/imports.rs delete mode 100644 crates/test-rust-wasm/src/bin/buffers.rs delete mode 100644 crates/wasmtime/src/exports.rs delete mode 100644 crates/wasmtime/src/imports.rs delete mode 100644 tests/codegen/legacy.witx delete mode 100644 tests/codegen/wasi-next/wasi-next.wit delete mode 100644 tests/codegen/wasi-next/wasi-types.wit delete mode 100644 tests/codegen/wasi_snapshot_preview1/typenames.witx delete mode 100644 tests/codegen/wasi_snapshot_preview1/wasi-snapshot-preview1.witx delete mode 100644 tests/runtime/buffers/exports.wit delete mode 100644 tests/runtime/buffers/host.py delete mode 100644 tests/runtime/buffers/host.rs delete mode 100644 tests/runtime/buffers/host.ts delete mode 100644 tests/runtime/buffers/imports.wit delete mode 100644 tests/runtime/buffers/wasm.c delete mode 100644 tests/runtime/buffers/wasm.rs diff --git a/Cargo.lock b/Cargo.lock index af09fc578..fac979ae9 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2019,7 +2019,7 @@ dependencies = [ "quote", "shellexpand", "syn", - "witx 0.9.1", + "witx", ] [[package]] @@ -2277,7 +2277,6 @@ dependencies = [ "unicode-normalization", "unicode-xid", "wast 33.0.0", - "witx 0.10.0", ] [[package]] @@ -2292,17 +2291,6 @@ dependencies = [ "wast 35.0.2", ] -[[package]] -name = "witx" -version = "0.10.0" -source = "git+https://github.com/alexcrichton/WASI?branch=abi-next#70a8c6363fb26be655e59a2587bd191e7baee59b" -dependencies = [ - "anyhow", - "log", - "thiserror", - "wast 33.0.0", -] - [[package]] name = "zstd" version = "0.10.0+zstd.1.5.2" diff --git a/Cargo.toml b/Cargo.toml index 0f823f018..cd948e301 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -21,7 +21,7 @@ test = false [dependencies] anyhow = "1.0" structopt = { version = "0.3", default-features = false } -wit-bindgen-gen-core = { path = 'crates/gen-core', features = ['witx-compat'] } +wit-bindgen-gen-core = { path = 'crates/gen-core' } wit-bindgen-gen-rust-wasm = { path = 'crates/gen-rust-wasm', features = ['structopt'] } wit-bindgen-gen-wasmtime = { path = 'crates/gen-wasmtime', features = ['structopt'] } wit-bindgen-gen-wasmtime-py = { path = 'crates/gen-wasmtime-py', features = ['structopt'] } diff --git a/crates/gen-c/Cargo.toml b/crates/gen-c/Cargo.toml index d33a9f349..a50dd8fdb 100644 --- a/crates/gen-c/Cargo.toml +++ b/crates/gen-c/Cargo.toml @@ -15,6 +15,3 @@ structopt = { version = "0.3", default-features = false, optional = true } [dev-dependencies] test-helpers = { path = '../test-helpers', features = ['wit-bindgen-gen-c'] } - -[features] -witx-compat = ['wit-bindgen-gen-core/witx-compat'] diff --git a/crates/gen-c/src/lib.rs b/crates/gen-c/src/lib.rs index 00e27490b..8c3383dee 100644 --- a/crates/gen-c/src/lib.rs +++ b/crates/gen-c/src/lib.rs @@ -2,7 +2,7 @@ use heck::*; use std::collections::{BTreeSet, HashMap, HashSet}; use std::mem; use wit_bindgen_gen_core::wit_parser::abi::{ - AbiVariant, Bindgen, Bitcast, Instruction, LiftLower, WasmType, WitxInstruction, + AbiVariant, Bindgen, Bitcast, Instruction, LiftLower, WasmType, }; use wit_bindgen_gen_core::{wit_parser::*, Direction, Files, Generator, Ns}; @@ -173,12 +173,7 @@ impl C { TypeDefKind::Type(t) => self.is_arg_by_pointer(iface, t), TypeDefKind::Variant(v) => !v.is_enum(), TypeDefKind::Record(r) if r.is_flags() => false, - TypeDefKind::Pointer(_) - | TypeDefKind::ConstPointer(_) - | TypeDefKind::Record(_) - | TypeDefKind::List(_) - | TypeDefKind::PushBuffer(_) - | TypeDefKind::PullBuffer(_) => true, + TypeDefKind::Record(_) | TypeDefKind::List(_) => true, }, _ => false, } @@ -257,24 +252,12 @@ impl C { self.print_ty_name(iface, &Type::Id(*id)); self.src.h("_t"); } - TypeDefKind::Pointer(t) => { - self.print_ty(iface, t); - self.src.h("*"); - } - TypeDefKind::ConstPointer(t) => { - self.src.h("const "); - self.print_ty(iface, t); - self.src.h("*"); - } TypeDefKind::List(Type::Char) => { self.print_namespace(iface); self.src.h("string_t"); self.needs_string = true; } - TypeDefKind::Record(_) - | TypeDefKind::List(_) - | TypeDefKind::PushBuffer(_) - | TypeDefKind::PullBuffer(_) => { + TypeDefKind::Record(_) | TypeDefKind::List(_) => { self.public_anonymous_types.insert(*id); self.private_anonymous_types.remove(id); self.print_namespace(iface); @@ -339,27 +322,11 @@ impl C { unimplemented!(); } } - TypeDefKind::Pointer(t) => { - self.src.h("ptr_"); - self.print_ty_name(iface, t); - } - TypeDefKind::ConstPointer(t) => { - self.src.h("const_ptr_ "); - self.print_ty_name(iface, t); - } TypeDefKind::List(Type::Char) => self.src.h("string"), TypeDefKind::List(t) => { self.src.h("list_"); self.print_ty_name(iface, t); } - TypeDefKind::PushBuffer(t) => { - self.src.h("push_buffer_"); - self.print_ty_name(iface, t); - } - TypeDefKind::PullBuffer(t) => { - self.src.h("pull_buffer_"); - self.print_ty_name(iface, t); - } } } } @@ -370,7 +337,7 @@ impl C { self.src.h("typedef "); let kind = &iface.types[ty].kind; match kind { - TypeDefKind::Type(_) | TypeDefKind::Pointer(_) | TypeDefKind::ConstPointer(_) => { + TypeDefKind::Type(_) => { unreachable!() } TypeDefKind::Record(r) => { @@ -424,17 +391,6 @@ impl C { self.src.h("size_t len;\n"); self.src.h("}"); } - TypeDefKind::PushBuffer(t) | TypeDefKind::PullBuffer(t) => { - self.src.h("struct {\n"); - self.src.h("int32_t is_handle;\n"); - if let TypeDefKind::PullBuffer(_) = kind { - self.src.h("const "); - } - self.print_ty(iface, t); - self.src.h(" *ptr;\n"); - self.src.h("size_t len;\n"); - self.src.h("}"); - } } self.src.h(" "); self.print_namespace(iface); @@ -565,11 +521,6 @@ impl C { } self.src.c("}\n"); } - - TypeDefKind::PushBuffer(_) - | TypeDefKind::PullBuffer(_) - | TypeDefKind::Pointer(_) - | TypeDefKind::ConstPointer(_) => {} } self.src.c("}\n"); } @@ -584,8 +535,6 @@ impl C { TypeDefKind::Type(t) => self.owns_anything(iface, t), TypeDefKind::Record(r) => r.fields.iter().any(|t| self.owns_anything(iface, &t.ty)), TypeDefKind::List(_) => true, - TypeDefKind::PushBuffer(_) | TypeDefKind::PullBuffer(_) => false, - TypeDefKind::Pointer(_) | TypeDefKind::ConstPointer(_) => false, TypeDefKind::Variant(v) => v .cases .iter() @@ -640,14 +589,7 @@ impl Return { TypeDefKind::Record(_) => self.splat_tuples(iface, ty, orig_ty), // other records/lists/buffers always go to return pointers - TypeDefKind::List(_) | TypeDefKind::PushBuffer(_) | TypeDefKind::PullBuffer(_) => { - self.retptrs.push(*orig_ty) - } - - // pointers are scalars - TypeDefKind::Pointer(_) | TypeDefKind::ConstPointer(_) => { - self.scalar = Some(Scalar::Type(*orig_ty)); - } + TypeDefKind::List(_) => self.retptrs.push(*orig_ty), // Enums are scalars (this includes bools) TypeDefKind::Variant(v) if v.is_enum() => { @@ -713,7 +655,7 @@ impl Return { impl Generator for C { fn preprocess_one(&mut self, iface: &Interface, dir: Direction) { let variant = Self::abi_variant(dir); - self.sizes.fill(variant, iface); + self.sizes.fill(iface); self.in_import = variant == AbiVariant::GuestImport; for func in iface.functions.iter() { @@ -879,56 +821,10 @@ impl Generator for C { .insert(id, mem::replace(&mut self.src.header, prev)); } - fn type_pointer( - &mut self, - iface: &Interface, - _id: TypeId, - name: &str, - const_: bool, - ty: &Type, - docs: &Docs, - ) { - drop((iface, _id, name, const_, ty, docs)); - } - fn type_builtin(&mut self, iface: &Interface, _id: TypeId, name: &str, ty: &Type, docs: &Docs) { drop((iface, _id, name, ty, docs)); } - fn type_push_buffer( - &mut self, - iface: &Interface, - id: TypeId, - name: &str, - ty: &Type, - docs: &Docs, - ) { - self.type_pull_buffer(iface, id, name, ty, docs); - } - - fn type_pull_buffer( - &mut self, - iface: &Interface, - id: TypeId, - name: &str, - ty: &Type, - docs: &Docs, - ) { - let prev = mem::take(&mut self.src.header); - self.docs(docs); - self.src.h("typedef struct {\n"); - self.src.h("int32_t is_handle;\n"); - self.print_ty(iface, ty); - self.src.h(" *ptr;\n"); - self.src.h("size_t len;\n"); - self.src.h("} "); - self.print_namespace(iface); - self.src.h(&name.to_snake_case()); - self.src.h("_t;\n"); - self.types - .insert(id, mem::replace(&mut self.src.header, prev)); - } - fn import(&mut self, iface: &Interface, func: &Function) { assert!(!func.is_async, "async not supported yet"); let prev = mem::take(&mut self.src); @@ -1365,13 +1261,6 @@ impl Bindgen for FunctionBindgen<'_> { self.blocks.push((src.into(), mem::take(operands))); } - fn allocate_typed_space(&mut self, iface: &Interface, ty: TypeId) -> String { - let ty = self.gen.type_string(iface, &Type::Id(ty)); - let name = self.locals.tmp("tmp"); - self.src.push_str(&format!("{} {};\n", ty, name)); - format!("(int32_t) (&{})", name) - } - fn i64_return_pointer_area(&mut self, amt: usize) -> String { assert!(amt <= self.gen.i64_return_pointer_area_size); let ptr = self.locals.tmp("ptr"); @@ -1672,18 +1561,6 @@ impl Bindgen for FunctionBindgen<'_> { Instruction::IterElem { .. } => results.push("e".to_string()), Instruction::IterBasePointer => results.push("base".to_string()), - Instruction::BufferLowerPtrLen { .. } => { - drop(self.blocks.pop().unwrap()); - results.push(format!("({}).is_handle", operands[0])); - results.push(format!("(int32_t) ({}).ptr", operands[0])); - results.push(format!("({}).len", operands[0])); - } - - Instruction::BufferLiftHandle { .. } => { - drop(self.blocks.pop().unwrap()); - results.push(format!("({}).idx", operands[0])); - } - Instruction::CallWasm { sig, .. } => { match sig.results.len() { 0 => {} @@ -1897,21 +1774,6 @@ impl Bindgen for FunctionBindgen<'_> { self.src.push_str("INVALIDSTORE"); } - Instruction::Witx { instr } => match instr { - WitxInstruction::I32FromPointer | WitxInstruction::I32FromConstPointer => { - results.push(format!("(int32_t) ({})", operands[0])) - } - WitxInstruction::AddrOf => { - results.push(format!("(int32_t) (&{})", operands[0])); - } - WitxInstruction::ReuseReturn => { - results.push(self.wasm_return.clone().unwrap()); - } - i => unimplemented!("{:?}", i), - }, - - Instruction::BufferPayloadName => results.push("INVALID".into()), - i => unimplemented!("{:?}", i), } } diff --git a/crates/gen-core/Cargo.toml b/crates/gen-core/Cargo.toml index dce4e4652..b3bc9c90c 100644 --- a/crates/gen-core/Cargo.toml +++ b/crates/gen-core/Cargo.toml @@ -10,6 +10,3 @@ doctest = false [dependencies] wit-parser = { path = '../parser' } anyhow = "1" - -[features] -witx-compat = ['wit-parser/witx-compat'] diff --git a/crates/gen-core/src/lib.rs b/crates/gen-core/src/lib.rs index 5c7563ef9..959b99f9b 100644 --- a/crates/gen-core/src/lib.rs +++ b/crates/gen-core/src/lib.rs @@ -1,8 +1,7 @@ use anyhow::Result; -use std::collections::{btree_map::Entry, BTreeMap, HashMap, HashSet}; +use std::collections::{btree_map::Entry, BTreeMap, HashMap}; use std::ops::Deref; use std::path::Path; -use wit_parser::abi::Abi; use wit_parser::*; pub use wit_parser; @@ -67,32 +66,7 @@ pub trait Generator { fn type_resource(&mut self, iface: &Interface, ty: ResourceId); fn type_alias(&mut self, iface: &Interface, id: TypeId, name: &str, ty: &Type, docs: &Docs); fn type_list(&mut self, iface: &Interface, id: TypeId, name: &str, ty: &Type, docs: &Docs); - fn type_pointer( - &mut self, - iface: &Interface, - id: TypeId, - name: &str, - const_: bool, - ty: &Type, - docs: &Docs, - ); fn type_builtin(&mut self, iface: &Interface, id: TypeId, name: &str, ty: &Type, docs: &Docs); - fn type_push_buffer( - &mut self, - iface: &Interface, - id: TypeId, - name: &str, - ty: &Type, - docs: &Docs, - ); - fn type_pull_buffer( - &mut self, - iface: &Interface, - id: TypeId, - name: &str, - ty: &Type, - docs: &Docs, - ); // fn const_(&mut self, iface: &Interface, name: &str, ty: &str, val: u64, docs: &Docs); fn import(&mut self, iface: &Interface, func: &Function); fn export(&mut self, iface: &Interface, func: &Function); @@ -118,13 +92,7 @@ pub trait Generator { self.type_variant(iface, id, name, variant, &ty.docs) } TypeDefKind::List(t) => self.type_list(iface, id, name, t, &ty.docs), - TypeDefKind::PushBuffer(t) => self.type_push_buffer(iface, id, name, t, &ty.docs), - TypeDefKind::PullBuffer(t) => self.type_pull_buffer(iface, id, name, t, &ty.docs), TypeDefKind::Type(t) => self.type_alias(iface, id, name, t, &ty.docs), - TypeDefKind::Pointer(t) => self.type_pointer(iface, id, name, false, t, &ty.docs), - TypeDefKind::ConstPointer(t) => { - self.type_pointer(iface, id, name, true, t, &ty.docs) - } } } @@ -164,8 +132,6 @@ pub trait Generator { #[derive(Default)] pub struct Types { type_info: HashMap, - handle_dtors: HashSet, - dtor_funcs: HashSet, } #[derive(Default, Clone, Copy)] @@ -183,12 +149,6 @@ pub struct TypeInfo { /// Whether or not this type (transitively) has a handle. pub has_handle: bool, - - /// Whether or not this type (transitively) has a push buffer. - pub has_push_buffer: bool, - - /// Whether or not this type (transitively) has a pull buffer. - pub has_pull_buffer: bool, } impl std::ops::BitOrAssign for TypeInfo { @@ -197,8 +157,6 @@ impl std::ops::BitOrAssign for TypeInfo { self.result |= rhs.result; self.has_list |= rhs.has_list; self.has_handle |= rhs.has_handle; - self.has_push_buffer |= rhs.has_push_buffer; - self.has_pull_buffer |= rhs.has_pull_buffer; } } @@ -214,50 +172,6 @@ impl Types { for (_, ty) in f.results.iter() { self.set_param_result_ty(iface, ty, false, true); } - self.maybe_set_preview1_dtor(iface, f); - } - } - - fn maybe_set_preview1_dtor(&mut self, iface: &Interface, f: &Function) { - match f.abi { - Abi::Preview1 => {} - _ => return, - } - - // Dtors only happen when the function has a singular parameter - if f.params.len() != 1 { - return; - } - - // Dtors are inferred to be `${type}_close` right now. - let name = f.name.as_str(); - let prefix = match name.strip_suffix("_close") { - Some(prefix) => prefix, - None => return, - }; - - // The singular parameter type name must be the prefix of this - // function's own name. - let resource = match find_handle(iface, &f.params[0].1) { - Some(id) => id, - None => return, - }; - if iface.resources[resource].name != prefix { - return; - } - - self.handle_dtors.insert(resource); - self.dtor_funcs.insert(f.name.to_string()); - - fn find_handle(iface: &Interface, ty: &Type) -> Option { - match ty { - Type::Handle(r) => Some(*r), - Type::Id(id) => match &iface.types[*id].kind { - TypeDefKind::Type(t) => find_handle(iface, t), - _ => None, - }, - _ => None, - } } } @@ -265,14 +179,6 @@ impl Types { self.type_info[&id] } - pub fn has_preview1_dtor(&self, resource: ResourceId) -> bool { - self.handle_dtors.contains(&resource) - } - - pub fn is_preview1_dtor_func(&self, func: &Function) -> bool { - self.dtor_funcs.contains(&func.name) - } - pub fn type_id_info(&mut self, iface: &Interface, ty: TypeId) -> TypeInfo { if let Some(info) = self.type_info.get(&ty) { return *info; @@ -295,16 +201,8 @@ impl Types { info = self.type_info(iface, ty); info.has_list = true; } - TypeDefKind::PushBuffer(ty) => { - info = self.type_info(iface, ty); - info.has_push_buffer = true; - } - TypeDefKind::PullBuffer(ty) => { + TypeDefKind::Type(ty) => { info = self.type_info(iface, ty); - info.has_pull_buffer = true; - } - TypeDefKind::ConstPointer(ty) | TypeDefKind::Pointer(ty) | TypeDefKind::Type(ty) => { - info = self.type_info(iface, ty) } } self.type_info.insert(ty, info); @@ -335,11 +233,7 @@ impl Types { } } } - TypeDefKind::List(ty) - | TypeDefKind::PushBuffer(ty) - | TypeDefKind::PullBuffer(ty) - | TypeDefKind::Pointer(ty) - | TypeDefKind::ConstPointer(ty) => self.set_param_result_ty(iface, ty, param, result), + TypeDefKind::List(ty) => self.set_param_result_ty(iface, ty, param, result), TypeDefKind::Type(ty) => self.set_param_result_ty(iface, ty, param, result), } } diff --git a/crates/gen-js/Cargo.toml b/crates/gen-js/Cargo.toml index 4c4565da0..30f38e0a1 100644 --- a/crates/gen-js/Cargo.toml +++ b/crates/gen-js/Cargo.toml @@ -15,6 +15,3 @@ structopt = { version = "0.3", default-features = false, optional = true } [dev-dependencies] test-helpers = { path = '../test-helpers', features = ['wit-bindgen-gen-js'] } - -[features] -wit-compat = ['wit-bindgen-gen-core/witx-compat'] diff --git a/crates/gen-js/src/lib.rs b/crates/gen-js/src/lib.rs index fc3bf6281..57492f877 100644 --- a/crates/gen-js/src/lib.rs +++ b/crates/gen-js/src/lib.rs @@ -2,7 +2,7 @@ use heck::*; use std::collections::{BTreeMap, BTreeSet, HashMap}; use std::mem; use wit_bindgen_gen_core::wit_parser::abi::{ - AbiVariant, Bindgen, Bitcast, Instruction, LiftLower, WasmType, WitxInstruction, + AbiVariant, Bindgen, Bitcast, Instruction, LiftLower, WasmType, }; use wit_bindgen_gen_core::{wit_parser::*, Direction, Files, Generator}; @@ -21,8 +21,6 @@ pub struct Js { exported_resources: BTreeSet, needs_ty_option: bool, needs_ty_result: bool, - needs_ty_push_buffer: bool, - needs_ty_pull_buffer: bool, } #[derive(Default)] @@ -57,8 +55,6 @@ enum Intrinsic { ClampGuest, ClampHost, ClampHost64, - PushBuffer, - PullBuffer, DataView, ValidateF32, ValidateF64, @@ -84,8 +80,6 @@ impl Intrinsic { Intrinsic::ClampGuest => "clamp_guest", Intrinsic::ClampHost => "clamp_host", Intrinsic::ClampHost64 => "clamp_host64", - Intrinsic::PushBuffer => "PushBuffer", - Intrinsic::PullBuffer => "PullBuffer", Intrinsic::DataView => "data_view", Intrinsic::ValidateF32 => "validate_f32", Intrinsic::ValidateF64 => "validate_f64", @@ -200,11 +194,6 @@ impl Js { } } TypeDefKind::List(v) => self.print_list(iface, v), - TypeDefKind::PushBuffer(v) => self.print_buffer(iface, true, v), - TypeDefKind::PullBuffer(v) => self.print_buffer(iface, false, v), - TypeDefKind::Pointer(_) | TypeDefKind::ConstPointer(_) => { - self.src.ts("number"); - } } } } @@ -235,24 +224,6 @@ impl Js { self.src.ts("]"); } - fn print_buffer(&mut self, iface: &Interface, push: bool, ty: &Type) { - match self.array_ty(iface, ty) { - Some(ty) => self.src.ts(ty), - None => { - if push { - self.needs_ty_push_buffer = true; - self.src.ts("PushBuffer"); - } else { - self.needs_ty_pull_buffer = true; - self.src.ts("PullBuffer"); - } - self.src.ts("<"); - self.print_ty(iface, ty); - self.src.ts(">"); - } - } - } - fn docs(&mut self, docs: &Docs) { let docs = match &docs.contents { Some(docs) => docs, @@ -373,7 +344,7 @@ impl Js { impl Generator for Js { fn preprocess_one(&mut self, iface: &Interface, dir: Direction) { let variant = Self::abi_variant(dir); - self.sizes.fill(variant, iface); + self.sizes.fill(iface); self.in_import = variant == AbiVariant::GuestImport; } @@ -530,52 +501,10 @@ impl Generator for Js { self.src.ts(";\n"); } - fn type_pointer( - &mut self, - iface: &Interface, - _id: TypeId, - name: &str, - const_: bool, - ty: &Type, - docs: &Docs, - ) { - drop((iface, _id, name, const_, ty, docs)); - } - fn type_builtin(&mut self, iface: &Interface, _id: TypeId, name: &str, ty: &Type, docs: &Docs) { drop((iface, _id, name, ty, docs)); } - fn type_push_buffer( - &mut self, - iface: &Interface, - _id: TypeId, - name: &str, - ty: &Type, - docs: &Docs, - ) { - self.docs(docs); - self.src - .ts(&format!("export type {} = ", name.to_camel_case())); - self.print_buffer(iface, true, ty); - self.src.ts(";\n"); - } - - fn type_pull_buffer( - &mut self, - iface: &Interface, - _id: TypeId, - name: &str, - ty: &Type, - docs: &Docs, - ) { - self.docs(docs); - self.src - .ts(&format!("export type {} = ", name.to_camel_case())); - self.print_buffer(iface, false, ty); - self.src.ts(";\n"); - } - // As with `abi_variant` above, we're generating host-side bindings here // so a user "export" uses the "guest import" ABI variant on the inside of // this `Generator` implementation. @@ -878,7 +807,7 @@ impl Generator for Js { } self.src.ts(" - /** + /** * This is a low-level method which can be used to add any * intrinsics necessary for this instance to operate to an * import object. @@ -1102,22 +1031,6 @@ impl Generator for Js { "export type Result = { tag: \"ok\", val: T } | { tag: \"err\", val: E };\n", ); } - if mem::take(&mut self.needs_ty_push_buffer) { - self.src.ts(" - export class PushBuffer { - length: number; - push(val: T): boolean; - } - "); - } - if mem::take(&mut self.needs_ty_pull_buffer) { - self.src.ts(" - export class PullBuffer { - length: number; - pull(): T | undefined; - } - "); - } if self.intrinsics.len() > 0 { self.src.js("import { "); @@ -1276,10 +1189,6 @@ impl Bindgen for FunctionBindgen<'_> { self.blocks.push((src.into(), mem::take(operands))); } - fn allocate_typed_space(&mut self, _iface: &Interface, _ty: TypeId) -> String { - unimplemented!() - } - fn i64_return_pointer_area(&mut self, _amt: usize) -> String { unimplemented!() } @@ -1532,7 +1441,6 @@ impl Bindgen for FunctionBindgen<'_> { } Instruction::VariantPayloadName => results.push("e".to_string()), - Instruction::BufferPayloadName => results.push("e".to_string()), Instruction::VariantLower { variant, results: result_types, @@ -1869,86 +1777,6 @@ impl Bindgen for FunctionBindgen<'_> { Instruction::IterBasePointer => results.push("base".to_string()), - Instruction::BufferLiftPtrLen { push, ty } => { - let (block, block_results) = self.blocks.pop().unwrap(); - // assert_eq!(block_results.len(), 1); - let tmp = self.tmp(); - self.needs_memory = true; - self.src - .js(&format!("const ptr{} = {};\n", tmp, operands[1])); - self.src - .js(&format!("const len{} = {};\n", tmp, operands[2])); - if let Some(ty) = self.gen.array_ty(iface, ty) { - // TODO: this is the wrong endianness - results.push(format!("new {}(memory.buffer, ptr{}, len{1})", ty, tmp)); - } else { - let size = self.gen.sizes.size(ty); - if *push { - let buf = self.gen.intrinsic(Intrinsic::PushBuffer); - assert!(block_results.is_empty()); - results.push(format!( - "new {}(ptr{}, len{1}, {}, (e, base) => {{ - {} - }})", - buf, tmp, size, block - )); - } else { - let buf = self.gen.intrinsic(Intrinsic::PullBuffer); - assert_eq!(block_results.len(), 1); - results.push(format!( - "new {}(ptr{}, len{1}, {}, (base) => {{ - {} - return {}; - }})", - buf, tmp, size, block, block_results[0], - )); - } - } - } - - // Instruction::BufferLowerHandle { push, ty } => { - // let block = self.blocks.pop().unwrap(); - // let size = self.sizes.size(ty); - // let tmp = self.tmp(); - // let handle = format!("handle{}", tmp); - // let closure = format!("closure{}", tmp); - // self.needs_buffer_transaction = true; - // if iface.all_bits_valid(ty) { - // let method = if *push { "push_out_raw" } else { "push_in_raw" }; - // self.push_str(&format!( - // "let {} = unsafe {{ buffer_transaction.{}({}) }};\n", - // handle, method, operands[0], - // )); - // } else if *push { - // self.closures.push_str(&format!( - // "let {} = |memory: &wasmtime::Memory, base: i32| {{ - // Ok(({}, {})) - // }};\n", - // closure, block, size, - // )); - // self.push_str(&format!( - // "let {} = unsafe {{ buffer_transaction.push_out({}, &{}) }};\n", - // handle, operands[0], closure, - // )); - // } else { - // let start = self.src.len(); - // self.print_ty(iface, ty, TypeMode::AllBorrowed("'_")); - // let ty = self.src[start..].to_string(); - // self.src.truncate(start); - // self.closures.push_str(&format!( - // "let {} = |memory: &wasmtime::Memory, base: i32, e: {}| {{ - // {}; - // Ok({}) - // }};\n", - // closure, ty, block, size, - // )); - // self.push_str(&format!( - // "let {} = unsafe {{ buffer_transaction.push_in({}, &{}) }};\n", - // handle, operands[0], closure, - // )); - // } - // results.push(format!("{}", handle)); - // } Instruction::CallWasm { module: _, name, @@ -2157,11 +1985,6 @@ impl Bindgen for FunctionBindgen<'_> { Instruction::I32Store8 { offset } => self.store("setInt8", *offset, operands), Instruction::I32Store16 { offset } => self.store("setInt16", *offset, operands), - Instruction::Witx { instr } => match instr { - WitxInstruction::PointerFromI32 { .. } => results.push(operands[0].clone()), - i => unimplemented!("{:?}", i), - }, - i => unimplemented!("{:?}", i), } } @@ -2213,52 +2036,6 @@ impl Js { return i; } "), - Intrinsic::PushBuffer => self.src.js(" - export class PushBuffer { - constructor(ptr, len, size, write) { - this._ptr = ptr; - this._len = len; - this._size = size; - this._write = write; - } - - get length() { - return this._len; - } - - push(val) { - if (this._len == 0) - return false; - this._len -= 1; - this._write(val, this._ptr); - this._ptr += this._size; - return true; - } - } - "), - Intrinsic::PullBuffer => self.src.js(" - export class PullBuffer { - constructor(ptr, len, size, read) { - this._len = len; - this._ptr = ptr; - this._size = size; - this._read = read; - } - - get length() { - return this._len; - } - - pull() { - if (this._len == 0) - return undefined; - this._len -= 1; - const ret = this._read(this._ptr); - this._ptr += this._size; - return ret; - } - } - "), Intrinsic::DataView => self.src.js(" let DATA_VIEW = new DataView(new ArrayBuffer()); diff --git a/crates/gen-markdown/src/lib.rs b/crates/gen-markdown/src/lib.rs index 2ab80cab8..df91200f4 100644 --- a/crates/gen-markdown/src/lib.rs +++ b/crates/gen-markdown/src/lib.rs @@ -1,7 +1,6 @@ use heck::*; use pulldown_cmark::{html, Event, LinkType, Parser, Tag}; use std::collections::HashMap; -use wit_bindgen_gen_core::wit_parser::abi::AbiVariant; use wit_bindgen_gen_core::{wit_parser, Direction, Files, Generator, Source}; use wit_parser::*; @@ -34,14 +33,6 @@ impl Markdown { Markdown::default() } - fn abi_variant(dir: Direction) -> AbiVariant { - // This generator uses the obvious direction to ABI variant mapping. - match dir { - Direction::Export => AbiVariant::GuestExport, - Direction::Import => AbiVariant::GuestImport, - } - } - fn print_ty(&mut self, iface: &Interface, ty: &Type, skip_name: bool) { match ty { Type::U8 => self.src.push_str("`u8`"), @@ -116,26 +107,6 @@ impl Markdown { self.print_ty(iface, t, false); self.src.push_str(">"); } - TypeDefKind::PushBuffer(t) => { - self.src.push_str("push-buffer<"); - self.print_ty(iface, t, false); - self.src.push_str(">"); - } - TypeDefKind::PullBuffer(t) => { - self.src.push_str("pull-buffer<"); - self.print_ty(iface, t, false); - self.src.push_str(">"); - } - TypeDefKind::Pointer(t) => { - self.src.push_str("pointer<"); - self.print_ty(iface, t, false); - self.src.push_str(">"); - } - TypeDefKind::ConstPointer(t) => { - self.src.push_str("const-pointer<"); - self.print_ty(iface, t, false); - self.src.push_str(">"); - } } } } @@ -177,9 +148,8 @@ impl Markdown { } impl Generator for Markdown { - fn preprocess_one(&mut self, iface: &Interface, dir: Direction) { - let variant = Self::abi_variant(dir); - self.sizes.fill(variant, iface); + fn preprocess_one(&mut self, iface: &Interface, _dir: Direction) { + self.sizes.fill(iface); } fn type_record( @@ -268,44 +238,10 @@ impl Generator for Markdown { self.type_alias(iface, id, name, &Type::Id(id), docs); } - fn type_pointer( - &mut self, - iface: &Interface, - id: TypeId, - name: &str, - _const: bool, - _ty: &Type, - docs: &Docs, - ) { - self.type_alias(iface, id, name, &Type::Id(id), docs); - } - fn type_builtin(&mut self, iface: &Interface, id: TypeId, name: &str, ty: &Type, docs: &Docs) { self.type_alias(iface, id, name, ty, docs) } - fn type_push_buffer( - &mut self, - iface: &Interface, - id: TypeId, - name: &str, - _ty: &Type, - docs: &Docs, - ) { - self.type_alias(iface, id, name, &Type::Id(id), docs); - } - - fn type_pull_buffer( - &mut self, - iface: &Interface, - id: TypeId, - name: &str, - _ty: &Type, - docs: &Docs, - ) { - self.type_alias(iface, id, name, &Type::Id(id), docs); - } - fn import(&mut self, iface: &Interface, func: &Function) { if self.funcs == 0 { self.src.push_str("# Functions\n\n"); diff --git a/crates/gen-rust-wasm/Cargo.toml b/crates/gen-rust-wasm/Cargo.toml index 0663293a9..4eea70db7 100644 --- a/crates/gen-rust-wasm/Cargo.toml +++ b/crates/gen-rust-wasm/Cargo.toml @@ -17,6 +17,3 @@ structopt = { version = "0.3", default-features = false, optional = true } [dev-dependencies] wit-bindgen-rust = { path = '../rust-wasm' } test-helpers = { path = '../test-helpers', features = ['wit-bindgen-gen-rust-wasm'] } - -[features] -witx-compat = ['wit-bindgen-gen-core/witx-compat'] diff --git a/crates/gen-rust-wasm/src/lib.rs b/crates/gen-rust-wasm/src/lib.rs index 2d4cfd87c..68f0ad18c 100644 --- a/crates/gen-rust-wasm/src/lib.rs +++ b/crates/gen-rust-wasm/src/lib.rs @@ -4,7 +4,7 @@ use std::io::{Read, Write}; use std::mem; use std::process::{Command, Stdio}; use wit_bindgen_gen_core::wit_parser::abi::{ - AbiVariant, Bindgen, Instruction, LiftLower, WasmType, WitxInstruction, + AbiVariant, Bindgen, Instruction, LiftLower, WasmType, }; use wit_bindgen_gen_core::{wit_parser::*, Direction, Files, Generator, Source, TypeInfo, Types}; use wit_bindgen_gen_rust::{ @@ -137,12 +137,9 @@ impl RustGenerator for RustWasm { let manually_drop = match ty { Type::Id(id) => match &iface.types[*id].kind { TypeDefKind::Record(_) => true, - TypeDefKind::List(_) - | TypeDefKind::Variant(_) - | TypeDefKind::PushBuffer(_) - | TypeDefKind::PullBuffer(_) - | TypeDefKind::Type(_) => panic!("unsupported pointer type"), - TypeDefKind::Pointer(_) | TypeDefKind::ConstPointer(_) => true, + TypeDefKind::List(_) | TypeDefKind::Variant(_) | TypeDefKind::Type(_) => { + panic!("unsupported pointer type") + } }, Type::Handle(_) => true, _ => false, @@ -174,44 +171,6 @@ impl RustGenerator for RustWasm { } self.push_str(" str"); } - - fn print_lib_buffer( - &mut self, - iface: &Interface, - push: bool, - ty: &Type, - mode: TypeMode, - lt: &'static str, - ) { - let prefix = if push { "Push" } else { "Pull" }; - if self.in_import { - if let TypeMode::AllBorrowed(_) = mode { - self.push_str("&"); - if lt != "'_" { - self.push_str(lt); - } - self.push_str(" mut "); - } - self.push_str(&format!( - "wit_bindgen_rust::imports::{}Buffer<{}, ", - prefix, lt, - )); - self.print_ty(iface, ty, if push { TypeMode::Owned } else { mode }); - self.push_str(">"); - } else { - // Buffers in exports are represented with special types from the - // library support crate since they're wrappers around - // externally-provided handles. - self.push_str("wit_bindgen_rust::exports::"); - self.push_str(prefix); - self.push_str("Buffer"); - self.push_str("<"); - self.push_str(lt); - self.push_str(", "); - self.print_ty(iface, ty, if push { TypeMode::Owned } else { mode }); - self.push_str(">"); - } - } } impl Generator for RustWasm { @@ -235,7 +194,7 @@ impl Generator for RustWasm { self.i64_return_pointer_area_size.max(results.len()); } } - self.sizes.fill(variant, iface); + self.sizes.fill(iface); } fn type_record( @@ -452,35 +411,21 @@ impl Generator for RustWasm { self.src.push_str("impl Drop for "); self.src.push_str(&name.to_camel_case()); - if self.types.has_preview1_dtor(ty) { - self.src.push_str(&format!( - "{{ - fn drop(&mut self) {{ - unsafe {{ - drop({}_close({}(self.0))); - }} + self.src.push_str(&format!( + "{{ + fn drop(&mut self) {{ + #[link(wasm_import_module = \"canonical_abi\")] + extern \"C\" {{ + #[link_name = \"resource_drop_{}\"] + fn close(fd: i32); }} - }}\n", - name, - name.to_camel_case(), - )); - } else { - self.src.push_str(&format!( - "{{ - fn drop(&mut self) {{ - #[link(wasm_import_module = \"canonical_abi\")] - extern \"C\" {{ - #[link_name = \"resource_drop_{}\"] - fn close(fd: i32); - }} - unsafe {{ - close(self.0); - }} + unsafe {{ + close(self.0); }} - }}\n", - name, - )); - } + }} + }}\n", + name, + )); self.src.push_str("impl Clone for "); self.src.push_str(&name.to_camel_case()); @@ -509,23 +454,6 @@ impl Generator for RustWasm { self.print_type_list(iface, id, ty, docs); } - fn type_pointer( - &mut self, - iface: &Interface, - _id: TypeId, - name: &str, - const_: bool, - ty: &Type, - docs: &Docs, - ) { - self.rustdoc(docs); - let mutbl = if const_ { "const" } else { "mut" }; - self.src - .push_str(&format!("pub type {} = *{} ", name.to_camel_case(), mutbl,)); - self.print_ty(iface, ty, TypeMode::Owned); - self.src.push_str(";\n"); - } - fn type_builtin(&mut self, iface: &Interface, _id: TypeId, name: &str, ty: &Type, docs: &Docs) { self.rustdoc(docs); self.src @@ -535,48 +463,9 @@ impl Generator for RustWasm { self.src.push_str(";\n"); } - fn type_push_buffer( - &mut self, - iface: &Interface, - id: TypeId, - _name: &str, - ty: &Type, - docs: &Docs, - ) { - self.print_typedef_buffer(iface, id, true, ty, docs); - } - - fn type_pull_buffer( - &mut self, - iface: &Interface, - id: TypeId, - _name: &str, - ty: &Type, - docs: &Docs, - ) { - self.print_typedef_buffer(iface, id, false, ty, docs); - } - - // fn const_(&mut self, name: &Id, ty: &Id, val: u64, docs: &str) { - // self.rustdoc(docs); - // self.src.push_str(&format!( - // "pub const {}_{}: {} = {};\n", - // ty.to_shouty_snake_case(), - // name.to_shouty_snake_case(), - // ty.to_camel_case(), - // val - // )); - // } - fn import(&mut self, iface: &Interface, func: &Function) { - let is_dtor = self.types.is_preview1_dtor_func(func); let mut sig = FnSig::default(); - let param_mode = if is_dtor { - sig.unsafe_ = true; - TypeMode::Owned - } else { - TypeMode::AllBorrowed("'_") - }; + let param_mode = TypeMode::AllBorrowed("'_"); sig.async_ = func.is_async; match &func.kind { FunctionKind::Freestanding => {} @@ -594,11 +483,9 @@ impl Generator for RustWasm { } let params = self.print_signature(iface, func, param_mode, &sig); self.src.push_str("{\n"); - if !is_dtor { - self.src.push_str("unsafe {\n"); - } + self.src.push_str("unsafe {\n"); - let mut f = FunctionBindgen::new(self, is_dtor, params); + let mut f = FunctionBindgen::new(self, params); iface.call( AbiVariant::GuestImport, LiftLower::LowerArgsLiftResults, @@ -616,9 +503,7 @@ impl Generator for RustWasm { } self.src.push_str(&String::from(src)); - if !is_dtor { - self.src.push_str("}\n"); - } + self.src.push_str("}\n"); self.src.push_str("}\n"); match &func.kind { @@ -630,7 +515,6 @@ impl Generator for RustWasm { } fn export(&mut self, iface: &Interface, func: &Function) { - let is_dtor = self.types.is_preview1_dtor_func(func); let rust_name = func.name.to_snake_case(); self.src.push_str("#[export_name = \""); @@ -666,7 +550,7 @@ impl Generator for RustWasm { self.src.push_str("let future = async move {\n"); } - let mut f = FunctionBindgen::new(self, is_dtor, params); + let mut f = FunctionBindgen::new(self, params); iface.call( AbiVariant::GuestExport, LiftLower::LiftArgsLowerResults, @@ -797,15 +681,13 @@ struct FunctionBindgen<'a> { tmp: usize, needs_cleanup_list: bool, cleanup: Vec<(String, String)>, - is_dtor: bool, } impl FunctionBindgen<'_> { - fn new(gen: &mut RustWasm, is_dtor: bool, params: Vec) -> FunctionBindgen<'_> { + fn new(gen: &mut RustWasm, params: Vec) -> FunctionBindgen<'_> { FunctionBindgen { gen, params, - is_dtor, src: Default::default(), blocks: Vec::new(), block_storage: Vec::new(), @@ -928,19 +810,6 @@ impl Bindgen for FunctionBindgen<'_> { } } - fn allocate_typed_space(&mut self, _iface: &Interface, ty: TypeId) -> String { - let tmp = self.tmp(); - self.push_str(&format!( - "let mut rp{} = core::mem::MaybeUninit::<[u8;", - tmp - )); - let size = self.gen.sizes.size(&Type::Id(ty)); - self.push_str(&size.to_string()); - self.push_str("]>::uninit();\n"); - self.push_str(&format!("let ptr{} = rp{0}.as_mut_ptr() as i32;\n", tmp)); - format!("ptr{}", tmp) - } - fn i64_return_pointer_area(&mut self, amt: usize) -> String { assert!(amt <= self.gen.i64_return_pointer_area_size); let tmp = self.tmp(); @@ -1049,7 +918,6 @@ impl Bindgen for FunctionBindgen<'_> { )); } Instruction::HandleBorrowedFromI32 { .. } => { - assert!(!self.is_dtor); results.push(format!( "wit_bindgen_rust::Handle::from_raw({})", operands[0], @@ -1058,11 +926,7 @@ impl Bindgen for FunctionBindgen<'_> { // handles in imports Instruction::I32FromBorrowedHandle { .. } => { - if self.is_dtor { - results.push(format!("{}.into_raw()", operands[0])); - } else { - results.push(format!("{}.0", operands[0])); - } + results.push(format!("{}.0", operands[0])); } Instruction::HandleOwnedFromI32 { ty } => { results.push(format!( @@ -1105,7 +969,6 @@ impl Bindgen for FunctionBindgen<'_> { } Instruction::VariantPayloadName => results.push("e".to_string()), - Instruction::BufferPayloadName => results.push("e".to_string()), Instruction::VariantLower { variant, @@ -1311,86 +1174,6 @@ impl Bindgen for FunctionBindgen<'_> { Instruction::IterBasePointer => results.push("base".to_string()), - // Never used due to the call modes that this binding generator - // uses - Instruction::BufferLowerHandle { .. } => unimplemented!(), - Instruction::BufferLiftPtrLen { .. } => unimplemented!(), - - Instruction::BufferLowerPtrLen { push, ty } => { - let block = self.blocks.pop().unwrap(); - let size = self.gen.sizes.size(ty); - let tmp = self.tmp(); - let ptr = format!("ptr{}", tmp); - let len = format!("len{}", tmp); - if iface.all_bits_valid(ty) { - let vec = format!("vec{}", tmp); - self.push_str(&format!("let {} = {};\n", vec, operands[0])); - self.push_str(&format!("let {} = {}.as_ptr() as i32;\n", ptr, vec)); - self.push_str(&format!("let {} = {}.len() as i32;\n", len, vec)); - } else { - if *push { - self.push_str("let ("); - self.push_str(&ptr); - self.push_str(", "); - self.push_str(&len); - self.push_str(") = "); - self.push_str(&operands[0]); - self.push_str(".ptr_len::<"); - self.push_str(&size.to_string()); - self.push_str(">(|base| {\n"); - self.push_str(&block); - self.push_str("});\n"); - } else { - self.push_str("let ("); - self.push_str(&ptr); - self.push_str(", "); - self.push_str(&len); - self.push_str(") = "); - self.push_str(&operands[0]); - self.push_str(".serialize::<_, "); - self.push_str(&size.to_string()); - self.push_str(">(|e, base| {\n"); - self.push_str(&block); - self.push_str("});\n"); - } - } - results.push("0".to_string()); - results.push(ptr); - results.push(len); - } - - Instruction::BufferLiftHandle { push, ty } => { - let block = self.blocks.pop().unwrap(); - let size = self.gen.sizes.size(ty); - let mut result = String::from("wit_bindgen_rust::exports::"); - if *push { - result.push_str("Push"); - } else { - result.push_str("Pull"); - } - result.push_str("Buffer"); - if iface.all_bits_valid(ty) { - result.push_str("Raw::new("); - result.push_str(&operands[0]); - result.push_str(")"); - } else { - result.push_str("::new("); - result.push_str(&operands[0]); - result.push_str(", "); - result.push_str(&size.to_string()); - result.push_str(", "); - if *push { - result.push_str("|base, e|"); - result.push_str(&block); - } else { - result.push_str("|base|"); - result.push_str(&block); - } - result.push_str(")"); - } - results.push(result); - } - Instruction::CallWasm { module, name, sig } => { let func = self.declare_import(module, name, &sig.params, &sig.results); @@ -1606,18 +1389,6 @@ impl Bindgen for FunctionBindgen<'_> { operands[1], offset, operands[0] )); } - - Instruction::Witx { instr } => match instr { - WitxInstruction::I32FromPointer => top_as("i32"), - WitxInstruction::I32FromConstPointer => top_as("i32"), - WitxInstruction::ReuseReturn => results.push("ret".to_string()), - WitxInstruction::AddrOf => { - let i = self.tmp(); - self.push_str(&format!("let t{} = {};\n", i, operands[0])); - results.push(format!("&t{} as *const _ as i32", i)); - } - i => unimplemented!("{:?}", i), - }, } } } diff --git a/crates/gen-rust-wasm/tests/codegen.rs b/crates/gen-rust-wasm/tests/codegen.rs index 2f7d9e47f..ff3a08f8c 100644 --- a/crates/gen-rust-wasm/tests/codegen.rs +++ b/crates/gen-rust-wasm/tests/codegen.rs @@ -7,7 +7,6 @@ fn ok() {} mod imports { test_helpers::codegen_rust_wasm_import!( "*.wit" - "*.witx" // If you want to exclude a specific test you can include it here with // gitignore glob syntax: diff --git a/crates/gen-rust/src/lib.rs b/crates/gen-rust/src/lib.rs index 80f168137..73744801c 100644 --- a/crates/gen-rust/src/lib.rs +++ b/crates/gen-rust/src/lib.rs @@ -24,14 +24,6 @@ pub trait RustGenerator { lifetime: &'static str, ); fn print_borrowed_str(&mut self, lifetime: &'static str); - fn print_lib_buffer( - &mut self, - iface: &Interface, - push: bool, - ty: &Type, - mode: TypeMode, - lt: &'static str, - ); fn default_param_mode(&self) -> TypeMode; fn handle_projection(&self) -> Option<(&'static str, String)>; fn handle_wrapper(&self) -> Option<&'static str>; @@ -246,11 +238,7 @@ pub trait RustGenerator { fn needs_generics(iface: &Interface, ty: &TypeDefKind) -> bool { match ty { - TypeDefKind::Variant(_) - | TypeDefKind::Record(_) - | TypeDefKind::List(_) - | TypeDefKind::PushBuffer(_) - | TypeDefKind::PullBuffer(_) => true, + TypeDefKind::Variant(_) | TypeDefKind::Record(_) | TypeDefKind::List(_) => true, TypeDefKind::Type(Type::Id(t)) => needs_generics(iface, &iface.types[*t].kind), TypeDefKind::Type(Type::Handle(_)) => true, _ => false, @@ -261,9 +249,6 @@ pub trait RustGenerator { match &ty.kind { TypeDefKind::List(t) => self.print_list(iface, t, mode), - TypeDefKind::Pointer(t) => self.print_pointer(iface, false, t), - TypeDefKind::ConstPointer(t) => self.print_pointer(iface, true, t), - // Variants can be printed natively if they're `Option`, // `Result` , or `bool`, otherwise they must be named for now. TypeDefKind::Variant(v) if v.is_bool() => self.push_str("bool"), @@ -306,9 +291,6 @@ pub trait RustGenerator { panic!("unsupported anonymous type reference: record") } - TypeDefKind::PushBuffer(r) => self.print_buffer(iface, true, r, mode), - TypeDefKind::PullBuffer(r) => self.print_buffer(iface, false, r, mode), - TypeDefKind::Type(t) => self.print_ty(iface, t, mode), } } @@ -323,13 +305,11 @@ pub trait RustGenerator { }, t => match mode { TypeMode::AllBorrowed(lt) => { - let mutbl = self.needs_mutable_slice(iface, ty); - self.print_borrowed_slice(iface, mutbl, ty, lt); + self.print_borrowed_slice(iface, false, ty, lt); } TypeMode::LeafBorrowed(lt) => { if iface.all_bits_valid(t) { - let mutbl = self.needs_mutable_slice(iface, ty); - self.print_borrowed_slice(iface, mutbl, ty, lt); + self.print_borrowed_slice(iface, false, ty, lt); } else { self.push_str("Vec<"); self.print_ty(iface, ty, mode); @@ -345,20 +325,6 @@ pub trait RustGenerator { } } - fn print_buffer(&mut self, iface: &Interface, push: bool, ty: &Type, mode: TypeMode) { - let lt = match mode { - TypeMode::AllBorrowed(s) | TypeMode::HandlesBorrowed(s) | TypeMode::LeafBorrowed(s) => { - s - } - TypeMode::Owned => unimplemented!(), - }; - if iface.all_bits_valid(ty) { - self.print_borrowed_slice(iface, push, ty, lt) - } else { - self.print_lib_buffer(iface, push, ty, mode, lt) - } - } - fn print_rust_slice( &mut self, iface: &Interface, @@ -444,9 +410,7 @@ pub trait RustGenerator { } self.push_str(");\n"); } else { - if info.has_pull_buffer || info.has_push_buffer { - // skip copy/clone ... - } else if !info.owns_data() { + if !info.owns_data() { self.push_str("#[repr(C)]\n"); self.push_str("#[derive(Copy, Clone)]\n"); } else if !info.has_handle { @@ -534,8 +498,6 @@ pub trait RustGenerator { self.push_str("#[repr("); self.int_repr(variant.tag); self.push_str(")]\n#[derive(Clone, Copy, PartialEq, Eq)]\n"); - } else if info.has_pull_buffer || info.has_push_buffer { - // skip copy/clone } else if !info.owns_data() { self.push_str("#[derive(Clone, Copy)]\n"); } else if !info.has_handle { @@ -683,26 +645,6 @@ pub trait RustGenerator { } } - fn print_typedef_buffer( - &mut self, - iface: &Interface, - id: TypeId, - push: bool, - ty: &Type, - docs: &Docs, - ) { - let info = self.info(id); - for (name, mode) in self.modes_of(iface, id) { - let lt = self.lifetime_for(&info, mode); - self.rustdoc(docs); - self.push_str(&format!("pub type {}", name)); - self.print_generics(&info, lt, true); - self.push_str(" = "); - self.print_buffer(iface, push, ty, mode); - self.push_str(";\n"); - } - } - fn param_name(&self, iface: &Interface, ty: TypeId) -> String { let info = self.info(ty); let name = iface.types[ty].name.as_ref().unwrap().to_camel_case(); @@ -737,57 +679,14 @@ pub trait RustGenerator { fn lifetime_for(&self, info: &TypeInfo, mode: TypeMode) -> Option<&'static str> { match mode { TypeMode::AllBorrowed(s) | TypeMode::LeafBorrowed(s) - if info.has_list - || info.has_handle - || info.has_push_buffer - || info.has_pull_buffer => - { - Some(s) - } - TypeMode::HandlesBorrowed(s) - if info.has_handle || info.has_pull_buffer || info.has_push_buffer => + if info.has_list || info.has_handle => { Some(s) } + TypeMode::HandlesBorrowed(s) if info.has_handle => Some(s), _ => None, } } - - fn needs_mutable_slice(&mut self, iface: &Interface, ty: &Type) -> bool { - let info = self.types_mut().type_info(iface, ty); - // If there's any out-buffers transitively then a mutable slice is - // required because the out-buffers could be modified. Otherwise a - // mutable slice is also required if, transitively, `InBuffer` is used - // which is used when we're a buffer of a type where not all bits are - // valid (e.g. the rust representation and the canonical abi may differ). - info.has_push_buffer || self.has_pull_buffer_invalid_bits(iface, ty) - } - - fn has_pull_buffer_invalid_bits(&self, iface: &Interface, ty: &Type) -> bool { - let id = match ty { - Type::Id(id) => *id, - _ => return false, - }; - match &iface.types[id].kind { - TypeDefKind::Type(t) - | TypeDefKind::Pointer(t) - | TypeDefKind::ConstPointer(t) - | TypeDefKind::PushBuffer(t) - | TypeDefKind::List(t) => self.has_pull_buffer_invalid_bits(iface, t), - TypeDefKind::Record(r) => r - .fields - .iter() - .any(|t| self.has_pull_buffer_invalid_bits(iface, &t.ty)), - TypeDefKind::Variant(v) => v - .cases - .iter() - .filter_map(|c| c.ty.as_ref()) - .any(|t| self.has_pull_buffer_invalid_bits(iface, t)), - TypeDefKind::PullBuffer(t) => { - !iface.all_bits_valid(t) || self.has_pull_buffer_invalid_bits(iface, t) - } - } - } } #[derive(Default)] @@ -1045,7 +944,7 @@ trait TypeInfoExt { impl TypeInfoExt for TypeInfo { fn owns_data(&self) -> bool { - self.has_list || self.has_handle || self.has_pull_buffer || self.has_push_buffer + self.has_list || self.has_handle } } diff --git a/crates/gen-spidermonkey/src/lib.rs b/crates/gen-spidermonkey/src/lib.rs index 71d357681..6fcf56363 100644 --- a/crates/gen-spidermonkey/src/lib.rs +++ b/crates/gen-spidermonkey/src/lib.rs @@ -389,14 +389,6 @@ impl<'a> SpiderMonkeyWasm<'a> { } } - fn abi_variant(dir: Direction) -> AbiVariant { - // This generator uses the obvious direction to ABI variant mapping. - match dir { - Direction::Export => AbiVariant::GuestExport, - Direction::Import => AbiVariant::GuestImport, - } - } - /// Configure how `spidermonkey.wasm` is linked. /// /// By default, the whole `spidermonkey.wasm` module is embedded inside our @@ -931,8 +923,8 @@ impl Generator for SpiderMonkeyWasm<'_> { } } - fn preprocess_one(&mut self, iface: &Interface, dir: Direction) { - self.sizes.fill(Self::abi_variant(dir), iface); + fn preprocess_one(&mut self, iface: &Interface, _dir: Direction) { + self.sizes.fill(iface); } fn type_record( @@ -974,54 +966,13 @@ impl Generator for SpiderMonkeyWasm<'_> { todo!() } - fn type_pointer( - &mut self, - iface: &Interface, - id: TypeId, - name: &str, - const_: bool, - ty: &Type, - docs: &Docs, - ) { - let _ = (iface, id, name, const_, ty, docs); - todo!() - } - fn type_builtin(&mut self, iface: &Interface, id: TypeId, name: &str, ty: &Type, docs: &Docs) { let _ = (iface, id, name, name, ty, docs); todo!() } - fn type_push_buffer( - &mut self, - iface: &Interface, - id: TypeId, - name: &str, - ty: &Type, - docs: &Docs, - ) { - let _ = (iface, id, name, name, ty, docs); - todo!() - } - - fn type_pull_buffer( - &mut self, - iface: &Interface, - id: TypeId, - name: &str, - ty: &Type, - docs: &Docs, - ) { - let _ = (iface, id, name, name, ty, docs); - todo!() - } - fn import(&mut self, iface: &Interface, func: &Function) { assert!(!func.is_async, "async not supported yet"); - assert!( - func.abi == abi::Abi::Canonical, - "We only support the canonical ABI right now" - ); // Add the raw Wasm import. let wasm_sig = iface.wasm_signature(AbiVariant::GuestImport, func); @@ -1059,10 +1010,6 @@ impl Generator for SpiderMonkeyWasm<'_> { fn export(&mut self, iface: &Interface, func: &Function) { assert!(!func.is_async, "async not supported yet"); - assert!( - func.abi == abi::Abi::Canonical, - "We only support the canonical ABI right now" - ); let wasm_sig = iface.wasm_signature(AbiVariant::GuestExport, func); let type_index = self.intern_type(wasm_sig.clone()); @@ -1908,11 +1855,6 @@ impl abi::Bindgen for Bindgen<'_, '_> { results.push(Operand::Wasm(iter_base_pointer)); } - abi::Instruction::BufferPayloadName => todo!(), - abi::Instruction::BufferLowerPtrLen { push: _, ty: _ } => todo!(), - abi::Instruction::BufferLowerHandle { push: _, ty: _ } => todo!(), - abi::Instruction::BufferLiftPtrLen { push: _, ty: _ } => todo!(), - abi::Instruction::BufferLiftHandle { push: _, ty: _ } => todo!(), abi::Instruction::RecordLower { record: _, name: _, @@ -2153,17 +2095,9 @@ impl abi::Bindgen for Bindgen<'_, '_> { abi::Instruction::ReturnAsyncExport { .. } => todo!(), abi::Instruction::ReturnAsyncImport { .. } => todo!(), - - abi::Instruction::Witx { instr: _ } => { - unreachable!("we do not support the preview1 ABI") - } } } - fn allocate_typed_space(&mut self, _iface: &Interface, _ty: TypeId) -> Self::Operand { - todo!() - } - fn i64_return_pointer_area(&mut self, amt: usize) -> Self::Operand { assert!(amt <= self.gen.i64_return_pointer_area_size); let local = self.new_local(wasm_encoder::ValType::I32); diff --git a/crates/gen-wasmtime-py/Cargo.toml b/crates/gen-wasmtime-py/Cargo.toml index af75de407..a41c3ffa0 100644 --- a/crates/gen-wasmtime-py/Cargo.toml +++ b/crates/gen-wasmtime-py/Cargo.toml @@ -15,6 +15,3 @@ structopt = { version = "0.3", default-features = false, optional = true } [dev-dependencies] test-helpers = { path = '../test-helpers', features = ['wit-bindgen-gen-wasmtime-py'] } - -[features] -witx-compat = ['wit-bindgen-gen-core/witx-compat'] diff --git a/crates/gen-wasmtime-py/src/lib.rs b/crates/gen-wasmtime-py/src/lib.rs index 9e236e7d3..8ea632c2d 100644 --- a/crates/gen-wasmtime-py/src/lib.rs +++ b/crates/gen-wasmtime-py/src/lib.rs @@ -2,7 +2,7 @@ use heck::*; use std::collections::{BTreeMap, BTreeSet, HashMap}; use std::mem; use wit_bindgen_gen_core::wit_parser::abi::{ - AbiVariant, Bindgen, Bitcast, Instruction, LiftLower, WasmType, WitxInstruction, + AbiVariant, Bindgen, Bitcast, Instruction, LiftLower, WasmType, }; use wit_bindgen_gen_core::{wit_parser::*, Direction, Files, Generator, Ns}; @@ -27,8 +27,6 @@ pub struct WasmtimePy { needs_encode_utf8: bool, needs_list_canon_lift: bool, needs_list_canon_lower: bool, - needs_push_buffer: bool, - needs_pull_buffer: bool, needs_t_typevar: bool, pyimports: BTreeMap>>, } @@ -362,61 +360,6 @@ impl WasmtimePy { ", ); } - if self.needs_push_buffer { - self.pyimport("typing", "TypeVar"); - self.pyimport("typing", "Generic"); - self.pyimport("typing", "Callable"); - self.needs_t_typevar = true; - self.src.push_str( - " - class PushBuffer(Generic[T]): - def __init__(self, ptr: int, len: int, size: int, write: Callable) -> None: - self.ptr = ptr - self.len = len - self.size = size - self.write = write - - def __len__(self) -> int: - return self.len - - def push(self, val: T) -> bool: - if self.len == 0: - return False; - self.len -= 1; - self.write(val, self.ptr); - self.ptr += self.size; - return True - ", - ) - } - if self.needs_pull_buffer { - self.pyimport("typing", "TypeVar"); - self.pyimport("typing", "Generic"); - self.pyimport("typing", "Callable"); - self.pyimport("typing", "Optional"); - self.needs_t_typevar = true; - self.src.push_str( - " - class PullBuffer(Generic[T]): - def __init__(self, ptr: int, len: int, size: int, read: Callable) -> None: - self.len = len - self.ptr = ptr - self.size = size - self.read = read - - def __len__(self) -> int: - return self.len - - def pull(self) -> Optional[T]: - if self.len == 0: - return None - self.len -= 1 - ret: T = self.read(self.ptr) - self.ptr += self.size - return ret - ", - ) - } } fn type_string(&mut self, iface: &Interface, ty: &Type) -> String { @@ -496,11 +439,6 @@ impl WasmtimePy { } } TypeDefKind::List(t) => self.print_list(iface, t), - TypeDefKind::Pointer(_) | TypeDefKind::ConstPointer(_) => { - self.src.push_str("int") - } - TypeDefKind::PushBuffer(t) => self.print_buffer(iface, true, t), - TypeDefKind::PullBuffer(t) => self.print_buffer(iface, false, t), } } } @@ -522,19 +460,6 @@ impl WasmtimePy { self.src.push_str("]"); } - fn print_buffer(&mut self, iface: &Interface, push: bool, ty: &Type) { - if push { - self.needs_push_buffer = true; - self.src.push_str("PushBuffer"); - } else { - self.needs_pull_buffer = true; - self.src.push_str("PullBuffer"); - } - self.src.push_str("["); - self.print_ty(iface, ty); - self.src.push_str("]"); - } - fn print_list(&mut self, iface: &Interface, element: &Type) { match element { Type::Char => self.src.push_str("str"), @@ -647,7 +572,7 @@ impl WasmtimePy { impl Generator for WasmtimePy { fn preprocess_one(&mut self, iface: &Interface, dir: Direction) { let variant = Self::abi_variant(dir); - self.sizes.fill(variant, iface); + self.sizes.fill(iface); self.in_import = variant == AbiVariant::GuestImport; } @@ -802,50 +727,10 @@ impl Generator for WasmtimePy { self.src.push_str("\n"); } - fn type_pointer( - &mut self, - _iface: &Interface, - _id: TypeId, - _name: &str, - _const_: bool, - _ty: &Type, - _docs: &Docs, - ) { - // drop((iface, _id, name, const_, ty, docs)); - } - fn type_builtin(&mut self, iface: &Interface, id: TypeId, name: &str, ty: &Type, docs: &Docs) { self.type_alias(iface, id, name, ty, docs); } - fn type_push_buffer( - &mut self, - iface: &Interface, - _id: TypeId, - name: &str, - ty: &Type, - docs: &Docs, - ) { - self.docs(docs); - self.src.push_str(&format!("{} = ", name.to_camel_case())); - self.print_buffer(iface, true, ty); - self.src.push_str("\n"); - } - - fn type_pull_buffer( - &mut self, - iface: &Interface, - _id: TypeId, - name: &str, - ty: &Type, - docs: &Docs, - ) { - self.docs(docs); - self.src.push_str(&format!("{} = ", name.to_camel_case())); - self.print_buffer(iface, false, ty); - self.src.push_str("\n"); - } - // As with `abi_variant` above, we're generating host-side bindings here // so a user "export" uses the "guest import" ABI variant on the inside of // this `Generator` implementation. @@ -1425,10 +1310,6 @@ impl Bindgen for FunctionBindgen<'_> { self.blocks.push((src.into(), mem::take(operands))); } - fn allocate_typed_space(&mut self, _iface: &Interface, _ty: TypeId) -> String { - unimplemented!() - } - fn i64_return_pointer_area(&mut self, _amt: usize) -> String { unimplemented!() } @@ -1634,7 +1515,6 @@ impl Bindgen for FunctionBindgen<'_> { results.push(name.clone()); self.payloads.push(name); } - Instruction::BufferPayloadName => results.push("e".to_string()), Instruction::VariantLower { variant, results: result_types, @@ -2001,39 +1881,6 @@ impl Bindgen for FunctionBindgen<'_> { self.payloads.push(name); } - Instruction::BufferLiftPtrLen { push, ty } => { - let (block, block_results) = self.blocks.pop().unwrap(); - let base = self.payloads.pop().unwrap(); - self.needs_memory = true; - let ptr = self.locals.tmp("ptr"); - let len = self.locals.tmp("len"); - self.src.push_str(&format!("{} = {}\n", ptr, operands[1])); - self.src.push_str(&format!("{} = {}\n", len, operands[2])); - let size = self.gen.sizes.size(ty); - if *push { - self.gen.needs_push_buffer = true; - assert!(block_results.is_empty()); - let write = self.locals.tmp("write_val"); - self.src - .push_str(&format!("def {}(e, {}): # type: ignore\n", write, base)); - self.src.indent(2); - self.src.push_str(&block); - self.src.deindent(2); - results.push(format!("PushBuffer({}, {}, {}, {})", ptr, len, size, write)); - } else { - self.gen.needs_pull_buffer = true; - assert_eq!(block_results.len(), 1); - let read = self.locals.tmp("read_val"); - self.src - .push_str(&format!("def {}({}): # type: ignore\n", read, base)); - self.src.indent(2); - self.src.push_str(&block); - self.src.push_str(&format!("return {}\n", block_results[0])); - self.src.deindent(2); - results.push(format!("PullBuffer({}, {}, {}, {})", ptr, len, size, read)); - } - } - // Instruction::BufferLowerHandle { push, ty } => { // let block = self.blocks.pop().unwrap(); // let size = self.sizes.size(ty); @@ -2167,10 +2014,6 @@ impl Bindgen for FunctionBindgen<'_> { Instruction::I32Store8 { offset } => self.store("c_uint8", *offset, operands), Instruction::I32Store16 { offset } => self.store("c_uint16", *offset, operands), - Instruction::Witx { instr } => match instr { - WitxInstruction::PointerFromI32 { .. } => results.push(operands[0].clone()), - i => unimplemented!("{:?}", i), - }, i => unimplemented!("{:?}", i), } } diff --git a/crates/gen-wasmtime/Cargo.toml b/crates/gen-wasmtime/Cargo.toml index 9fd5d9bab..85db8d7a6 100644 --- a/crates/gen-wasmtime/Cargo.toml +++ b/crates/gen-wasmtime/Cargo.toml @@ -20,6 +20,3 @@ test-helpers = { path = '../test-helpers', features = ['wit-bindgen-gen-wasmtime wasmtime = "0.35.2" wasmtime-wasi = "0.35.2" wit-bindgen-wasmtime = { path = '../wasmtime', features = ['tracing', 'async'] } - -[features] -witx-compat = ['wit-bindgen-gen-core/witx-compat'] diff --git a/crates/gen-wasmtime/src/lib.rs b/crates/gen-wasmtime/src/lib.rs index 707132197..1698b45e2 100644 --- a/crates/gen-wasmtime/src/lib.rs +++ b/crates/gen-wasmtime/src/lib.rs @@ -5,7 +5,7 @@ use std::mem; use std::process::{Command, Stdio}; use std::str::FromStr; use wit_bindgen_gen_core::wit_parser::abi::{ - Abi, AbiVariant, Bindgen, Instruction, LiftLower, WasmType, WitxInstruction, + AbiVariant, Bindgen, Instruction, LiftLower, WasmType, }; use wit_bindgen_gen_core::{wit_parser::*, Direction, Files, Generator, Source, TypeInfo, Types}; use wit_bindgen_gen_rust::{ @@ -36,7 +36,6 @@ pub struct Wasmtime { in_import: bool, in_trait: bool, trait_name: String, - has_preview1_dtor: bool, sizes: SizeAlign, } @@ -318,58 +317,6 @@ impl RustGenerator for Wasmtime { } self.push_str(" str"); } - - fn print_lib_buffer( - &mut self, - iface: &Interface, - push: bool, - ty: &Type, - mode: TypeMode, - lt: &'static str, - ) { - if self.in_import { - if let TypeMode::AllBorrowed(_) = mode { - self.push_str("&"); - if lt != "'_" { - self.push_str(lt); - } - self.push_str(" mut "); - } - self.push_str(&format!( - "wit_bindgen_wasmtime::exports::{}Buffer<{}, ", - if push { "Push" } else { "Pull" }, - lt, - )); - self.print_ty(iface, ty, if push { TypeMode::Owned } else { mode }); - self.push_str(">"); - } else { - if push { - // Push buffers, where wasm pushes, are a `Vec` which is pushed onto - self.push_str("&"); - if lt != "'_" { - self.push_str(lt); - } - self.push_str(" mut Vec<"); - self.print_ty(iface, ty, if push { TypeMode::Owned } else { mode }); - self.push_str(">"); - } else { - // Pull buffers, which wasm pulls from, are modeled as iterators - // in Rust. - self.push_str("&"); - if lt != "'_" { - self.push_str(lt); - } - self.push_str(" mut (dyn ExactSizeIterator"); - if lt != "'_" { - self.push_str(" + "); - self.push_str(lt); - } - self.push_str(")"); - } - } - } } impl Generator for Wasmtime { @@ -382,7 +329,7 @@ impl Generator for Wasmtime { .push_str(&format!("pub mod {} {{\n", iface.name.to_snake_case())); self.src .push_str("#[allow(unused_imports)]\nuse wit_bindgen_wasmtime::{wasmtime, anyhow};\n"); - self.sizes.fill(variant, iface); + self.sizes.fill(iface); } fn type_record( @@ -525,23 +472,6 @@ impl Generator for Wasmtime { self.print_type_list(iface, id, ty, docs); } - fn type_pointer( - &mut self, - iface: &Interface, - _id: TypeId, - name: &str, - const_: bool, - ty: &Type, - docs: &Docs, - ) { - self.rustdoc(docs); - let mutbl = if const_ { "const" } else { "mut" }; - self.src - .push_str(&format!("pub type {} = *{} ", name.to_camel_case(), mutbl,)); - self.print_ty(iface, ty, TypeMode::Owned); - self.src.push_str(";\n"); - } - fn type_builtin(&mut self, iface: &Interface, _id: TypeId, name: &str, ty: &Type, docs: &Docs) { self.rustdoc(docs); self.src @@ -551,39 +481,6 @@ impl Generator for Wasmtime { self.src.push_str(";\n"); } - fn type_push_buffer( - &mut self, - iface: &Interface, - id: TypeId, - _name: &str, - ty: &Type, - docs: &Docs, - ) { - self.print_typedef_buffer(iface, id, true, ty, docs); - } - - fn type_pull_buffer( - &mut self, - iface: &Interface, - id: TypeId, - _name: &str, - ty: &Type, - docs: &Docs, - ) { - self.print_typedef_buffer(iface, id, false, ty, docs); - } - - // fn const_(&mut self, name: &Id, ty: &Id, val: u64, docs: &str) { - // self.rustdoc(docs); - // self.src.push_str(&format!( - // "pub const {}_{}: {} = {};\n", - // ty.to_shouty_snake_case(), - // name.to_shouty_snake_case(), - // ty.to_camel_case(), - // val - // )); - // } - // As with `abi_variant` above, we're generating host-side bindings here // so a user "export" uses the "guest import" ABI variant on the inside of // this `Generator` implementation. @@ -591,21 +488,13 @@ impl Generator for Wasmtime { assert!(!func.is_async, "async not supported yet"); let prev = mem::take(&mut self.src); - let is_dtor = self.types.is_preview1_dtor_func(func); - self.has_preview1_dtor = self.has_preview1_dtor || is_dtor; - // Generate the closure that's passed to a `Linker`, the final piece of // codegen here. let sig = iface.wasm_signature(AbiVariant::GuestImport, func); let params = (0..sig.params.len()) .map(|i| format!("arg{}", i)) .collect::>(); - let mut f = FunctionBindgen::new(self, is_dtor, params); - f.func_takes_all_memory = func.abi == Abi::Preview1 - && func - .params - .iter() - .any(|(_, t)| iface.has_preview1_pointer(t)); + let mut f = FunctionBindgen::new(self, params); iface.call( AbiVariant::GuestImport, LiftLower::LiftArgsLowerResults, @@ -621,33 +510,20 @@ impl Generator for Wasmtime { needs_functions, closures, async_intrinsic_called, - func_takes_all_memory, .. } = f; assert!(cleanup.is_none()); assert!(!needs_buffer_transaction); // Generate the signature this function will have in the final trait - let mut self_arg = "&mut self".to_string(); - if func_takes_all_memory { - self_arg.push_str(", mem: wit_bindgen_wasmtime::RawMemory"); - } + let self_arg = "&mut self".to_string(); self.in_trait = true; let mut fnsig = FnSig::default(); fnsig.private = true; fnsig.async_ = self.opts.async_.includes(&func.name); fnsig.self_arg = Some(self_arg); - self.print_docs_and_params( - iface, - func, - if is_dtor { - TypeMode::Owned - } else { - TypeMode::LeafBorrowed("'_") - }, - &fnsig, - ); + self.print_docs_and_params(iface, func, TypeMode::LeafBorrowed("'_"), &fnsig); // The Rust return type may differ from the wasm return type based on // the `custom_error` configuration of this code generator. match self.classify_fn_ret(iface, func) { @@ -788,16 +664,12 @@ impl Generator for Wasmtime { self.print_results(iface, func); self.push_str(", wasmtime::Trap> {\n"); - let is_dtor = self.types.is_preview1_dtor_func(func); - if is_dtor { - assert_eq!(func.results.len(), 0, "destructors cannot have results"); - } let params = func .params .iter() .map(|(name, _)| to_rust_ident(name).to_string()) .collect(); - let mut f = FunctionBindgen::new(self, is_dtor, params); + let mut f = FunctionBindgen::new(self, params); iface.call( AbiVariant::GuestExport, LiftLower::LowerArgsLiftResults, @@ -858,9 +730,7 @@ impl Generator for Wasmtime { self.src.push_str(&String::from(src)); self.src.push_str("}\n"); let func_body = mem::replace(&mut self.src, prev); - if !is_dtor { - exports.funcs.push(func_body.into()); - } + exports.funcs.push(func_body.into()); // Create the code snippet which will define the type of this field in // the struct that we're exporting and additionally extracts the @@ -1006,28 +876,26 @@ impl Generator for Wasmtime { method, module, f.name, f.closure, )); } - if !self.has_preview1_dtor { - for handle in self.all_needed_handles.iter() { - self.src.push_str(&format!( - "linker.func_wrap( - \"canonical_abi\", - \"resource_drop_{name}\", - move |mut caller: wasmtime::Caller<'_, T>, handle: u32| {{ - let (host, tables) = get(caller.data_mut()); - let handle = tables - .{snake}_table - .remove(handle) - .map_err(|e| {{ - wasmtime::Trap::new(format!(\"failed to remove handle: {{}}\", e)) - }})?; - host.drop_{snake}(handle); - Ok(()) - }} - )?;\n", - name = handle, - snake = handle.to_snake_case(), - )); - } + for handle in self.all_needed_handles.iter() { + self.src.push_str(&format!( + "linker.func_wrap( + \"canonical_abi\", + \"resource_drop_{name}\", + move |mut caller: wasmtime::Caller<'_, T>, handle: u32| {{ + let (host, tables) = get(caller.data_mut()); + let handle = tables + .{snake}_table + .remove(handle) + .map_err(|e| {{ + wasmtime::Trap::new(format!(\"failed to remove handle: {{}}\", e)) + }})?; + host.drop_{snake}(handle); + Ok(()) + }} + )?;\n", + name = handle, + snake = handle.to_snake_case(), + )); } self.push_str("Ok(())\n}\n"); } @@ -1076,9 +944,6 @@ impl Generator for Wasmtime { self.push_str(ty); self.push_str(",\n"); } - // if self.needs_buffer_glue { - // self.push_str("buffer_glue: wit_bindgen_wasmtime::imports::BufferGlue,"); - // } self.push_str("}\n"); let bound = if self.opts.async_.is_none() { "" @@ -1172,45 +1037,6 @@ impl Generator for Wasmtime { suffix = suffix, )); } - // if self.needs_buffer_glue { - // self.push_str( - // " - // use wit_bindgen_wasmtime::rt::get_memory; - - // let buffer_glue = wit_bindgen_wasmtime::imports::BufferGlue::default(); - // let g = buffer_glue.clone(); - // linker.func( - // \"wit_canonical_buffer_abi\", - // \"in_len\", - // move |handle: u32| g.in_len(handle), - // )?; - // let g = buffer_glue.clone(); - // linker.func( - // \"wit_canonical_buffer_abi\", - // \"in_read\", - // move |caller: wasmtime::Caller<'_>, handle: u32, len: u32, offset: u32| { - // let memory = get_memory(&mut caller, \"memory\")?; - // g.in_read(handle, &memory, offset, len) - // }, - // )?; - // let g = buffer_glue.clone(); - // linker.func( - // \"wit_canonical_buffer_abi\", - // \"out_len\", - // move |handle: u32| g.out_len(handle), - // )?; - // let g = buffer_glue.clone(); - // linker.func( - // \"wit_canonical_buffer_abi\", - // \"out_write\", - // move |caller: wasmtime::Caller<'_>, handle: u32, len: u32, offset: u32| { - // let memory = get_memory(&mut caller, \"memory\")?; - // g.out_write(handle, &memory, offset, len) - // }, - // )?; - // ", - // ); - // } self.push_str("Ok(())\n"); self.push_str("}\n"); @@ -1388,9 +1214,6 @@ struct FunctionBindgen<'a> { // Destination where source code is pushed onto for this function src: Source, - // Whether or not this function is a preview1 dtor - is_dtor: bool, - // The named parameters that are available to this function params: Vec, @@ -1411,9 +1234,6 @@ struct FunctionBindgen<'a> { // Code that must be executed before a return, generated during instruction // lowering. cleanup: Option, - // Only present for preview1 ABIs where some arguments might be a `pointer` - // type. - func_takes_all_memory: bool, // Rust clousures for buffers that must be placed at the front of the // function. @@ -1428,7 +1248,7 @@ struct FunctionBindgen<'a> { } impl FunctionBindgen<'_> { - fn new(gen: &mut Wasmtime, is_dtor: bool, params: Vec) -> FunctionBindgen<'_> { + fn new(gen: &mut Wasmtime, params: Vec) -> FunctionBindgen<'_> { FunctionBindgen { gen, block_storage: Vec::new(), @@ -1439,13 +1259,11 @@ impl FunctionBindgen<'_> { async_intrinsic_called: false, tmp: 0, cleanup: None, - func_takes_all_memory: false, closures: Source::default(), needs_buffer_transaction: false, needs_borrow_checker: false, needs_memory: false, needs_functions: HashMap::new(), - is_dtor, params, } } @@ -1495,14 +1313,6 @@ impl FunctionBindgen<'_> { self.caller_memory_available = false; // invalidated by call } - fn type_string(&mut self, iface: &Interface, ty: &Type, mode: TypeMode) -> String { - let start = self.gen.src.len(); - self.gen.print_ty(iface, ty, mode); - let ty = self.gen.src[start..].to_string(); - self.gen.src.as_mut_string().truncate(start); - ty - } - fn load(&mut self, offset: i32, ty: &str, operands: &[String]) -> String { let mem = self.memory_src(); self.gen.needs_raw_mem = true; @@ -1578,10 +1388,6 @@ impl Bindgen for FunctionBindgen<'_> { self.caller_memory_available = false; } - fn allocate_typed_space(&mut self, _iface: &Interface, _ty: TypeId) -> String { - unimplemented!() - } - fn i64_return_pointer_area(&mut self, _amt: usize) -> String { unimplemented!() } @@ -1683,23 +1489,13 @@ impl Bindgen for FunctionBindgen<'_> { } Instruction::HandleBorrowedFromI32 { ty } => { let name = &iface.resources[*ty].name; - if self.is_dtor { - results.push(format!( - "_tables.{}_table.remove(({}) as u32).map_err(|e| {{ - wasmtime::Trap::new(format!(\"failed to remove handle: {{}}\", e)) - }})?", - name.to_snake_case(), - operands[0] - )); - } else { - results.push(format!( - "_tables.{}_table.get(({}) as u32).ok_or_else(|| {{ + results.push(format!( + "_tables.{}_table.get(({}) as u32).ok_or_else(|| {{ wasmtime::Trap::new(\"invalid handle index\") }})?", - name.to_snake_case(), - operands[0] - )); - } + name.to_snake_case(), + operands[0] + )); } Instruction::I32FromBorrowedHandle { ty } => { let tmp = self.tmp(); @@ -1770,7 +1566,6 @@ impl Bindgen for FunctionBindgen<'_> { } Instruction::VariantPayloadName => results.push("e".to_string()), - Instruction::BufferPayloadName => results.push("e".to_string()), Instruction::VariantLower { variant, @@ -2005,91 +1800,6 @@ impl Bindgen for FunctionBindgen<'_> { Instruction::IterBasePointer => results.push("base".to_string()), - // Never used due to the call modes that this binding generator - // uses - Instruction::BufferLowerPtrLen { .. } => unreachable!(), - Instruction::BufferLiftHandle { .. } => unimplemented!(), - - Instruction::BufferLiftPtrLen { push, ty } => { - let block = self.blocks.pop().unwrap(); - self.needs_borrow_checker = true; - let tmp = self.tmp(); - self.push_str(&format!("let _ = {};\n", operands[0])); - self.push_str(&format!("let ptr{} = {};\n", tmp, operands[1])); - self.push_str(&format!("let len{} = {};\n", tmp, operands[2])); - if iface.all_bits_valid(ty) { - let method = if *push { "slice_mut" } else { "slice" }; - results.push(format!("_bc.{}(ptr{1}, len{1})?", method, tmp)); - } else { - let size = self.gen.sizes.size(ty); - let closure = format!("closure{}", tmp); - self.closures.push_str(&format!("let {} = ", closure)); - if *push { - self.closures.push_str("|_bc: &mut [u8], e:"); - let ty = self.type_string(iface, ty, TypeMode::Owned); - self.closures.push_str(&ty); - self.closures.push_str("| {let base = 0;\n"); - self.closures.push_str(&block); - self.closures.push_str("; Ok(()) };\n"); - results.push(format!( - "wit_bindgen_wasmtime::exports::PushBuffer::new( - &mut _bc, ptr{}, len{}, {}, &{})?", - tmp, tmp, size, closure - )); - } else { - self.closures.push_str("|_bc: &[u8]| { let base = 0;Ok("); - self.closures.push_str(&block); - self.closures.push_str(") };\n"); - results.push(format!( - "wit_bindgen_wasmtime::exports::PullBuffer::new( - &mut _bc, ptr{}, len{}, {}, &{})?", - tmp, tmp, size, closure - )); - } - } - } - - Instruction::BufferLowerHandle { push, ty } => { - let block = self.blocks.pop().unwrap(); - let size = self.gen.sizes.size(ty); - let tmp = self.tmp(); - let handle = format!("handle{}", tmp); - let closure = format!("closure{}", tmp); - self.needs_buffer_transaction = true; - if iface.all_bits_valid(ty) { - let method = if *push { "push_out_raw" } else { "push_in_raw" }; - self.push_str(&format!( - "let {} = unsafe {{ buffer_transaction.{}({}) }};\n", - handle, method, operands[0], - )); - } else if *push { - self.closures.push_str(&format!( - "let {} = |memory: &wasmtime::Memory, base: i32| {{ - Ok(({}, {})) - }};\n", - closure, block, size, - )); - self.push_str(&format!( - "let {} = unsafe {{ buffer_transaction.push_out({}, &{}) }};\n", - handle, operands[0], closure, - )); - } else { - let ty = self.type_string(iface, ty, TypeMode::AllBorrowed("'_")); - self.closures.push_str(&format!( - "let {} = |memory: &wasmtime::Memory, base: i32, e: {}| {{ - {}; - Ok({}) - }};\n", - closure, ty, block, size, - )); - self.push_str(&format!( - "let {} = unsafe {{ buffer_transaction.push_in({}, &{}) }};\n", - handle, operands[0], closure, - )); - } - results.push(format!("{}", handle)); - } - Instruction::CallWasm { module: _, name, @@ -2147,17 +1857,7 @@ impl Bindgen for FunctionBindgen<'_> { self.push_str(");\n"); } - if self.func_takes_all_memory { - let mem = self.memory_src(); - self.push_str("let raw_memory = wit_bindgen_wasmtime::RawMemory { slice: "); - self.push_str(&mem); - self.push_str(".raw() };\n"); - } - let mut call = format!("host.{}(", func.name.to_snake_case()); - if self.func_takes_all_memory { - call.push_str("raw_memory, "); - } for i in 0..operands.len() { call.push_str(&format!("param{}, ", i)); } @@ -2261,12 +1961,6 @@ impl Bindgen for FunctionBindgen<'_> { Instruction::I32Store16 { offset } => { self.store(*offset, "as_i32", " as u16", operands) } - - Instruction::Witx { instr } => match instr { - WitxInstruction::PointerFromI32 { .. } - | WitxInstruction::ConstPointerFromI32 { .. } => top_as("u32"), - i => unimplemented!("{:?}", i), - }, } } } diff --git a/crates/gen-wasmtime/tests/codegen.rs b/crates/gen-wasmtime/tests/codegen.rs index cac6e244f..4bdc1e6e0 100644 --- a/crates/gen-wasmtime/tests/codegen.rs +++ b/crates/gen-wasmtime/tests/codegen.rs @@ -8,7 +8,6 @@ fn main() { mod exports { test_helpers::codegen_wasmtime_export!( "*.wit" - "*.witx" // TODO: implement async support "!async-functions.wit" diff --git a/crates/parser/Cargo.toml b/crates/parser/Cargo.toml index bb66426df..61e87dca7 100644 --- a/crates/parser/Cargo.toml +++ b/crates/parser/Cargo.toml @@ -8,7 +8,6 @@ edition = "2018" id-arena = "2" anyhow = "1.0" pulldown-cmark = { version = "0.8", default-features = false } -witx = { git = 'https://github.com/alexcrichton/WASI', branch = 'abi-next', optional = true } wast = { version = "33", default-features = false, optional = true } unicode-xid = "0.2.2" unicode-normalization = "0.1.19" @@ -21,6 +20,3 @@ serde = { version = "1", features = ['derive'] } [[test]] name = "all" harness = false - -[features] -witx-compat = ['witx', 'wast'] diff --git a/crates/parser/src/abi.rs b/crates/parser/src/abi.rs index f6804fb2d..0e37a8a7f 100644 --- a/crates/parser/src/abi.rs +++ b/crates/parser/src/abi.rs @@ -48,24 +48,6 @@ impl From for WasmType { } } -/// Possible ABIs for interface functions to have. -/// -/// Note that this is a stopgap until we have more of interface types. Interface -/// types functions do not have ABIs, they have APIs. For the meantime, however, -/// we mandate ABIs to ensure we can all talk to each other. -#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)] -pub enum Abi { - /// Only stable ABI currently, and is the historical WASI ABI since it was - /// first created. - /// - /// Note that this ABI is limited notably in its return values where it can - /// only return 0 results or one `Result` lookalike. - Preview1, - - /// In-progress "canonical ABI" as proposed for interface types. - Canonical, -} - // Helper macro for defining instructions without having to have tons of // exhaustive `match` statements to update macro_rules! def_instruction { @@ -487,19 +469,6 @@ def_instruction! { /// This is used for both lifting and lowering lists. IterBasePointer : [0] => [1], - // buffers - - /// Pops a buffer value, pushes the pointer/length of where it points - /// to in memory. - BufferLowerPtrLen { push: bool, ty: &'a Type } : [1] => [3], - /// Pops a buffer value, pushes an integer handle for the buffer. - BufferLowerHandle { push: bool, ty: &'a Type } : [1] => [1], - /// Pops a ptr/len, pushes a buffer wrapping that ptr/len of the memory - /// from the origin module. - BufferLiftPtrLen { push: bool, ty: &'a Type } : [3] => [1], - /// Pops an i32, pushes a buffer wrapping that i32 handle. - BufferLiftHandle { push: bool, ty: &'a Type } : [1] => [1], - // records /// Pops a record value off the stack, decomposes the record to all of @@ -552,9 +521,6 @@ def_instruction! { /// lowers a payload it will expect something bound to this name. VariantPayloadName : [0] => [1], - /// TODO - BufferPayloadName : [0] => [1], - /// Pops a variant off the stack as well as `ty.cases.len()` blocks /// from the code generator. Uses each of those blocks and the value /// from the stack to produce `nresults` of items. @@ -676,14 +642,6 @@ def_instruction! { params: usize, } : [*params + 2] => [0], - - // ... - - /// An instruction from an extended instruction set that's specific to - /// `*.witx` and the "Preview1" ABI. - Witx { - instr: &'a WitxInstruction<'a>, - } : [instr.operands_len()] => [instr.results_len()], } } @@ -706,29 +664,6 @@ pub enum Bitcast { None, } -def_instruction! { - #[derive(Debug)] - pub enum WitxInstruction<'a> { - /// Takes the value off the top of the stack and writes it into linear - /// memory. Pushes the address in linear memory as an `i32`. - AddrOf : [1] => [1], - - /// Converts a language-specific pointer value to a wasm `i32`. - I32FromPointer : [1] => [1], - /// Converts a language-specific pointer value to a wasm `i32`. - I32FromConstPointer : [1] => [1], - /// Converts a native wasm `i32` to a language-specific pointer. - PointerFromI32 { ty: &'a Type }: [1] => [1], - /// Converts a native wasm `i32` to a language-specific pointer. - ConstPointerFromI32 { ty: &'a Type } : [1] => [1], - - /// This is a special instruction specifically for the original ABI of - /// WASI. The raw return `i32` of a function is re-pushed onto the - /// stack for reuse. - ReuseReturn : [0] => [1], - } -} - /// Whether the glue code surrounding a call is lifting arguments and lowering /// results or vice versa. #[derive(Clone, Copy, PartialEq, Eq)] @@ -802,20 +737,11 @@ pub trait Bindgen { results: &mut Vec, ); - /// Allocates temporary space in linear memory for the type `ty`. - /// - /// This is called when calling some wasm functions where a return pointer - /// is needed. Only used for the `Abi::Preview1` ABI. - /// - /// Returns an `Operand` which has type `i32` and is the base of the typed - /// allocation in memory. - fn allocate_typed_space(&mut self, iface: &Interface, ty: TypeId) -> Self::Operand; - /// Allocates temporary space in linear memory for a fixed number of `i64` /// values. /// - /// This is only called in the `Abi::Canonical` ABI for when a function - /// would otherwise have multiple results. + /// This is only called when a function would otherwise have multiple + /// results. /// /// Returns an `Operand` which has type `i32` and points to the base of the /// fixed-size-array allocation. @@ -857,154 +783,6 @@ pub trait Bindgen { } impl Interface { - /// Validates the parameters/results of a function are representable in its - /// ABI. - /// - /// Returns an error string if they're not representable or returns `Ok` if - /// they're indeed representable. - pub fn validate_abi(&self, func: &Function) -> Result<(), String> { - for (_, ty) in func.params.iter() { - self.validate_abi_ty(func.abi, ty, true)?; - } - for (_, ty) in func.results.iter() { - self.validate_abi_ty(func.abi, ty, false)?; - } - match func.abi { - Abi::Preview1 => { - // validated below... - } - Abi::Canonical => return Ok(()), - } - match func.results.len() { - 0 => Ok(()), - 1 => self.validate_preview1_return(&func.results[0].1), - _ => Err("more than one result".to_string()), - } - } - - fn validate_preview1_return(&self, ty: &Type) -> Result<(), String> { - let id = match ty { - Type::Id(id) => *id, - _ => return Ok(()), - }; - match &self.types[id].kind { - TypeDefKind::Type(t) => self.validate_preview1_return(t), - TypeDefKind::Variant(v) => { - let (ok, err) = match v.as_expected() { - Some(pair) => pair, - None => return Err("invalid return type".to_string()), - }; - if let Some(ty) = ok { - let id = match ty { - Type::Id(id) => *id, - _ => return Err("only named types are allowed in results".to_string()), - }; - match &self.types[id].kind { - TypeDefKind::Record(r) if r.is_tuple() => { - for field in r.fields.iter() { - self.validate_ty_named(&field.ty)?; - } - } - _ => { - self.validate_ty_named(ty)?; - } - } - } - - if let Some(ty) = err { - let kind = self.validate_ty_named(ty)?; - if let TypeDefKind::Variant(v) = kind { - if v.is_enum() { - return Ok(()); - } - } - return Err("invalid type in error payload of result".to_string()); - } - Ok(()) - } - TypeDefKind::Record(r) if r.is_flags() => Ok(()), - TypeDefKind::Record(_) - | TypeDefKind::List(_) - | TypeDefKind::PushBuffer(_) - | TypeDefKind::PullBuffer(_) => Err("invalid return type".to_string()), - TypeDefKind::Pointer(_) | TypeDefKind::ConstPointer(_) => Ok(()), - } - } - - fn validate_ty_named(&self, ty: &Type) -> Result<&TypeDefKind, String> { - let id = match ty { - Type::Id(id) => *id, - _ => return Err("only named types are allowed in results".to_string()), - }; - let ty = &self.types[id]; - if ty.name.is_none() { - return Err("only named types are allowed in results".to_string()); - } - Ok(&ty.kind) - } - - fn validate_abi_ty(&self, abi: Abi, ty: &Type, param: bool) -> Result<(), String> { - let id = match ty { - Type::Id(id) => *id, - // Type::U8 { lang_c_char: true } => { - // if let Abi::Next = self { - // return Err("cannot use `(@witx char8)` in this ABI".to_string()); - // } - // Ok(()) - // } - // Type::U32 { lang_ptr_size: true } => { - // if let Abi::Next = self { - // return Err("cannot use `(@witx usize)` in this ABI".to_string()); - // } - // Ok(()) - // } - _ => return Ok(()), - }; - match &self.types[id].kind { - TypeDefKind::Type(t) => self.validate_abi_ty(abi, t, param), - TypeDefKind::Record(r) => { - for r in r.fields.iter() { - self.validate_abi_ty(abi, &r.ty, param)?; - } - Ok(()) - } - TypeDefKind::Variant(v) => { - for case in v.cases.iter() { - if let Some(ty) = &case.ty { - self.validate_abi_ty(abi, ty, param)?; - } - } - Ok(()) - } - TypeDefKind::List(t) => self.validate_abi_ty(abi, t, param), - TypeDefKind::Pointer(t) => { - if let Abi::Canonical = abi { - return Err("cannot use `(@witx pointer)` in this ABI".to_string()); - } - self.validate_abi_ty(abi, t, param) - } - TypeDefKind::ConstPointer(t) => { - if let Abi::Canonical = abi { - return Err("cannot use `(@witx const_pointer)` in this ABI".to_string()); - } - self.validate_abi_ty(abi, t, param) - } - TypeDefKind::PushBuffer(t) | TypeDefKind::PullBuffer(t) => { - if !param { - return Err("cannot use buffers in the result position".to_string()); - } - let param = match &self.types[id].kind { - TypeDefKind::PushBuffer(_) => false, - TypeDefKind::PullBuffer(_) => param, - _ => unreachable!(), - }; - // If this is an output buffer then validate `t` as if it were a - // result because the callee can't give us buffers back. - self.validate_abi_ty(abi, t, param) - } - } - } - /// Get the WebAssembly type signature for this interface function /// /// The first entry returned is the list of parameters and the second entry @@ -1013,39 +791,11 @@ impl Interface { let mut params = Vec::new(); let mut results = Vec::new(); for (_, param) in func.params.iter() { - if let (Abi::Preview1, Type::Id(id)) = (func.abi, param) { - match &self.types[*id].kind { - TypeDefKind::Variant(_) => { - params.push(WasmType::I32); - continue; - } - TypeDefKind::Record(r) if !r.is_flags() => { - params.push(WasmType::I32); - continue; - } - _ => {} - } - } - self.push_wasm(func.abi, variant, param, &mut params); + self.push_wasm(variant, param, &mut params); } for (_, result) in func.results.iter() { - if let (Abi::Preview1, Type::Id(id)) = (func.abi, result) { - if let TypeDefKind::Variant(v) = &self.types[*id].kind { - results.push(v.tag.into()); - if v.is_enum() { - continue; - } - // return pointer for payload, if any - if let Some(ty) = &v.cases[0].ty { - for _ in 0..self.preview1_num_types(ty) { - params.push(WasmType::I32); - } - } - continue; - } - } - self.push_wasm(func.abi, variant, result, &mut results); + self.push_wasm(variant, result, &mut results); } let mut retptr = None; @@ -1095,17 +845,7 @@ impl Interface { } } - fn preview1_num_types(&self, ty: &Type) -> usize { - match ty { - Type::Id(id) => match &self.types[*id].kind { - TypeDefKind::Record(r) if r.is_tuple() => r.fields.len(), - _ => 1, - }, - _ => 1, - } - } - - fn push_wasm(&self, abi: Abi, variant: AbiVariant, ty: &Type, result: &mut Vec) { + fn push_wasm(&self, variant: AbiVariant, ty: &Type, result: &mut Vec) { match ty { Type::S8 | Type::U8 @@ -1123,7 +863,7 @@ impl Interface { Type::F64 => result.push(WasmType::F64), Type::Id(id) => match &self.types[*id].kind { - TypeDefKind::Type(t) => self.push_wasm(abi, variant, t, result), + TypeDefKind::Type(t) => self.push_wasm(variant, t, result), TypeDefKind::Record(r) if r.is_flags() => match self.flags_repr(r) { Some(int) => result.push(int.into()), @@ -1136,7 +876,7 @@ impl Interface { TypeDefKind::Record(r) => { for field in r.fields.iter() { - self.push_wasm(abi, variant, &field.ty, result); + self.push_wasm(variant, &field.ty, result); } } @@ -1145,18 +885,6 @@ impl Interface { result.push(WasmType::I32); } - TypeDefKind::Pointer(_) | TypeDefKind::ConstPointer(_) => { - result.push(WasmType::I32); - } - - TypeDefKind::PushBuffer(_) | TypeDefKind::PullBuffer(_) => { - result.push(WasmType::I32); - if variant == AbiVariant::GuestImport { - result.push(WasmType::I32); - result.push(WasmType::I32); - } - } - TypeDefKind::Variant(v) => { result.push(v.tag.into()); let start = result.len(); @@ -1173,7 +901,7 @@ impl Interface { Some(ty) => ty, None => continue, }; - self.push_wasm(abi, variant, ty, &mut temp); + self.push_wasm(variant, ty, &mut temp); for (i, ty) in temp.drain(..).enumerate() { match result.get_mut(start + i) { @@ -1221,19 +949,11 @@ impl Interface { func: &Function, bindgen: &mut impl Bindgen, ) { - if Abi::Preview1 == func.abi { - // The Preview1 ABI only works with WASI which is only intended - // for use with these modes. - if variant == AbiVariant::GuestExport { - panic!("the preview1 ABI only supports import modes"); - } - } - Generator::new(self, func.abi, variant, lift_lower, bindgen).call(func); + Generator::new(self, variant, lift_lower, bindgen).call(func); } } struct Generator<'a, B: Bindgen> { - abi: Abi, variant: AbiVariant, lift_lower: LiftLower, bindgen: &'a mut B, @@ -1247,14 +967,12 @@ struct Generator<'a, B: Bindgen> { impl<'a, B: Bindgen> Generator<'a, B> { fn new( iface: &'a Interface, - abi: Abi, variant: AbiVariant, lift_lower: LiftLower, bindgen: &'a mut B, ) -> Generator<'a, B> { Generator { iface, - abi, variant, lift_lower, bindgen, @@ -1351,32 +1069,16 @@ impl<'a, B: Bindgen> Generator<'a, B> { // directly due to various conversions and return pointers, so // we need to somewhat manually calculate all the arguments // which are converted as interface types arguments below. - let nargs = match self.abi { - Abi::Preview1 => { - func.params.len() - + func - .params - .iter() - .filter(|(_, t)| match t { - Type::Id(id) => { - matches!(&self.iface.types[*id].kind, TypeDefKind::List(_)) - } - _ => false, - }) - .count() - } - Abi::Canonical => { - let skip_cnt = if func.is_async { - match self.variant { - AbiVariant::GuestExport => 1, - AbiVariant::GuestImport => 2, - } - } else { - (sig.retptr.is_some() && self.variant == AbiVariant::GuestImport) - as usize - }; - sig.params.len() - skip_cnt - } + let nargs = { + let skip_cnt = if func.is_async { + match self.variant { + AbiVariant::GuestExport => 1, + AbiVariant::GuestImport => 2, + } + } else { + (sig.retptr.is_some() && self.variant == AbiVariant::GuestImport) as usize + }; + sig.params.len() - skip_cnt }; for nth in 0..nargs { self.emit(&Instruction::GetArg { nth }); @@ -1503,19 +1205,10 @@ impl<'a, B: Bindgen> Generator<'a, B> { .iter() .rev() .map(|(_, ty)| { - let ntys = match self.abi { - Abi::Preview1 => match ty { - Type::Id(id) => match &self.iface.types[*id].kind { - TypeDefKind::List(_) => 2, - _ => 1, - }, - _ => 1, - }, - Abi::Canonical => { - temp.truncate(0); - self.iface.push_wasm(self.abi, self.variant, ty, &mut temp); - temp.len() - } + let ntys = { + temp.truncate(0); + self.iface.push_wasm(self.variant, ty, &mut temp); + temp.len() }; self.stack .drain(self.stack.len() - ntys..) @@ -1561,10 +1254,6 @@ impl<'a, B: Bindgen> Generator<'a, B> { retptr } - fn witx(&mut self, instr: &WitxInstruction<'_>) { - self.emit(&Instruction::Witx { instr }); - } - fn emit(&mut self, inst: &Instruction<'_>) { self.operands.clear(); self.results.clear(); @@ -1610,7 +1299,6 @@ impl<'a, B: Bindgen> Generator<'a, B> { fn lower(&mut self, ty: &Type, retptr: Option<&mut usize>) { use Instruction::*; - use WitxInstruction::*; match *ty { Type::S8 => self.emit(&I32FromS8), @@ -1662,58 +1350,25 @@ impl<'a, B: Bindgen> Generator<'a, B> { } Type::Id(id) => match &self.iface.types[id].kind { TypeDefKind::Type(t) => self.lower(t, retptr), - TypeDefKind::Pointer(_) => self.witx(&I32FromPointer), - TypeDefKind::ConstPointer(_) => self.witx(&I32FromConstPointer), - TypeDefKind::List(element) => match self.abi { - Abi::Preview1 => self.emit(&ListCanonLower { - element, - realloc: None, - }), - Abi::Canonical => { - // Lowering parameters calling a wasm import means - // we don't need to pass ownership, but we pass - // ownership in all other cases. - let realloc = match (self.variant, self.lift_lower) { - (AbiVariant::GuestImport, LiftLower::LowerArgsLiftResults) => None, - _ => Some("canonical_abi_realloc"), - }; - if self.is_char(element) - || self.bindgen.is_list_canonical(self.iface, element) - { - self.emit(&ListCanonLower { element, realloc }); - } else { - self.push_block(); - self.emit(&IterElem { element }); - self.emit(&IterBasePointer); - let addr = self.stack.pop().unwrap(); - self.write_to_memory(element, addr, 0); - self.finish_block(0); - self.emit(&ListLower { element, realloc }); - } - } - }, - TypeDefKind::PushBuffer(ty) | TypeDefKind::PullBuffer(ty) => { - let push = matches!(&self.iface.types[id].kind, TypeDefKind::PushBuffer(_)); - self.translate_buffer(push, ty); - - // Buffers are only used in the parameter position, so if we - // are lowering them, then we had better be lowering args - // and lifting results. - assert!(self.lift_lower == LiftLower::LowerArgsLiftResults); - - match self.variant { - AbiVariant::GuestImport => { - // When calling an imported function we're passing a raw view - // into memory, and the adapter will convert it into something - // else if necessary. - self.emit(&BufferLowerPtrLen { push, ty }); - } - AbiVariant::GuestExport => { - // When calling an exported function we're passing a handle to - // the caller's memory, and this part of the adapter is - // responsible for converting it into something that's a handle. - self.emit(&BufferLowerHandle { push, ty }); - } + TypeDefKind::List(element) => { + // Lowering parameters calling a wasm import means + // we don't need to pass ownership, but we pass + // ownership in all other cases. + let realloc = match (self.variant, self.lift_lower) { + (AbiVariant::GuestImport, LiftLower::LowerArgsLiftResults) => None, + _ => Some("canonical_abi_realloc"), + }; + if self.is_char(element) || self.bindgen.is_list_canonical(self.iface, element) + { + self.emit(&ListCanonLower { element, realloc }); + } else { + self.push_block(); + self.emit(&IterElem { element }); + self.emit(&IterBasePointer); + let addr = self.stack.pop().unwrap(); + self.write_to_memory(element, addr, 0); + self.finish_block(0); + self.emit(&ListLower { element, realloc }); } } TypeDefKind::Record(record) if record.is_flags() => { @@ -1730,103 +1385,27 @@ impl<'a, B: Bindgen> Generator<'a, B> { }), } } - TypeDefKind::Record(record) => match self.abi { - Abi::Preview1 => self.witx(&AddrOf), - - Abi::Canonical => { - self.emit(&RecordLower { - record, - ty: id, - name: self.iface.types[id].name.as_deref(), - }); - let values = self - .stack - .drain(self.stack.len() - record.fields.len()..) - .collect::>(); - for (field, value) in record.fields.iter().zip(values) { - self.stack.push(value); - self.lower(&field.ty, None); - } - } - }, - - // Variants in the return position of an import must be a Result in - // the preview1 ABI and they're a bit special about where all the - // pieces are. - TypeDefKind::Variant(v) - if self.abi == Abi::Preview1 - && self.variant == AbiVariant::GuestImport - && self.lift_lower == LiftLower::LiftArgsLowerResults - && !v.is_enum() => - { - let retptr = retptr.unwrap(); - let (ok, err) = v.as_expected().unwrap(); - self.push_block(); - self.emit(&VariantPayloadName); - let payload_name = self.stack.pop().unwrap(); - if let Some(ok) = ok { - self.stack.push(payload_name); - let store = |me: &mut Self, ty: &Type, n| { - me.emit(&GetArg { nth: *retptr + n }); - let addr = me.stack.pop().unwrap(); - me.write_to_memory(ty, addr, 0); - }; - match *ok { - Type::Id(okid) => match &self.iface.types[okid].kind { - TypeDefKind::Record(record) if record.is_tuple() => { - self.emit(&RecordLower { - record, - ty: id, - name: self.iface.types[okid].name.as_deref(), - }); - // Note that `rev()` is used here due to the order - // that tuples are pushed onto the stack and how we - // consume the last item first from the stack. - for (i, field) in record.fields.iter().enumerate().rev() { - store(self, &field.ty, i); - } - } - _ => store(self, ok, 0), - }, - _ => store(self, ok, 0), - } - }; - self.emit(&I32Const { val: 0 }); - self.finish_block(1); - - self.push_block(); - self.emit(&VariantPayloadName); - let payload_name = self.stack.pop().unwrap(); - if let Some(ty) = err { - self.stack.push(payload_name); - self.lower(ty, None); - } - self.finish_block(1); - - self.emit(&VariantLower { - variant: v, + TypeDefKind::Record(record) => { + self.emit(&RecordLower { + record, ty: id, name: self.iface.types[id].name.as_deref(), - results: &[WasmType::I32], }); - } - - // Variant arguments in the Preview1 ABI are all passed by pointer - TypeDefKind::Variant(v) - if self.abi == Abi::Preview1 - && self.variant == AbiVariant::GuestImport - && self.lift_lower == LiftLower::LowerArgsLiftResults - && !v.is_enum() => - { - self.witx(&AddrOf) + let values = self + .stack + .drain(self.stack.len() - record.fields.len()..) + .collect::>(); + for (field, value) in record.fields.iter().zip(values) { + self.stack.push(value); + self.lower(&field.ty, None); + } } TypeDefKind::Variant(v) => { let mut results = Vec::new(); let mut temp = Vec::new(); let mut casts = Vec::new(); - self.iface - .push_wasm(self.abi, self.variant, ty, &mut results); + self.iface.push_wasm(self.variant, ty, &mut results); for (i, case) in v.cases.iter().enumerate() { self.push_block(); self.emit(&VariantPayloadName); @@ -1843,7 +1422,7 @@ impl<'a, B: Bindgen> Generator<'a, B> { // pushed, and record how many. If we pushed too few // then we'll need to push some zeros after this. temp.truncate(0); - self.iface.push_wasm(self.abi, self.variant, ty, &mut temp); + self.iface.push_wasm(self.variant, ty, &mut temp); pushed += temp.len(); // For all the types pushed we may need to insert some @@ -1881,57 +1460,14 @@ impl<'a, B: Bindgen> Generator<'a, B> { } fn prep_return_pointer(&mut self, sig: &WasmSignature, results: &[(String, Type)]) { - match self.abi { - Abi::Preview1 => { - assert!(results.len() <= 1); - let ty = match results.get(0) { - Some((_, ty)) => ty, - None => return, - }; - // Return pointers are only needed for `Result`... - let variant = match ty { - Type::Id(id) => match &self.iface.types[*id].kind { - TypeDefKind::Variant(v) => v, - _ => return, - }, - _ => return, - }; - // ... and only if `T` is actually present in `Result` - let ok = match &variant.cases[0].ty { - Some(Type::Id(id)) => *id, - _ => return, - }; - - // Tuples have each individual item in a separate return pointer while - // all other types go through a singular return pointer. - let iface = self.iface; - let mut prep = |ty: TypeId| { - let ptr = self.bindgen.allocate_typed_space(iface, ty); - self.return_pointers.push(ptr.clone()); - self.stack.push(ptr); - }; - match &iface.types[ok].kind { - TypeDefKind::Record(r) if r.is_tuple() => { - for field in r.fields.iter() { - match field.ty { - Type::Id(id) => prep(id), - _ => unreachable!(), - } - } - } - _ => prep(ok), - } - } - // If a return pointer was automatically injected into this function - // then we need to allocate a proper amount of space for it and then - // add it to the stack to get passed to the callee. - Abi::Canonical => { - if let Some(results) = &sig.retptr { - let ptr = self.bindgen.i64_return_pointer_area(results.len()); - self.return_pointers.push(ptr.clone()); - self.stack.push(ptr); - } - } + drop(results); // FIXME: update to the new canonical abi and use this + // If a return pointer was automatically injected into this function + // then we need to allocate a proper amount of space for it and then + // add it to the stack to get passed to the callee. + if let Some(results) = &sig.retptr { + let ptr = self.bindgen.i64_return_pointer_area(results.len()); + self.return_pointers.push(ptr.clone()); + self.stack.push(ptr); } } @@ -1939,7 +1475,6 @@ impl<'a, B: Bindgen> Generator<'a, B> { /// `lower` function above. This is intentional and should be kept this way! fn lift(&mut self, ty: &Type) { use Instruction::*; - use WitxInstruction::*; match *ty { Type::S8 => self.emit(&S8FromI32), @@ -1970,64 +1505,32 @@ impl<'a, B: Bindgen> Generator<'a, B> { } Type::Id(id) => match &self.iface.types[id].kind { TypeDefKind::Type(t) => self.lift(t), - TypeDefKind::Pointer(ty) => self.witx(&PointerFromI32 { ty }), - TypeDefKind::ConstPointer(ty) => self.witx(&ConstPointerFromI32 { ty }), - TypeDefKind::List(element) => match self.abi { - Abi::Preview1 => self.emit(&ListCanonLift { - element, - free: None, - ty: id, - }), - Abi::Canonical => { - // Lifting the arguments of a defined import means that, if - // possible, the caller still retains ownership and we don't - // free anything. - let free = match (self.variant, self.lift_lower) { - (AbiVariant::GuestImport, LiftLower::LiftArgsLowerResults) => None, - _ => Some("canonical_abi_free"), - }; - if self.is_char(element) - || self.bindgen.is_list_canonical(self.iface, element) - { - self.emit(&ListCanonLift { - element, - free, - ty: id, - }); - } else { - self.push_block(); - self.emit(&IterBasePointer); - let addr = self.stack.pop().unwrap(); - self.read_from_memory(element, addr, 0); - self.finish_block(1); - self.emit(&ListLift { - element, - free, - ty: id, - }); - } - } - }, - TypeDefKind::PushBuffer(ty) | TypeDefKind::PullBuffer(ty) => { - let push = matches!(&self.iface.types[id].kind, TypeDefKind::PushBuffer(_)); - self.translate_buffer(push, ty); - // Buffers are only used in the parameter position, which - // means lifting a buffer should only happen when we are - // lifting arguments and lowering results. - assert!(self.lift_lower == LiftLower::LiftArgsLowerResults); - - match self.variant { - AbiVariant::GuestImport => { - // When calling a defined imported function then we're coming - // from a pointer/length, and the embedding context will figure - // out what to do with that pointer/length. - self.emit(&BufferLiftPtrLen { push, ty }) - } - AbiVariant::GuestExport => { - // When calling an exported function we're given a handle to the - // buffer, which is then interpreted in the calling context. - self.emit(&BufferLiftHandle { push, ty }) - } + TypeDefKind::List(element) => { + // Lifting the arguments of a defined import means that, if + // possible, the caller still retains ownership and we don't + // free anything. + let free = match (self.variant, self.lift_lower) { + (AbiVariant::GuestImport, LiftLower::LiftArgsLowerResults) => None, + _ => Some("canonical_abi_free"), + }; + if self.is_char(element) || self.bindgen.is_list_canonical(self.iface, element) + { + self.emit(&ListCanonLift { + element, + free, + ty: id, + }); + } else { + self.push_block(); + self.emit(&IterBasePointer); + let addr = self.stack.pop().unwrap(); + self.read_from_memory(element, addr, 0); + self.finish_block(1); + self.emit(&ListLift { + element, + free, + ty: id, + }); } } TypeDefKind::Record(record) if record.is_flags() => { @@ -2044,101 +1547,31 @@ impl<'a, B: Bindgen> Generator<'a, B> { }), } } - TypeDefKind::Record(record) => match self.abi { - Abi::Preview1 => { - let addr = self.stack.pop().unwrap(); - self.read_from_memory(ty, addr, 0); - } - Abi::Canonical => { - let mut temp = Vec::new(); - self.iface.push_wasm(self.abi, self.variant, ty, &mut temp); - let mut args = self - .stack - .drain(self.stack.len() - temp.len()..) - .collect::>(); - for field in record.fields.iter() { - temp.truncate(0); - self.iface - .push_wasm(self.abi, self.variant, &field.ty, &mut temp); - self.stack.extend(args.drain(..temp.len())); - self.lift(&field.ty); - } - self.emit(&RecordLift { - record, - ty: id, - name: self.iface.types[id].name.as_deref(), - }); - } - }, - - // Variants in the return position of an import must be a Result in - // the preview1 ABI and they're a bit special about where all the - // pieces are. - TypeDefKind::Variant(v) - if self.abi == Abi::Preview1 - && self.variant == AbiVariant::GuestImport - && self.lift_lower == LiftLower::LowerArgsLiftResults - && !v.is_enum() => - { - let (ok, err) = v.as_expected().unwrap(); - self.push_block(); - if let Some(ok) = ok { - let mut n = 0; - let mut load = |me: &mut Self, ty: &Type| { - me.read_from_memory(ty, me.return_pointers[n].clone(), 0); - n += 1; - }; - match *ok { - Type::Id(okid) => match &self.iface.types[okid].kind { - TypeDefKind::Record(record) if record.is_tuple() => { - for field in record.fields.iter() { - load(self, &field.ty); - } - self.emit(&RecordLift { - record, - ty: okid, - name: self.iface.types[okid].name.as_deref(), - }); - } - _ => load(self, ok), - }, - _ => load(self, ok), - } - } - self.finish_block(ok.is_some() as usize); - - self.push_block(); - if let Some(ty) = err { - self.witx(&ReuseReturn); - self.lift(ty); + TypeDefKind::Record(record) => { + let mut temp = Vec::new(); + self.iface.push_wasm(self.variant, ty, &mut temp); + let mut args = self + .stack + .drain(self.stack.len() - temp.len()..) + .collect::>(); + for field in record.fields.iter() { + temp.truncate(0); + self.iface.push_wasm(self.variant, &field.ty, &mut temp); + self.stack.extend(args.drain(..temp.len())); + self.lift(&field.ty); } - self.finish_block(err.is_some() as usize); - - self.emit(&VariantLift { - variant: v, + self.emit(&RecordLift { + record, ty: id, name: self.iface.types[id].name.as_deref(), }); } - // Variant arguments in the Preview1 ABI are all passed by pointer, - // so we read them here. - TypeDefKind::Variant(v) - if self.abi == Abi::Preview1 - && self.variant == AbiVariant::GuestImport - && self.lift_lower == LiftLower::LiftArgsLowerResults - && !v.is_enum() => - { - let addr = self.stack.pop().unwrap(); - self.read_from_memory(ty, addr, 0) - } - TypeDefKind::Variant(v) => { let mut params = Vec::new(); let mut temp = Vec::new(); let mut casts = Vec::new(); - self.iface - .push_wasm(self.abi, self.variant, ty, &mut params); + self.iface.push_wasm(self.variant, ty, &mut params); let block_inputs = self .stack .drain(self.stack.len() + 1 - params.len()..) @@ -2149,7 +1582,7 @@ impl<'a, B: Bindgen> Generator<'a, B> { // Push only the values we need for this variant onto // the stack. temp.truncate(0); - self.iface.push_wasm(self.abi, self.variant, ty, &mut temp); + self.iface.push_wasm(self.variant, ty, &mut temp); self.stack .extend(block_inputs[..temp.len()].iter().cloned()); @@ -2197,9 +1630,6 @@ impl<'a, B: Bindgen> Generator<'a, B> { Type::Id(id) => match &self.iface.types[id].kind { TypeDefKind::Type(t) => self.write_to_memory(t, addr, offset), - TypeDefKind::Pointer(_) | TypeDefKind::ConstPointer(_) => { - self.lower_and_emit(ty, addr, &I32Store { offset }); - } // After lowering the list there's two i32 values on the stack // which we write into memory, writing the pointer into the low address @@ -2212,21 +1642,6 @@ impl<'a, B: Bindgen> Generator<'a, B> { self.emit(&I32Store { offset }); } - // Lower the buffer to its raw values, and then write the values - // into memory, which may be more than one value depending on - // our import/export direction. - TypeDefKind::PushBuffer(_) | TypeDefKind::PullBuffer(_) => { - self.lower(ty, None); - if self.variant == AbiVariant::GuestImport { - self.stack.push(addr.clone()); - self.emit(&I32Store { offset: offset + 8 }); - self.stack.push(addr.clone()); - self.emit(&I32Store { offset: offset + 4 }); - } - self.stack.push(addr); - self.emit(&I32Store { offset }); - } - TypeDefKind::Record(r) if r.is_flags() => { self.lower(ty, None); match self.iface.flags_repr(r) { @@ -2327,9 +1742,6 @@ impl<'a, B: Bindgen> Generator<'a, B> { Type::Id(id) => match &self.iface.types[id].kind { TypeDefKind::Type(t) => self.read_from_memory(t, addr, offset), - TypeDefKind::Pointer(_) | TypeDefKind::ConstPointer(_) => { - self.emit_and_lift(ty, addr, &I32Load { offset }) - } // Read the pointer/len and then perform the standard lifting // proceses. @@ -2341,22 +1753,6 @@ impl<'a, B: Bindgen> Generator<'a, B> { self.lift(ty); } - // Read the requisite number of values from memory and then lift as - // appropriate. - TypeDefKind::PushBuffer(_) | TypeDefKind::PullBuffer(_) => { - self.stack.push(addr.clone()); - self.emit(&I32Load { offset }); - if self.variant == AbiVariant::GuestImport - && self.lift_lower == LiftLower::LiftArgsLowerResults - { - self.stack.push(addr.clone()); - self.emit(&I32Load { offset: offset + 4 }); - self.stack.push(addr); - self.emit(&I32Load { offset: offset + 8 }); - } - self.lift(ty); - } - TypeDefKind::Record(r) if r.is_flags() => { match self.iface.flags_repr(r) { Some(repr) => { @@ -2449,36 +1845,6 @@ impl<'a, B: Bindgen> Generator<'a, B> { }); } - fn translate_buffer(&mut self, push: bool, ty: &Type) { - let do_write = match self.lift_lower { - // For declared items, input/output is defined in the context of - // what the callee will do. The callee will read input buffers, - // meaning we write to them, and write to output buffers, meaning - // we'll read from them. - LiftLower::LowerArgsLiftResults => !push, - - // Defined item mirror declared imports because buffers are - // defined from the caller's perspective, so we don't invert the - // `out` setting like above. - LiftLower::LiftArgsLowerResults => push, - }; - self.emit(&Instruction::IterBasePointer); - let addr = self.stack.pop().unwrap(); - - self.push_block(); - - let size = if do_write { - self.emit(&Instruction::BufferPayloadName); - self.write_to_memory(ty, addr, 0); - 0 - } else { - self.read_from_memory(ty, addr, 0); - 1 - }; - - self.finish_block(size); - } - fn is_char(&self, ty: &Type) -> bool { match ty { Type::Char => true, diff --git a/crates/parser/src/ast.rs b/crates/parser/src/ast.rs index b91ee47c4..972538a4b 100644 --- a/crates/parser/src/ast.rs +++ b/crates/parser/src/ast.rs @@ -1,4 +1,3 @@ -use crate::abi::Abi; use anyhow::Result; use lex::{Span, Token, Tokenizer}; use std::borrow::Cow; @@ -94,12 +93,6 @@ enum Type<'a> { List(Box>), Record(Record<'a>), Variant(Variant<'a>), - PushBuffer(Box>), - PullBuffer(Box>), - #[allow(dead_code)] - Pointer(Box>), - #[allow(dead_code)] - ConstPointer(Box>), } struct Record<'a> { @@ -135,7 +128,6 @@ pub struct Value<'a> { enum ValueKind<'a> { Function { is_async: bool, - abi: crate::abi::Abi, params: Vec<(Id<'a>, Type<'a>)>, results: Vec<(Id<'a>, Type<'a>)>, }, @@ -152,10 +144,6 @@ pub struct Interface<'a> { impl<'a> Ast<'a> { pub fn parse(input: &'a str) -> Result> { let mut lexer = Tokenizer::new(input)?; - #[cfg(feature = "witx-compat")] - if lexer.eat(Token::Semicolon)? || lexer.eat(Token::LeftParen)? { - return Ast::parse_old_witx(input); - } let mut items = Vec::new(); while lexer.clone().next()?.is_some() { let docs = parse_docs(&mut lexer)?; @@ -173,276 +161,6 @@ impl<'a> Ast<'a> { let instance = resolver.resolve(name, &self.items, map)?; Ok(instance) } - - #[cfg(feature = "witx-compat")] - fn parse_old_witx(input: &'a str) -> Result> { - use witx::parser as old; - let buf = wast::parser::ParseBuffer::new(&input)?; - let doc = wast::parser::parse::(&buf)?; - let mut items = Vec::new(); - for d in doc.decls { - let item = match d.item { - old::TopLevelSyntax::Use(u) => Item::Use(Use { - from: vec![id(&u.from)], - names: match u.names { - old::UsedNames::All(_) => None, - old::UsedNames::List(names) => Some( - names - .iter() - .map(|n| UseName { - name: id(&n.other_name), - as_: Some(id(&n.our_name)), - }) - .collect(), - ), - }, - }), - old::TopLevelSyntax::Decl(u) => match u { - old::DeclSyntax::Typename(t) => Item::TypeDef(TypeDef { - docs: docs(&d.comments), - name: id(&t.ident), - ty: ty(&t.def), - }), - old::DeclSyntax::Resource(r) => Item::Resource(Resource { - docs: docs(&d.comments), - name: id(&r.ident), - values: Vec::new(), - }), - old::DeclSyntax::Const(_) => unimplemented!(), - }, - }; - items.push(item); - } - - for f in doc.functions { - let item = Item::Value(Value { - docs: docs(&f.comments), - name: Id { - name: f.item.export.to_string().into(), - span: span(f.item.export_loc), - }, - kind: ValueKind::Function { - is_async: false, - abi: match f.item.abi { - witx::Abi::Next => Abi::Canonical, - witx::Abi::Preview1 => Abi::Preview1, - }, - params: f - .item - .params - .iter() - .map(|p| (id(&p.item.name), ty(&p.item.type_))) - .collect(), - results: f - .item - .results - .iter() - .map(|p| (id(&p.item.name), ty(&p.item.type_))) - .collect(), - }, - }); - items.push(item); - } - - return Ok(Ast { items }); - - fn ty(t: &old::TypedefSyntax<'_>) -> Type<'static> { - match t { - old::TypedefSyntax::Record(e) => Type::Record(Record { - tuple_hint: false, - flags_repr: None, - fields: e - .fields - .iter() - .map(|f| Field { - docs: docs(&f.comments), - name: id(&f.item.name), - ty: ty(&f.item.type_), - }) - .collect(), - }), - old::TypedefSyntax::Flags(e) => Type::Record(Record { - tuple_hint: false, - flags_repr: e.repr.as_ref().map(|t| Box::new(builtin(t))), - fields: e - .flags - .iter() - .map(|f| Field { - docs: docs(&f.comments), - name: id(&f.item), - ty: Type::bool(), - }) - .collect(), - }), - old::TypedefSyntax::Tuple(e) => Type::Record(Record { - tuple_hint: true, - flags_repr: None, - fields: e - .types - .iter() - .enumerate() - .map(|(i, t)| Field { - docs: Docs::default(), - name: Id::from(i.to_string()), - ty: ty(t), - }) - .collect(), - }), - - old::TypedefSyntax::Variant(e) => Type::Variant(Variant { - tag: e.tag.as_ref().map(|t| Box::new(ty(t))), - span: Span { start: 0, end: 0 }, - cases: e - .cases - .iter() - .map(|c| Case { - docs: docs(&c.comments), - name: id(&c.item.name), - ty: c.item.ty.as_ref().map(ty), - }) - .collect(), - }), - old::TypedefSyntax::Enum(e) => Type::Variant(Variant { - tag: e.repr.as_ref().map(|t| Box::new(builtin(t))), - span: Span { start: 0, end: 0 }, - cases: e - .members - .iter() - .map(|c| Case { - docs: docs(&c.comments), - name: id(&c.item), - ty: None, - }) - .collect(), - }), - old::TypedefSyntax::Expected(e) => Type::Variant(Variant { - tag: None, - span: Span { start: 0, end: 0 }, - cases: vec![ - Case { - docs: Docs::default(), - name: "ok".into(), - ty: e.ok.as_ref().map(|t| ty(t)), - }, - Case { - docs: Docs::default(), - name: "err".into(), - ty: e.err.as_ref().map(|t| ty(t)), - }, - ], - }), - old::TypedefSyntax::Option(e) => Type::Variant(Variant { - tag: None, - span: Span { start: 0, end: 0 }, - cases: vec![ - Case { - docs: Docs::default(), - name: "none".into(), - ty: None, - }, - Case { - docs: Docs::default(), - name: "some".into(), - ty: Some(ty(&e.ty)), - }, - ], - }), - old::TypedefSyntax::Union(e) => Type::Variant(Variant { - tag: e.tag.as_ref().map(|t| Box::new(ty(t))), - span: Span { start: 0, end: 0 }, - cases: e - .fields - .iter() - .enumerate() - .map(|(i, c)| Case { - docs: docs(&c.comments), - name: i.to_string().into(), - ty: Some(ty(&c.item)), - }) - .collect(), - }), - - old::TypedefSyntax::Handle(e) => Type::Handle(id(&e.resource)), - old::TypedefSyntax::List(e) => Type::List(Box::new(ty(e))), - old::TypedefSyntax::Pointer(e) => Type::Pointer(Box::new(ty(e))), - old::TypedefSyntax::ConstPointer(e) => Type::ConstPointer(Box::new(ty(e))), - old::TypedefSyntax::Buffer(e) => { - if e.out { - Type::PushBuffer(Box::new(ty(&e.ty))) - } else { - Type::PullBuffer(Box::new(ty(&e.ty))) - } - } - old::TypedefSyntax::Builtin(e) => builtin(e), - old::TypedefSyntax::Ident(e) => Type::Name(id(e)), - old::TypedefSyntax::String => Type::List(Box::new(Type::Char)), - old::TypedefSyntax::Bool => Type::bool(), - } - } - - fn builtin(e: &witx::BuiltinType) -> Type<'static> { - use witx::BuiltinType::*; - match e { - Char => Type::Char, - U8 { lang_c_char: false } => Type::U8, - U8 { lang_c_char: true } => Type::CChar, - S8 => Type::S8, - U16 => Type::U16, - S16 => Type::S16, - U32 { - lang_ptr_size: false, - } => Type::U32, - U32 { - lang_ptr_size: true, - } => Type::Usize, - S32 => Type::S32, - U64 => Type::U64, - S64 => Type::S64, - F32 => Type::F32, - F64 => Type::F64, - } - } - - fn docs(docs: &old::CommentSyntax<'_>) -> Docs<'static> { - let docs = docs.docs(); - Docs { - docs: docs.lines().map(|s| format!("//{}\n", s).into()).collect(), - } - } - - fn id(id: &wast::Id<'_>) -> Id<'static> { - Id { - name: id.name().to_string().into(), - span: span(id.span()), - } - } - - // TODO: should add an `offset` accessor to `wast::Span` upstream... - fn span(span: wast::Span) -> Span { - let mut low = 0; - let mut high = 1024; - while span > wast::Span::from_offset(high) { - high *= 2; - } - while low != high { - let val = (high + low) / 2; - let mid = wast::Span::from_offset(val); - if span < mid { - high = val - 1; - } else if span > mid { - low = val + 1; - } else { - low = val; - high = val; - } - } - let low = low as u32; - Span { - start: low, - end: low + 1, - } - } - } } impl<'a> Item<'a> { @@ -695,7 +413,6 @@ impl<'a> Value<'a> { } Ok(ValueKind::Function { is_async, - abi: Abi::Canonical, params, results, }) @@ -888,22 +605,6 @@ impl<'a> Type<'a> { span, })), - // push-buffer - Some((_span, Token::PushBuffer)) => { - tokens.expect(Token::LessThan)?; - let ty = Type::parse(tokens)?; - tokens.expect(Token::GreaterThan)?; - Ok(Type::PushBuffer(Box::new(ty))) - } - - // pull-buffer - Some((_span, Token::PullBuffer)) => { - tokens.expect(Token::LessThan)?; - let ty = Type::parse(tokens)?; - tokens.expect(Token::GreaterThan)?; - Ok(Type::PullBuffer(Box::new(ty))) - } - other => Err(err_expected(tokens, "a type", other).into()), } } @@ -1010,12 +711,6 @@ impl fmt::Display for Error { impl std::error::Error for Error {} pub fn rewrite_error(err: &mut anyhow::Error, file: &str, contents: &str) { - #[cfg(feature = "witx-compat")] - if let Some(err) = err.downcast_mut::() { - err.set_path(file.as_ref()); - err.set_text(contents); - return; - } let parse = match err.downcast_mut::() { Some(err) => err, None => return lex::rewrite_error(err, file, contents), diff --git a/crates/parser/src/ast/lex.rs b/crates/parser/src/ast/lex.rs index 7362e947c..31c4b27d8 100644 --- a/crates/parser/src/ast/lex.rs +++ b/crates/parser/src/ast/lex.rs @@ -73,8 +73,6 @@ pub enum Token { Expected, List, Underscore, - PushBuffer, - PullBuffer, As, From_, Static, @@ -262,8 +260,6 @@ impl<'a> Tokenizer<'a> { "expected" => Expected, "list" => List, "_" => Underscore, - "push-buffer" => PushBuffer, - "pull-buffer" => PullBuffer, "as" => As, "from" => From_, "static" => Static, @@ -527,8 +523,6 @@ impl Token { Underscore => "keyword `_`", Id => "an identifier", ExplicitId => "an '%' identifier", - PushBuffer => "keyword `push-buffer`", - PullBuffer => "keyword `pull-buffer`", RArrow => "`->`", Star => "`*`", As => "keyword `as`", diff --git a/crates/parser/src/ast/resolve.rs b/crates/parser/src/ast/resolve.rs index 9e5a16842..9f8886372 100644 --- a/crates/parser/src/ast/resolve.rs +++ b/crates/parser/src/ast/resolve.rs @@ -22,10 +22,6 @@ enum Key { Variant(Vec<(String, Option)>), Record(Vec<(String, Type)>), List(Type), - PushBuffer(Type), - PullBuffer(Type), - Pointer(Type), - ConstPointer(Type), } impl Resolver { @@ -221,16 +217,6 @@ impl Resolver { tag: v.tag, }), TypeDefKind::List(t) => TypeDefKind::List(self.copy_type(dep_name, dep, *t)), - TypeDefKind::PullBuffer(t) => { - TypeDefKind::PullBuffer(self.copy_type(dep_name, dep, *t)) - } - TypeDefKind::PushBuffer(t) => { - TypeDefKind::PushBuffer(self.copy_type(dep_name, dep, *t)) - } - TypeDefKind::Pointer(t) => TypeDefKind::Pointer(self.copy_type(dep_name, dep, *t)), - TypeDefKind::ConstPointer(t) => { - TypeDefKind::ConstPointer(self.copy_type(dep_name, dep, *t)) - } }, }; let id = self.types.alloc(ty); @@ -365,22 +351,6 @@ impl Resolver { let ty = self.resolve_type(list)?; TypeDefKind::List(ty) } - super::Type::Pointer(list) => { - let ty = self.resolve_type(list)?; - TypeDefKind::Pointer(ty) - } - super::Type::ConstPointer(list) => { - let ty = self.resolve_type(list)?; - TypeDefKind::ConstPointer(ty) - } - super::Type::PushBuffer(ty) => { - let ty = self.resolve_type(ty)?; - TypeDefKind::PushBuffer(ty) - } - super::Type::PullBuffer(ty) => { - let ty = self.resolve_type(ty)?; - TypeDefKind::PullBuffer(ty) - } super::Type::Record(record) => { let fields = record .fields @@ -495,10 +465,6 @@ impl Resolver { .collect::>(), ), TypeDefKind::List(ty) => Key::List(*ty), - TypeDefKind::Pointer(ty) => Key::Pointer(*ty), - TypeDefKind::ConstPointer(ty) => Key::ConstPointer(*ty), - TypeDefKind::PushBuffer(ty) => Key::PushBuffer(*ty), - TypeDefKind::PullBuffer(ty) => Key::PullBuffer(*ty), }; let types = &mut self.types; let id = self @@ -536,7 +502,6 @@ impl Resolver { match &value.kind { ValueKind::Function { is_async, - abi, params, results, } => { @@ -549,7 +514,6 @@ impl Resolver { .map(|(name, ty)| Ok((name.name.to_string(), self.resolve_type(ty)?))) .collect::>()?; self.functions.push(Function { - abi: *abi, docs, name: value.name.name.to_string(), kind: FunctionKind::Freestanding, @@ -574,13 +538,12 @@ impl Resolver { let mut names = HashSet::new(); let id = self.resource_lookup[&*resource.name.name]; for (statik, value) in resource.values.iter() { - let (abi, is_async, params, results) = match &value.kind { + let (is_async, params, results) = match &value.kind { ValueKind::Function { - abi, is_async, params, results, - } => (*abi, *is_async, params, results), + } => (*is_async, params, results), ValueKind::Global(_) => { return Err(Error { span: value.name.span, @@ -618,7 +581,6 @@ impl Resolver { } }; self.functions.push(Function { - abi, is_async, docs, name: format!("{}::{}", resource.name.name, value.name.name), @@ -649,12 +611,7 @@ impl Resolver { } match &self.types[ty].kind { - TypeDefKind::List(Type::Id(id)) - | TypeDefKind::Pointer(Type::Id(id)) - | TypeDefKind::ConstPointer(Type::Id(id)) - | TypeDefKind::PushBuffer(Type::Id(id)) - | TypeDefKind::PullBuffer(Type::Id(id)) - | TypeDefKind::Type(Type::Id(id)) => { + TypeDefKind::List(Type::Id(id)) | TypeDefKind::Type(Type::Id(id)) => { self.validate_type_not_recursive(span, *id, visiting, valid)? } TypeDefKind::Variant(v) => { @@ -672,12 +629,7 @@ impl Resolver { } } - TypeDefKind::List(_) - | TypeDefKind::Pointer(_) - | TypeDefKind::ConstPointer(_) - | TypeDefKind::PushBuffer(_) - | TypeDefKind::PullBuffer(_) - | TypeDefKind::Type(_) => {} + TypeDefKind::List(_) | TypeDefKind::Type(_) => {} } valid.insert(ty); diff --git a/crates/parser/src/lib.rs b/crates/parser/src/lib.rs index 06a8dde2d..1db996117 100644 --- a/crates/parser/src/lib.rs +++ b/crates/parser/src/lib.rs @@ -48,10 +48,6 @@ pub enum TypeDefKind { Record(Record), Variant(Variant), List(Type), - Pointer(Type), - ConstPointer(Type), - PushBuffer(Type), - PullBuffer(Type), Type(Type), } @@ -246,7 +242,6 @@ pub struct Global { #[derive(Debug)] pub struct Function { - pub abi: abi::Abi, pub is_async: bool, pub docs: Docs, pub name: String, @@ -404,12 +399,7 @@ impl Interface { return; } match &self.types[id].kind { - TypeDefKind::Type(t) - | TypeDefKind::List(t) - | TypeDefKind::PushBuffer(t) - | TypeDefKind::PullBuffer(t) - | TypeDefKind::Pointer(t) - | TypeDefKind::ConstPointer(t) => self.topo_visit_ty(t, list, visited), + TypeDefKind::Type(t) | TypeDefKind::List(t) => self.topo_visit_ty(t, list, visited), TypeDefKind::Record(r) => { for f in r.fields.iter() { self.topo_visit_ty(&f.ty, list, visited); @@ -450,34 +440,13 @@ impl Interface { Type::Char | Type::Handle(_) => false, Type::Id(id) => match &self.types[*id].kind { - TypeDefKind::List(_) - | TypeDefKind::Variant(_) - | TypeDefKind::PushBuffer(_) - | TypeDefKind::PullBuffer(_) => false, + TypeDefKind::List(_) | TypeDefKind::Variant(_) => false, TypeDefKind::Type(t) => self.all_bits_valid(t), TypeDefKind::Record(r) => r.fields.iter().all(|f| self.all_bits_valid(&f.ty)), - TypeDefKind::Pointer(_) | TypeDefKind::ConstPointer(_) => true, }, } } - pub fn has_preview1_pointer(&self, ty: &Type) -> bool { - match ty { - Type::Id(id) => match &self.types[*id].kind { - TypeDefKind::List(t) | TypeDefKind::PushBuffer(t) | TypeDefKind::PullBuffer(t) => { - self.has_preview1_pointer(t) - } - TypeDefKind::Type(t) => self.has_preview1_pointer(t), - TypeDefKind::Pointer(_) | TypeDefKind::ConstPointer(_) => true, - TypeDefKind::Record(r) => r.fields.iter().any(|f| self.has_preview1_pointer(&f.ty)), - TypeDefKind::Variant(v) => v.cases.iter().any(|c| match &c.ty { - Some(ty) => self.has_preview1_pointer(ty), - None => false, - }), - }, - _ => false, - } - } pub fn get_variant(&self, ty: &Type) -> Option<&Variant> { if let Type::Id(id) = ty { match &self.types[*id].kind { @@ -491,11 +460,8 @@ impl Interface { } fn load_fs(root: &Path, name: &str) -> Result<(PathBuf, String)> { - // TODO: only read one, not both let wit = root.join(name).with_extension("wit"); - let witx = root.join(name).with_extension("witx"); - let contents = fs::read_to_string(&wit) - .or_else(|_| fs::read_to_string(&witx)) - .context(format!("failed to read `{}`", wit.display()))?; + let contents = + fs::read_to_string(&wit).context(format!("failed to read `{}`", wit.display()))?; Ok((wit, contents)) } diff --git a/crates/parser/src/sizealign.rs b/crates/parser/src/sizealign.rs index 0ab61c564..b840754fa 100644 --- a/crates/parser/src/sizealign.rs +++ b/crates/parser/src/sizealign.rs @@ -1,4 +1,3 @@ -use crate::abi::AbiVariant; use crate::{Int, Interface, Record, RecordKind, Type, TypeDef, TypeDefKind, Variant}; #[derive(Default)] @@ -7,23 +6,18 @@ pub struct SizeAlign { } impl SizeAlign { - pub fn fill(&mut self, variant: AbiVariant, iface: &Interface) { + pub fn fill(&mut self, iface: &Interface) { self.map = vec![(0, 0); iface.types.len()]; for ty in iface.topological_types() { - let pair = self.calculate(variant, &iface.types[ty]); + let pair = self.calculate(&iface.types[ty]); self.map[ty.index()] = pair; } } - fn calculate(&self, variant: AbiVariant, ty: &TypeDef) -> (usize, usize) { + fn calculate(&self, ty: &TypeDef) -> (usize, usize) { match &ty.kind { TypeDefKind::Type(t) => (self.size(t), self.align(t)), TypeDefKind::List(_) => (8, 4), - TypeDefKind::Pointer(_) | TypeDefKind::ConstPointer(_) => (4, 4), - TypeDefKind::PushBuffer(_) | TypeDefKind::PullBuffer(_) => match variant { - AbiVariant::GuestImport => (12, 4), - AbiVariant::GuestExport => (4, 4), - }, TypeDefKind::Record(r) => { if let RecordKind::Flags(repr) = r.kind { return match repr { diff --git a/crates/parser/tests/all.rs b/crates/parser/tests/all.rs index c87226d78..4a64f1ad0 100644 --- a/crates/parser/tests/all.rs +++ b/crates/parser/tests/all.rs @@ -195,10 +195,6 @@ fn to_json(i: &Interface) -> String { cases: Vec<(String, Option)>, }, List(String), - PushBuffer(String), - PullBuffer(String), - Pointer(String), - ConstPointer(String), } #[derive(Serialize)] @@ -279,11 +275,7 @@ fn to_json(i: &Interface) -> String { .map(|f| (f.name.clone(), f.ty.as_ref().map(translate_type))) .collect(), }, - TypeDefKind::PushBuffer(ty) => Type::PushBuffer(translate_type(ty)), - TypeDefKind::PullBuffer(ty) => Type::PullBuffer(translate_type(ty)), TypeDefKind::List(ty) => Type::List(translate_type(ty)), - TypeDefKind::Pointer(ty) => Type::Pointer(translate_type(ty)), - TypeDefKind::ConstPointer(ty) => Type::ConstPointer(translate_type(ty)), } } diff --git a/crates/parser/tests/ui/parse-fail/cycle6.wit b/crates/parser/tests/ui/parse-fail/cycle6.wit deleted file mode 100644 index ea5d5da61..000000000 --- a/crates/parser/tests/ui/parse-fail/cycle6.wit +++ /dev/null @@ -1,3 +0,0 @@ -// parse-fail -type foo = bar -type bar = push-buffer diff --git a/crates/parser/tests/ui/parse-fail/cycle6.wit.result b/crates/parser/tests/ui/parse-fail/cycle6.wit.result deleted file mode 100644 index 16759eea7..000000000 --- a/crates/parser/tests/ui/parse-fail/cycle6.wit.result +++ /dev/null @@ -1,5 +0,0 @@ -type can recursively refer to itself - --> tests/ui/parse-fail/cycle6.wit:2:6 - | - 2 | type foo = bar - | ^-- \ No newline at end of file diff --git a/crates/parser/tests/ui/parse-fail/cycle7.wit b/crates/parser/tests/ui/parse-fail/cycle7.wit deleted file mode 100644 index c339819ac..000000000 --- a/crates/parser/tests/ui/parse-fail/cycle7.wit +++ /dev/null @@ -1,3 +0,0 @@ -// parse-fail -type foo = bar -type bar = pull-buffer diff --git a/crates/parser/tests/ui/parse-fail/cycle7.wit.result b/crates/parser/tests/ui/parse-fail/cycle7.wit.result deleted file mode 100644 index 2334f5220..000000000 --- a/crates/parser/tests/ui/parse-fail/cycle7.wit.result +++ /dev/null @@ -1,5 +0,0 @@ -type can recursively refer to itself - --> tests/ui/parse-fail/cycle7.wit:2:6 - | - 2 | type foo = bar - | ^-- \ No newline at end of file diff --git a/crates/parser/tests/ui/types.wit b/crates/parser/tests/ui/types.wit index a43e65adc..7776bc7f0 100644 --- a/crates/parser/tests/ui/types.wit +++ b/crates/parser/tests/ui/types.wit @@ -48,8 +48,6 @@ type t44 = string type t45 = list>> type t46 = t44 type t47 = %t44 -type t48 = push-buffer -type t49 = pull-buffer // type order doesn't matter type foo = bar diff --git a/crates/parser/tests/ui/types.wit.result b/crates/parser/tests/ui/types.wit.result index 2fd7c268a..8b13ff5ee 100644 --- a/crates/parser/tests/ui/types.wit.result +++ b/crates/parser/tests/ui/types.wit.result @@ -302,15 +302,15 @@ "fields": [ [ "a", - "type-53" + "type-51" ], [ "b", - "type-53" + "type-51" ], [ "c", - "type-53" + "type-51" ] ] } @@ -322,15 +322,15 @@ "fields": [ [ "a", - "type-53" + "type-51" ], [ "b", - "type-53" + "type-51" ], [ "c", - "type-53" + "type-51" ] ] } @@ -406,7 +406,7 @@ ], [ "b", - "type-54" + "type-52" ] ] } @@ -438,7 +438,7 @@ ], [ "1", - "type-54" + "type-52" ] ] } @@ -454,7 +454,7 @@ ], [ "1", - "type-54" + "type-52" ] ] } @@ -523,7 +523,7 @@ { "idx": 46, "name": "t45", - "list": "type-56" + "list": "type-54" }, { "idx": 47, @@ -537,26 +537,16 @@ }, { "idx": 49, - "name": "t48", - "push-buffer": "u8" - }, - { - "idx": 50, - "name": "t49", - "pull-buffer": "u8" - }, - { - "idx": 51, "name": "foo", - "primitive": "type-52" + "primitive": "type-50" }, { - "idx": 52, + "idx": 50, "name": "bar", "primitive": "u32" }, { - "idx": 53, + "idx": 51, "variant": { "cases": [ [ @@ -571,7 +561,7 @@ } }, { - "idx": 54, + "idx": 52, "variant": { "cases": [ [ @@ -586,12 +576,12 @@ } }, { - "idx": 55, + "idx": 53, "list": "type-33" }, { - "idx": 56, - "list": "type-55" + "idx": 54, + "list": "type-53" } ] } \ No newline at end of file diff --git a/crates/parser/tests/ui/wasi-http.wit b/crates/parser/tests/ui/wasi-http.wit index 0b4da86de..90169067a 100644 --- a/crates/parser/tests/ui/wasi-http.wit +++ b/crates/parser/tests/ui/wasi-http.wit @@ -86,13 +86,13 @@ resource body { /// @return result - a result containing the number of bytes written on success // TODO: check if `out-buffer` is the right way to express this // NOTE: s/expected/result/ - read: function(dest: push-buffer) -> expected + read: function(dest: list) -> expected /// Write to a body. /// @param source - source buffer to read from /// @return result - a result containing the number of bytes read on success // TODO: check if `in-buffer` is the right way to express this - write: function(source: pull-buffer) -> expected + write: function(source: list) -> expected } /* diff --git a/crates/parser/tests/ui/wasi-http.wit.result b/crates/parser/tests/ui/wasi-http.wit.result index 6794a63e0..61c8910eb 100644 --- a/crates/parser/tests/ui/wasi-http.wit.result +++ b/crates/parser/tests/ui/wasi-http.wit.result @@ -83,7 +83,7 @@ }, { "idx": 8, - "push-buffer": "u8" + "list": "u8" }, { "idx": 9, @@ -99,10 +99,6 @@ ] ] } - }, - { - "idx": 10, - "pull-buffer": "u8" } ], "functions": [ @@ -200,7 +196,7 @@ "name": "body::write", "params": [ "handle-3", - "type-10" + "type-8" ], "results": [ "type-9" diff --git a/crates/rust-wasm-impl/Cargo.toml b/crates/rust-wasm-impl/Cargo.toml index df0e9686d..ed311f6d2 100644 --- a/crates/rust-wasm-impl/Cargo.toml +++ b/crates/rust-wasm-impl/Cargo.toml @@ -14,6 +14,3 @@ proc-macro2 = "1.0" syn = "1.0" wit-bindgen-gen-core = { path = "../gen-core", version = "0.1" } wit-bindgen-gen-rust-wasm = { path = "../gen-rust-wasm", version = "0.1" } - -[features] -witx-compat = ['wit-bindgen-gen-core/witx-compat'] diff --git a/crates/rust-wasm/Cargo.toml b/crates/rust-wasm/Cargo.toml index 45f87fade..b65adb125 100644 --- a/crates/rust-wasm/Cargo.toml +++ b/crates/rust-wasm/Cargo.toml @@ -8,6 +8,3 @@ edition = "2018" wit-bindgen-rust-impl = { path = "../rust-wasm-impl" } async-trait = "0.1.51" bitflags = "1.3" - -[features] -witx-compat = ['wit-bindgen-rust-impl/witx-compat'] diff --git a/crates/rust-wasm/src/exports.rs b/crates/rust-wasm/src/exports.rs deleted file mode 100644 index 982f2925e..000000000 --- a/crates/rust-wasm/src/exports.rs +++ /dev/null @@ -1,239 +0,0 @@ -use std::fmt; -use std::marker; - -#[link(wasm_import_module = "wit_canonical_buffer_abi")] -extern "C" { - fn in_len(handle: i32) -> usize; - fn in_read(handle: i32, amount: usize, dst: *mut u8); - fn out_len(handle: i32) -> usize; - fn out_write(handle: i32, amount: usize, dst: *const u8); -} - -/// Implementation of `(in-buffer T)` for raw types `T` that can be directly -/// copied into. -pub struct InBufferRaw<'a, T> { - handle: i32, - _marker: marker::PhantomData<&'a T>, -} - -impl<'a, T> InBufferRaw<'a, T> { - /// Only intended for adapter use. - /// - /// `unsafe` because this requires a valid `handle` and also requires `T` to - /// be valid to copy into. Additionally requires a valid `'a` - pub unsafe fn new(handle: i32) -> InBufferRaw<'a, T> { - InBufferRaw { - handle, - _marker: marker::PhantomData, - } - } - - /// Returns the length of the buffer provided by the caller. - /// - /// Returns the number of items, in units of `T`, that are available to - /// `copy` to receive. - pub fn len(&self) -> usize { - unsafe { in_len(self.handle) } - } - - /// Copies elements from the caller into `space`. - /// - /// This will abort the program if `space` is larger than `self.len()`. - /// Otherwise the `space` array will be entirely filled upon returning. - pub fn copy(&self, space: &mut [T]) { - unsafe { - in_read(self.handle, space.len(), space.as_mut_ptr() as *mut u8); - } - } -} - -impl fmt::Debug for InBufferRaw<'_, T> { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - f.debug_struct("InBufferRaw") - .field("handle", &self.handle) - .field("len", &self.len()) - .finish() - } -} - -/// Implementation of `(in-buffer T)` -pub struct InBuffer<'a, T> { - handle: i32, - deserialize: fn(i32) -> T, - element_size: usize, - _marker: marker::PhantomData<&'a T>, -} - -impl<'a, T> InBuffer<'a, T> { - /// Only intended for adapter use. - pub unsafe fn new( - handle: i32, - element_size: i32, - deserialize: fn(i32) -> T, - ) -> InBuffer<'a, T> { - InBuffer { - handle, - element_size: element_size as u32 as usize, - deserialize, - _marker: marker::PhantomData, - } - } - - /// Returns the length of the buffer provided by the caller. - /// - /// Returns the number of items, in units of `T`, that are available to - /// `iter` to copy in. - pub fn len(&self) -> usize { - unsafe { in_len(self.handle) } - } - - /// Returns the size of a `T` to gauge how much scratch space to pass to - /// [`InBuffer::iter`]. - pub fn element_size(&self) -> usize { - self.element_size - } - - /// Copies items from the caller into `scratch` and then returns an - /// iterator over the deserialized versions. - /// - /// The `scratch` buffer should be appropriately sized for the number of - /// items you wish to iterate over. - pub fn iter<'b>(&self, scratch: &'b mut [u8]) -> impl ExactSizeIterator + 'b - where - 'a: 'b, - { - // TODO: need to deserialize/drop remaining items if the iterator - // doesn't finish - unsafe { - let element_size = self.element_size; - let len = scratch.len() / element_size; - in_read(self.handle, len, scratch.as_mut_ptr()); - let deserialize = self.deserialize; - (0..len).map(move |i| { - deserialize(scratch[i * element_size..][..element_size].as_ptr() as i32) - }) - } - } -} - -impl fmt::Debug for InBuffer<'_, T> { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - f.debug_struct("InBuffer") - .field("handle", &self.handle) - .field("len", &self.len()) - .finish() - } -} - -/// Implementation of `(out-buffer T)` for raw types `T` that can be directly -/// copied to the caller. -pub struct OutBufferRaw<'a, T> { - handle: i32, - _marker: marker::PhantomData<&'a mut T>, -} - -impl<'a, T> OutBufferRaw<'a, T> { - /// Only intended for adapter use. - /// - /// `unsafe` because this requires a valid `handle`, requires `T` to - /// be valid to copy into, and requires a valid `'a`. - pub unsafe fn new(handle: i32) -> OutBufferRaw<'a, T> { - OutBufferRaw { - handle, - _marker: marker::PhantomData, - } - } - - /// Returns the capacity of the buffer provided by the caller. - /// - /// Returns the number of items, in units of `T`, that are available to - /// `write` to receive. - pub fn capacity(&self) -> usize { - unsafe { out_len(self.handle) } - } - - /// Copies elements to the caller from `items`. - /// - /// This will abort the program if `items` is larger than `self.capacity()`. - pub fn write(&self, items: &[T]) { - unsafe { - out_write(self.handle, items.len(), items.as_ptr() as *const u8); - } - } -} - -impl fmt::Debug for OutBufferRaw<'_, T> { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - f.debug_struct("OutBufferRaw") - .field("handle", &self.handle) - .field("capacity", &self.capacity()) - .finish() - } -} - -/// Implementation of `(in-buffer T)` -pub struct OutBuffer<'a, T> { - handle: i32, - serialize: fn(i32, T), - element_size: usize, - _marker: marker::PhantomData<&'a mut T>, -} - -impl<'a, T> OutBuffer<'a, T> { - /// Only intended for adapter use. - pub unsafe fn new(handle: i32, element_size: i32, serialize: fn(i32, T)) -> OutBuffer<'a, T> { - OutBuffer { - handle, - element_size: element_size as u32 as usize, - serialize, - _marker: marker::PhantomData, - } - } - - /// Returns the capacity of the buffer provided by the caller. - /// - /// Returns the number of items, in units of `T`, that are available to - /// `iter` to copy in. - pub fn capacity(&self) -> usize { - unsafe { out_len(self.handle) } - } - - /// Returns the size of a `T` to gauge how much scratch space to pass to - /// [`OutBuffer::write`]. - pub fn element_size(&self) -> usize { - self.element_size - } - - /// Writes items into this buffer. - /// - /// This method will write the `items` provided into this buffer to get - /// passed to the caller. The `scratch` space provided must be large enough - /// to contain the encoded size of all of `items`, and the amount of - /// `scratch` needed can be gauged with the [`OutBuffer::element_size`] - /// method. - pub fn write(&self, scratch: &mut [u8], items: impl ExactSizeIterator) { - assert!(items.len().checked_mul(self.element_size).unwrap() <= scratch.len()); - let mut len = 0; - // TODO: if `items` ends up being longer than expected then we leak all - // items previously serialized. - for (i, item) in items.enumerate() { - len += 1; - (self.serialize)( - scratch[i * self.element_size..][..self.element_size].as_mut_ptr() as i32, - item, - ); - } - unsafe { - out_write(self.handle, len, scratch.as_ptr()); - } - } -} - -impl fmt::Debug for OutBuffer<'_, T> { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - f.debug_struct("OutBuffer") - .field("handle", &self.handle) - .field("capacity", &self.capacity()) - .finish() - } -} diff --git a/crates/rust-wasm/src/imports.rs b/crates/rust-wasm/src/imports.rs deleted file mode 100644 index c50b1ef9a..000000000 --- a/crates/rust-wasm/src/imports.rs +++ /dev/null @@ -1,105 +0,0 @@ -use std::fmt; - -/// Implementation of `(in-buffer T)`. -/// -/// Holds a region of memory to store into as well as an iterator of items to -/// serialize when calling an imported API. -pub struct PullBuffer<'a, T: 'a> { - storage: &'a mut [u8], - items: &'a mut dyn ExactSizeIterator, - len: usize, -} - -impl<'a, T: 'a> PullBuffer<'a, T> { - /// Creates a new buffer where `items` are serialized into `storage` when - /// this buffer is passed to a function call. - /// - /// Note that `storage` must be large enough to store all the `items` - /// provided. This will panic otherwise when passed to a callee. - pub fn new( - storage: &'a mut [u8], - items: &'a mut dyn ExactSizeIterator, - ) -> PullBuffer<'a, T> { - PullBuffer { - len: items.len(), - storage, - items, - } - } - - /// Called from adapters with implementation of how to serialize. - #[doc(hidden)] - pub unsafe fn serialize(&mut self, mut write: F) -> (i32, i32) - where - F: FnMut(T, i32), - { - for (i, item) in self.items.enumerate() { - let storage = &mut self.storage[N * i..][..N]; - write(item, storage.as_mut_ptr() as i32); - } - (self.storage.as_ptr() as i32, self.len as i32) - } -} - -impl fmt::Debug for PullBuffer<'_, T> { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - f.debug_struct("PullBuffer") - .field("bytes", &self.storage.len()) - .field("items", &self.items.len()) - .finish() - } -} - -/// Implementation of `(out-buffer T)` -pub struct PushBuffer<'a, T: 'a> { - storage: &'a mut [u8], - deserialize: fn(i32) -> T, - element_size: usize, -} - -impl<'a, T: 'a> PushBuffer<'a, T> { - pub fn new(storage: &'a mut [u8]) -> PushBuffer<'a, T> { - PushBuffer { - storage, - deserialize: |_| loop {}, - element_size: usize::max_value(), - } - } - - /// Called from adapters with implementation of how to deserialize. - #[doc(hidden)] - pub fn ptr_len(&mut self, deserialize: fn(i32) -> T) -> (i32, i32) { - self.element_size = N; - self.deserialize = deserialize; - ( - self.storage.as_ptr() as i32, - (self.storage.len() / N) as i32, - ) - } - - /// Consumes this output buffer, returning an iterator of the deserialized - /// version of all items that callee wrote. - /// - /// This is `unsafe` because the `amt` here is not known to be valid, and - /// deserializing arbitrary bytes is not safe. The callee should always - /// indicate how many items were written into this output buffer by some - /// other means. - pub unsafe fn into_iter(self, amt: usize) -> impl Iterator + 'a - where - T: 'a, - { - let size = self.element_size; - (0..amt) - .map(move |i| i * size) - .map(move |i| (self.deserialize)(self.storage[i..][..size].as_mut_ptr() as i32)) - // TODO: data is leaked if this iterator isn't run in full - } -} - -impl fmt::Debug for PushBuffer<'_, T> { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - f.debug_struct("PushBuffer") - .field("bytes", &self.storage.len()) - .finish() - } -} diff --git a/crates/rust-wasm/src/lib.rs b/crates/rust-wasm/src/lib.rs index 308317ed7..f3d04093d 100644 --- a/crates/rust-wasm/src/lib.rs +++ b/crates/rust-wasm/src/lib.rs @@ -5,9 +5,7 @@ use std::mem; use std::ops::Deref; pub use wit_bindgen_rust_impl::{export, import}; -pub mod exports; mod futures; -pub mod imports; // Re-export `bitflags` so that we can reference it from macros. #[doc(hidden)] diff --git a/crates/test-helpers/Cargo.toml b/crates/test-helpers/Cargo.toml index d7e1d5b4a..84a2a04fd 100644 --- a/crates/test-helpers/Cargo.toml +++ b/crates/test-helpers/Cargo.toml @@ -23,7 +23,7 @@ wit-bindgen-gen-wasmtime-py = { path = '../gen-wasmtime-py', optional = true } wit-bindgen-gen-js = { path = '../gen-js', optional = true } wit-bindgen-gen-c = { path = '../gen-c', optional = true } wit-bindgen-gen-spidermonkey = { path = '../gen-spidermonkey', optional = true } -wit-parser = { path = '../parser', features = ['witx-compat'] } +wit-parser = { path = '../parser' } filetime = "0.2" [build-dependencies] @@ -33,7 +33,6 @@ wit-bindgen-gen-core = { path = '../gen-core' } [features] default = ['wasm-rust', 'wasm-c', 'wasm-spidermonkey'] -witx-compat = ['wit-bindgen-gen-core/witx-compat'] wasm-rust = [] wasm-c = [] wasm-spidermonkey = [] diff --git a/crates/test-helpers/src/lib.rs b/crates/test-helpers/src/lib.rs index 9f1cfd25d..ec5d37afe 100644 --- a/crates/test-helpers/src/lib.rs +++ b/crates/test-helpers/src/lib.rs @@ -179,14 +179,6 @@ pub fn codegen_rust_wasm_export(input: TokenStream) -> TokenStream { } match &ty.kind { TypeDefKind::Type(t) => quote_ty(param, iface, t), - TypeDefKind::Pointer(t) => { - let t = quote_ty(param, iface, t); - quote::quote! { *mut #t } - } - TypeDefKind::ConstPointer(t) => { - let t = quote_ty(param, iface, t); - quote::quote! { *const #t } - } TypeDefKind::List(t) => { if *t == Type::Char { quote::quote! { String } @@ -195,8 +187,6 @@ pub fn codegen_rust_wasm_export(input: TokenStream) -> TokenStream { quote::quote! { Vec<#t> } } } - TypeDefKind::PushBuffer(_) => panic!("unimplemented push-buffer"), - TypeDefKind::PullBuffer(_) => panic!("unimplemented pull-buffer"), TypeDefKind::Record(r) => { let fields = r.fields.iter().map(|f| quote_ty(param, iface, &f.ty)); quote::quote! { (#(#fields,)*) } diff --git a/crates/test-rust-wasm/Cargo.toml b/crates/test-rust-wasm/Cargo.toml index 4bbf09c44..3da333da6 100644 --- a/crates/test-rust-wasm/Cargo.toml +++ b/crates/test-rust-wasm/Cargo.toml @@ -7,7 +7,7 @@ publish = false [dependencies] futures-util = { version = "0.3.17", default-features = true } -wit-bindgen-rust = { path = "../rust-wasm", features = ['witx-compat'] } +wit-bindgen-rust = { path = "../rust-wasm" } [features] unchecked = [] @@ -36,10 +36,6 @@ test = false name = "handles" test = false -[[bin]] -name = "buffers" -test = false - [[bin]] name = "flavorful" test = false diff --git a/crates/test-rust-wasm/src/bin/buffers.rs b/crates/test-rust-wasm/src/bin/buffers.rs deleted file mode 100644 index a3c67c11d..000000000 --- a/crates/test-rust-wasm/src/bin/buffers.rs +++ /dev/null @@ -1,3 +0,0 @@ -include!("../../../../tests/runtime/buffers/wasm.rs"); - -fn main() {} diff --git a/crates/wasmlink/Cargo.toml b/crates/wasmlink/Cargo.toml index 04726c077..d29834afa 100644 --- a/crates/wasmlink/Cargo.toml +++ b/crates/wasmlink/Cargo.toml @@ -2,7 +2,7 @@ name = "wasmlink" version = "0.1.0" authors = ["Peter Huene "] -edition = "2018" +edition = "2021" [dependencies] anyhow = "1.0.40" diff --git a/crates/wasmlink/src/adapter/call.rs b/crates/wasmlink/src/adapter/call.rs index e9b5545c7..c9058bc3d 100644 --- a/crates/wasmlink/src/adapter/call.rs +++ b/crates/wasmlink/src/adapter/call.rs @@ -555,10 +555,6 @@ impl<'a> CallAdapter<'a> { params.next().unwrap(); } } - TypeDefKind::Pointer(_) | TypeDefKind::ConstPointer(_) => { - params.next().unwrap(); - } - TypeDefKind::PushBuffer(_) | TypeDefKind::PullBuffer(_) => todo!(), }, Type::Handle(id) => { let addr = params.next().unwrap(); @@ -683,8 +679,6 @@ impl<'a> CallAdapter<'a> { }); } } - TypeDefKind::Pointer(_) | TypeDefKind::ConstPointer(_) => {} - TypeDefKind::PushBuffer(_) | TypeDefKind::PullBuffer(_) => todo!(), }, Type::Handle(id) => { // Params need to be cloned, so add a local diff --git a/crates/wasmlink/src/module.rs b/crates/wasmlink/src/module.rs index 011627d08..a48bdaac0 100644 --- a/crates/wasmlink/src/module.rs +++ b/crates/wasmlink/src/module.rs @@ -53,7 +53,6 @@ fn has_list(interface: &WitInterface, ty: &WitType) -> bool { .map(|t| has_list(interface, t)) .unwrap_or(false) }), - _ => false, }, _ => false, } @@ -119,7 +118,7 @@ impl Interface { .collect(); let mut sizes = SizeAlign::default(); - sizes.fill(AbiVariant::GuestExport, &inner); + sizes.fill(&inner); let has_resources = inner .resources diff --git a/crates/wasmlink/src/resources.rs b/crates/wasmlink/src/resources.rs index 179d25d52..2dac2a722 100644 --- a/crates/wasmlink/src/resources.rs +++ b/crates/wasmlink/src/resources.rs @@ -63,8 +63,7 @@ struct Resource<'a> { impl Resource<'_> { fn funcs(&self) -> impl ExactSizeIterator { // This is used to define a stable order of the functions - let funcs = [&self.new, &self.get, &self.clone, &self.drop]; - std::array::IntoIter::new(funcs) + [&self.new, &self.get, &self.clone, &self.drop].into_iter() } } diff --git a/crates/wasmtime-impl/Cargo.toml b/crates/wasmtime-impl/Cargo.toml index e90d3e5da..13e93b668 100644 --- a/crates/wasmtime-impl/Cargo.toml +++ b/crates/wasmtime-impl/Cargo.toml @@ -16,6 +16,5 @@ wit-bindgen-gen-core = { path = "../gen-core", version = "0.1" } wit-bindgen-gen-wasmtime = { path = "../gen-wasmtime", version = "0.1" } [features] -witx-compat = ['wit-bindgen-gen-wasmtime/witx-compat'] tracing = [] async = [] diff --git a/crates/wasmtime/Cargo.toml b/crates/wasmtime/Cargo.toml index f4046caa6..c2582c03d 100644 --- a/crates/wasmtime/Cargo.toml +++ b/crates/wasmtime/Cargo.toml @@ -22,6 +22,3 @@ tracing = ['tracing-lib', 'wit-bindgen-wasmtime-impl/tracing'] # Enables async support for generated code, although when enabled this still # needs to be configured through the macro invocation. async = ['async-trait', 'wit-bindgen-wasmtime-impl/async'] - -# Enables the ability to parse the old s-expression-based `*.witx` format. -witx-compat = ['wit-bindgen-wasmtime-impl/witx-compat'] diff --git a/crates/wasmtime/src/exports.rs b/crates/wasmtime/src/exports.rs deleted file mode 100644 index a716e79d3..000000000 --- a/crates/wasmtime/src/exports.rs +++ /dev/null @@ -1,90 +0,0 @@ -use crate::BorrowChecker; -use std::fmt; -use std::mem; -use wasmtime::Trap; - -pub struct PullBuffer<'a, T> { - mem: &'a [u8], - size: usize, - deserialize: &'a (dyn Fn(&'a [u8]) -> Result + Send + Sync + 'a), -} - -impl<'a, T> PullBuffer<'a, T> { - pub fn new( - mem: &mut BorrowChecker<'a>, - offset: i32, - len: i32, - size: i32, - deserialize: &'a (dyn Fn(&'a [u8]) -> Result + Send + Sync + 'a), - ) -> Result, Trap> { - Ok(PullBuffer { - mem: mem.slice(offset, len.saturating_mul(size))?, - size: size as usize, - deserialize, - }) - } - - pub fn len(&self) -> usize { - self.mem.len() / self.size - } - - pub fn iter(&self) -> impl Iterator> + 'a { - let deserialize = self.deserialize; - self.mem.chunks(self.size).map(deserialize) - } -} - -impl fmt::Debug for PullBuffer<'_, T> { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - f.debug_struct("PullBuffer") - .field("len", &self.len()) - .finish() - } -} - -pub struct PushBuffer<'a, T> { - mem: &'a mut [u8], - size: usize, - serialize: &'a (dyn Fn(&mut [u8], T) -> Result<(), Trap> + Send + Sync + 'a), -} - -impl<'a, T> PushBuffer<'a, T> { - pub fn new( - mem: &mut BorrowChecker<'a>, - offset: i32, - len: i32, - size: i32, - serialize: &'a (dyn Fn(&mut [u8], T) -> Result<(), Trap> + Send + Sync + 'a), - ) -> Result, Trap> { - let mem = mem.slice_mut(offset, (len as u32).saturating_mul(size as u32) as i32)?; - Ok(PushBuffer { - mem, - size: size as usize, - serialize, - }) - } - - pub fn capacity(&self) -> usize { - self.mem.len() / self.size - } - - pub fn write(&mut self, iter: impl IntoIterator) -> Result<(), Trap> { - for item in iter { - if self.mem.len() == 0 { - return Err(Trap::new("too many results in `PushBuffer::write`")); - } - let (chunk, rest) = mem::take(&mut self.mem).split_at_mut(self.size); - self.mem = rest; - (self.serialize)(chunk, item)?; - } - Ok(()) - } -} - -impl fmt::Debug for PushBuffer<'_, T> { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - f.debug_struct("PushBuffer") - .field("capacity", &self.capacity()) - .finish() - } -} diff --git a/crates/wasmtime/src/imports.rs b/crates/wasmtime/src/imports.rs deleted file mode 100644 index d29c0054a..000000000 --- a/crates/wasmtime/src/imports.rs +++ /dev/null @@ -1,415 +0,0 @@ -use crate::slab::Slab; -use std::cell::RefCell; -use std::convert::TryFrom; -use std::mem; -use std::rc::Rc; -use wasmtime::{Memory, Trap}; - -#[derive(Default, Clone)] -pub struct BufferGlue { - inner: Rc>, -} - -#[derive(Default)] -struct Inner { - in_buffers: Slab>, - out_buffers: Slab>, -} - -struct Buffer { - len: u32, - kind: T, -} - -enum Input { - Bytes(*const u8, usize), - General { - shim: unsafe fn([usize; 2], *const u8, &Memory, i32, u32, &mut u32) -> Result<(), Trap>, - iterator: [usize; 2], - serialize: *const u8, - }, -} - -enum Output { - Bytes(*mut u8, usize), - General { - shim: unsafe fn(*mut u8, *const u8, &Memory, i32, u32) -> Result<(), Trap>, - dst: *mut u8, - deserialize: *const u8, - }, -} - -impl BufferGlue { - pub fn transaction(&self) -> BufferTransaction<'_> { - BufferTransaction { - handles: Vec::new(), - glue: self, - } - } - - pub fn in_len(&self, handle: u32) -> Result { - let mut inner = self.inner.borrow_mut(); - let b = inner - .in_buffers - .get_mut(handle) - .ok_or_else(|| Trap::new("invalid in-buffer handle"))?; - Ok(b.len) - } - - /// Implementation of the canonical abi "in_read" function - pub fn in_read( - &self, - handle: u32, - store: impl wasmtime::AsContextMut, - memory: &wasmtime::Memory, - base: u32, - len: u32, - ) -> Result<(), Trap> { - let mut inner = self.inner.borrow_mut(); - let b = inner - .in_buffers - .get_mut(handle) - .ok_or_else(|| Trap::new("invalid in-buffer handle"))?; - if len > b.len { - return Err(Trap::new( - "more items requested from in-buffer than are available", - )); - } - unsafe { - match &mut b.kind { - Input::Bytes(ptr, elem_size) => { - let write_size = (len as usize) * *elem_size; - memory - .write( - store, - base as usize, - std::slice::from_raw_parts(*ptr, write_size), - ) - .map_err(|_| Trap::new("out-of-bounds write while reading in-buffer"))?; - *ptr = (*ptr).add(write_size); - b.len -= len; - Ok(()) - } - &mut Input::General { - shim, - iterator, - serialize, - } => { - drop(inner); - let mut processed = 0; - let res = shim( - iterator, - serialize, - memory, - base as i32, - len, - &mut processed, - ); - self.inner - .borrow_mut() - .in_buffers - .get_mut(handle) - .expect("should still be there") - .len -= processed; - res - } - } - } - } - - pub fn out_len(&self, handle: u32) -> Result { - let mut inner = self.inner.borrow_mut(); - let b = inner - .out_buffers - .get_mut(handle) - .ok_or_else(|| Trap::new("out in-buffer handle"))?; - Ok(b.len) - } - - /// Implementation of the canonical abi "out_write" function - pub fn out_write( - &self, - handle: u32, - store: impl wasmtime::AsContext, - memory: &wasmtime::Memory, - base: u32, - len: u32, - ) -> Result<(), Trap> { - let mut inner = self.inner.borrow_mut(); - let b = inner - .out_buffers - .get_mut(handle) - .ok_or_else(|| Trap::new("invalid out-buffer handle"))?; - if len > b.len { - return Err(Trap::new( - "more items written to out-buffer than are available", - )); - } - unsafe { - match &mut b.kind { - Output::Bytes(ptr, elem_size) => { - let read_size = (len as usize) * *elem_size; - memory - .read( - &store, - base as usize, - std::slice::from_raw_parts_mut(*ptr, read_size), - ) - .map_err(|_| Trap::new("out-of-bounds read while writing to out-buffer"))?; - *ptr = (*ptr).add(read_size); - b.len -= len; - Ok(()) - } - &mut Output::General { - shim, - dst, - deserialize, - } => { - shim(dst, deserialize, memory, base as i32, len)?; - b.len -= len; - Ok(()) - } - } - } - } -} - -pub struct BufferTransaction<'a> { - glue: &'a BufferGlue, - handles: Vec<(bool, u32)>, -} - -impl<'call> BufferTransaction<'call> { - pub unsafe fn push_in_raw<'a, T>(&mut self, buffer: &'a [T]) -> i32 - where - 'a: 'call, - { - let mut inner = self.glue.inner.borrow_mut(); - let handle = inner.in_buffers.insert(Buffer { - len: u32::try_from(buffer.len()).unwrap(), - kind: Input::Bytes(buffer.as_ptr() as *const u8, mem::size_of::()), - }); - self.handles.push((false, handle)); - return handle as i32; - } - - pub unsafe fn push_in<'a, T, F>( - &mut self, - iter: &'a mut (dyn ExactSizeIterator + 'a), - write: &'a F, - ) -> i32 - where - F: Fn(&Memory, i32, T) -> Result + 'a, - 'a: 'call, - { - let mut inner = self.glue.inner.borrow_mut(); - let handle = inner.in_buffers.insert(Buffer { - len: u32::try_from(iter.len()).unwrap(), - kind: Input::General { - shim: shim::, - iterator: mem::transmute(iter), - serialize: write as *const F as *const u8, - }, - }); - self.handles.push((false, handle)); - return handle as i32; - - unsafe fn shim( - iter: [usize; 2], - serialize: *const u8, - memory: &Memory, - mut offset: i32, - len: u32, - processed: &mut u32, - ) -> Result<(), Trap> - where - F: Fn(&Memory, i32, T) -> Result, - { - let iter = mem::transmute::<_, &mut dyn ExactSizeIterator>(iter); - let write = &*(serialize as *const F); - for _ in 0..len { - let item = iter.next().unwrap(); - offset += write(memory, offset, item)?; - *processed += 1; - } - Ok(()) - } - } - - pub unsafe fn push_out_raw<'a, T>(&mut self, buffer: &'a mut [T]) -> i32 - where - 'a: 'call, - { - let mut inner = self.glue.inner.borrow_mut(); - let handle = inner.out_buffers.insert(Buffer { - len: u32::try_from(buffer.len()).unwrap(), - kind: Output::Bytes(buffer.as_mut_ptr() as *mut u8, mem::size_of::()), - }); - self.handles.push((true, handle)); - return handle as i32; - } - - pub unsafe fn push_out<'a, T, F>(&mut self, dst: &'a mut Vec, read: &'a F) -> i32 - where - F: Fn(&Memory, i32) -> Result<(T, i32), Trap> + 'a, - 'a: 'call, - { - let mut inner = self.glue.inner.borrow_mut(); - let handle = inner.out_buffers.insert(Buffer { - len: u32::try_from(dst.capacity() - dst.len()).unwrap(), - kind: Output::General { - shim: shim::, - dst: dst as *mut Vec as *mut u8, - deserialize: read as *const F as *const u8, - }, - }); - self.handles.push((true, handle)); - return handle as i32; - - unsafe fn shim( - dst: *mut u8, - deserialize: *const u8, - memory: &Memory, - mut offset: i32, - len: u32, - ) -> Result<(), Trap> - where - F: Fn(&Memory, i32) -> Result<(T, i32), Trap>, - { - let dst = &mut *(dst as *mut Vec); - let read = &*(deserialize as *const F); - for _ in 0..len { - let (item, size) = read(memory, offset)?; - dst.push(item); - offset += size; - } - Ok(()) - } - } -} - -impl Drop for BufferTransaction<'_> { - fn drop(&mut self) { - let mut inner = self.glue.inner.borrow_mut(); - for (out, handle) in self.handles.iter() { - if *out { - inner.out_buffers.remove(*handle); - } else { - inner.in_buffers.remove(*handle); - } - } - } -} - -///// Implementation of `(in-buffer T)`. -///// -///// Holds a region of memory to store into as well as an iterator of items to -///// serialize when calling an API. -//pub struct InBuffer<'a, T> { -// storage: &'a mut [u8], -// items: &'a mut dyn Iterator, -//} - -//impl<'a, T: 'a> InBuffer<'a, T> { -// /// Creates a new buffer where `items` are serialized into `storage` when -// /// this buffer is passed to a function call. -// /// -// /// # Panics -// /// -// /// `storage` must be large enough to store all the `items` -// /// provided. This will panic otherwise when passed to a callee. -// pub fn new(storage: &'a mut [u8], items: &'a mut dyn Iterator) -> InBuffer<'a, T> { -// InBuffer { storage, items } -// } - -// /// Called from adapters with implementation of how to serialize. -// #[doc(hidden)] -// pub fn serialize(&mut self, mut write: F) -> Result<&[u8], Trap> -// where -// F: FnMut(&mut [u8], T) -> Result<(), Trap>, -// { -// let mut len = 0; -// for (i, item) in self.items.enumerate() { -// let storage = &mut self.storage[N * i..][..N]; -// write(storage, item)?; -// len += 1; -// } -// Ok(&self.storage[..len * N]) -// } -//} - -//impl fmt::Debug for InBuffer<'_, T> { -// fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { -// f.debug_struct("InBuffer") -// .field("bytes", &self.storage.len()) -// .finish() -// } -//} - -///// Implementation of `(out-buffer T)` -//pub struct OutBuffer<'a, T: 'a> { -// storage: &'a mut [u8], -// deserialize: fn(&[u8]) -> T, -// element_size: usize, -//} - -//impl<'a, T: 'a> OutBuffer<'a, T> { -// /// Creates a new buffer with `storage` as where to store raw byte given to -// /// the host from wasm. -// /// -// /// The `storage` should be appropriately sized to hold the desired number -// /// of items to receive. -// pub fn new(storage: &'a mut [u8]) -> OutBuffer<'a, T> { -// OutBuffer { -// storage, -// deserialize: |_| loop {}, -// element_size: usize::max_value(), -// } -// } - -// #[doc(hidden)] -// pub fn storage( -// &mut self, -// _: usize, -// _: impl Fn(&[u8]) -> Result + Clone + 'static, -// ) -> &mut [u8] { -// &mut *self.storage -// } - -// ///// Called from adapters with implementation of how to deserialize. -// //#[doc(hidden)] -// //pub fn ptr_len(&mut self, deserialize: fn(i32) -> T) -> (i32, i32) { -// // self.element_size = N; -// // self.deserialize = deserialize; -// // ( -// // self.storage.as_ptr() as i32, -// // (self.storage.len() / N) as i32, -// // ) -// //} - -// ///// Consumes this output buffer, returning an iterator of the deserialized -// ///// version of all items that callee wrote. -// ///// -// ///// This is `unsafe` because the `amt` here is not known to be valid, and -// ///// deserializing arbitrary bytes is not safe. The callee should always -// ///// indicate how many items were written into this output buffer by some -// ///// other means. -// //pub unsafe fn into_iter(self, amt: usize) -> impl Iterator + 'a -// //where -// // T: 'a, -// //{ -// // let size = self.element_size; -// // (0..amt) -// // .map(move |i| i * size) -// // .map(move |i| (self.deserialize)(self.storage[i..][..size].as_mut_ptr() as i32)) -// // // TODO: data is leaked if this iterator isn't run in full -// //} -//} - -//impl fmt::Debug for OutBuffer<'_, T> { -// fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { -// f.debug_struct("OutBuffer") -// .field("bytes", &self.storage.len()) -// .finish() -// } -//} diff --git a/crates/wasmtime/src/lib.rs b/crates/wasmtime/src/lib.rs index 5b6c695c1..2c2f49129 100644 --- a/crates/wasmtime/src/lib.rs +++ b/crates/wasmtime/src/lib.rs @@ -8,8 +8,6 @@ pub use tracing_lib as tracing; pub use {anyhow, bitflags, wasmtime}; mod error; -pub mod exports; -pub mod imports; mod le; mod region; mod slab; @@ -20,16 +18,6 @@ pub use le::{Endian, Le}; pub use region::{AllBytesValid, BorrowChecker, Region}; pub use table::*; -pub struct RawMemory { - pub slice: *mut [u8], -} - -// This type is threadsafe despite its internal pointer because it allows no -// safe access to the internal pointer. Consumers must uphold Send/Sync -// guarantees themselves. -unsafe impl Send for RawMemory {} -unsafe impl Sync for RawMemory {} - #[doc(hidden)] pub mod rt { use crate::slab::Slab; diff --git a/crates/wit-bindgen-demo/Cargo.toml b/crates/wit-bindgen-demo/Cargo.toml index 08c6fd3e6..119bf324b 100644 --- a/crates/wit-bindgen-demo/Cargo.toml +++ b/crates/wit-bindgen-demo/Cargo.toml @@ -11,7 +11,7 @@ test = false doctest = false [dependencies] -wit-bindgen-gen-core = { path = '../gen-core', features = ['witx-compat'] } +wit-bindgen-gen-core = { path = '../gen-core' } wit-bindgen-gen-rust-wasm = { path = '../gen-rust-wasm' } wit-bindgen-gen-wasmtime = { path = '../gen-wasmtime' } wit-bindgen-gen-wasmtime-py = { path = '../gen-wasmtime-py' } diff --git a/crates/wit-component/src/decoding.rs b/crates/wit-component/src/decoding.rs index e4ad13f7f..2444d6e99 100644 --- a/crates/wit-component/src/decoding.rs +++ b/crates/wit-component/src/decoding.rs @@ -5,8 +5,8 @@ use wasmparser::{ Validator, WasmFeatures, }; use wit_parser::{ - abi::Abi, validate_id, Case, Docs, Field, Function, FunctionKind, Int, Interface, Record, - RecordKind, Type, TypeDef, TypeDefKind, TypeId, Variant, + validate_id, Case, Docs, Field, Function, FunctionKind, Int, Interface, Record, RecordKind, + Type, TypeDef, TypeDefKind, TypeId, Variant, }; /// Represents information about a decoded WebAssembly component. @@ -249,7 +249,6 @@ impl<'a> InterfaceDecoder<'a> { } self.interface.functions.push(Function { - abi: Abi::Canonical, is_async: false, docs: Docs::default(), name: func_name.to_string(), diff --git a/crates/wit-component/src/encoding.rs b/crates/wit-component/src/encoding.rs index 2287a6f9c..f16d7ec2f 100644 --- a/crates/wit-component/src/encoding.rs +++ b/crates/wit-component/src/encoding.rs @@ -12,7 +12,7 @@ use std::{ use wasm_encoder::*; use wasmparser::{Validator, WasmFeatures}; use wit_parser::{ - abi::{Abi, AbiVariant, WasmSignature, WasmType}, + abi::{AbiVariant, WasmSignature, WasmType}, Docs, Field, Function, FunctionKind, Interface, Record, RecordKind, Type, TypeDef, TypeDefKind, Variant, }; @@ -192,10 +192,6 @@ impl Hash for TypeDefKey<'_> { } .hash(state); } - TypeDefKind::Pointer(_) - | TypeDefKind::ConstPointer(_) - | TypeDefKind::PushBuffer(_) - | TypeDefKind::PullBuffer(_) => unreachable!(), } } } @@ -450,12 +446,6 @@ impl<'a> TypeEncoder<'a> { InterfaceTypeRef::Type(index) } TypeDefKind::Type(ty) => self.encode_type(interface, instance, ty)?, - TypeDefKind::Pointer(_) | TypeDefKind::ConstPointer(_) => { - bail!("the use of pointers in interfaces is not supported") - } - TypeDefKind::PushBuffer(_) | TypeDefKind::PullBuffer(_) => { - bail!("the use of buffers in interfaces is not currently supported") - } }; if ty.name.is_some() { @@ -689,10 +679,6 @@ impl RequiredOptions { Self::for_type(interface, t) | Self::Into } TypeDefKind::Type(t) => Self::for_type(interface, t), - TypeDefKind::Pointer(_) - | TypeDefKind::ConstPointer(_) - | TypeDefKind::PushBuffer(_) - | TypeDefKind::PullBuffer(_) => Self::None, }, _ => Self::None, } @@ -1234,13 +1220,6 @@ impl<'a> ComponentEncoder<'a> { ); } - if !matches!(function.abi, Abi::Canonical) { - bail!( - "unsupported function `{}`: only canonical functions are supported", - function.name - ); - } - if function.is_async { bail!( "unsupported function `{}`: only synchronous functions are currently supported", diff --git a/crates/wit-component/src/printing.rs b/crates/wit-component/src/printing.rs index cc7ac4750..4c66e37b4 100644 --- a/crates/wit-component/src/printing.rs +++ b/crates/wit-component/src/printing.rs @@ -82,11 +82,6 @@ impl InterfacePrinter { } } TypeDefKind::Type(ty) => self.print_type_name(interface, ty)?, - - TypeDefKind::Pointer(_) - | TypeDefKind::ConstPointer(_) - | TypeDefKind::PushBuffer(_) - | TypeDefKind::PullBuffer(_) => bail!("interface has unsupported type"), } } @@ -182,11 +177,6 @@ impl InterfacePrinter { } None => bail!("unnamed type in interface"), }, - - TypeDefKind::Pointer(_) - | TypeDefKind::ConstPointer(_) - | TypeDefKind::PushBuffer(_) - | TypeDefKind::PullBuffer(_) => bail!("interface has unsupported type"), } } diff --git a/tests/codegen/legacy.witx b/tests/codegen/legacy.witx deleted file mode 100644 index 5c9149227..000000000 --- a/tests/codegen/legacy.witx +++ /dev/null @@ -1,68 +0,0 @@ -(module $legacy - (typename $f1 (flags $a $b)) - (typename $f2 (flags (@witx repr u64) $c $d $e)) - (typename $r1 (record (field $a u8) (field $b $f1))) - (typename $e1 (enum $a $b)) - - (typename $flag8 (flags $b0 $b1 $b2 $b3 $b4 $b5 $b6 $b7)) - (typename $flag16 (flags - $b0 $b1 $b2 $b3 $b4 $b5 $b6 $b7 - $b8 $b9 $b10 $b11 $b12 $b13 $b14 $b15 - )) - (typename $flag32 (flags - $b0 $b1 $b2 $b3 $b4 $b5 $b6 $b7 - $b8 $b9 $b10 $b11 $b12 $b13 $b14 $b15 - $b16 $b17 $b18 $b19 $b20 $b21 $b22 $b23 - $b24 $b25 $b26 $b27 $b28 $b29 $b30 $b31 - )) - (typename $flag64 (flags - $b0 $b1 $b2 $b3 $b4 $b5 $b6 $b7 - $b8 $b9 $b10 $b11 $b12 $b13 $b14 $b15 - $b16 $b17 $b18 $b19 $b20 $b21 $b22 $b23 - $b24 $b25 $b26 $b27 $b28 $b29 $b30 $b31 - $b32 $b33 $b34 $b35 $b36 $b37 $b38 $b39 - $b40 $b41 $b42 $b43 $b44 $b45 $b46 $b47 - $b48 $b49 $b50 $b51 $b52 $b53 $b54 $b55 - $b56 $b57 $b58 $b59 $b60 $b61 $b62 $b63 - )) - - (typename $s8 s8) - (typename $u8 u8) - (typename $s16 s16) - (typename $u16 u16) - (typename $s32 s32) - (typename $u32 u32) - (typename $s64 s64) - (typename $u64 u64) - (typename $f32 f32) - (typename $f64 f64) - (typename $legacy-result (tuple - ;; primitives with varying bit widths and signedness - $s8 $u8 - $s16 $u16 - $s32 $u32 - $s64 $u64 - $f32 $f64 - ;; records - $r1 - )) - - (@interface func (export "roundtrip-usize") (param $a (@witx usize)) (result $b (@witx usize))) - (@interface func (export "legacy-flags1") (param $a $flag8) (result $r0 $flag8)) - (@interface func (export "legacy-flags2") (param $a $flag16) (result $r0 $flag16)) - (@interface func (export "legacy-flags3") (param $a $flag32) (result $r0 $flag32)) - (@interface func (export "legacy-flags4") (param $a $flag64) (result $r0 $flag64)) - - (@interface func (export "legacy-params") - (param $a (tuple u32 u32)) - ;; test aggregates - (param $b $r1) - ;; tests many kinds of loads - (param $c (tuple u8 s8 u16 s16 u32 s32 u64 s64 f32 f64)) - ) - - (@interface func (export "legacy-result") - (param $succeed bool) - (result $b (expected $legacy-result (error $e1))) - ) -) diff --git a/tests/codegen/wasi-next/wasi-next.wit b/tests/codegen/wasi-next/wasi-next.wit deleted file mode 100644 index 62facd76b..000000000 --- a/tests/codegen/wasi-next/wasi-next.wit +++ /dev/null @@ -1,411 +0,0 @@ -// WASI Preview. This is an evolution of the API that WASI initially -// launched with. -// -// Some content here is derived from [CloudABI](https://github.com/NuxiNL/cloudabi). - -use * from wasi-types -/// Read command-line argument data. -/// The size of the array should match that returned by `args-sizes-get`. -/// Each argument is expected to be `\0` terminated. -args-get: function(buf: push-buffer) -> expected<_, errno> - -/// Return command-line argument data sizes. -/// -/// Returns the number of arguments and the size of the argument string -/// data, or an error. -args-sizes-get: function() -> expected, errno> - - -/// Read environment variable data. -/// The sizes of the buffers should match that returned by `environ-sizes-get`. -/// Key/value pairs are expected to be joined with `=`s, and terminated with `\0`s. -environ-get: function(buf: push-buffer) -> expected<_, errno> - -/// Return environment variable data sizes. -/// -/// Returns the number of environment variable arguments and the size of the -/// environment variable data. -environ-sizes-get: function() -> expected, errno> - -/// Return the resolution of a clock. -/// Implementations are required to provide a non-zero value for supported clocks. For unsupported clocks, -/// return `errno::inval`. -/// Note: This is similar to `clock-getres` in POSIX. - /// The clock for which to return the resolution. - /// The resolution of the clock, or an error if one happened. -clock-res-get: function(id: clockid) -> expected - -/// Return the time value of a clock. -/// Note: This is similar to `clock-gettime` in POSIX. - /// The clock for which to return the time. - /// The maximum lag (exclusive) that the returned time value may have, compared to its actual value. - /// The time value of the clock. -clock-time-get: function(id: clockid, precision: timestamp) -> expected - -/// Provide file advisory information on a file descriptor. -/// Note: This is similar to `posix-fadvise` in POSIX. - /// The offset within the file to which the advisory applies. - /// The length of the region to which the advisory applies. - /// The advice. -fd-advise: function(fd: fd, offset: filesize, len: filesize, advice: advice) - -> expected<_, errno> - -/// Force the allocation of space in a file. -/// Note: This is similar to `posix-fallocate` in POSIX. - /// The offset at which to start the allocation. - /// The length of the area that is allocated. -fd-allocate: function(fd: fd, offset: filesize, len: filesize) -> expected<_, errno> - -/* - /// Close a file descriptor. - /// Note: This is similar to `close` in POSIX. - (@interface func (export "fd-close") - (param $fd $fd) - (result $error (expected (error $errno))) - ) -*/ - -/// Synchronize the data of a file to disk. -/// Note: This is similar to `fdatasync` in POSIX. -fd-datasync: function(fd: fd) -> expected<_, errno> - -/// Get the attributes of a file descriptor. -/// Note: This returns similar flags to `fsync(fd, F-GETFL)` in POSIX, as well as additional fields. - /// The buffer where the file descriptor's attributes are stored. -fd-fdstat-get: function(fd: fd) -> expected - -/// Adjust the flags associated with a file descriptor. -/// Note: This is similar to `fcntl(fd, F-SETFL, flags)` in POSIX. - /// The desired values of the file descriptor flags. -fd-fdstat-set-flags: function(fd: fd, %flags: fdflags) -> expected<_, errno> - - /// Adjust the rights associated with a file descriptor. - /// This can only be used to remove rights, and returns `errno::notcapable` if called in a way that would attempt to add rights -fd-fdstat-set-rights: function( - fd: fd, - /// The desired rights of the file descriptor. - fs-rights-base: rights, - fs-rights-inheriting: rights, -) -> expected<_, errno> - -/// Return the attributes of an open file. - /// The buffer where the file's attributes are stored. -fd-filestat-get: function(fd: fd) -> expected - -/// Adjust the size of an open file. If this increases the file's size, the extra bytes are filled with zeros. -/// Note: This is similar to `ftruncate` in POSIX. - /// The desired file size. -fd-filestat-set-size: function(fd: fd, size: filesize) -> expected<_, errno> - -/// Adjust the timestamps of an open file or directory. -/// Note: This is similar to `futimens` in POSIX. -fd-filestat-set-times: function( - fd: fd, - /// The desired values of the data access timestamp. - atim: timestamp, - /// The desired values of the data modification timestamp. - mtim: timestamp, - /// A bitmask indicating which timestamps to adjust. - fst-flags: fstflags, -) -> expected<_, errno> - -/// Read from a file descriptor, without using and updating the file descriptor's offset. -/// Note: This is similar to `preadv` in POSIX. -fd-pread: function( - fd: fd, - /// Buffer to read into - buf: push-buffer, - /// The offset within the file at which to read. - offset: filesize, -) -> expected - -/// Return a description of the given preopened file descriptor. -fd-prestat-get: function(fd: fd) -> expected - -/// Return a description of the given preopened file descriptor. - /// A buffer into which to write the preopened directory name. -fd-prestat-dir-name: function(fd: fd, buf: push-buffer) -> expected<_, errno> - -/// Write to a file descriptor, without using and updating the file descriptor's offset. -/// Note: This is similar to `pwritev` in POSIX. -fd-pwrite: function( - fd: fd, - /// Data to write - buf: pull-buffer, - /// The offset within the file at which to write. - offset: filesize, -) -> expected - -/// Read from a file descriptor. -/// Note: This is similar to `readv` in POSIX. -fd-read: function( - fd: fd, - /// Where to read into - buf: push-buffer, -) -> expected - -/// Read directory entries from a directory. -/// When successful, the contents of the output buffer consist of a sequence of -/// directory entries. Each directory entry consists of a `dirent` object, -/// followed by `dirent::d-namlen` bytes holding the name of the directory -/// entry. -// -/// This function fills the output buffer as much as possible, potentially -/// truncating the last directory entry. This allows the caller to grow its -/// read buffer size in case it's too small to fit a single large directory -/// entry, or skip the oversized directory entry. -fd-readdir: function( - fd: fd, - /// The buffer where directory entries are stored - buf: push-buffer, - /// The location within the directory to start reading - cookie: dircookie, -) - /// The number of bytes stored in the read buffer. If less than the size of the read buffer, the end of the directory has been reached. - -> expected - -/* -/// Atomically replace a file descriptor by renumbering another file descriptor. -/// -/// Due to the strong focus on thread safety, this environment does not provide -/// a mechanism to duplicate or renumber a file descriptor to an arbitrary -/// number, like `dup2()`. This would be prone to race conditions, as an actual -/// file descriptor with the same number could be allocated by a different -/// thread at the same time. -/// -/// This function provides a way to atomically renumber file descriptors, which -/// would disappear if `dup2()` were to be removed entirely. -interface func (export "fd-renumber") - (param $fd $fd) - /// The file descriptor to overwrite. - (param $to $fd) - (result $error (expected (error $errno))) -) -*/ - -/// Move the offset of a file descriptor. -/// Note: This is similar to `lseek` in POSIX. -fd-seek: function( - fd: fd, - /// The number of bytes to move. - offset: filedelta, - /// The base from which the offset is relative. - whence: whence, -) - /// The new offset of the file descriptor, relative to the start of the file. - -> expected - -/// Synchronize the data and metadata of a file to disk. -/// Note: This is similar to `fsync` in POSIX. -fd-sync: function(fd: fd) -> expected<_, errno> - -/// Return the current offset of a file descriptor. -/// Note: This is similar to `lseek(fd, 0, SEEK-CUR)` in POSIX. - /// The current offset of the file descriptor, relative to the start of the file. -fd-tell: function(fd: fd) -> expected - -/// Write to a file descriptor. -/// Note: This is similar to `writev` in POSIX. -fd-write: function( - fd: fd, - /// Data to write - buf: pull-buffer, -) -> expected - -/// Create a directory. -/// Note: This is similar to `mkdirat` in POSIX. -path-create-directory: function( - fd: fd, - /// The path at which to create the directory. - path: string, -) -> expected<_, errno> - -/// Return the attributes of a file or directory. -/// Note: This is similar to `stat` in POSIX. -path-filestat-get: function( - fd: fd, - /// Flags determining the method of how the path is resolved. - %flags: lookupflags, - /// The path of the file or directory to inspect. - path: string, -) - /// The buffer where the file's attributes are stored. - -> expected - -/// Adjust the timestamps of a file or directory. -/// Note: This is similar to `utimensat` in POSIX. -path-filestat-set-times: function( - fd: fd, - /// Flags determining the method of how the path is resolved. - %flags: lookupflags, - /// The path of the file or directory to operate on. - path: string, - /// The desired values of the data access timestamp. - atim: timestamp, - /// The desired values of the data modification timestamp. - mtim: timestamp, - /// A bitmask indicating which timestamps to adjust. - fst-flags: fstflags, -) -> expected<_, errno> - -/// Create a hard link. -/// Note: This is similar to `linkat` in POSIX. -path-link: function( - old-fd: fd, - /// Flags determining the method of how the path is resolved. - old-flags: lookupflags, - /// The source path from which to link. - old-path: string, - /// The working directory at which the resolution of the new path starts. - new-fd: fd, - /// The destination path at which to create the hard link. - new-path: string, -) -> expected<_, errno> - -/// Open a file or directory. -// -/// The returned file descriptor is not guaranteed to be the lowest-numbered -/// file descriptor not currently open/ it is randomized to prevent -/// applications from depending on making assumptions about indexes, since this -/// is error-prone in multi-threaded contexts. The returned file descriptor is -/// guaranteed to be less than 2**31. -// -/// Note: This is similar to `openat` in POSIX. -path-open: function( - fd: fd, - /// Flags determining the method of how the path is resolved. - dirflags: lookupflags, - /// The relative path of the file or directory to open, relative to the - /// `path-open::fd` directory. - path: string, - /// The method by which to open the file. - oflags: oflags, - /// The initial rights of the newly created file descriptor. The - /// implementation is allowed to return a file descriptor with fewer rights - /// than specified, if and only if those rights do not apply to the type of - /// file being opened. - // - /// The *base* rights are rights that will apply to operations using the file - /// descriptor itself, while the *inheriting* rights are rights that apply to - /// file descriptors derived from it. - fs-rights-base: rights, - fs-rights-inheriting: rights, - fdflags: fdflags, -) - /// The file descriptor of the file that has been opened. - -> expected - -/// Read the contents of a symbolic link. -/// Note: This is similar to `readlinkat` in POSIX. -path-readlink: function( - fd: fd, - /// The path of the symbolic link from which to read. - path: string, - /// The buffer to which to write the contents of the symbolic link. - buf: push-buffer, -) - /// The number of bytes placed in the buffer. - -> expected - -/// Remove a directory. -/// Return `errno::notempty` if the directory is not empty. -/// Note: This is similar to `unlinkat(fd, path, AT-REMOVEDIR)` in POSIX. -path-remove-directory: function( - fd: fd, - /// The path to a directory to remove. - path: string, -) -> expected<_, errno> - -/// Rename a file or directory. -/// Note: This is similar to `renameat` in POSIX. -path-rename: function( - fd: fd, - /// The source path of the file or directory to rename. - old-path: string, - /// The working directory at which the resolution of the new path starts. - new-fd: fd, - /// The destination path to which to rename the file or directory. - new-path: string, -) -> expected<_, errno> - -/// Create a symbolic link. -/// Note: This is similar to `symlinkat` in POSIX. -path-symlink: function( - /// The contents of the symbolic link. - old-path: string, - fd: fd, - /// The destination path at which to create the symbolic link. - new-path: string, -) -> expected<_, errno> - -/// Unlink a file. -/// Return `errno::isdir` if the path refers to a directory. -/// Note: This is similar to `unlinkat(fd, path, 0)` in POSIX. -path-unlink-file: function( - fd: fd, - /// The path to a file to unlink. - path: string, -) -> expected<_, errno> - -/// Concurrently poll for the occurrence of a set of events. -poll-oneoff: function( - /// The events to which to subscribe. - subscriptions: list, - /// Where to write events that occurred. - events: push-buffer, -) - /// The number of events stored.d - -> expected - -/// Terminate the process normally. An exit code of 0 indicates successful -/// termination of the program. The meanings of other values is dependent on -/// the environment. - /// The exit code returned by the process. - // (@witx noreturn) // TODO -proc-exit: function(rval: exitcode) - -/// Temporarily yield execution of the calling thread. -/// Note: This is similar to `sched-yield` in POSIX. -sched-yield: function() -> expected<_, errno> - -/// Write high-quality random data into a buffer. -/// This function blocks when the implementation is unable to immediately -/// provide sufficient high-quality random data. -/// This function may execute slowly, so when large mounts of random data are -/// required, it's advisable to use this function to seed a pseudo-random -/// number generator, rather than to provide the random data directly. -random-get: function(buf: push-buffer) -> expected<_, errno> - -/// Receive a message from a socket. -/// Note: This is similar to `recv` in POSIX, though it also supports reading -/// the data into multiple buffers in the manner of `readv`. -sock-recv: function( - fd: fd, - /// Where to write received data - ri-data: push-buffer, - /// Message flags. - ri-flags: riflags, -) - /// Number of bytes stored in ri-data and message flags. - -> expected, errno> - -/// Send a message on a socket. -/// Note: This is similar to `send` in POSIX, though it also supports writing -/// the data from multiple buffers in the manner of `writev`. -sock-send: function( - fd: fd, - /// Data to send - si-data: pull-buffer, - /// Message flags. - si-flags: siflags, -) - /// Number of bytes transmitted. - -> expected - -/// Shut down socket send and receive channels. -/// Note: This is similar to `shutdown` in POSIX. -sock-shutdown: function( - fd: fd, - /// Which channels on the socket to shut down. - how: sdflags, -) -> expected<_, errno> diff --git a/tests/codegen/wasi-next/wasi-types.wit b/tests/codegen/wasi-next/wasi-types.wit deleted file mode 100644 index 1fa69d324..000000000 --- a/tests/codegen/wasi-next/wasi-types.wit +++ /dev/null @@ -1,562 +0,0 @@ -// Type names used by low-level WASI interfaces. -// -// Some content here is derived from [CloudABI](https://github.com/NuxiNL/cloudabi). -// -// This is a `witx` file. See [here](https://github.com/WebAssembly/WASI/tree/master/docs/witx.md) -// for an explanation of what that means. - -type size = u32 - -/// Non-negative file size or length of a region within a file. -type filesize = u64 - -/// Timestamp in nanoseconds. -type timestamp = u64 - -/// Identifiers for clocks. -enum clockid { - /// The clock measuring real time. Time value zero corresponds with - /// 1970-01-01T00:00:00Z. - realtime, - /// The store-wide monotonic clock, which is defined as a clock measuring - /// real time, whose value cannot be adjusted and which cannot have negative - /// clock jumps. The epoch of this clock is undefined. The absolute time - /// value of this clock therefore has no meaning. - monotonic, - /// The CPU-time clock associated with the current process. - process-cputime-id, - /// The CPU-time clock associated with the current thread. - thread-cputime-id, -} - -/// Error codes returned by functions. -/// Not all of these error codes are returned by the functions provided by this -/// API/ some are used in higher-level library layers, and others are provided -/// merely for alignment with POSIX. -enum errno { - /// No error occurred. System call completed successfully. - success, - /// Argument list too long. - toobig, - /// Permission denied. - access, - /// Address in use. - addrinuse, - /// Address not available. - addrnotavail, - /// Address family not supported. - afnosupport, - /// Resource unavailable, or operation would block. - again, - /// Connection already in progress. - already, - /// Bad file descriptor. - badf, - /// Bad message. - badmsg, - /// Device or resource busy. - busy, - /// Operation canceled. - canceled, - /// No child processes. - child, - /// Connection aborted. - connaborted, - /// Connection refused. - connrefused, - /// Connection reset. - connreset, - /// Resource deadlock would occur. - deadlk, - /// Destination address required. - destaddrreq, - /// Mathematics argument out of domain of function. - dom, - /// Reserved. - dquot, - /// File exists. - exist, - /// Bad address. - fault, - /// File too large. - fbig, - /// Host is unreachable. - hostunreach, - /// Identifier removed. - idrm, - /// Illegal byte sequence. - ilseq, - /// Operation in progress. - inprogress, - /// Interrupted function. - intr, - /// Invalid argument. - inval, - /// I/O error. - io, - /// Socket is connected. - isconn, - /// Is a directory. - isdir, - /// Too many levels of symbolic links. - loop, - /// File descriptor value too large. - mfile, - /// Too many links. - mlink, - /// Message too large. - msgsize, - /// Reserved. - multihop, - /// Filename too long. - nametoolong, - /// Network is down. - netdown, - /// Connection aborted by network. - netreset, - /// Network unreachable. - netunreach, - /// Too many files open in system. - nfile, - /// No buffer space available. - nobufs, - /// No such device. - nodev, - /// No such file or directory. - noent, - /// Executable file format error. - noexec, - /// No locks available. - nolck, - /// Reserved. - nolink, - /// Not enough space. - nomem, - /// No message of the desired type. - nomsg, - /// Protocol not available. - noprotoopt, - /// No space left on device. - nospc, - /// Function not supported. - nosys, - /// The socket is not connected. - notconn, - /// Not a directory or a symbolic link to a directory. - notdir, - /// Directory not empty. - notempty, - /// State not recoverable. - notrecoverable, - /// Not a socket. - notsock, - /// Not supported, or operation not supported on socket. - notsup, - /// Inappropriate I/O control operation. - notty, - /// No such device or address. - nxio, - /// Value too large to be stored in data type. - overflow, - /// Previous owner died. - ownerdead, - /// Operation not permitted. - perm, - /// Broken pipe. - pipe, - /// Protocol error. - proto, - /// Protocol not supported. - protonosupport, - /// Protocol wrong type for socket. - prototype, - /// Result too large. - range, - /// Read-only file system. - rofs, - /// Invalid seek. - spipe, - /// No such process. - srch, - /// Reserved. - stale, - /// Connection timed out. - timedout, - /// Text file busy. - txtbsy, - /// Cross-device link. - xdev, - /// Extension: Capabilities insufficient. - notcapable, -} - -/// File descriptor rights, determining which actions may be performed. -flags rights { - /// The right to invoke `fd-datasync`. - // - /// If `path-open` is set, includes the right to invoke - /// `path-open` with `fdflags::dsync`. - fd-datasync, - /// The right to invoke `fd-read` and `sock-recv`. - // - /// If `rights::fd-seek` is set, includes the right to invoke `fd-pread`. - fd-read, - /// The right to invoke `fd-seek`. This flag implies `rights::fd-tell`. - fd-seek, - /// The right to invoke `fd-fdstat-set-flags`. - fd-fdstat-set-flags, - /// The right to invoke `fd-sync`. - // - /// If `path-open` is set, includes the right to invoke - /// `path-open` with `fdflags::rsync` and `fdflags::dsync`. - fd-sync, - /// The right to invoke `fd-seek` in such a way that the file offset - /// remains unaltered (i.e., `whence::cur` with offset zero), or to - /// invoke `fd-tell`. - fd-tell, - /// The right to invoke `fd-write` and `sock-send`. - /// If `rights::fd-seek` is set, includes the right to invoke `fd-pwrite`. - fd-write, - /// The right to invoke `fd-advise`. - fd-advise, - /// The right to invoke `fd-allocate`. - fd-allocate, - /// The right to invoke `path-create-directory`. - path-create-directory, - /// If `path-open` is set, the right to invoke `path-open` with `oflags::creat`. - path-create-file, - /// The right to invoke `path-link` with the file descriptor as the - /// source directory. - path-link-source, - /// The right to invoke `path-link` with the file descriptor as the - /// target directory. - path-link-target, - /// The right to invoke `path-open`. - path-open, - /// The right to invoke `fd-readdir`. - fd-readdir, - /// The right to invoke `path-readlink`. - path-readlink, - /// The right to invoke `path-rename` with the file descriptor as the source directory. - path-rename-source, - /// The right to invoke `path-rename` with the file descriptor as the target directory. - path-rename-target, - /// The right to invoke `path-filestat-get`. - path-filestat-get, - /// The right to change a file's size (there is no `path-filestat-set-size`). - /// If `path-open` is set, includes the right to invoke `path-open` with `oflags::trunc`. - path-filestat-set-size, - /// The right to invoke `path-filestat-set-times`. - path-filestat-set-times, - /// The right to invoke `fd-filestat-get`. - fd-filestat-get, - /// The right to invoke `fd-filestat-set-size`. - fd-filestat-set-size, - /// The right to invoke `fd-filestat-set-times`. - fd-filestat-set-times, - /// The right to invoke `path-symlink`. - path-symlink, - /// The right to invoke `path-remove-directory`. - path-remove-directory, - /// The right to invoke `path-unlink-file`. - path-unlink-file, - /// If `rights::fd-read` is set, includes the right to invoke `poll-oneoff` to subscribe to `eventtype::fd-read`. - /// If `rights::fd-write` is set, includes the right to invoke `poll-oneoff` to subscribe to `eventtype::fd-write`. - poll-fd-readwrite, - /// The right to invoke `sock-shutdown`. - sock-shutdown, -} - -resource file-descriptor -/// A file descriptor handle. -type fd = handle file-descriptor - -/// Relative offset within a file. -type filedelta = s64 - - -/// The position relative to which to set the offset of the file descriptor. -enum whence { - /// Seek relative to start-of-file. - set, - /// Seek relative to current position. - cur, - /// Seek relative to end-of-file. - end, -} - -/// A reference to the offset of a directory entry. -/// -/// The value 0 signifies the start of the directory. -type dircookie = u64 - -/// The type for the `dirent::d-namlen` field of `dirent` struct. -type dirnamlen = u32 - -/// File serial number that is unique within its file system. -type inode = u64 - -/// The type of a file descriptor or file. -enum filetype { - /// The type of the file descriptor or file is unknown or is different from any of the other types specified. - unknown, - /// The file descriptor or file refers to a block device inode. - block-device, - /// The file descriptor or file refers to a character device inode. - character-device, - /// The file descriptor or file refers to a directory inode. - directory, - /// The file descriptor or file refers to a regular file inode. - regular-file, - /// The file descriptor or file refers to a datagram socket. - socket-dgram, - /// The file descriptor or file refers to a byte-stream socket. - socket-stream, - /// The file refers to a symbolic link inode. - symbolic-link, -} - -/// A directory entry. -record dirent { - /// The offset of the next directory entry stored in this directory. - d-next: dircookie, - /// The serial number of the file referred to by this directory entry. - d-ino: inode, - /// The length of the name of the directory entry. - d-namlen: dirnamlen, - /// The type of the file referred to by this directory entry. - d-type: filetype, -} - -/// File or memory access pattern advisory information. -enum advice { - /// The application has no advice to give on its behavior with respect to the specified data. - normal, - /// The application expects to access the specified data sequentially from lower offsets to higher offsets. - sequential, - /// The application expects to access the specified data in a random order. - random, - /// The application expects to access the specified data in the near future. - willneed, - /// The application expects that it will not access the specified data in the near future. - dontneed, - /// The application expects to access the specified data once and then not reuse it thereafter. - noreuse, -} - -/// File descriptor flags. -flags fdflags { - /// Append mode: Data written to the file is always appended to the file's end. - append, - /// Write according to synchronized I/O data integrity completion. Only the data stored in the file is synchronized. - dsync, - /// Non-blocking mode. - nonblock, - /// Synchronized read I/O operations. - rsync, - /// Write according to synchronized I/O file integrity completion. In - /// addition to synchronizing the data stored in the file, the implementation - /// may also synchronously update the file's metadata. - sync, -} - -/// File descriptor attributes. -record fdstat { - /// File type. - fs-filetype: filetype, - /// File descriptor flags. - fs-flags: fdflags, - /// Rights that apply to this file descriptor. - fs-rights-base: rights, - /// Maximum set of rights that may be installed on new file descriptors that - /// are created through this file descriptor, e.g., through `path-open`. - fs-rights-inheriting: rights, -} - -/// Identifier for a device containing a file system. Can be used in combination -/// with `inode` to uniquely identify a file or directory in the filesystem. -type device = u64 - -/// Which file time attributes to adjust. -flags fstflags { - /// Adjust the last data access timestamp to the value stored in `filestat::atim`. - atim, - /// Adjust the last data access timestamp to the time of clock `clockid::realtime`. - atim-now, - /// Adjust the last data modification timestamp to the value stored in `filestat::mtim`. - mtim, - /// Adjust the last data modification timestamp to the time of clock `clockid::realtime`. - mtim-now, -} - - -/// Flags determining the method of how paths are resolved. -flags lookupflags { - /// As long as the resolved path corresponds to a symbolic link, it is expanded. - symlink-follow, -} - -/// Open flags used by `path-open`. -flags oflags { - /// Create file if it does not exist. - creat, - /// Fail if not a directory. - directory, - /// Fail if file already exists. - excl, - /// Truncate file to size 0. - trunc, -} - -/// Number of hard links to an inode. -type linkcount = u64 - -/// File attributes. -record filestat { - /// Device ID of device containing the file. - dev: device, - /// File serial number. - ino: inode, - /// File type. - filetype: filetype, - /// Number of hard links to the file. - nlink: linkcount, - /// For regular files, the file size in bytes. For symbolic links, the length in bytes of the pathname contained in the symbolic link. - size: filesize, - /// Last data access timestamp. - atim: timestamp, - /// Last data modification timestamp. - mtim: timestamp, - /// Last file status change timestamp. - ctim: timestamp, -} - - -/// User-provided value that may be attached to objects that is retained when -/// extracted from the implementation. -type userdata = u64 - -/// The state of the file descriptor subscribed to with -/// `eventtype::fd-read` or `eventtype::fd-write`. -flags eventrwflags { - /// The peer of this socket has closed or disconnected. - fd-readwrite-hangup, -} - -/// The contents of an `event` when type is `fd-read` or -/// `fd-write`. -record event-fd-readwrite { - /// The number of bytes available for reading or writing. - nbytes: filesize, - /// The state of the file descriptor. - %flags: eventrwflags, -} - -variant event-u { - clock, - fd-read(event-fd-readwrite), - fd-write(event-fd-readwrite), -} - -/// An event that occurred. -record event { - /// User-provided value that got attached to `subscription::userdata`. - userdata: userdata, - /// If non-zero, an error that occurred while processing the subscription request. - error: errno, - /// The type of event that occured, along with the contents of the event. - %type: event-u, -} - -/// Flags determining how to interpret the timestamp provided in -/// `subscription-clock::timeout`. -flags subclockflags { - /// If set, treat the timestamp provided in - /// `subscription-clock::timeout` as an absolute timestamp of clock - /// `subscription-clock::id`. If clear, treat the timestamp - /// provided in `subscription-clock::timeout` relative to the - /// current time value of clock `subscription-clock::id`. - subscription-clock-abstime, -} - -/// The contents of a `subscription` when type is `eventtype::clock`. -record subscription-clock { - /// The clock against which to compare the timestamp. - id: clockid, - /// The absolute or relative timestamp. - timeout: timestamp, - /// The amount of time that the implementation may wait additionally - /// to coalesce with other events. - precision: timestamp, - /// Flags specifying whether the timeout is absolute or relative - %flags: subclockflags, -} - -/// The contents of a `subscription` when type is type is -/// `fd-read` or `fd-write`. -record subscription-fd-readwrite { - /// The file descriptor on which to wait for it to become ready for reading or - /// writing. - file-descriptor: fd, -} - -/// The contents of a `subscription`. -variant subscription-u { - /// The time value of clock `subscription-clock::id` has - /// reached timestamp `subscription-clock::timeout`. - clock(subscription-clock), - /// File descriptor `subscription-fd-readwrite::file-descriptor` has data - /// available for reading. This event always triggers for regular files. - fd-read(subscription-fd-readwrite), - /// File descriptor `subscription-fd-readwrite::file-descriptor` has capacity - /// available for writing. This event always triggers for regular files. - fd-write(subscription-fd-readwrite), -} - -/// Subscription to an event. -record subscription { - /// User-provided value that is attached to the subscription in the - /// implementation and returned through `event::userdata`. - userdata: userdata, - /// The type of the event to which to subscribe, and its contents - u: subscription-u, -} - - -/// Exit code generated by a process when exiting. -type exitcode = u32 - -/// Flags provided to `sock-recv`. -flags riflags { - /// Returns the message without removing it from the socket's receive queue. - recv-peek, - /// On byte-stream sockets, block until the full amount of data can be returned. - recv-waitall, -} - - -/// Flags returned by `sock-recv`. -flags roflags { - /// Returned by `sock-recv`: Message data has been truncated. - recv-data-truncated, -} - - -/// Flags provided to `sock-send`. As there are currently no flags -/// defined, it must be set to zero. -flags siflags {} - -/// Which channels on a socket to shut down. -flags sdflags { - /// Disables further receive operations. - rd, - /// Disables further send operations. - wr, -} - -/// Information about a pre-opened capability. -variant prestat { - /// A pre-opened directory with the length of the directory name for use with - /// `fd-prestat-dir-name`. - dir(size), -} diff --git a/tests/codegen/wasi_snapshot_preview1/typenames.witx b/tests/codegen/wasi_snapshot_preview1/typenames.witx deleted file mode 100644 index 5dc6edddb..000000000 --- a/tests/codegen/wasi_snapshot_preview1/typenames.witx +++ /dev/null @@ -1,751 +0,0 @@ -;; Type names used by low-level WASI interfaces. -;; -;; Some content here is derived from [CloudABI](https://github.com/NuxiNL/cloudabi). -;; -;; This is a `witx` file. See [here](https://github.com/WebAssembly/WASI/tree/master/docs/witx.md) -;; for an explanation of what that means. - -(module $typenames - -(typename $size u32) - -;;; Non-negative file size or length of a region within a file. -(typename $filesize u64) - -;;; Timestamp in nanoseconds. -(typename $timestamp u64) - -;;; Identifiers for clocks. -(typename $clockid - (enum (@witx tag u32) - ;;; The clock measuring real time. Time value zero corresponds with - ;;; 1970-01-01T00:00:00Z. - $realtime - ;;; The store-wide monotonic clock, which is defined as a clock measuring - ;;; real time, whose value cannot be adjusted and which cannot have negative - ;;; clock jumps. The epoch of this clock is undefined. The absolute time - ;;; value of this clock therefore has no meaning. - $monotonic - ;;; The CPU-time clock associated with the current process. - $process_cputime_id - ;;; The CPU-time clock associated with the current thread. - $thread_cputime_id - ) -) - -;;; Error codes returned by functions. -;;; Not all of these error codes are returned by the functions provided by this -;;; API; some are used in higher-level library layers, and others are provided -;;; merely for alignment with POSIX. -(typename $errno - (enum (@witx tag u16) - ;;; No error occurred. System call completed successfully. - $success - ;;; Argument list too long. - $2big - ;;; Permission denied. - $access - ;;; Address in use. - $addrinuse - ;;; Address not available. - $addrnotavail - ;;; Address family not supported. - $afnosupport - ;;; Resource unavailable, or operation would block. - $again - ;;; Connection already in progress. - $already - ;;; Bad file descriptor. - $badf - ;;; Bad message. - $badmsg - ;;; Device or resource busy. - $busy - ;;; Operation canceled. - $canceled - ;;; No child processes. - $child - ;;; Connection aborted. - $connaborted - ;;; Connection refused. - $connrefused - ;;; Connection reset. - $connreset - ;;; Resource deadlock would occur. - $deadlk - ;;; Destination address required. - $destaddrreq - ;;; Mathematics argument out of domain of function. - $dom - ;;; Reserved. - $dquot - ;;; File exists. - $exist - ;;; Bad address. - $fault - ;;; File too large. - $fbig - ;;; Host is unreachable. - $hostunreach - ;;; Identifier removed. - $idrm - ;;; Illegal byte sequence. - $ilseq - ;;; Operation in progress. - $inprogress - ;;; Interrupted function. - $intr - ;;; Invalid argument. - $inval - ;;; I/O error. - $io - ;;; Socket is connected. - $isconn - ;;; Is a directory. - $isdir - ;;; Too many levels of symbolic links. - $loop - ;;; File descriptor value too large. - $mfile - ;;; Too many links. - $mlink - ;;; Message too large. - $msgsize - ;;; Reserved. - $multihop - ;;; Filename too long. - $nametoolong - ;;; Network is down. - $netdown - ;;; Connection aborted by network. - $netreset - ;;; Network unreachable. - $netunreach - ;;; Too many files open in system. - $nfile - ;;; No buffer space available. - $nobufs - ;;; No such device. - $nodev - ;;; No such file or directory. - $noent - ;;; Executable file format error. - $noexec - ;;; No locks available. - $nolck - ;;; Reserved. - $nolink - ;;; Not enough space. - $nomem - ;;; No message of the desired type. - $nomsg - ;;; Protocol not available. - $noprotoopt - ;;; No space left on device. - $nospc - ;;; Function not supported. - $nosys - ;;; The socket is not connected. - $notconn - ;;; Not a directory or a symbolic link to a directory. - $notdir - ;;; Directory not empty. - $notempty - ;;; State not recoverable. - $notrecoverable - ;;; Not a socket. - $notsock - ;;; Not supported, or operation not supported on socket. - $notsup - ;;; Inappropriate I/O control operation. - $notty - ;;; No such device or address. - $nxio - ;;; Value too large to be stored in data type. - $overflow - ;;; Previous owner died. - $ownerdead - ;;; Operation not permitted. - $perm - ;;; Broken pipe. - $pipe - ;;; Protocol error. - $proto - ;;; Protocol not supported. - $protonosupport - ;;; Protocol wrong type for socket. - $prototype - ;;; Result too large. - $range - ;;; Read-only file system. - $rofs - ;;; Invalid seek. - $spipe - ;;; No such process. - $srch - ;;; Reserved. - $stale - ;;; Connection timed out. - $timedout - ;;; Text file busy. - $txtbsy - ;;; Cross-device link. - $xdev - ;;; Extension: Capabilities insufficient. - $notcapable - ) -) - -;;; File descriptor rights, determining which actions may be performed. -(typename $rights - (flags (@witx repr u64) - ;;; The right to invoke `fd_datasync`. - ;; - ;;; If `path_open` is set, includes the right to invoke - ;;; `path_open` with `fdflags::dsync`. - $fd_datasync - ;;; The right to invoke `fd_read` and `sock_recv`. - ;; - ;;; If `rights::fd_seek` is set, includes the right to invoke `fd_pread`. - $fd_read - ;;; The right to invoke `fd_seek`. This flag implies `rights::fd_tell`. - $fd_seek - ;;; The right to invoke `fd_fdstat_set_flags`. - $fd_fdstat_set_flags - ;;; The right to invoke `fd_sync`. - ;; - ;;; If `path_open` is set, includes the right to invoke - ;;; `path_open` with `fdflags::rsync` and `fdflags::dsync`. - $fd_sync - ;;; The right to invoke `fd_seek` in such a way that the file offset - ;;; remains unaltered (i.e., `whence::cur` with offset zero), or to - ;;; invoke `fd_tell`. - $fd_tell - ;;; The right to invoke `fd_write` and `sock_send`. - ;;; If `rights::fd_seek` is set, includes the right to invoke `fd_pwrite`. - $fd_write - ;;; The right to invoke `fd_advise`. - $fd_advise - ;;; The right to invoke `fd_allocate`. - $fd_allocate - ;;; The right to invoke `path_create_directory`. - $path_create_directory - ;;; If `path_open` is set, the right to invoke `path_open` with `oflags::creat`. - $path_create_file - ;;; The right to invoke `path_link` with the file descriptor as the - ;;; source directory. - $path_link_source - ;;; The right to invoke `path_link` with the file descriptor as the - ;;; target directory. - $path_link_target - ;;; The right to invoke `path_open`. - $path_open - ;;; The right to invoke `fd_readdir`. - $fd_readdir - ;;; The right to invoke `path_readlink`. - $path_readlink - ;;; The right to invoke `path_rename` with the file descriptor as the source directory. - $path_rename_source - ;;; The right to invoke `path_rename` with the file descriptor as the target directory. - $path_rename_target - ;;; The right to invoke `path_filestat_get`. - $path_filestat_get - ;;; The right to change a file's size (there is no `path_filestat_set_size`). - ;;; If `path_open` is set, includes the right to invoke `path_open` with `oflags::trunc`. - $path_filestat_set_size - ;;; The right to invoke `path_filestat_set_times`. - $path_filestat_set_times - ;;; The right to invoke `fd_filestat_get`. - $fd_filestat_get - ;;; The right to invoke `fd_filestat_set_size`. - $fd_filestat_set_size - ;;; The right to invoke `fd_filestat_set_times`. - $fd_filestat_set_times - ;;; The right to invoke `path_symlink`. - $path_symlink - ;;; The right to invoke `path_remove_directory`. - $path_remove_directory - ;;; The right to invoke `path_unlink_file`. - $path_unlink_file - ;;; If `rights::fd_read` is set, includes the right to invoke `poll_oneoff` to subscribe to `eventtype::fd_read`. - ;;; If `rights::fd_write` is set, includes the right to invoke `poll_oneoff` to subscribe to `eventtype::fd_write`. - $poll_fd_readwrite - ;;; The right to invoke `sock_shutdown`. - $sock_shutdown - ) -) - -;;; A file descriptor handle. -(resource $fd) - -;;; A region of memory for scatter/gather reads. -(typename $iovec - (record - ;;; The address of the buffer to be filled. - (field $buf (@witx pointer u8)) - ;;; The length of the buffer to be filled. - (field $buf_len $size) - ) -) - -;;; A region of memory for scatter/gather writes. -(typename $ciovec - (record - ;;; The address of the buffer to be written. - (field $buf (@witx const_pointer u8)) - ;;; The length of the buffer to be written. - (field $buf_len $size) - ) -) - -(typename $iovec_array (list $iovec)) -(typename $ciovec_array (list $ciovec)) - -;;; Relative offset within a file. -(typename $filedelta s64) - -;;; The position relative to which to set the offset of the file descriptor. -(typename $whence - (enum (@witx tag u8) - ;;; Seek relative to start-of-file. - $set - ;;; Seek relative to current position. - $cur - ;;; Seek relative to end-of-file. - $end - ) -) - -;;; A reference to the offset of a directory entry. -;;; -;;; The value 0 signifies the start of the directory. -(typename $dircookie u64) - -;;; The type for the `dirent::d_namlen` field of `dirent` struct. -(typename $dirnamlen u32) - -;;; File serial number that is unique within its file system. -(typename $inode u64) - -;;; The type of a file descriptor or file. -(typename $filetype - (enum (@witx tag u8) - ;;; The type of the file descriptor or file is unknown or is different from any of the other types specified. - $unknown - ;;; The file descriptor or file refers to a block device inode. - $block_device - ;;; The file descriptor or file refers to a character device inode. - $character_device - ;;; The file descriptor or file refers to a directory inode. - $directory - ;;; The file descriptor or file refers to a regular file inode. - $regular_file - ;;; The file descriptor or file refers to a datagram socket. - $socket_dgram - ;;; The file descriptor or file refers to a byte-stream socket. - $socket_stream - ;;; The file refers to a symbolic link inode. - $symbolic_link - ) -) - -;;; A directory entry. -(typename $dirent - (record - ;;; The offset of the next directory entry stored in this directory. - (field $d_next $dircookie) - ;;; The serial number of the file referred to by this directory entry. - (field $d_ino $inode) - ;;; The length of the name of the directory entry. - (field $d_namlen $dirnamlen) - ;;; The type of the file referred to by this directory entry. - (field $d_type $filetype) - ) -) - -;;; File or memory access pattern advisory information. -(typename $advice - (enum (@witx tag u8) - ;;; The application has no advice to give on its behavior with respect to the specified data. - $normal - ;;; The application expects to access the specified data sequentially from lower offsets to higher offsets. - $sequential - ;;; The application expects to access the specified data in a random order. - $random - ;;; The application expects to access the specified data in the near future. - $willneed - ;;; The application expects that it will not access the specified data in the near future. - $dontneed - ;;; The application expects to access the specified data once and then not reuse it thereafter. - $noreuse - ) -) - -;;; File descriptor flags. -(typename $fdflags - (flags (@witx repr u16) - ;;; Append mode: Data written to the file is always appended to the file's end. - $append - ;;; Write according to synchronized I/O data integrity completion. Only the data stored in the file is synchronized. - $dsync - ;;; Non-blocking mode. - $nonblock - ;;; Synchronized read I/O operations. - $rsync - ;;; Write according to synchronized I/O file integrity completion. In - ;;; addition to synchronizing the data stored in the file, the implementation - ;;; may also synchronously update the file's metadata. - $sync - ) -) - -;;; File descriptor attributes. -(typename $fdstat - (record - ;;; File type. - (field $fs_filetype $filetype) - ;;; File descriptor flags. - (field $fs_flags $fdflags) - ;;; Rights that apply to this file descriptor. - (field $fs_rights_base $rights) - ;;; Maximum set of rights that may be installed on new file descriptors that - ;;; are created through this file descriptor, e.g., through `path_open`. - (field $fs_rights_inheriting $rights) - ) -) - -;;; Identifier for a device containing a file system. Can be used in combination -;;; with `inode` to uniquely identify a file or directory in the filesystem. -(typename $device u64) - -;;; Which file time attributes to adjust. -(typename $fstflags - (flags (@witx repr u16) - ;;; Adjust the last data access timestamp to the value stored in `filestat::atim`. - $atim - ;;; Adjust the last data access timestamp to the time of clock `clockid::realtime`. - $atim_now - ;;; Adjust the last data modification timestamp to the value stored in `filestat::mtim`. - $mtim - ;;; Adjust the last data modification timestamp to the time of clock `clockid::realtime`. - $mtim_now - ) -) - -;;; Flags determining the method of how paths are resolved. -(typename $lookupflags - (flags (@witx repr u32) - ;;; As long as the resolved path corresponds to a symbolic link, it is expanded. - $symlink_follow - ) -) - -;;; Open flags used by `path_open`. -(typename $oflags - (flags (@witx repr u16) - ;;; Create file if it does not exist. - $creat - ;;; Fail if not a directory. - $directory - ;;; Fail if file already exists. - $excl - ;;; Truncate file to size 0. - $trunc - ) -) - -;;; Number of hard links to an inode. -(typename $linkcount u64) - -;;; File attributes. -(typename $filestat - (record - ;;; Device ID of device containing the file. - (field $dev $device) - ;;; File serial number. - (field $ino $inode) - ;;; File type. - (field $filetype $filetype) - ;;; Number of hard links to the file. - (field $nlink $linkcount) - ;;; For regular files, the file size in bytes. For symbolic links, the length in bytes of the pathname contained in the symbolic link. - (field $size $filesize) - ;;; Last data access timestamp. - (field $atim $timestamp) - ;;; Last data modification timestamp. - (field $mtim $timestamp) - ;;; Last file status change timestamp. - (field $ctim $timestamp) - ) -) - -;;; User-provided value that may be attached to objects that is retained when -;;; extracted from the implementation. -(typename $userdata u64) - -;;; Type of a subscription to an event or its occurrence. -(typename $eventtype - (enum (@witx tag u8) - ;;; The time value of clock `subscription_clock::id` has - ;;; reached timestamp `subscription_clock::timeout`. - $clock - ;;; File descriptor `subscription_fd_readwrite::file_descriptor` has data - ;;; available for reading. This event always triggers for regular files. - $fd_read - ;;; File descriptor `subscription_fd_readwrite::file_descriptor` has capacity - ;;; available for writing. This event always triggers for regular files. - $fd_write - ) -) - -;;; The state of the file descriptor subscribed to with -;;; `eventtype::fd_read` or `eventtype::fd_write`. -(typename $eventrwflags - (flags (@witx repr u16) - ;;; The peer of this socket has closed or disconnected. - $fd_readwrite_hangup - ) -) - -;;; The contents of an `event` when type is `eventtype::fd_read` or -;;; `eventtype::fd_write`. -(typename $event_fd_readwrite - (record - ;;; The number of bytes available for reading or writing. - (field $nbytes $filesize) - ;;; The state of the file descriptor. - (field $flags $eventrwflags) - ) -) - -;;; An event that occurred. -(typename $event - (record - ;;; User-provided value that got attached to `subscription::userdata`. - (field $userdata $userdata) - ;;; If non-zero, an error that occurred while processing the subscription request. - (field $error $errno) - ;;; The type of event that occured - (field $type $eventtype) - ;;; The contents of the event, if it is an `eventtype::fd_read` or - ;;; `eventtype::fd_write`. `eventtype::clock` events ignore this field. - (field $fd_readwrite $event_fd_readwrite) - ) -) - -;;; Flags determining how to interpret the timestamp provided in -;;; `subscription_clock::timeout`. -(typename $subclockflags - (flags (@witx repr u16) - ;;; If set, treat the timestamp provided in - ;;; `subscription_clock::timeout` as an absolute timestamp of clock - ;;; `subscription_clock::id`. If clear, treat the timestamp - ;;; provided in `subscription_clock::timeout` relative to the - ;;; current time value of clock `subscription_clock::id`. - $subscription_clock_abstime - ) -) - -;;; The contents of a `subscription` when type is `eventtype::clock`. -(typename $subscription_clock - (record - ;;; The clock against which to compare the timestamp. - (field $id $clockid) - ;;; The absolute or relative timestamp. - (field $timeout $timestamp) - ;;; The amount of time that the implementation may wait additionally - ;;; to coalesce with other events. - (field $precision $timestamp) - ;;; Flags specifying whether the timeout is absolute or relative - (field $flags $subclockflags) - ) -) - -;;; The contents of a `subscription` when type is type is -;;; `eventtype::fd_read` or `eventtype::fd_write`. -(typename $subscription_fd_readwrite - (record - ;;; The file descriptor on which to wait for it to become ready for reading or writing. - (field $file_descriptor $fd) - ) -) - -;;; The contents of a `subscription`. -(typename $subscription_u - (union - (@witx tag $eventtype) - $subscription_clock - $subscription_fd_readwrite - $subscription_fd_readwrite - ) -) - -;;; Subscription to an event. -(typename $subscription - (record - ;;; User-provided value that is attached to the subscription in the - ;;; implementation and returned through `event::userdata`. - (field $userdata $userdata) - ;;; The type of the event to which to subscribe, and its contents - (field $u $subscription_u) - ) -) - -;;; Exit code generated by a process when exiting. -(typename $exitcode u32) - -;;; Signal condition. -(typename $signal - (enum (@witx tag u8) - ;;; No signal. Note that POSIX has special semantics for `kill(pid, 0)`, - ;;; so this value is reserved. - $none - ;;; Hangup. - ;;; Action: Terminates the process. - $hup - ;;; Terminate interrupt signal. - ;;; Action: Terminates the process. - $int - ;;; Terminal quit signal. - ;;; Action: Terminates the process. - $quit - ;;; Illegal instruction. - ;;; Action: Terminates the process. - $ill - ;;; Trace/breakpoint trap. - ;;; Action: Terminates the process. - $trap - ;;; Process abort signal. - ;;; Action: Terminates the process. - $abrt - ;;; Access to an undefined portion of a memory object. - ;;; Action: Terminates the process. - $bus - ;;; Erroneous arithmetic operation. - ;;; Action: Terminates the process. - $fpe - ;;; Kill. - ;;; Action: Terminates the process. - $kill - ;;; User-defined signal 1. - ;;; Action: Terminates the process. - $usr1 - ;;; Invalid memory reference. - ;;; Action: Terminates the process. - $segv - ;;; User-defined signal 2. - ;;; Action: Terminates the process. - $usr2 - ;;; Write on a pipe with no one to read it. - ;;; Action: Ignored. - $pipe - ;;; Alarm clock. - ;;; Action: Terminates the process. - $alrm - ;;; Termination signal. - ;;; Action: Terminates the process. - $term - ;;; Child process terminated, stopped, or continued. - ;;; Action: Ignored. - $chld - ;;; Continue executing, if stopped. - ;;; Action: Continues executing, if stopped. - $cont - ;;; Stop executing. - ;;; Action: Stops executing. - $stop - ;;; Terminal stop signal. - ;;; Action: Stops executing. - $tstp - ;;; Background process attempting read. - ;;; Action: Stops executing. - $ttin - ;;; Background process attempting write. - ;;; Action: Stops executing. - $ttou - ;;; High bandwidth data is available at a socket. - ;;; Action: Ignored. - $urg - ;;; CPU time limit exceeded. - ;;; Action: Terminates the process. - $xcpu - ;;; File size limit exceeded. - ;;; Action: Terminates the process. - $xfsz - ;;; Virtual timer expired. - ;;; Action: Terminates the process. - $vtalrm - ;;; Profiling timer expired. - ;;; Action: Terminates the process. - $prof - ;;; Window changed. - ;;; Action: Ignored. - $winch - ;;; I/O possible. - ;;; Action: Terminates the process. - $poll - ;;; Power failure. - ;;; Action: Terminates the process. - $pwr - ;;; Bad system call. - ;;; Action: Terminates the process. - $sys - ) -) - -;;; Flags provided to `sock_recv`. -(typename $riflags - (flags (@witx repr u16) - ;;; Returns the message without removing it from the socket's receive queue. - $recv_peek - ;;; On byte-stream sockets, block until the full amount of data can be returned. - $recv_waitall - ) -) - -;;; Flags returned by `sock_recv`. -(typename $roflags - (flags (@witx repr u16) - ;;; Returned by `sock_recv`: Message data has been truncated. - $recv_data_truncated - ) -) - -;;; Flags provided to `sock_send`. As there are currently no flags -;;; defined, it must be set to zero. -(typename $siflags u16) - -;;; Which channels on a socket to shut down. -(typename $sdflags - (flags (@witx repr u8) - ;;; Disables further receive operations. - $rd - ;;; Disables further send operations. - $wr - ) -) - -;;; Identifiers for preopened capabilities. -(typename $preopentype - (enum (@witx tag u8) - ;;; A pre-opened directory. - $dir - ) -) - -;;; The contents of a $prestat when type is `preopentype::dir`. -(typename $prestat_dir - (record - ;;; The length of the directory name for use with `fd_prestat_dir_name`. - (field $pr_name_len $size) - ) -) - -;;; Information about a pre-opened capability. -(typename $prestat - (union (@witx tag $preopentype) - $prestat_dir - ) -) - -) diff --git a/tests/codegen/wasi_snapshot_preview1/wasi-snapshot-preview1.witx b/tests/codegen/wasi_snapshot_preview1/wasi-snapshot-preview1.witx deleted file mode 100644 index 9f098479f..000000000 --- a/tests/codegen/wasi_snapshot_preview1/wasi-snapshot-preview1.witx +++ /dev/null @@ -1,507 +0,0 @@ -;; WASI Preview. This is an evolution of the API that WASI initially -;; launched with. -;; -;; Some content here is derived from [CloudABI](https://github.com/NuxiNL/cloudabi). -;; -;; This is a `witx` file. See [here](https://github.com/WebAssembly/WASI/tree/master/docs/witx.md) -;; for an explanation of what that means. - -(module $wasi_snapshot_preview1 - (use * from $typenames) - - ;;; Read command-line argument data. - ;;; The size of the array should match that returned by `args_sizes_get`. - ;;; Each argument is expected to be `\0` terminated. - (@interface func (export "args_get") - (param $argv (@witx pointer (@witx pointer u8))) - (param $argv_buf (@witx pointer u8)) - (result $error (expected (error $errno))) - ) - ;;; Return command-line argument data sizes. - (@interface func (export "args_sizes_get") - ;;; Returns the number of arguments and the size of the argument string - ;;; data, or an error. - (result $error (expected (tuple $size $size) (error $errno))) - ) - - ;;; Read environment variable data. - ;;; The sizes of the buffers should match that returned by `environ_sizes_get`. - ;;; Key/value pairs are expected to be joined with `=`s, and terminated with `\0`s. - (@interface func (export "environ_get") - (param $environ (@witx pointer (@witx pointer u8))) - (param $environ_buf (@witx pointer u8)) - (result $error (expected (error $errno))) - ) - ;;; Return environment variable data sizes. - (@interface func (export "environ_sizes_get") - ;;; Returns the number of environment variable arguments and the size of the - ;;; environment variable data. - (result $error (expected (tuple $size $size) (error $errno))) - ) - - ;;; Return the resolution of a clock. - ;;; Implementations are required to provide a non-zero value for supported clocks. For unsupported clocks, - ;;; return `errno::inval`. - ;;; Note: This is similar to `clock_getres` in POSIX. - (@interface func (export "clock_res_get") - ;;; The clock for which to return the resolution. - (param $id $clockid) - ;;; The resolution of the clock, or an error if one happened. - (result $error (expected $timestamp (error $errno))) - ) - ;;; Return the time value of a clock. - ;;; Note: This is similar to `clock_gettime` in POSIX. - (@interface func (export "clock_time_get") - ;;; The clock for which to return the time. - (param $id $clockid) - ;;; The maximum lag (exclusive) that the returned time value may have, compared to its actual value. - (param $precision $timestamp) - ;;; The time value of the clock. - (result $error (expected $timestamp (error $errno))) - ) - - ;;; Provide file advisory information on a file descriptor. - ;;; Note: This is similar to `posix_fadvise` in POSIX. - (@interface func (export "fd_advise") - (param $fd $fd) - ;;; The offset within the file to which the advisory applies. - (param $offset $filesize) - ;;; The length of the region to which the advisory applies. - (param $len $filesize) - ;;; The advice. - (param $advice $advice) - (result $error (expected (error $errno))) - ) - - ;;; Force the allocation of space in a file. - ;;; Note: This is similar to `posix_fallocate` in POSIX. - (@interface func (export "fd_allocate") - (param $fd $fd) - ;;; The offset at which to start the allocation. - (param $offset $filesize) - ;;; The length of the area that is allocated. - (param $len $filesize) - (result $error (expected (error $errno))) - ) - - ;;; Close a file descriptor. - ;;; Note: This is similar to `close` in POSIX. - (@interface func (export "fd_close") - (param $fd $fd) - (result $error (expected (error $errno))) - ) - - ;;; Synchronize the data of a file to disk. - ;;; Note: This is similar to `fdatasync` in POSIX. - (@interface func (export "fd_datasync") - (param $fd $fd) - (result $error (expected (error $errno))) - ) - - ;;; Get the attributes of a file descriptor. - ;;; Note: This returns similar flags to `fsync(fd, F_GETFL)` in POSIX, as well as additional fields. - (@interface func (export "fd_fdstat_get") - (param $fd $fd) - ;;; The buffer where the file descriptor's attributes are stored. - (result $error (expected $fdstat (error $errno))) - ) - - ;;; Adjust the flags associated with a file descriptor. - ;;; Note: This is similar to `fcntl(fd, F_SETFL, flags)` in POSIX. - (@interface func (export "fd_fdstat_set_flags") - (param $fd $fd) - ;;; The desired values of the file descriptor flags. - (param $flags $fdflags) - (result $error (expected (error $errno))) - ) - - ;;; Adjust the rights associated with a file descriptor. - ;;; This can only be used to remove rights, and returns `errno::notcapable` if called in a way that would attempt to add rights - (@interface func (export "fd_fdstat_set_rights") - (param $fd $fd) - ;;; The desired rights of the file descriptor. - (param $fs_rights_base $rights) - (param $fs_rights_inheriting $rights) - (result $error (expected (error $errno))) - ) - - ;;; Return the attributes of an open file. - (@interface func (export "fd_filestat_get") - (param $fd $fd) - ;;; The buffer where the file's attributes are stored. - (result $error (expected $filestat (error $errno))) - ) - - ;;; Adjust the size of an open file. If this increases the file's size, the extra bytes are filled with zeros. - ;;; Note: This is similar to `ftruncate` in POSIX. - (@interface func (export "fd_filestat_set_size") - (param $fd $fd) - ;;; The desired file size. - (param $size $filesize) - (result $error (expected (error $errno))) - ) - - ;;; Adjust the timestamps of an open file or directory. - ;;; Note: This is similar to `futimens` in POSIX. - (@interface func (export "fd_filestat_set_times") - (param $fd $fd) - ;;; The desired values of the data access timestamp. - (param $atim $timestamp) - ;;; The desired values of the data modification timestamp. - (param $mtim $timestamp) - ;;; A bitmask indicating which timestamps to adjust. - (param $fst_flags $fstflags) - (result $error (expected (error $errno))) - ) - - ;;; Read from a file descriptor, without using and updating the file descriptor's offset. - ;;; Note: This is similar to `preadv` in POSIX. - (@interface func (export "fd_pread") - (param $fd $fd) - ;;; List of scatter/gather vectors in which to store data. - (param $iovs $iovec_array) - ;;; The offset within the file at which to read. - (param $offset $filesize) - ;;; The number of bytes read. - (result $error (expected $size (error $errno))) - ) - - ;;; Return a description of the given preopened file descriptor. - (@interface func (export "fd_prestat_get") - (param $fd $fd) - ;;; The buffer where the description is stored. - (result $error (expected $prestat (error $errno))) - ) - - ;;; Return a description of the given preopened file descriptor. - (@interface func (export "fd_prestat_dir_name") - (param $fd $fd) - ;;; A buffer into which to write the preopened directory name. - (param $path (@witx pointer u8)) - (param $path_len $size) - (result $error (expected (error $errno))) - ) - - ;;; Write to a file descriptor, without using and updating the file descriptor's offset. - ;;; Note: This is similar to `pwritev` in POSIX. - (@interface func (export "fd_pwrite") - (param $fd $fd) - ;;; List of scatter/gather vectors from which to retrieve data. - (param $iovs $ciovec_array) - ;;; The offset within the file at which to write. - (param $offset $filesize) - ;;; The number of bytes written. - (result $error (expected $size (error $errno))) - ) - - ;;; Read from a file descriptor. - ;;; Note: This is similar to `readv` in POSIX. - (@interface func (export "fd_read") - (param $fd $fd) - ;;; List of scatter/gather vectors to which to store data. - (param $iovs $iovec_array) - ;;; The number of bytes read. - (result $error (expected $size (error $errno))) - ) - - ;;; Read directory entries from a directory. - ;;; When successful, the contents of the output buffer consist of a sequence of - ;;; directory entries. Each directory entry consists of a `dirent` object, - ;;; followed by `dirent::d_namlen` bytes holding the name of the directory - ;;; entry. - ;; - ;;; This function fills the output buffer as much as possible, potentially - ;;; truncating the last directory entry. This allows the caller to grow its - ;;; read buffer size in case it's too small to fit a single large directory - ;;; entry, or skip the oversized directory entry. - (@interface func (export "fd_readdir") - (param $fd $fd) - ;;; The buffer where directory entries are stored - (param $buf (@witx pointer u8)) - (param $buf_len $size) - ;;; The location within the directory to start reading - (param $cookie $dircookie) - ;;; The number of bytes stored in the read buffer. If less than the size of the read buffer, the end of the directory has been reached. - (result $error (expected $size (error $errno))) - ) - - ;;; Atomically replace a file descriptor by renumbering another file descriptor. - ;; - ;;; Due to the strong focus on thread safety, this environment does not provide - ;;; a mechanism to duplicate or renumber a file descriptor to an arbitrary - ;;; number, like `dup2()`. This would be prone to race conditions, as an actual - ;;; file descriptor with the same number could be allocated by a different - ;;; thread at the same time. - ;; - ;;; This function provides a way to atomically renumber file descriptors, which - ;;; would disappear if `dup2()` were to be removed entirely. - (@interface func (export "fd_renumber") - (param $fd $fd) - ;;; The file descriptor to overwrite. - (param $to $fd) - (result $error (expected (error $errno))) - ) - - ;;; Move the offset of a file descriptor. - ;;; Note: This is similar to `lseek` in POSIX. - (@interface func (export "fd_seek") - (param $fd $fd) - ;;; The number of bytes to move. - (param $offset $filedelta) - ;;; The base from which the offset is relative. - (param $whence $whence) - ;;; The new offset of the file descriptor, relative to the start of the file. - (result $error (expected $filesize (error $errno))) - ) - - ;;; Synchronize the data and metadata of a file to disk. - ;;; Note: This is similar to `fsync` in POSIX. - (@interface func (export "fd_sync") - (param $fd $fd) - (result $error (expected (error $errno))) - ) - - ;;; Return the current offset of a file descriptor. - ;;; Note: This is similar to `lseek(fd, 0, SEEK_CUR)` in POSIX. - (@interface func (export "fd_tell") - (param $fd $fd) - ;;; The current offset of the file descriptor, relative to the start of the file. - (result $error (expected $filesize (error $errno))) - ) - - ;;; Write to a file descriptor. - ;;; Note: This is similar to `writev` in POSIX. - (@interface func (export "fd_write") - (param $fd $fd) - ;;; List of scatter/gather vectors from which to retrieve data. - (param $iovs $ciovec_array) - (result $error (expected $size (error $errno))) - ) - - ;;; Create a directory. - ;;; Note: This is similar to `mkdirat` in POSIX. - (@interface func (export "path_create_directory") - (param $fd $fd) - ;;; The path at which to create the directory. - (param $path string) - (result $error (expected (error $errno))) - ) - - ;;; Return the attributes of a file or directory. - ;;; Note: This is similar to `stat` in POSIX. - (@interface func (export "path_filestat_get") - (param $fd $fd) - ;;; Flags determining the method of how the path is resolved. - (param $flags $lookupflags) - ;;; The path of the file or directory to inspect. - (param $path string) - ;;; The buffer where the file's attributes are stored. - (result $error (expected $filestat (error $errno))) - ) - - ;;; Adjust the timestamps of a file or directory. - ;;; Note: This is similar to `utimensat` in POSIX. - (@interface func (export "path_filestat_set_times") - (param $fd $fd) - ;;; Flags determining the method of how the path is resolved. - (param $flags $lookupflags) - ;;; The path of the file or directory to operate on. - (param $path string) - ;;; The desired values of the data access timestamp. - (param $atim $timestamp) - ;;; The desired values of the data modification timestamp. - (param $mtim $timestamp) - ;;; A bitmask indicating which timestamps to adjust. - (param $fst_flags $fstflags) - (result $error (expected (error $errno))) - ) - - ;;; Create a hard link. - ;;; Note: This is similar to `linkat` in POSIX. - (@interface func (export "path_link") - (param $old_fd $fd) - ;;; Flags determining the method of how the path is resolved. - (param $old_flags $lookupflags) - ;;; The source path from which to link. - (param $old_path string) - ;;; The working directory at which the resolution of the new path starts. - (param $new_fd $fd) - ;;; The destination path at which to create the hard link. - (param $new_path string) - (result $error (expected (error $errno))) - ) - - ;;; Open a file or directory. - ;; - ;;; The returned file descriptor is not guaranteed to be the lowest-numbered - ;;; file descriptor not currently open; it is randomized to prevent - ;;; applications from depending on making assumptions about indexes, since this - ;;; is error-prone in multi-threaded contexts. The returned file descriptor is - ;;; guaranteed to be less than 2**31. - ;; - ;;; Note: This is similar to `openat` in POSIX. - (@interface func (export "path_open") - (param $fd $fd) - ;;; Flags determining the method of how the path is resolved. - (param $dirflags $lookupflags) - ;;; The relative path of the file or directory to open, relative to the - ;;; `path_open::fd` directory. - (param $path string) - ;;; The method by which to open the file. - (param $oflags $oflags) - ;;; The initial rights of the newly created file descriptor. The - ;;; implementation is allowed to return a file descriptor with fewer rights - ;;; than specified, if and only if those rights do not apply to the type of - ;;; file being opened. - ;; - ;;; The *base* rights are rights that will apply to operations using the file - ;;; descriptor itself, while the *inheriting* rights are rights that apply to - ;;; file descriptors derived from it. - (param $fs_rights_base $rights) - (param $fs_rights_inheriting $rights) - (param $fdflags $fdflags) - ;;; The file descriptor of the file that has been opened. - (result $error (expected $fd (error $errno))) - ) - - ;;; Read the contents of a symbolic link. - ;;; Note: This is similar to `readlinkat` in POSIX. - (@interface func (export "path_readlink") - (param $fd $fd) - ;;; The path of the symbolic link from which to read. - (param $path string) - ;;; The buffer to which to write the contents of the symbolic link. - (param $buf (@witx pointer u8)) - (param $buf_len $size) - ;;; The number of bytes placed in the buffer. - (result $error (expected $size (error $errno))) - ) - - ;;; Remove a directory. - ;;; Return `errno::notempty` if the directory is not empty. - ;;; Note: This is similar to `unlinkat(fd, path, AT_REMOVEDIR)` in POSIX. - (@interface func (export "path_remove_directory") - (param $fd $fd) - ;;; The path to a directory to remove. - (param $path string) - (result $error (expected (error $errno))) - ) - - ;;; Rename a file or directory. - ;;; Note: This is similar to `renameat` in POSIX. - (@interface func (export "path_rename") - (param $fd $fd) - ;;; The source path of the file or directory to rename. - (param $old_path string) - ;;; The working directory at which the resolution of the new path starts. - (param $new_fd $fd) - ;;; The destination path to which to rename the file or directory. - (param $new_path string) - (result $error (expected (error $errno))) - ) - - ;;; Create a symbolic link. - ;;; Note: This is similar to `symlinkat` in POSIX. - (@interface func (export "path_symlink") - ;;; The contents of the symbolic link. - (param $old_path string) - (param $fd $fd) - ;;; The destination path at which to create the symbolic link. - (param $new_path string) - (result $error (expected (error $errno))) - ) - - - ;;; Unlink a file. - ;;; Return `errno::isdir` if the path refers to a directory. - ;;; Note: This is similar to `unlinkat(fd, path, 0)` in POSIX. - (@interface func (export "path_unlink_file") - (param $fd $fd) - ;;; The path to a file to unlink. - (param $path string) - (result $error (expected (error $errno))) - ) - - ;;; Concurrently poll for the occurrence of a set of events. - (@interface func (export "poll_oneoff") - ;;; The events to which to subscribe. - (param $in (@witx const_pointer $subscription)) - ;;; The events that have occurred. - (param $out (@witx pointer $event)) - ;;; Both the number of subscriptions and events. - (param $nsubscriptions $size) - ;;; The number of events stored. - (result $error (expected $size (error $errno))) - ) - - ;;; Terminate the process normally. An exit code of 0 indicates successful - ;;; termination of the program. The meanings of other values is dependent on - ;;; the environment. - (@interface func (export "proc_exit") - ;;; The exit code returned by the process. - (param $rval $exitcode) - (@witx noreturn) - ) - - ;;; Send a signal to the process of the calling thread. - ;;; Note: This is similar to `raise` in POSIX. - (@interface func (export "proc_raise") - ;;; The signal condition to trigger. - (param $sig $signal) - (result $error (expected (error $errno))) - ) - - ;;; Temporarily yield execution of the calling thread. - ;;; Note: This is similar to `sched_yield` in POSIX. - (@interface func (export "sched_yield") - (result $error (expected (error $errno))) - ) - - ;;; Write high-quality random data into a buffer. - ;;; This function blocks when the implementation is unable to immediately - ;;; provide sufficient high-quality random data. - ;;; This function may execute slowly, so when large mounts of random data are - ;;; required, it's advisable to use this function to seed a pseudo-random - ;;; number generator, rather than to provide the random data directly. - (@interface func (export "random_get") - ;;; The buffer to fill with random data. - (param $buf (@witx pointer u8)) - (param $buf_len $size) - (result $error (expected (error $errno))) - ) - - ;;; Receive a message from a socket. - ;;; Note: This is similar to `recv` in POSIX, though it also supports reading - ;;; the data into multiple buffers in the manner of `readv`. - (@interface func (export "sock_recv") - (param $fd $fd) - ;;; List of scatter/gather vectors to which to store data. - (param $ri_data $iovec_array) - ;;; Message flags. - (param $ri_flags $riflags) - ;;; Number of bytes stored in ri_data and message flags. - (result $error (expected (tuple $size $roflags) (error $errno))) - ) - - ;;; Send a message on a socket. - ;;; Note: This is similar to `send` in POSIX, though it also supports writing - ;;; the data from multiple buffers in the manner of `writev`. - (@interface func (export "sock_send") - (param $fd $fd) - ;;; List of scatter/gather vectors to which to retrieve data - (param $si_data $ciovec_array) - ;;; Message flags. - (param $si_flags $siflags) - ;;; Number of bytes transmitted. - (result $error (expected $size (error $errno))) - ) - - ;;; Shut down socket send and receive channels. - ;;; Note: This is similar to `shutdown` in POSIX. - (@interface func (export "sock_shutdown") - (param $fd $fd) - ;;; Which channels on the socket to shut down. - (param $how $sdflags) - (result $error (expected (error $errno))) - ) -) diff --git a/tests/runtime/buffers/exports.wit b/tests/runtime/buffers/exports.wit deleted file mode 100644 index b2bf2fcf9..000000000 --- a/tests/runtime/buffers/exports.wit +++ /dev/null @@ -1,46 +0,0 @@ -test-imports: function() - -variant buffer-in-variant { - a(push-buffer), - b(pull-buffer), - c(push-buffer), - d(pull-buffer), -} - -record buffer-in-record { - a: push-buffer, - b: pull-buffer, - c: push-buffer, - d: pull-buffer, - e: buffer-in-variant, -} - -type param-in-buffer-u8 = push-buffer -type param-out-buffer-u8 = pull-buffer -type param-in-buffer-bool = push-buffer -type param-out-buffer-bool = pull-buffer - - -/* TODO -;; =========================================== -;; buffers -;; =========================================== -(export "buffer-u8" (func (param $a (in-buffer u8)) (param $b (out-buffer u8)) (result $r u32))) -(export "buffer-u32" (func (param $a (in-buffer u32)) (param $b (out-buffer u32)) (result $r u32))) -(export "buffer-bool" (func (param $a (in-buffer bool)) (param $b (out-buffer bool)) (result $r u32))) -(export "buffer-string" (func (param $a (in-buffer string)) (param $b (out-buffer string)) (result $r u32))) -(export "buffer-list-bool" (func (param $a (in-buffer (list bool))) (param $b (out-buffer (list bool))) (result $r u32))) -;; TODO: somehow get this working in wasmtime -;;(export "buffer-buffer-bool" (func (param $a (in-buffer (in-buffer bool))))) -(export "buffer-mutable1" (func (param $a (list (in-buffer bool))))) -(export "buffer-mutable2" (func (param $a (list (out-buffer u8))) (result $r u32))) -(export "buffer-mutable3" (func (param $a (list (out-buffer bool))) (result $r u32))) -(export "buffer-in-record" (func (param $a $buffer-in-record))) -(export "buffer-typedef" (func - (param $a $param-in-buffer-u8) - (param $b $param-out-buffer-u8) - (param $c $param-in-buffer-bool) - (param $d $param-out-buffer-bool) -)) -*/ - diff --git a/tests/runtime/buffers/host.py b/tests/runtime/buffers/host.py deleted file mode 100644 index 311234f6c..000000000 --- a/tests/runtime/buffers/host.py +++ /dev/null @@ -1,91 +0,0 @@ -from exports.bindings import Exports -from imports.bindings import add_imports_to_linker, Imports -from typing import Tuple, List -import exports.bindings as e -import imports.bindings as i -import sys -import wasmtime - -class MyImports: - def buffer_u8(self, a: i.PullBuffer[int], b: i.PushBuffer[int]) -> int: - assert(len(a) == 1) - assert(len(b) == 10) - assert(a.pull() == 0) - assert(a.pull() == None) - b.push(1) - b.push(2) - b.push(3) - return 3 - - def buffer_u32(self, a: i.PullBuffer[int], b: i.PushBuffer[int]) -> int: - assert(len(a) == 1) - assert(len(b) == 10) - assert(a.pull() == 0) - assert(a.pull() == None) - b.push(1) - b.push(2) - b.push(3) - return 3 - - def buffer_bool(self, a: i.PullBuffer[bool], b: i.PushBuffer[bool]) -> int: - assert(len(a) <= len(b)) - n = 0 - while True: - val = a.pull() - if val is None: - break - b.push(not val) - n += 1 - return n - - def buffer_mutable1(self, x: List[i.PullBuffer[bool]]) -> None: - assert(len(x) == 1) - assert(len(x[0]) == 5) - assert(x[0].pull() == True) - assert(x[0].pull() == False) - assert(x[0].pull() == True) - assert(x[0].pull() == True) - assert(x[0].pull() == False) - assert(x[0].pull() == None) - - def buffer_mutable2(self, a: List[i.PushBuffer[int]]) -> int: - assert(len(a) == 1) - assert(len(a[0]) > 4) - a[0].push(1) - a[0].push(2) - a[0].push(3) - a[0].push(4) - return 4 - - def buffer_mutable3(self, a: List[i.PushBuffer[bool]]) -> int: - assert(len(a) == 1) - assert(len(a[0]) > 3) - a[0].push(False) - a[0].push(True) - a[0].push(False) - return 3 - - def buffer_in_record(self, a: i.BufferInRecord) -> None: - pass - - def buffer_typedef(self, a: i.ParamInBufferU8, b: i.ParamOutBufferU8, c: i.ParamInBufferBool, d: i.ParamOutBufferBool) -> None: - pass - -def run(wasm_file: str) -> None: - store = wasmtime.Store() - module = wasmtime.Module.from_file(store.engine, wasm_file) - linker = wasmtime.Linker(store.engine) - linker.define_wasi() - wasi = wasmtime.WasiConfig() - wasi.inherit_stdout() - wasi.inherit_stderr() - store.set_wasi(wasi) - - imports = MyImports() - add_imports_to_linker(linker, store, imports) - wasm = Exports(store, linker, module) - - wasm.test_imports(store) - -if __name__ == '__main__': - run(sys.argv[1]) diff --git a/tests/runtime/buffers/host.rs b/tests/runtime/buffers/host.rs deleted file mode 100644 index 0d24f76e6..000000000 --- a/tests/runtime/buffers/host.rs +++ /dev/null @@ -1,194 +0,0 @@ -wit_bindgen_wasmtime::export!("../../tests/runtime/buffers/imports.wit"); - -use anyhow::Result; -use imports::*; -use wit_bindgen_wasmtime::exports::{PullBuffer, PushBuffer}; -use wit_bindgen_wasmtime::Le; - -#[derive(Default)] -pub struct MyImports; - -impl Imports for MyImports { - fn buffer_u8(&mut self, in_: &[u8], out: &mut [u8]) -> u32 { - assert_eq!(in_, [0]); - assert_eq!(out.len(), 10); - out[0] = 1; - out[1] = 2; - out[2] = 3; - 3 - } - - fn buffer_u32(&mut self, in_: &[Le], out: &mut [Le]) -> u32 { - assert_eq!(in_.len(), 1); - assert_eq!(in_[0].get(), 0); - assert_eq!(out.len(), 10); - out[0].set(1); - out[1].set(2); - out[2].set(3); - 3 - } - - fn buffer_bool(&mut self, in_: PullBuffer<'_, bool>, mut out: PushBuffer<'_, bool>) -> u32 { - assert!(in_.len() <= out.capacity()); - let len = in_.len(); - for item in in_.iter() { - let item = item.unwrap(); - out.write(Some(!item)).unwrap(); - } - len as u32 - } - - // fn buffer_string( - // &mut self, - // in_: PullBuffer<'_, GuestPtr<'_, str>>, - // mut out: PushBuffer<'_, String>, - // ) -> u32 { - // assert!(in_.len() < out.capacity()); - // let len = in_.len(); - // for item in in_.iter().unwrap() { - // let item = item.unwrap(); - // let s = item.borrow().unwrap(); - // out.write(Some(s.to_uppercase())).unwrap(); - // } - // len as u32 - // } - - // fn buffer_list_bool( - // &mut self, - // in_: PullBuffer<'_, Vec>, - // mut out: PushBuffer<'_, Vec>, - // ) -> u32 { - // assert!(in_.len() < out.capacity()); - // let len = in_.len(); - // for item in in_.iter().unwrap() { - // let item = item.unwrap(); - // out.write(Some(item.into_iter().map(|b| !b).collect())) - // .unwrap(); - // } - // len as u32 - // } - - // fn buffer_buffer_bool(&mut self, in_: PullBuffer<'_, PullBuffer<'_, bool>>) { - // assert_eq!(in_.len(), 1); - // let buf = in_.iter().unwrap().next().unwrap().unwrap(); - // assert_eq!(buf.len(), 5); - // assert_eq!( - // buf.iter() - // .unwrap() - // .collect::, _>>() - // .unwrap(), - // [true, false, true, true, false] - // ); - // } - - fn buffer_mutable1(&mut self, a: Vec>) { - assert_eq!(a.len(), 1); - assert_eq!(a[0].len(), 5); - assert_eq!( - a[0].iter().collect::, _>>().unwrap(), - [true, false, true, true, false] - ); - } - - fn buffer_mutable2(&mut self, mut a: Vec<&mut [u8]>) -> u32 { - assert_eq!(a.len(), 1); - assert!(a[0].len() > 4); - a[0][..4].copy_from_slice(&[1, 2, 3, 4]); - return 4; - } - - fn buffer_mutable3(&mut self, mut a: Vec>) -> u32 { - assert_eq!(a.len(), 1); - assert!(a[0].capacity() > 3); - a[0].write([false, true, false].iter().copied()).unwrap(); - return 3; - } - - fn buffer_in_record(&mut self, _: BufferInRecord<'_>) {} - fn buffer_typedef( - &mut self, - _: ParamInBufferU8<'_>, - _: ParamOutBufferU8<'_>, - _: ParamInBufferBool<'_>, - _: ParamOutBufferBool<'_>, - ) { - } -} - -wit_bindgen_wasmtime::import!("../../tests/runtime/buffers/exports.wit"); - -fn run(wasm: &str) -> Result<()> { - use exports::*; - - let (exports, mut store) = crate::instantiate( - wasm, - |linker| imports::add_to_linker(linker, |cx| -> &mut MyImports { &mut cx.imports }), - |store, module, linker| Exports::instantiate(store, module, linker, |cx| &mut cx.exports), - )?; - - exports.test_imports(&mut store)?; - // fn buffers(wasm: &Wasm) -> Result<()> { - // let mut out = [0; 10]; - // let n = wasm.buffer_u8(&[0u8], &mut out)? as usize; - // assert_eq!(n, 3); - // assert_eq!(&out[..n], [1, 2, 3]); - // assert!(out[n..].iter().all(|x| *x == 0)); - - // let mut out = [0; 10]; - // let n = wasm.buffer_u32(&[0], &mut out)? as usize; - // assert_eq!(n, 3); - // assert_eq!(&out[..n], [1, 2, 3]); - // assert!(out[n..].iter().all(|x| *x == 0)); - - // assert_eq!(wasm.buffer_bool(&mut iter::empty(), &mut Vec::new())?, 0); - // assert_eq!(wasm.buffer_string(&mut iter::empty(), &mut Vec::new())?, 0); - // assert_eq!( - // wasm.buffer_list_bool(&mut iter::empty(), &mut Vec::new())?, - // 0 - // ); - - // let mut bools = [true, false, true].iter().copied(); - // let mut out = Vec::with_capacity(4); - // let n = wasm.buffer_bool(&mut bools, &mut out)?; - // assert_eq!(n, 3); - // assert_eq!(out, [false, true, false]); - - // let mut strings = ["foo", "bar", "baz"].iter().copied(); - // let mut out = Vec::with_capacity(3); - // let n = wasm.buffer_string(&mut strings, &mut out)?; - // assert_eq!(n, 3); - // assert_eq!(out, ["FOO", "BAR", "BAZ"]); - - // let a = &[true, false, true][..]; - // let b = &[false, false][..]; - // let list = [a, b]; - // let mut lists = list.iter().copied(); - // let mut out = Vec::with_capacity(4); - // let n = wasm.buffer_list_bool(&mut lists, &mut out)?; - // assert_eq!(n, 2); - // assert_eq!(out, [vec![false, true, false], vec![true, true]]); - - // let a = [true, false, true, true, false]; - // // let mut bools = a.iter().copied(); - // // let mut list = [&mut bools as &mut dyn ExactSizeIterator]; - // // let mut buffers = list.iter_mut().map(|b| &mut **b); - // // wasm.buffer_buffer_bool(&mut buffers)?; - - // let mut bools = a.iter().copied(); - // wasm.buffer_mutable1(&mut [&mut bools])?; - - // let mut dst = [0; 10]; - // let n = wasm.buffer_mutable2(&mut [&mut dst])? as usize; - // assert_eq!(n, 4); - // assert_eq!(&dst[..n], [1, 2, 3, 4]); - - // let mut out = Vec::with_capacity(10); - // let n = wasm.buffer_mutable3(&mut [&mut out])?; - // assert_eq!(n, 3); - // assert_eq!(out, [false, true, false]); - - // Ok(()) - // } - - Ok(()) -} diff --git a/tests/runtime/buffers/host.ts b/tests/runtime/buffers/host.ts deleted file mode 100644 index 35c3a12fe..000000000 --- a/tests/runtime/buffers/host.ts +++ /dev/null @@ -1,77 +0,0 @@ -import { addImportsToImports, Imports } from "./imports.js"; -import { Exports } from "./exports.js"; -import { getWasm, addWasiToImports } from "./helpers.js"; -// @ts-ignore -import * as assert from 'assert'; - -async function run() { - const importObj = {}; - const imports: Imports = { - bufferU8(x, out) { - assert.deepStrictEqual(Array.from(x), [0]); - assert.deepStrictEqual(out.length, 10); - out[0] = 1; - out[1] = 2; - out[2] = 3; - return 3; - }, - bufferU32(x, out) { - assert.deepStrictEqual(Array.from(x), [0]); - assert.deepStrictEqual(out.length, 10); - out[0] = 1; - out[1] = 2; - out[2] = 3; - return 3; - }, - bufferBool(x, out) { - assert.ok(x.length <= out.length); - let amt = 0; - while (true) { - const val = x.pull(); - if (val === undefined) - break; - out.push(!val); - amt += 1; - } - return amt; - }, - bufferMutable1(x) { - assert.strictEqual(x.length, 1); - assert.strictEqual(x[0].length, 5); - assert.strictEqual(x[0].pull(), true); - assert.strictEqual(x[0].pull(), false); - assert.strictEqual(x[0].pull(), true); - assert.strictEqual(x[0].pull(), true); - assert.strictEqual(x[0].pull(), false); - assert.strictEqual(x[0].pull(), undefined); - }, - bufferMutable2(x) { - assert.strictEqual(x.length, 1); - assert.ok(x[0].length > 4); - x[0].set([1, 2, 3, 4]); - return 4; - }, - bufferMutable3(x) { - assert.strictEqual(x.length, 1); - assert.ok(x[0].length > 3); - x[0].push(false); - x[0].push(true); - x[0].push(false); - return 3; - }, - bufferInRecord(x) { }, - bufferTypedef(a, b, c, d) {}, - }; - let instance: WebAssembly.Instance; - addImportsToImports(importObj, imports, name => instance.exports[name]); - const wasi = addWasiToImports(importObj); - - const wasm = new Exports(); - await wasm.instantiate(getWasm(), importObj); - wasi.start(wasm.instance); - instance = wasm.instance; - - wasm.testImports(); -} - -await run() diff --git a/tests/runtime/buffers/imports.wit b/tests/runtime/buffers/imports.wit deleted file mode 100644 index e2c04ec6a..000000000 --- a/tests/runtime/buffers/imports.wit +++ /dev/null @@ -1,36 +0,0 @@ -buffer-u8: function(a: pull-buffer, b: push-buffer) -> u32 -buffer-u32: function(a: pull-buffer, b: push-buffer) -> u32 -buffer-bool: function(a: pull-buffer, b: push-buffer) -> u32 - -/* -(export "buffer-string" (func (param $a (in-buffer string)) (param $b (out-buffer string)) (result $r u32))) -(export "buffer-list-bool" (func (param $a (in-buffer (list bool))) (param $b (out-buffer (list bool))) (result $r u32))) -(export "buffer-buffer-bool" (func (param $a (in-buffer (in-buffer bool))))) -*/ - -buffer-mutable1: function(a: list>) -buffer-mutable2: function(a: list>) -> u32 -buffer-mutable3: function(a: list>) -> u32 - -variant buffer-in-variant { - a(push-buffer), - b(pull-buffer), - c(push-buffer), - d(pull-buffer), -} - -record buffer-in-record { - a: push-buffer, - b: pull-buffer, - c: push-buffer, - d: pull-buffer, - e: buffer-in-variant, -} -buffer-in-record: function(a: buffer-in-record) - -type param-in-buffer-u8 = push-buffer -type param-out-buffer-u8 = pull-buffer -type param-in-buffer-bool = push-buffer -type param-out-buffer-bool = pull-buffer -buffer-typedef: function(a: param-in-buffer-u8, b: param-out-buffer-u8, c: param-in-buffer-bool, d: param-out-buffer-bool) - diff --git a/tests/runtime/buffers/wasm.c b/tests/runtime/buffers/wasm.c deleted file mode 100644 index 86c22a59d..000000000 --- a/tests/runtime/buffers/wasm.c +++ /dev/null @@ -1,132 +0,0 @@ -#include -#include -#include -#include - -void exports_test_imports() { - { - imports_push_buffer_u8_t push; - uint8_t out[10]; - memset(out, 0, sizeof(out)); - push.is_handle = 0; - push.ptr = out; - push.len = 10; - - imports_pull_buffer_u8_t pull; - pull.is_handle = 0; - uint8_t in[1]; - in[0] = 0; - pull.ptr = in; - pull.len = 1; - uint32_t len = imports_buffer_u8(&pull, &push); - assert(len == 3); - assert(memcmp(push.ptr, "\x01\x02\x03", 3) == 0); - assert(memcmp(&push.ptr[3], "\0\0\0\0\0\0\0", 7) == 0); - } - - { - imports_push_buffer_u32_t push; - uint32_t out[10]; - memset(out, 0, sizeof(out)); - push.is_handle = 0; - push.ptr = out; - push.len = 10; - - imports_pull_buffer_u32_t pull; - pull.is_handle = 0; - uint32_t in[1]; - in[0] = 0; - pull.ptr = in; - pull.len = 1; - uint32_t len = imports_buffer_u32(&pull, &push); - assert(len == 3); - assert(push.ptr[0] == 1); - assert(push.ptr[1] == 2); - assert(push.ptr[2] == 3); - assert(push.ptr[3] == 0); - assert(push.ptr[4] == 0); - assert(push.ptr[5] == 0); - assert(push.ptr[6] == 0); - assert(push.ptr[7] == 0); - assert(push.ptr[8] == 0); - assert(push.ptr[9] == 0); - } - - { - imports_push_buffer_bool_t push; - imports_pull_buffer_bool_t pull; - push.is_handle = 0; - push.len = 0; - pull.is_handle = 0; - pull.len = 0; - uint32_t len = imports_buffer_bool(&pull, &push); - assert(len == 0); - } - - { - imports_push_buffer_bool_t push; - bool push_ptr[10]; - push.is_handle = 0; - push.len = 10; - push.ptr = push_ptr; - - imports_pull_buffer_bool_t pull; - bool pull_ptr[3] = {true, false, true}; - pull.is_handle = 0; - pull.len = 3; - pull.ptr = pull_ptr; - - uint32_t len = imports_buffer_bool(&pull, &push); - assert(len == 3); - assert(push_ptr[0] == false); - assert(push_ptr[1] == true); - assert(push_ptr[2] == false); - } - - { - imports_pull_buffer_bool_t pull; - bool pull_ptr[5] = {true, false, true, true, false}; - pull.is_handle = 0; - pull.len = 5; - pull.ptr = pull_ptr; - - imports_list_pull_buffer_bool_t a; - a.len = 1; - a.ptr = &pull; - imports_buffer_mutable1(&a); - } - - { - imports_push_buffer_u8_t push; - uint8_t push_ptr[10]; - push.is_handle = 0; - push.len = 10; - push.ptr = push_ptr; - - imports_list_push_buffer_u8_t a; - a.len = 1; - a.ptr = &push; - assert(imports_buffer_mutable2(&a) == 4); - assert(push_ptr[0] == 1); - assert(push_ptr[1] == 2); - assert(push_ptr[2] == 3); - assert(push_ptr[3] == 4); - } - - { - imports_push_buffer_bool_t push; - bool push_ptr[10]; - push.is_handle = 0; - push.len = 10; - push.ptr = push_ptr; - - imports_list_push_buffer_bool_t a; - a.len = 1; - a.ptr = &push; - assert(imports_buffer_mutable3(&a) == 3); - assert(push_ptr[0] == false); - assert(push_ptr[1] == true); - assert(push_ptr[2] == false); - } -} - diff --git a/tests/runtime/buffers/wasm.rs b/tests/runtime/buffers/wasm.rs deleted file mode 100644 index a5db7a69f..000000000 --- a/tests/runtime/buffers/wasm.rs +++ /dev/null @@ -1,205 +0,0 @@ -wit_bindgen_rust::import!("../../tests/runtime/buffers/imports.wit"); -wit_bindgen_rust::export!("../../tests/runtime/buffers/exports.wit"); - -use std::iter; - -struct Exports; - -impl exports::Exports for Exports { - fn test_imports() { - use imports::*; - use wit_bindgen_rust::imports::{PullBuffer, PushBuffer}; - - let _guard = test_rust_wasm::guard(); - - let mut out = [0; 10]; - let n = buffer_u8(&[0u8], &mut out) as usize; - assert_eq!(n, 3); - assert_eq!(&out[..n], [1, 2, 3]); - assert!(out[n..].iter().all(|x| *x == 0)); - - let mut out = [0; 10]; - let n = buffer_u32(&[0], &mut out) as usize; - assert_eq!(n, 3); - assert_eq!(&out[..n], [1, 2, 3]); - assert!(out[n..].iter().all(|x| *x == 0)); - - let mut space1 = [0; 200]; - let mut space2 = [0; 200]; - - assert_eq!( - buffer_bool( - &mut PullBuffer::new(&mut space1, &mut iter::empty()), - &mut PushBuffer::new(&mut space2) - ), - 0 - ); - // assert_eq!( - // buffer_string( - // &mut PullBuffer::new(&mut space1, &mut iter::empty()), - // &mut PushBuffer::new(&mut space2) - // ), - // 0 - // ); - // assert_eq!( - // buffer_list_bool( - // &mut PullBuffer::new(&mut space1, &mut iter::empty()), - // &mut PushBuffer::new(&mut space2) - // ), - // 0 - // ); - - let mut bools = [true, false, true].iter().copied(); - let mut out = PushBuffer::new(&mut space2); - let n = buffer_bool(&mut PullBuffer::new(&mut space1, &mut bools), &mut out); - unsafe { - assert_eq!(n, 3); - assert_eq!(out.into_iter(3).collect::>(), [false, true, false]); - } - - // let mut strings = ["foo", "bar", "baz"].iter().copied(); - // let mut out = PushBuffer::new(&mut space2); - // let n = buffer_string(&mut PullBuffer::new(&mut space1, &mut strings), &mut out); - // unsafe { - // assert_eq!(n, 3); - // assert_eq!(out.into_iter(3).collect::>(), ["FOO", "BAR", "BAZ"]); - // } - - // let a = &[true, false, true][..]; - // let b = &[false, false][..]; - // let list = [a, b]; - // let mut lists = list.iter().copied(); - // let mut out = PushBuffer::new(&mut space2); - // let n = buffer_list_bool(&mut PullBuffer::new(&mut space1, &mut lists), &mut out); - // unsafe { - // assert_eq!(n, 2); - // assert_eq!( - // out.into_iter(2).collect::>(), - // [vec![false, true, false], vec![true, true]] - // ); - // } - - let a = [true, false, true, true, false]; - // let mut bools = a.iter().copied(); - // let mut b = PullBuffer::new(&mut space2, &mut bools); - // let mut list = [&mut b]; - // let mut buffers = &mut list.iter_mut().map(|b| &mut **b); - // buffer_buffer_bool(&mut PullBuffer::new(&mut space1, &mut buffers)); - - let mut bools = a.iter().copied(); - buffer_mutable1(&mut [&mut PullBuffer::new(&mut space1, &mut bools)]); - - let n = buffer_mutable2(&mut [&mut space2]) as usize; - assert_eq!(n, 4); - assert_eq!(&space2[..n], [1, 2, 3, 4]); - - let mut out = PushBuffer::new(&mut space1); - let n = buffer_mutable3(&mut [&mut out]); - unsafe { - assert_eq!(n, 3); - assert_eq!(out.into_iter(3).collect::>(), [false, true, false],); - } - } - - // fn buffer_u8( in_: InBufferRaw<'_, u8>, out: OutBufferRaw<'_, u8>) -> u32 { - // assert_eq!(in_.len(), 1); - // let mut input = [0]; - // in_.copy(&mut input); - // assert_eq!(input, [0]); - - // assert_eq!(out.capacity(), 10); - // out.write(&[1, 2, 3]); - // 3 - // } - - // fn buffer_u32( in_: InBufferRaw<'_, u32>, out: OutBufferRaw<'_, u32>) -> u32 { - // assert_eq!(in_.len(), 1); - // let mut input = [0]; - // in_.copy(&mut input); - // assert_eq!(input, [0]); - - // assert_eq!(out.capacity(), 10); - // out.write(&[1, 2, 3]); - // 3 - // } - - // fn buffer_bool( in_: InBuffer<'_, bool>, out: OutBuffer<'_, bool>) -> u32 { - // assert!(in_.len() <= out.capacity()); - // let len = in_.len(); - // let mut storage = vec![0; in_.len() * in_.element_size()]; - // let items = in_.iter(&mut storage).map(|b| !b).collect::>(); - // out.write(&mut storage, items.into_iter()); - // len as u32 - // } - - // fn buffer_string( in_: InBuffer<'_, String>, out: OutBuffer<'_, String>) -> u32 { - // assert!(in_.len() <= out.capacity()); - // let len = in_.len(); - // let mut storage = vec![0; in_.len() * in_.element_size()]; - // let items = in_ - // .iter(&mut storage) - // .map(|s| s.to_uppercase()) - // .collect::>(); - // out.write(&mut storage, items.into_iter()); - // len as u32 - // } - - // fn buffer_list_bool( in_: InBuffer<'_, Vec>, out: OutBuffer<'_, Vec>) -> u32 { - // assert!(in_.len() <= out.capacity()); - // let len = in_.len(); - // let mut storage = vec![0; in_.len() * in_.element_size()]; - // let items = in_ - // .iter(&mut storage) - // .map(|s| s.into_iter().map(|b| !b).collect::>()) - // .collect::>(); - // out.write(&mut storage, items.into_iter()); - // len as u32 - // } - - // // fn buffer_buffer_bool( in_: InBuffer<'_, InBuffer<'_, bool>>) { - // // assert_eq!(in_.len(), 1); - // // let mut storage = vec![0; in_.len() * in_.element_size()]; - // // let buf = in_.iter(&mut storage).next().unwrap(); - // // assert_eq!(buf.len(), 5); - // // let mut storage2 = vec![0; buf.len() * buf.element_size()]; - // // assert_eq!( - // // buf.iter(&mut storage2).collect::>(), - // // [true, false, true, true, false] - // // ); - // // } - - // fn buffer_mutable1( a: Vec>) { - // assert_eq!(a.len(), 1); - // assert_eq!(a[0].len(), 5); - // let mut storage = vec![0; a[0].len() * a[0].element_size()]; - // assert_eq!( - // a[0].iter(&mut storage).collect::>(), - // [true, false, true, true, false] - // ); - // } - - // fn buffer_mutable2( a: Vec>) -> u32 { - // assert_eq!(a.len(), 1); - // assert!(a[0].capacity() > 4); - // a[0].write(&[1, 2, 3, 4]); - // return 4; - // } - - // fn buffer_mutable3( a: Vec>) -> u32 { - // assert_eq!(a.len(), 1); - // assert!(a[0].capacity() > 3); - // let mut storage = [0; 200]; - // a[0].write(&mut storage, [false, true, false].iter().copied()); - // return 3; - // } - - // fn buffer_in_record( _: BufferInRecord<'_>) {} - // fn buffer_typedef( - // - // _: ParamInBufferU8<'_>, - // _: ParamOutBufferU8<'_>, - // _: ParamInBufferBool<'_>, - // _: ParamOutBufferBool<'_>, - // ) { - // } -}