diff --git a/crates/cli-support/src/js/binding.rs b/crates/cli-support/src/js/binding.rs index f79936e1985..d5ed01363ad 100644 --- a/crates/cli-support/src/js/binding.rs +++ b/crates/cli-support/src/js/binding.rs @@ -704,28 +704,34 @@ fn instruction( } } - Instruction::IntToWasm { input, .. } => { + Instruction::Int32ToWasm => { let val = js.pop(); - if matches!( - input, - AdapterType::I64 | AdapterType::S64 | AdapterType::U64 - ) { - js.assert_bigint(&val); + js.assert_number(&val); + js.push(val); + } + Instruction::WasmToInt32 { unsigned_32 } => { + let val = js.pop(); + if *unsigned_32 { + // When converting to a JS number we need to specially handle the `u32` + // case because if the high bit is set then it comes out as a negative + // number, but we want to switch that to an unsigned representation. + js.push(format!("{} >>> 0", val)) } else { - js.assert_number(&val); + js.push(val) } - js.push(val); } - // When converting to a JS number we need to specially handle the `u32` - // case because if the high bit is set then it comes out as a negative - // number, but we want to switch that to an unsigned representation. - Instruction::WasmToInt { output, .. } => { + Instruction::Int64ToWasm => { let val = js.pop(); - match output { - AdapterType::U32 | AdapterType::NonNull => js.push(format!("{} >>> 0", val)), - AdapterType::U64 => js.push(format!("BigInt.asUintN(64, {val})")), - _ => js.push(val), + js.assert_bigint(&val); + js.push(val); + } + Instruction::WasmToInt64 { unsigned } => { + let val = js.pop(); + if *unsigned { + js.push(format!("BigInt.asUintN(64, {val})")) + } else { + js.push(val) } } @@ -765,7 +771,7 @@ fn instruction( js.push(wasm_to_string_enum(name, &index)) } - Instruction::OptionWasmToStringEnum { name, .. } => { + Instruction::OptionWasmToStringEnum { name } => { // Since hole is currently variant_count+1 and the lookup is // ["a","b","c"][index], the lookup will implicitly return map // the hole to undefined, because OOB indexes will return undefined. diff --git a/crates/cli-support/src/js/mod.rs b/crates/cli-support/src/js/mod.rs index babbfc09d93..72b0273d71f 100644 --- a/crates/cli-support/src/js/mod.rs +++ b/crates/cli-support/src/js/mod.rs @@ -1,8 +1,8 @@ use crate::descriptor::VectorKind; use crate::intrinsic::Intrinsic; use crate::wit::{ - Adapter, AdapterId, AdapterJsImportKind, AdapterType, AuxExportedMethodKind, AuxReceiverKind, - AuxStringEnum, AuxValue, + Adapter, AdapterId, AdapterJsImportKind, AuxExportedMethodKind, AuxReceiverKind, AuxStringEnum, + AuxValue, }; use crate::wit::{AdapterKind, Instruction, InstructionData}; use crate::wit::{AuxEnum, AuxExport, AuxExportKind, AuxImport, AuxStruct}; @@ -3119,16 +3119,14 @@ __wbg_set_wasm(wasm);" // Conversions to Wasm integers are always supported since // they're coerced into i32/f32/f64 appropriately. - IntToWasm { .. } => {} + Int32ToWasm => {} + Int64ToWasm => {} - // Converts from Wasm to JS, however, only supports most - // integers. Converting into a u32 isn't supported because we + // Converting into a u32 isn't supported because we // need to generate glue to change the sign. - WasmToInt { - output: AdapterType::U32, - .. - } => return false, - WasmToInt { .. } => {} + WasmToInt32 { unsigned_32: false } => {} + // A Wasm `i64` is already a signed JS BigInt, so no glue needed. + WasmToInt64 { unsigned: false } => {} // JS spec automatically coerces boolean values to i32 of 0 or 1 // depending on true/false @@ -3279,7 +3277,6 @@ __wbg_set_wasm(wasm);" dtor, mutable, adapter, - nargs: _, } => { assert!(kind == AdapterJsImportKind::Normal); assert!(!variadic); diff --git a/crates/cli-support/src/wit/incoming.rs b/crates/cli-support/src/wit/incoming.rs index c0ad9ad34bf..0309ef8c9c9 100644 --- a/crates/cli-support/src/wit/incoming.rs +++ b/crates/cli-support/src/wit/incoming.rs @@ -43,7 +43,6 @@ impl InstructionBuilder<'_, '_> { } fn _incoming(&mut self, arg: &Descriptor) -> Result<(), Error> { - use walrus::ValType as WasmVT; match arg { Descriptor::Boolean => { self.instruction( @@ -82,14 +81,14 @@ impl InstructionBuilder<'_, '_> { &[AdapterType::I32], ); } - Descriptor::I8 => self.number(AdapterType::S8, WasmVT::I32), - Descriptor::U8 => self.number(AdapterType::U8, WasmVT::I32), - Descriptor::I16 => self.number(AdapterType::S16, WasmVT::I32), - Descriptor::U16 => self.number(AdapterType::U16, WasmVT::I32), - Descriptor::I32 => self.number(AdapterType::S32, WasmVT::I32), - Descriptor::U32 => self.number(AdapterType::U32, WasmVT::I32), - Descriptor::I64 => self.number(AdapterType::S64, WasmVT::I64), - Descriptor::U64 => self.number(AdapterType::U64, WasmVT::I64), + Descriptor::I8 => self.number_i32(AdapterType::S8), + Descriptor::U8 => self.number_i32(AdapterType::U8), + Descriptor::I16 => self.number_i32(AdapterType::S16), + Descriptor::U16 => self.number_i32(AdapterType::U16), + Descriptor::I32 => self.number_i32(AdapterType::S32), + Descriptor::U32 => self.number_i32(AdapterType::U32), + Descriptor::I64 => self.number_i64(AdapterType::S64), + Descriptor::U64 => self.number_i64(AdapterType::U64), Descriptor::I128 => { self.instruction( &[AdapterType::S128], @@ -115,10 +114,7 @@ impl InstructionBuilder<'_, '_> { Descriptor::Enum { name, .. } => { self.instruction( &[AdapterType::Enum(name.clone())], - Instruction::IntToWasm { - input: AdapterType::U32, - output: ValType::I32, - }, + Instruction::Int32ToWasm, &[AdapterType::I32], ); }, @@ -470,12 +466,11 @@ impl InstructionBuilder<'_, '_> { self.output.extend_from_slice(outputs); } - fn number(&mut self, input: AdapterType, output: walrus::ValType) { - let instr = Instruction::IntToWasm { - input: input.clone(), - output, - }; - self.instruction(&[input], instr, &[AdapterType::from_wasm(output).unwrap()]); + fn number_i32(&mut self, input: AdapterType) { + self.instruction(&[input], Instruction::Int32ToWasm, &[AdapterType::I32]); + } + fn number_i64(&mut self, input: AdapterType) { + self.instruction(&[input], Instruction::Int64ToWasm, &[AdapterType::I64]); } fn in_option_native(&mut self, wasm: ValType) { diff --git a/crates/cli-support/src/wit/mod.rs b/crates/cli-support/src/wit/mod.rs index 07a09860e0c..2f1d7f52691 100644 --- a/crates/cli-support/src/wit/mod.rs +++ b/crates/cli-support/src/wit/mod.rs @@ -197,7 +197,6 @@ impl<'a> Context<'a> { // aren't present in the signature but are present in the wasm // signature. let mut function = descriptor.function.clone(); - let nargs = function.arguments.len(); function.arguments.insert(0, Descriptor::I32); function.arguments.insert(0, Descriptor::I32); let adapter = self.table_element_adapter(descriptor.shim_idx, function)?; @@ -206,7 +205,6 @@ impl<'a> Context<'a> { AuxImport::Closure { dtor: descriptor.dtor_idx, mutable: descriptor.mutable, - nargs, adapter, }, ); diff --git a/crates/cli-support/src/wit/nonstandard.rs b/crates/cli-support/src/wit/nonstandard.rs index 4ff93298281..35f30a74497 100644 --- a/crates/cli-support/src/wit/nonstandard.rs +++ b/crates/cli-support/src/wit/nonstandard.rs @@ -241,11 +241,12 @@ pub enum AuxImport { /// This import is intended to manufacture a JS closure with the given /// signature and then return that back to Rust. Closure { - mutable: bool, // whether or not this was a `FnMut` closure - dtor: u32, // table element index of the destructor function - adapter: AdapterId, // the adapter which translates the types for this closure - #[allow(dead_code)] - nargs: usize, + /// whether or not this was a `FnMut` closure + mutable: bool, + /// table element index of the destructor function + dtor: u32, + /// the adapter which translates the types for this closure + adapter: AdapterId, }, /// This import is expected to be a shim that simply calls the `foo` method diff --git a/crates/cli-support/src/wit/outgoing.rs b/crates/cli-support/src/wit/outgoing.rs index 2e34dd0d324..ba15babf5c9 100644 --- a/crates/cli-support/src/wit/outgoing.rs +++ b/crates/cli-support/src/wit/outgoing.rs @@ -316,13 +316,10 @@ impl InstructionBuilder<'_, '_> { &[AdapterType::Enum(name.clone()).option()], ); } - Descriptor::StringEnum { name, hole, .. } => { + Descriptor::StringEnum { name, .. } => { self.instruction( &[AdapterType::I32], - Instruction::OptionWasmToStringEnum { - name: name.clone(), - hole: *hole, - }, + Instruction::OptionWasmToStringEnum { name: name.clone() }, &[AdapterType::StringEnum(name.clone()).option()], ); } @@ -554,14 +551,6 @@ impl InstructionBuilder<'_, '_> { Ok(()) } - fn outgoing_i32(&mut self, output: AdapterType) { - let instr = Instruction::WasmToInt { - input: walrus::ValType::I32, - output: output.clone(), - }; - self.instruction(&[AdapterType::I32], instr, &[output]); - } - fn outgoing_string_enum(&mut self, name: &str) { self.instruction( &[AdapterType::I32], @@ -572,10 +561,15 @@ impl InstructionBuilder<'_, '_> { ); } + fn outgoing_i32(&mut self, output: AdapterType) { + let instr = Instruction::WasmToInt32 { + unsigned_32: output == AdapterType::U32 || output == AdapterType::NonNull, + }; + self.instruction(&[AdapterType::I32], instr, &[output]); + } fn outgoing_i64(&mut self, output: AdapterType) { - let instr = Instruction::WasmToInt { - input: walrus::ValType::I64, - output: output.clone(), + let instr = Instruction::WasmToInt64 { + unsigned: output == AdapterType::U64, }; self.instruction(&[AdapterType::I64], instr, &[output]); } diff --git a/crates/cli-support/src/wit/standard.rs b/crates/cli-support/src/wit/standard.rs index e34866d2609..b0b1cb6832e 100644 --- a/crates/cli-support/src/wit/standard.rs +++ b/crates/cli-support/src/wit/standard.rs @@ -137,17 +137,19 @@ pub enum Instruction { size: u32, }, - /// Pops a typed integer (`u8`, `s16`, etc.) and pushes a plain Wasm `i32` or `i64` equivalent. - IntToWasm { - input: AdapterType, - #[allow(dead_code)] - output: walrus::ValType, + /// Pops a 32/16/8-bit integer (`u8`, `s16`, etc.) and pushes a Wasm `i32`. + Int32ToWasm, + /// Pops a Wasm `i32` and pushes a 32-bit integer. + WasmToInt32 { + /// Whether the integer represents an unsigned 32-bit value. + unsigned_32: bool, }, - /// Pops a Wasm `i32` or `i64` and pushes a typed integer (`u8`, `s16`, etc.) equivalent. - WasmToInt { - #[allow(dead_code)] - input: walrus::ValType, - output: AdapterType, + + /// Pops a 64-bit integer and pushes a Wasm `i64`. + Int64ToWasm, + /// Pops a Wasm `i64` and pushes a 64-bit integer. + WasmToInt64 { + unsigned: bool, }, /// Pops a 128-bit integer and pushes 2 Wasm 64-bit ints. @@ -169,8 +171,6 @@ pub enum Instruction { OptionWasmToStringEnum { name: String, - #[allow(dead_code)] - hole: u32, }, /// pops a string and pushes the enum variant as an `i32`