diff --git a/crates/cli-support/src/js/binding.rs b/crates/cli-support/src/js/binding.rs index 1c5e91869d1c..bdaf39b7b93c 100644 --- a/crates/cli-support/src/js/binding.rs +++ b/crates/cli-support/src/js/binding.rs @@ -548,57 +548,32 @@ fn instruction(js: &mut JsBuilder, instr: &Instruction, log_error: &mut bool) -> | Instruction::CallExport(_) | Instruction::CallAdapter(_) | Instruction::CallTableElement(_) - | Instruction::DeferCallCore(_) => { + | Instruction::DeferFree { align, .. } => { let invoc = Invocation::from(instr, js.cx.module)?; let (mut params, results) = invoc.params_results(js.cx); + assert_eq!(results, 0, "deferred calls must have no results"); + // substract alignment + params -= 1; let mut args = Vec::new(); let tmp = js.tmp(); - if invoc.defer() { - // substract alignment - params -= 1; - // If the call is deferred, the arguments to the function still need to be - // accessible in the `finally` block, so we declare variables to hold the args - // outside of the try-finally block and then set those to the args. - for (i, arg) in js.stack[js.stack.len() - params..].iter().enumerate() { - let name = format!("deferred{tmp}_{i}"); - writeln!(js.pre_try, "let {name};").unwrap(); - writeln!(js.prelude, "{name} = {arg};").unwrap(); - args.push(name); - } - // add alignment - args.push(String::from("4")); - } else { - // Otherwise, pop off the number of parameters for the function we're calling. - for _ in 0..params { - args.push(js.pop()); - } - args.reverse(); + + // If the call is deferred, the arguments to the function still need to be + // accessible in the `finally` block, so we declare variables to hold the args + // outside of the try-finally block and then set those to the args. + for (i, arg) in js.stack[js.stack.len() - params..].iter().enumerate() { + let name = format!("deferred{tmp}_{i}"); + writeln!(js.pre_try, "let {name};").unwrap(); + writeln!(js.prelude, "{name} = {arg};").unwrap(); + args.push(name); } + // add alignment + args.push(align.to_string()); // Call the function through an export of the underlying module. let call = invoc.invoke(js.cx, &args, &mut js.prelude, log_error)?; - // And then figure out how to actually handle where the call - // happens. This is pretty conditional depending on the number of - // return values of the function. - match (invoc.defer(), results) { - (true, 0) => { - js.finally(&format!("{};", call)); - } - (true, _) => panic!("deferred calls must have no results"), - (false, 0) => js.prelude(&format!("{};", call)), - (false, n) => { - js.prelude(&format!("const ret = {};", call)); - if n == 1 { - js.push("ret".to_string()); - } else { - for i in 0..n { - js.push(format!("ret[{}]", i)); - } - } - } - } + js.finally(&format!("{};", call)); } Instruction::IntToWasm { input, .. } => { @@ -1194,8 +1169,8 @@ impl Invocation { defer: false, }, - DeferCallCore(f) => Invocation::Core { - id: *f, + DeferFree { free, .. } => Invocation::Core { + id: *free, defer: true, }, @@ -1264,13 +1239,6 @@ impl Invocation { } } } - - fn defer(&self) -> bool { - match self { - Invocation::Core { defer, .. } => *defer, - _ => false, - } - } } fn adapter2ts(ty: &AdapterType, dst: &mut String) { diff --git a/crates/cli-support/src/wit/outgoing.rs b/crates/cli-support/src/wit/outgoing.rs index 890b79b2fb0e..d90dcd3f5ee6 100644 --- a/crates/cli-support/src/wit/outgoing.rs +++ b/crates/cli-support/src/wit/outgoing.rs @@ -105,7 +105,7 @@ impl InstructionBuilder<'_, '_> { // ... then defer a call to `free` to happen later let free = self.cx.free()?; self.instructions.push(InstructionData { - instr: Instruction::DeferCallCore(free), + instr: Instruction::DeferFree { free, align: 1 }, stack_change: StackChange::Modified { popped: 2, pushed: 2, @@ -389,7 +389,7 @@ impl InstructionBuilder<'_, '_> { // special case it. assert!(!self.instructions[len..] .iter() - .any(|idata| matches!(idata.instr, Instruction::DeferCallCore(_)))); + .any(|idata| matches!(idata.instr, Instruction::DeferFree { .. }))); // Finally, we add the two inputs to UnwrapResult, and everything checks out // @@ -429,7 +429,7 @@ impl InstructionBuilder<'_, '_> { // implementation. let free = self.cx.free()?; self.instructions.push(InstructionData { - instr: Instruction::DeferCallCore(free), + instr: Instruction::DeferFree { free, align: 1 }, stack_change: StackChange::Modified { popped: 2, pushed: 2, diff --git a/crates/cli-support/src/wit/standard.rs b/crates/cli-support/src/wit/standard.rs index 953fbfa56880..ba29a75e417b 100644 --- a/crates/cli-support/src/wit/standard.rs +++ b/crates/cli-support/src/wit/standard.rs @@ -95,7 +95,10 @@ pub enum Instruction { CallCore(walrus::FunctionId), /// Schedules a function to be called after the whole lift/lower cycle is /// finished, e.g. to deallocate a string or something. - DeferCallCore(walrus::FunctionId), + DeferFree { + free: walrus::FunctionId, + align: usize, + }, /// A call to one of our own defined adapters, similar to the standard /// call-adapter instruction CallAdapter(AdapterId), @@ -423,7 +426,7 @@ impl walrus::CustomSection for NonstandardWitSection { }; for instr in instrs { match instr.instr { - DeferCallCore(f) | CallCore(f) => { + DeferFree { free: f, .. } | CallCore(f) => { roots.push_func(f); } StoreRetptr { mem, .. }