wasmer_compiler/translator/
middleware.rs

1//! The middleware parses the function binary bytecodes and transform them
2//! with the chosen functions.
3
4use smallvec::SmallVec;
5use std::collections::VecDeque;
6use std::fmt::Debug;
7use std::ops::{Deref, Range};
8use wasmer_types::{LocalFunctionIndex, MiddlewareError, ModuleInfo, WasmError, WasmResult};
9use wasmparser::{BinaryReader, FunctionBody, Operator, OperatorsReader, ValType};
10
11use super::error::from_binaryreadererror_wasmerror;
12use crate::translator::environ::FunctionBinaryReader;
13
14/// A shared builder for function middlewares.
15pub trait ModuleMiddleware: Debug + Send + Sync {
16    /// Generates a `FunctionMiddleware` for a given function.
17    ///
18    /// Here we generate a separate object for each function instead of executing directly on per-function operators,
19    /// in order to enable concurrent middleware application. Takes immutable `&self` because this function can be called
20    /// concurrently from multiple compilation threads.
21    fn generate_function_middleware(
22        &self,
23        local_function_index: LocalFunctionIndex,
24    ) -> Box<dyn FunctionMiddleware>;
25
26    /// Transforms a `ModuleInfo` struct in-place. This is called before application on functions begins.
27    fn transform_module_info(&self, _: &mut ModuleInfo) -> Result<(), MiddlewareError> {
28        Ok(())
29    }
30}
31
32/// A function middleware specialized for a single function.
33pub trait FunctionMiddleware: Debug {
34    /// Processes the given operator.
35    fn feed<'a>(
36        &mut self,
37        operator: Operator<'a>,
38        state: &mut MiddlewareReaderState<'a>,
39    ) -> Result<(), MiddlewareError> {
40        state.push_operator(operator);
41        Ok(())
42    }
43}
44
45/// A Middleware binary reader of the WebAssembly structures and types.
46pub struct MiddlewareBinaryReader<'a> {
47    /// Parsing state.
48    state: MiddlewareReaderState<'a>,
49
50    /// The backing middleware chain for this reader.
51    chain: Vec<Box<dyn FunctionMiddleware>>,
52}
53
54enum MiddlewareInnerReader<'a> {
55    Binary {
56        reader: BinaryReader<'a>,
57        original_reader: BinaryReader<'a>,
58    },
59    Operator(OperatorsReader<'a>),
60}
61
62/// The state of the binary reader. Exposed to middlewares to push their outputs.
63pub struct MiddlewareReaderState<'a> {
64    /// Raw binary reader.
65    inner: Option<MiddlewareInnerReader<'a>>,
66
67    /// The pending operations added by the middleware.
68    pending_operations: VecDeque<Operator<'a>>,
69}
70
71/// Trait for generating middleware chains from "prototype" (generator) chains.
72pub trait ModuleMiddlewareChain {
73    /// Generates a function middleware chain.
74    fn generate_function_middleware_chain(
75        &self,
76        local_function_index: LocalFunctionIndex,
77    ) -> Vec<Box<dyn FunctionMiddleware>>;
78
79    /// Applies the chain on a `ModuleInfo` struct.
80    fn apply_on_module_info(&self, module_info: &mut ModuleInfo) -> Result<(), MiddlewareError>;
81}
82
83impl<T: Deref<Target = dyn ModuleMiddleware>> ModuleMiddlewareChain for [T] {
84    /// Generates a function middleware chain.
85    fn generate_function_middleware_chain(
86        &self,
87        local_function_index: LocalFunctionIndex,
88    ) -> Vec<Box<dyn FunctionMiddleware>> {
89        self.iter()
90            .map(|x| x.generate_function_middleware(local_function_index))
91            .collect()
92    }
93
94    /// Applies the chain on a `ModuleInfo` struct.
95    fn apply_on_module_info(&self, module_info: &mut ModuleInfo) -> Result<(), MiddlewareError> {
96        for item in self {
97            item.transform_module_info(module_info)?;
98        }
99        Ok(())
100    }
101}
102
103impl<'a> MiddlewareReaderState<'a> {
104    /// Push an operator.
105    pub fn push_operator(&mut self, operator: Operator<'a>) {
106        self.pending_operations.push_back(operator);
107    }
108}
109
110impl<'a> Extend<Operator<'a>> for MiddlewareReaderState<'a> {
111    fn extend<I: IntoIterator<Item = Operator<'a>>>(&mut self, iter: I) {
112        self.pending_operations.extend(iter);
113    }
114}
115
116impl<'a: 'b, 'b> Extend<&'b Operator<'a>> for MiddlewareReaderState<'a> {
117    fn extend<I: IntoIterator<Item = &'b Operator<'a>>>(&mut self, iter: I) {
118        self.pending_operations.extend(iter.into_iter().cloned());
119    }
120}
121
122impl<'a> MiddlewareBinaryReader<'a> {
123    /// Constructs a `MiddlewareBinaryReader` with an explicit starting offset.
124    pub fn new_with_offset(data: &'a [u8], original_offset: usize) -> Self {
125        let inner = BinaryReader::new(data, original_offset);
126        Self {
127            state: MiddlewareReaderState {
128                inner: Some(MiddlewareInnerReader::Binary {
129                    original_reader: inner.clone(),
130                    reader: inner,
131                }),
132                pending_operations: VecDeque::new(),
133            },
134            chain: vec![],
135        }
136    }
137
138    /// Replaces the middleware chain with a new one.
139    pub fn set_middleware_chain(&mut self, stages: Vec<Box<dyn FunctionMiddleware>>) {
140        self.chain = stages;
141    }
142}
143
144impl<'a> FunctionBinaryReader<'a> for MiddlewareBinaryReader<'a> {
145    fn read_local_count(&mut self) -> WasmResult<u32> {
146        match self.state.inner.as_mut().expect("inner state must exist") {
147            MiddlewareInnerReader::Binary { reader, .. } => reader
148                .read_var_u32()
149                .map_err(from_binaryreadererror_wasmerror),
150            MiddlewareInnerReader::Operator(..) => Err(WasmError::InvalidWebAssembly {
151                message: "locals must be read before the function body".to_string(),
152                offset: self.current_position(),
153            }),
154        }
155    }
156
157    fn read_local_decl(&mut self) -> WasmResult<(u32, ValType)> {
158        match self.state.inner.as_mut().expect("inner state must exist") {
159            MiddlewareInnerReader::Binary { reader, .. } => {
160                let count = reader
161                    .read_var_u32()
162                    .map_err(from_binaryreadererror_wasmerror)?;
163                let ty: ValType = reader
164                    .read::<ValType>()
165                    .map_err(from_binaryreadererror_wasmerror)?;
166                Ok((count, ty))
167            }
168            MiddlewareInnerReader::Operator(..) => Err(WasmError::InvalidWebAssembly {
169                message: "locals must be read before the function body".to_string(),
170                offset: self.current_position(),
171            }),
172        }
173    }
174
175    fn read_operator(&mut self) -> WasmResult<Operator<'a>> {
176        if let Some(inner) = self.state.inner.take() {
177            self.state.inner = Some(match inner {
178                MiddlewareInnerReader::Binary {
179                    original_reader, ..
180                } => {
181                    let operator_reader = FunctionBody::new(original_reader)
182                        .get_operators_reader()
183                        .map_err(from_binaryreadererror_wasmerror)?;
184                    MiddlewareInnerReader::Operator(operator_reader)
185                }
186                other => other,
187            });
188        }
189
190        let read_operator = |state: &mut MiddlewareReaderState<'a>| {
191            let Some(MiddlewareInnerReader::Operator(operator_reader)) = state.inner.as_mut()
192            else {
193                unreachable!();
194            };
195            operator_reader
196                .read()
197                .map_err(from_binaryreadererror_wasmerror)
198        };
199
200        if self.chain.is_empty() {
201            // We short-circuit in case no chain is used
202            return read_operator(&mut self.state);
203        }
204
205        // Try to fill the `self.pending_operations` buffer, until it is non-empty.
206        while self.state.pending_operations.is_empty() {
207            let raw_op = read_operator(&mut self.state)?;
208
209            // Fill the initial raw operator into pending buffer.
210            self.state.pending_operations.push_back(raw_op);
211
212            // Run the operator through each stage.
213            for stage in &mut self.chain {
214                // Take the outputs from the previous stage.
215                let pending: SmallVec<[Operator<'a>; 2]> =
216                    self.state.pending_operations.drain(0..).collect();
217
218                // ...and feed them into the current stage.
219                for pending_op in pending {
220                    stage.feed(pending_op, &mut self.state)?;
221                }
222            }
223        }
224
225        Ok(self.state.pending_operations.pop_front().unwrap())
226    }
227
228    fn current_position(&self) -> usize {
229        match self.state.inner.as_ref().expect("inner state must exist") {
230            MiddlewareInnerReader::Binary { reader, .. } => reader.current_position(),
231            MiddlewareInnerReader::Operator(operator_reader) => {
232                operator_reader.get_binary_reader().current_position()
233            }
234        }
235    }
236
237    fn original_position(&self) -> usize {
238        match self.state.inner.as_ref().expect("inner state must exist") {
239            MiddlewareInnerReader::Binary { reader, .. } => reader.original_position(),
240            MiddlewareInnerReader::Operator(operator_reader) => operator_reader.original_position(),
241        }
242    }
243
244    fn bytes_remaining(&self) -> usize {
245        match self.state.inner.as_ref().expect("inner state must exist") {
246            MiddlewareInnerReader::Binary { reader, .. } => reader.bytes_remaining(),
247            MiddlewareInnerReader::Operator(operator_reader) => {
248                operator_reader.get_binary_reader().bytes_remaining()
249            }
250        }
251    }
252
253    fn eof(&self) -> bool {
254        match self.state.inner.as_ref().expect("inner state must exist") {
255            MiddlewareInnerReader::Binary { reader, .. } => reader.eof(),
256            MiddlewareInnerReader::Operator(operator_reader) => operator_reader.eof(),
257        }
258    }
259
260    fn range(&self) -> Range<usize> {
261        match self.state.inner.as_ref().expect("inner state must exist") {
262            MiddlewareInnerReader::Binary { reader, .. } => reader.range(),
263            MiddlewareInnerReader::Operator(operator_reader) => {
264                operator_reader.get_binary_reader().range()
265            }
266        }
267    }
268}