zingen/masm/
ret.rs

1//! Return handlers
2
3use crate::{wasm::ToLSBytes, Error, MacroAssembler, Result};
4use wasmparser::ValType;
5
6impl MacroAssembler {
7    /// Return with nothing.
8    pub(crate) fn handle_empty_return(&mut self) -> Result<()> {
9        self._push0()?;
10        self._push0()?;
11        self.asm._return()?;
12
13        Ok(())
14    }
15
16    /// Handle the end of the main function.
17    pub fn main_return(&mut self, results: &[ValType]) -> Result<()> {
18        if results.is_empty() {
19            return self.handle_empty_return();
20        }
21
22        let size = self.memory_write(results)?.size;
23        let offset =
24            self.mp_offset(|mp| mp.checked_sub(size).ok_or_else(|| Error::InvalidMP(0)))?;
25
26        self.push(&size.to_ls_bytes())?;
27        self.push(&offset)?;
28        self.asm._return()?;
29        Ok(())
30    }
31
32    /// Handle the return of a call.
33    pub fn call_return(&mut self, results: &[ValType]) -> Result<()> {
34        let len = results.len() as u16;
35
36        tracing::trace!("cleaning frame stack, target: {}", len + 1);
37        // TODO: clean stacks via the count of nested control stacks.
38        while self.sp() > len + 1 {
39            self._drop()?;
40        }
41
42        // Shift stack to prompt the jump instruction,
43        // what about just dup it?
44        //
45        // TODO: handle the length of results > u8::MAX.
46        self.shift_stack(len, false)?;
47        self._jump()
48    }
49}