linera_wasmer_compiler/translator/
state.rs

1// This file contains code from external sources.
2// Attributions: https://github.com/wasmerio/wasmer/blob/main/docs/ATTRIBUTIONS.md
3
4use std::boxed::Box;
5use wasmer_types::entity::PrimaryMap;
6use wasmer_types::{SignatureIndex, WasmResult};
7
8/// Map of signatures to a function's parameter and return types.
9pub(crate) type WasmTypes =
10    PrimaryMap<SignatureIndex, (Box<[wasmparser::ValType]>, Box<[wasmparser::ValType]>)>;
11
12/// Contains information decoded from the Wasm module that must be referenced
13/// during each Wasm function's translation.
14///
15/// This is only for data that is maintained by `wasmer-compiler` itself, as
16/// opposed to being maintained by the embedder. Data that is maintained by the
17/// embedder is represented with `ModuleEnvironment`.
18#[derive(Debug)]
19pub struct ModuleTranslationState {
20    /// A map containing a Wasm module's original, raw signatures.
21    ///
22    /// This is used for translating multi-value Wasm blocks inside functions,
23    /// which are encoded to refer to their type signature via index.
24    pub(crate) wasm_types: WasmTypes,
25}
26
27impl ModuleTranslationState {
28    /// Creates a new empty ModuleTranslationState.
29    pub fn new() -> Self {
30        Self {
31            wasm_types: PrimaryMap::new(),
32        }
33    }
34
35    /// Get the parameter and result types for the given Wasm blocktype.
36    pub fn blocktype_params_results<'a>(
37        &'a self,
38        ty_or_ft: &'a wasmparser::BlockType,
39    ) -> WasmResult<(&'a [wasmparser::ValType], SingleOrMultiValue<'a>)> {
40        Ok(match ty_or_ft {
41            wasmparser::BlockType::Type(ty) => (&[], SingleOrMultiValue::Single(ty)),
42            wasmparser::BlockType::FuncType(ty_index) => {
43                let sig_idx = SignatureIndex::from_u32(*ty_index);
44                let (ref params, ref results) = self.wasm_types[sig_idx];
45                (params, SingleOrMultiValue::Multi(results.as_ref()))
46            }
47            wasmparser::BlockType::Empty => (&[], SingleOrMultiValue::Multi(&[])),
48        })
49    }
50}
51
52/// A helper enum for representing either a single or multiple values.
53pub enum SingleOrMultiValue<'a> {
54    /// A single value.
55    Single(&'a wasmparser::ValType),
56    /// Multiple values.
57    Multi(&'a [wasmparser::ValType]),
58}
59
60impl<'a> SingleOrMultiValue<'a> {
61    /// True if empty.
62    pub fn is_empty(&self) -> bool {
63        match self {
64            SingleOrMultiValue::Single(_) => false,
65            SingleOrMultiValue::Multi(values) => values.is_empty(),
66        }
67    }
68
69    /// Count of values.
70    pub fn len(&self) -> usize {
71        match self {
72            SingleOrMultiValue::Single(_) => 1,
73            SingleOrMultiValue::Multi(values) => values.len(),
74        }
75    }
76
77    /// Iterate ofer the value types.
78    pub fn iter(&self) -> SingleOrMultiValueIterator<'_> {
79        match self {
80            SingleOrMultiValue::Single(v) => SingleOrMultiValueIterator::Single(v),
81            SingleOrMultiValue::Multi(items) => SingleOrMultiValueIterator::Multi {
82                index: 0,
83                values: items,
84            },
85        }
86    }
87}
88
89pub enum SingleOrMultiValueIterator<'a> {
90    Done,
91    Single(&'a wasmparser::ValType),
92    Multi {
93        index: usize,
94        values: &'a [wasmparser::ValType],
95    },
96}
97
98impl<'a> Iterator for SingleOrMultiValueIterator<'a> {
99    type Item = &'a wasmparser::ValType;
100
101    fn next(&mut self) -> Option<Self::Item> {
102        match self {
103            SingleOrMultiValueIterator::Done => None,
104            SingleOrMultiValueIterator::Single(v) => {
105                let v = *v;
106                *self = SingleOrMultiValueIterator::Done;
107                Some(v)
108            }
109            SingleOrMultiValueIterator::Multi { index, values } => {
110                if let Some(x) = values.get(*index) {
111                    *index += 1;
112                    Some(x)
113                } else {
114                    *self = SingleOrMultiValueIterator::Done;
115                    None
116                }
117            }
118        }
119    }
120}
121
122impl<'a> PartialEq<[wasmparser::ValType]> for SingleOrMultiValue<'a> {
123    fn eq(&self, other: &[wasmparser::ValType]) -> bool {
124        match self {
125            SingleOrMultiValue::Single(ty) => other.len() == 1 && &other[0] == *ty,
126            SingleOrMultiValue::Multi(tys) => *tys == other,
127        }
128    }
129}
130
131impl<'a> PartialEq<SingleOrMultiValue<'a>> for &'a [wasmparser::ValType] {
132    fn eq(&self, other: &SingleOrMultiValue<'a>) -> bool {
133        match other {
134            SingleOrMultiValue::Single(ty) => self.len() == 1 && &self[0] == *ty,
135            SingleOrMultiValue::Multi(tys) => tys == self,
136        }
137    }
138}