zingen/visitor/
local.rs

1//! Local instructions
2
3use crate::{wasm::ToLSBytes, Error, Function, Result};
4
5impl Function {
6    /// This instruction gets the value of a variable.
7    pub fn _local_get(&mut self, local_index: u32) -> Result<()> {
8        let local_index = local_index as usize;
9        if (self.is_main || self.abi.is_some()) && local_index < self.ty.params().len() {
10            // Parsing data from selector.
11            self._local_get_calldata(local_index)
12        } else {
13            // Passing data between local functions.
14            self._local_get_var(local_index)
15        }
16    }
17
18    /// This instruction sets the value of a variable.
19    pub fn _local_set(&mut self, local_index: u32) -> Result<()> {
20        self.masm.push(&self.env.alloc(local_index))?;
21        self.masm._mstore()?;
22
23        Ok(())
24    }
25
26    /// This _local_tee is like _local_set, but it also returns the value
27    /// on the stack.
28    pub fn _local_tee(&mut self, index: u32) -> Result<()> {
29        self.masm._dup1()?;
30        self._local_set(index)?;
31        Ok(())
32    }
33
34    /// This instruction gets the value of a variable.
35    pub fn _global_get(&mut self, _: u32) -> Result<()> {
36        todo!()
37    }
38
39    /// This instruction sets the value of a variable.
40    pub fn _global_set(&mut self, _: u32) -> Result<()> {
41        todo!()
42    }
43
44    /// Local get from calldata.
45    fn _local_get_calldata(&mut self, local_index: usize) -> Result<()> {
46        let mut offset = self.locals.offset_of(local_index)?;
47        if self.abi.is_some() {
48            offset = (4 + local_index * 32).to_ls_bytes().to_vec().into();
49        }
50
51        self.masm.push(&offset)?;
52        self.masm._calldataload()?;
53
54        Ok(())
55    }
56
57    /// Local get for variables.
58    fn _local_get_var(&mut self, local_index: usize) -> Result<()> {
59        tracing::debug!("Local get variable: {local_index}");
60        if local_index + 1 > self.locals.len() {
61            // The local we want is not from function arguments
62            return Err(Error::InvalidLocalIndex(local_index));
63        }
64
65        self.masm.push(&self.env.alloc(local_index as u32))?;
66        self.masm._mload()?;
67        Ok(())
68    }
69}