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<'_>, - // ) { - // } -}