wasmer_compiler/
function.rs

1// This file contains code from external sources.
2// Attributions: https://github.com/wasmerio/wasmer/blob/master/ATTRIBUTIONS.md
3
4//! A `Compilation` contains the compiled function bodies for a WebAssembly
5//! module (`CompiledFunction`).
6
7use crate::lib::std::vec::Vec;
8use crate::section::{CustomSection, SectionIndex};
9use crate::trap::TrapInformation;
10use crate::{
11    CompiledFunctionUnwindInfo, CompiledFunctionUnwindInfoRef, FunctionAddressMap,
12    JumpTableOffsets, Relocation,
13};
14use wasmer_types::entity::PrimaryMap;
15use wasmer_types::{FunctionIndex, LocalFunctionIndex, SignatureIndex};
16
17/// The frame info for a Compiled function.
18///
19/// This structure is only used for reconstructing
20/// the frame information after a `Trap`.
21#[derive(
22    rkyv::Serialize, rkyv::Deserialize, rkyv::Archive, Debug, Clone, PartialEq, Eq, Default,
23)]
24pub struct CompiledFunctionFrameInfo {
25    /// The traps (in the function body).
26    ///
27    /// Code offsets of the traps MUST be in ascending order.
28    pub traps: Vec<TrapInformation>,
29
30    /// The address map.
31    pub address_map: FunctionAddressMap,
32}
33
34/// The function body.
35#[derive(rkyv::Serialize, rkyv::Deserialize, rkyv::Archive, Debug, Clone, PartialEq, Eq)]
36pub struct FunctionBody {
37    /// The function body bytes.
38    pub body: Vec<u8>,
39
40    /// The function unwind info
41    pub unwind_info: Option<CompiledFunctionUnwindInfo>,
42}
43
44/// See [`FunctionBody`].
45#[derive(Clone, Copy)]
46pub struct FunctionBodyRef<'a> {
47    /// Function body bytes.
48    pub body: &'a [u8],
49    /// The function unwind info.
50    pub unwind_info: Option<CompiledFunctionUnwindInfoRef<'a>>,
51}
52
53impl<'a> From<&'a FunctionBody> for FunctionBodyRef<'a> {
54    fn from(body: &'a FunctionBody) -> Self {
55        FunctionBodyRef {
56            body: &*body.body,
57            unwind_info: body.unwind_info.as_ref().map(Into::into),
58        }
59    }
60}
61
62impl<'a> From<&'a ArchivedFunctionBody> for FunctionBodyRef<'a> {
63    fn from(body: &'a ArchivedFunctionBody) -> Self {
64        FunctionBodyRef {
65            body: &*body.body,
66            unwind_info: body.unwind_info.as_ref().map(Into::into),
67        }
68    }
69}
70
71/// The result of compiling a WebAssembly function.
72///
73/// This structure only have the compiled information data
74/// (function bytecode body, relocations, traps, jump tables
75/// and unwind information).
76#[derive(rkyv::Serialize, rkyv::Deserialize, rkyv::Archive, Debug, Clone, PartialEq, Eq)]
77pub struct CompiledFunction {
78    /// The function body.
79    pub body: FunctionBody,
80
81    /// The relocations (in the body)
82    pub relocations: Vec<Relocation>,
83
84    /// The jump tables offsets (in the body).
85    pub jt_offsets: JumpTableOffsets,
86
87    /// The frame information.
88    pub frame_info: CompiledFunctionFrameInfo,
89}
90
91/// The compiled functions map (index in the Wasm -> function)
92pub type Functions = PrimaryMap<LocalFunctionIndex, CompiledFunction>;
93
94/// The custom sections for a Compilation.
95pub type CustomSections = PrimaryMap<SectionIndex, CustomSection>;
96
97/// The DWARF information for this Compilation.
98///
99/// It is used for retrieving the unwind information once an exception
100/// happens.
101/// In the future this structure may also hold other information useful
102/// for debugging.
103#[derive(rkyv::Serialize, rkyv::Deserialize, rkyv::Archive, Debug, PartialEq, Eq, Clone)]
104pub struct Dwarf {
105    /// The section index in the [`Compilation`] that corresponds to the exception frames.
106    /// [Learn
107    /// more](https://refspecs.linuxfoundation.org/LSB_3.0.0/LSB-PDA/LSB-PDA/ehframechpt.html).
108    pub eh_frame: SectionIndex,
109}
110
111impl Dwarf {
112    /// Creates a `Dwarf` struct with the corresponding indices for its sections
113    pub fn new(eh_frame: SectionIndex) -> Self {
114        Self { eh_frame }
115    }
116}
117
118/// Trampolines section used by ARM short jump (26bits)
119#[derive(rkyv::Serialize, rkyv::Deserialize, rkyv::Archive, Debug, PartialEq, Eq, Clone)]
120pub struct TrampolinesSection {
121    /// SectionIndex for the actual Trampolines code
122    pub section_index: SectionIndex,
123    /// Number of jump slots in the section
124    pub slots: usize,
125    /// Slot size
126    pub size: usize,
127}
128
129impl TrampolinesSection {
130    /// Creates a `Trampolines` struct with the indice for its section, and number of slots and size of slot
131    pub fn new(section_index: SectionIndex, slots: usize, size: usize) -> Self {
132        Self {
133            section_index,
134            slots,
135            size,
136        }
137    }
138}
139
140/// The result of compiling a WebAssembly module's functions.
141#[derive(Debug, PartialEq, Eq)]
142pub struct Compilation {
143    /// Compiled code for the function bodies.
144    functions: Functions,
145
146    /// Custom sections for the module.
147    /// It will hold the data, for example, for constants used in a
148    /// function, global variables, rodata_64, hot/cold function partitioning, ...
149    custom_sections: CustomSections,
150
151    /// Trampolines to call a function defined locally in the wasm via a
152    /// provided `Vec` of values.
153    ///
154    /// This allows us to call easily Wasm functions, such as:
155    ///
156    /// ```ignore
157    /// let func = instance.exports.get_function("my_func");
158    /// func.call(&[Value::I32(1)]);
159    /// ```
160    function_call_trampolines: PrimaryMap<SignatureIndex, FunctionBody>,
161
162    /// Trampolines to call a dynamic function defined in
163    /// a host, from a Wasm module.
164    ///
165    /// This allows us to create dynamic Wasm functions, such as:
166    ///
167    /// ```ignore
168    /// fn my_func(values: &[Val]) -> Result<Vec<Val>, RuntimeError> {
169    ///     // do something
170    /// }
171    ///
172    /// let my_func_type = FunctionType::new(vec![Type::I32], vec![Type::I32]);
173    /// let imports = imports!{
174    ///     "namespace" => {
175    ///         "my_func" => Function::new(&store, my_func_type, my_func),
176    ///     }
177    /// }
178    /// ```
179    ///
180    /// Note: Dynamic function trampolines are only compiled for imported function types.
181    dynamic_function_trampolines: PrimaryMap<FunctionIndex, FunctionBody>,
182
183    /// Section ids corresponding to the Dwarf debug info
184    debug: Option<Dwarf>,
185
186    /// Trampolines for the arch that needs it
187    trampolines: Option<TrampolinesSection>,
188}
189
190impl Compilation {
191    /// Creates a compilation artifact from a contiguous function buffer and a set of ranges
192    pub fn new(
193        functions: Functions,
194        custom_sections: CustomSections,
195        function_call_trampolines: PrimaryMap<SignatureIndex, FunctionBody>,
196        dynamic_function_trampolines: PrimaryMap<FunctionIndex, FunctionBody>,
197        debug: Option<Dwarf>,
198        trampolines: Option<TrampolinesSection>,
199    ) -> Self {
200        Self {
201            functions,
202            custom_sections,
203            function_call_trampolines,
204            dynamic_function_trampolines,
205            debug,
206            trampolines,
207        }
208    }
209
210    /// Gets the bytes of a single function
211    pub fn get(&self, func: LocalFunctionIndex) -> &CompiledFunction {
212        &self.functions[func]
213    }
214
215    /// Gets the number of functions defined.
216    pub fn len(&self) -> usize {
217        self.functions.len()
218    }
219
220    /// Returns whether there are no functions defined.
221    pub fn is_empty(&self) -> bool {
222        self.functions.is_empty()
223    }
224
225    /// Gets functions relocations.
226    pub fn get_relocations(&self) -> PrimaryMap<LocalFunctionIndex, Vec<Relocation>> {
227        self.functions
228            .iter()
229            .map(|(_, func)| func.relocations.clone())
230            .collect::<PrimaryMap<LocalFunctionIndex, _>>()
231    }
232
233    /// Gets functions bodies.
234    pub fn get_function_bodies(&self) -> PrimaryMap<LocalFunctionIndex, FunctionBody> {
235        self.functions
236            .iter()
237            .map(|(_, func)| func.body.clone())
238            .collect::<PrimaryMap<LocalFunctionIndex, _>>()
239    }
240
241    /// Gets functions jump table offsets.
242    pub fn get_jt_offsets(&self) -> PrimaryMap<LocalFunctionIndex, JumpTableOffsets> {
243        self.functions
244            .iter()
245            .map(|(_, func)| func.jt_offsets.clone())
246            .collect::<PrimaryMap<LocalFunctionIndex, _>>()
247    }
248
249    /// Gets functions frame info.
250    pub fn get_frame_info(&self) -> PrimaryMap<LocalFunctionIndex, CompiledFunctionFrameInfo> {
251        self.functions
252            .iter()
253            .map(|(_, func)| func.frame_info.clone())
254            .collect::<PrimaryMap<LocalFunctionIndex, _>>()
255    }
256
257    /// Gets function call trampolines.
258    pub fn get_function_call_trampolines(&self) -> PrimaryMap<SignatureIndex, FunctionBody> {
259        self.function_call_trampolines.clone()
260    }
261
262    /// Gets function call trampolines.
263    pub fn get_dynamic_function_trampolines(&self) -> PrimaryMap<FunctionIndex, FunctionBody> {
264        self.dynamic_function_trampolines.clone()
265    }
266
267    /// Gets custom section data.
268    pub fn get_custom_sections(&self) -> PrimaryMap<SectionIndex, CustomSection> {
269        self.custom_sections.clone()
270    }
271
272    /// Gets relocations that apply to custom sections.
273    pub fn get_custom_section_relocations(&self) -> PrimaryMap<SectionIndex, Vec<Relocation>> {
274        self.custom_sections
275            .iter()
276            .map(|(_, section)| section.relocations.clone())
277            .collect::<PrimaryMap<SectionIndex, _>>()
278    }
279
280    /// Returns the Dwarf info.
281    pub fn get_debug(&self) -> Option<Dwarf> {
282        self.debug.clone()
283    }
284
285    /// Returns the Trampolines info.
286    pub fn get_trampolines(&self) -> Option<TrampolinesSection> {
287        self.trampolines.clone()
288    }
289}
290
291impl<'a> IntoIterator for &'a Compilation {
292    type IntoIter = Iter<'a>;
293    type Item = <Self::IntoIter as Iterator>::Item;
294
295    fn into_iter(self) -> Self::IntoIter {
296        Iter {
297            iterator: self.functions.iter(),
298        }
299    }
300}
301
302pub struct Iter<'a> {
303    iterator: <&'a Functions as IntoIterator>::IntoIter,
304}
305
306impl<'a> Iterator for Iter<'a> {
307    type Item = &'a CompiledFunction;
308
309    fn next(&mut self) -> Option<Self::Item> {
310        self.iterator.next().map(|(_, b)| b)
311    }
312}