Skip to main content

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    /// Offset of the code-section payload in the original Wasm file.
21    pub(crate) code_section_offset: Option<usize>,
22
23    /// A map containing a Wasm module's original, raw signatures.
24    ///
25    /// This is used for translating multi-value Wasm blocks inside functions,
26    /// which are encoded to refer to their type signature via index.
27    pub(crate) wasm_types: WasmTypes,
28}
29
30impl ModuleTranslationState {
31    /// Creates a new empty ModuleTranslationState.
32    pub fn new() -> Self {
33        Self {
34            code_section_offset: None,
35            wasm_types: PrimaryMap::new(),
36        }
37    }
38
39    /// Get the offset of the code-section payload in the original Wasm file.
40    pub fn code_section_offset(&self) -> Option<usize> {
41        self.code_section_offset
42    }
43
44    /// Get the parameter and result types for the given Wasm blocktype.
45    pub fn blocktype_params_results<'a>(
46        &'a self,
47        ty_or_ft: &'a wasmparser::BlockType,
48    ) -> WasmResult<(&'a [wasmparser::ValType], SingleOrMultiValue<'a>)> {
49        Ok(match ty_or_ft {
50            wasmparser::BlockType::Type(ty) => (&[], SingleOrMultiValue::Single(ty)),
51            wasmparser::BlockType::FuncType(ty_index) => {
52                let sig_idx = SignatureIndex::from_u32(*ty_index);
53                let (ref params, ref results) = self.wasm_types[sig_idx];
54                (params, SingleOrMultiValue::Multi(results.as_ref()))
55            }
56            wasmparser::BlockType::Empty => (&[], SingleOrMultiValue::Multi(&[])),
57        })
58    }
59}
60
61/// A helper enum for representing either a single or multiple values.
62#[derive(Clone)]
63pub enum SingleOrMultiValue<'a> {
64    /// A single value.
65    Single(&'a wasmparser::ValType),
66    /// Multiple values.
67    Multi(&'a [wasmparser::ValType]),
68}
69
70impl SingleOrMultiValue<'_> {
71    /// True if empty.
72    pub fn is_empty(&self) -> bool {
73        match self {
74            SingleOrMultiValue::Single(_) => false,
75            SingleOrMultiValue::Multi(values) => values.is_empty(),
76        }
77    }
78
79    /// Count of values.
80    pub fn len(&self) -> usize {
81        match self {
82            SingleOrMultiValue::Single(_) => 1,
83            SingleOrMultiValue::Multi(values) => values.len(),
84        }
85    }
86
87    /// Iterate offer the value types.
88    pub fn iter(&self) -> SingleOrMultiValueIterator<'_> {
89        match self {
90            SingleOrMultiValue::Single(v) => SingleOrMultiValueIterator::Single(v),
91            SingleOrMultiValue::Multi(items) => SingleOrMultiValueIterator::Multi {
92                index: 0,
93                values: items,
94            },
95        }
96    }
97}
98
99pub enum SingleOrMultiValueIterator<'a> {
100    Done,
101    Single(&'a wasmparser::ValType),
102    Multi {
103        index: usize,
104        values: &'a [wasmparser::ValType],
105    },
106}
107
108impl<'a> Iterator for SingleOrMultiValueIterator<'a> {
109    type Item = &'a wasmparser::ValType;
110
111    fn next(&mut self) -> Option<Self::Item> {
112        match self {
113            SingleOrMultiValueIterator::Done => None,
114            SingleOrMultiValueIterator::Single(v) => {
115                let v = *v;
116                *self = SingleOrMultiValueIterator::Done;
117                Some(v)
118            }
119            SingleOrMultiValueIterator::Multi { index, values } => {
120                if let Some(x) = values.get(*index) {
121                    *index += 1;
122                    Some(x)
123                } else {
124                    *self = SingleOrMultiValueIterator::Done;
125                    None
126                }
127            }
128        }
129    }
130}
131
132impl PartialEq<[wasmparser::ValType]> for SingleOrMultiValue<'_> {
133    fn eq(&self, other: &[wasmparser::ValType]) -> bool {
134        match self {
135            SingleOrMultiValue::Single(ty) => other.len() == 1 && &other[0] == *ty,
136            SingleOrMultiValue::Multi(tys) => *tys == other,
137        }
138    }
139}
140
141impl<'a> PartialEq<SingleOrMultiValue<'a>> for &'a [wasmparser::ValType] {
142    fn eq(&self, other: &SingleOrMultiValue<'a>) -> bool {
143        match other {
144            SingleOrMultiValue::Single(ty) => self.len() == 1 && &self[0] == *ty,
145            SingleOrMultiValue::Multi(tys) => tys == self,
146        }
147    }
148}