linera_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, WasmResult};
9use wasmparser::{BinaryReader, Operator, 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.
46#[derive(Debug)]
47pub struct MiddlewareBinaryReader<'a> {
48    /// Parsing state.
49    state: MiddlewareReaderState<'a>,
50
51    /// The backing middleware chain for this reader.
52    chain: Vec<Box<dyn FunctionMiddleware>>,
53}
54
55/// The state of the binary reader. Exposed to middlewares to push their outputs.
56#[derive(Debug)]
57pub struct MiddlewareReaderState<'a> {
58    /// Raw binary reader.
59    inner: BinaryReader<'a>,
60
61    /// The pending operations added by the middleware.
62    pending_operations: VecDeque<Operator<'a>>,
63}
64
65/// Trait for generating middleware chains from "prototype" (generator) chains.
66pub trait ModuleMiddlewareChain {
67    /// Generates a function middleware chain.
68    fn generate_function_middleware_chain(
69        &self,
70        local_function_index: LocalFunctionIndex,
71    ) -> Vec<Box<dyn FunctionMiddleware>>;
72
73    /// Applies the chain on a `ModuleInfo` struct.
74    fn apply_on_module_info(&self, module_info: &mut ModuleInfo) -> Result<(), MiddlewareError>;
75}
76
77impl<T: Deref<Target = dyn ModuleMiddleware>> ModuleMiddlewareChain for [T] {
78    /// Generates a function middleware chain.
79    fn generate_function_middleware_chain(
80        &self,
81        local_function_index: LocalFunctionIndex,
82    ) -> Vec<Box<dyn FunctionMiddleware>> {
83        self.iter()
84            .map(|x| x.generate_function_middleware(local_function_index))
85            .collect()
86    }
87
88    /// Applies the chain on a `ModuleInfo` struct.
89    fn apply_on_module_info(&self, module_info: &mut ModuleInfo) -> Result<(), MiddlewareError> {
90        for item in self {
91            item.transform_module_info(module_info)?;
92        }
93        Ok(())
94    }
95}
96
97impl<'a> MiddlewareReaderState<'a> {
98    /// Push an operator.
99    pub fn push_operator(&mut self, operator: Operator<'a>) {
100        self.pending_operations.push_back(operator);
101    }
102}
103
104impl<'a> Extend<Operator<'a>> for MiddlewareReaderState<'a> {
105    fn extend<I: IntoIterator<Item = Operator<'a>>>(&mut self, iter: I) {
106        self.pending_operations.extend(iter);
107    }
108}
109
110impl<'a: 'b, 'b> Extend<&'b Operator<'a>> for MiddlewareReaderState<'a> {
111    fn extend<I: IntoIterator<Item = &'b Operator<'a>>>(&mut self, iter: I) {
112        self.pending_operations.extend(iter.into_iter().cloned());
113    }
114}
115
116impl<'a> MiddlewareBinaryReader<'a> {
117    /// Constructs a `MiddlewareBinaryReader` with an explicit starting offset.
118    pub fn new_with_offset(data: &'a [u8], original_offset: usize) -> Self {
119        let inner = BinaryReader::new_with_offset(data, original_offset);
120        Self {
121            state: MiddlewareReaderState {
122                inner,
123                pending_operations: VecDeque::new(),
124            },
125            chain: vec![],
126        }
127    }
128
129    /// Replaces the middleware chain with a new one.
130    pub fn set_middleware_chain(&mut self, stages: Vec<Box<dyn FunctionMiddleware>>) {
131        self.chain = stages;
132    }
133}
134
135impl<'a> FunctionBinaryReader<'a> for MiddlewareBinaryReader<'a> {
136    fn read_local_count(&mut self) -> WasmResult<u32> {
137        self.state
138            .inner
139            .read_var_u32()
140            .map_err(from_binaryreadererror_wasmerror)
141    }
142
143    fn read_local_decl(&mut self) -> WasmResult<(u32, ValType)> {
144        let count = self
145            .state
146            .inner
147            .read_var_u32()
148            .map_err(from_binaryreadererror_wasmerror)?;
149        let ty: ValType = self
150            .state
151            .inner
152            .read::<ValType>()
153            .map_err(from_binaryreadererror_wasmerror)?;
154        Ok((count, ty))
155    }
156
157    fn read_operator(&mut self) -> WasmResult<Operator<'a>> {
158        if self.chain.is_empty() {
159            // We short-circuit in case no chain is used
160            return self
161                .state
162                .inner
163                .read_operator()
164                .map_err(from_binaryreadererror_wasmerror);
165        }
166
167        // Try to fill the `self.pending_operations` buffer, until it is non-empty.
168        while self.state.pending_operations.is_empty() {
169            let raw_op = self
170                .state
171                .inner
172                .read_operator()
173                .map_err(from_binaryreadererror_wasmerror)?;
174
175            // Fill the initial raw operator into pending buffer.
176            self.state.pending_operations.push_back(raw_op);
177
178            // Run the operator through each stage.
179            for stage in &mut self.chain {
180                // Take the outputs from the previous stage.
181                let pending: SmallVec<[Operator<'a>; 2]> =
182                    self.state.pending_operations.drain(0..).collect();
183
184                // ...and feed them into the current stage.
185                for pending_op in pending {
186                    stage.feed(pending_op, &mut self.state)?;
187                }
188            }
189        }
190
191        Ok(self.state.pending_operations.pop_front().unwrap())
192    }
193
194    fn current_position(&self) -> usize {
195        self.state.inner.current_position()
196    }
197
198    fn original_position(&self) -> usize {
199        self.state.inner.original_position()
200    }
201
202    fn bytes_remaining(&self) -> usize {
203        self.state.inner.bytes_remaining()
204    }
205
206    fn eof(&self) -> bool {
207        self.state.inner.eof()
208    }
209
210    fn range(&self) -> Range<usize> {
211        self.state.inner.range()
212    }
213}