wasmer_compiler/types/
function.rs

1/*
2 * ! Remove me once rkyv generates doc-comments for fields or generates an #[allow(missing_docs)]
3 * on their own.
4 */
5#![allow(missing_docs)]
6// This file contains code from external sources.
7// Attributions: https://github.com/wasmerio/wasmer/blob/main/docs/ATTRIBUTIONS.md
8
9//! A `Compilation` contains the compiled function bodies for a WebAssembly
10//! module (`CompiledFunction`).
11
12use std::path::PathBuf;
13
14use super::{
15    address_map::FunctionAddressMap,
16    relocation::Relocation,
17    section::{CustomSection, SectionIndex},
18    unwind::{
19        ArchivedCompiledFunctionUnwindInfo, CompiledFunctionUnwindInfo,
20        CompiledFunctionUnwindInfoLike,
21    },
22};
23use rkyv::{
24    Archive, Deserialize as RkyvDeserialize, Serialize as RkyvSerialize, option::ArchivedOption,
25};
26#[cfg(feature = "enable-serde")]
27use serde::{Deserialize, Serialize};
28use wasmer_types::{
29    FunctionIndex, LocalFunctionIndex, SignatureIndex, TrapInformation, entity::PrimaryMap,
30};
31
32/// The frame info for a Compiled function.
33///
34/// This structure is only used for reconstructing
35/// the frame information after a `Trap`.
36#[cfg_attr(feature = "artifact-size", derive(loupe::MemoryUsage))]
37#[cfg_attr(feature = "enable-serde", derive(Deserialize, Serialize))]
38#[derive(RkyvSerialize, RkyvDeserialize, Archive, Debug, Clone, PartialEq, Eq, Default)]
39#[rkyv(derive(Debug))]
40pub struct CompiledFunctionFrameInfo {
41    /// The traps (in the function body).
42    ///
43    /// Code offsets of the traps MUST be in ascending order.
44    pub traps: Vec<TrapInformation>,
45
46    /// The address map.
47    pub address_map: FunctionAddressMap,
48}
49
50/// The function body.
51#[cfg_attr(feature = "enable-serde", derive(Deserialize, Serialize))]
52#[cfg_attr(feature = "artifact-size", derive(loupe::MemoryUsage))]
53#[derive(RkyvSerialize, RkyvDeserialize, Archive, Debug, Clone, PartialEq, Eq)]
54#[rkyv(derive(Debug))]
55pub struct FunctionBody {
56    /// The function body bytes.
57    #[cfg_attr(feature = "enable-serde", serde(with = "serde_bytes"))]
58    pub body: Vec<u8>,
59
60    /// The function unwind info
61    pub unwind_info: Option<CompiledFunctionUnwindInfo>,
62}
63
64pub enum CompiledFunctionBody {
65    Rkyv(FunctionBody),
66    Elf(PathBuf),
67}
68
69/// Any struct that acts like a `FunctionBody`.
70#[allow(missing_docs)]
71pub trait FunctionBodyLike<'a> {
72    type UnwindInfo: CompiledFunctionUnwindInfoLike<'a>;
73
74    fn body(&'a self) -> &'a [u8];
75    fn unwind_info(&'a self) -> Option<&'a Self::UnwindInfo>;
76}
77
78impl<'a> FunctionBodyLike<'a> for FunctionBody {
79    type UnwindInfo = CompiledFunctionUnwindInfo;
80
81    fn body(&'a self) -> &'a [u8] {
82        self.body.as_ref()
83    }
84
85    fn unwind_info(&'a self) -> Option<&'a Self::UnwindInfo> {
86        self.unwind_info.as_ref()
87    }
88}
89
90impl<'a> FunctionBodyLike<'a> for ArchivedFunctionBody {
91    type UnwindInfo = ArchivedCompiledFunctionUnwindInfo;
92
93    fn body(&'a self) -> &'a [u8] {
94        self.body.as_ref()
95    }
96
97    fn unwind_info(&'a self) -> Option<&'a Self::UnwindInfo> {
98        match self.unwind_info {
99            ArchivedOption::Some(ref x) => Some(x),
100            ArchivedOption::None => None,
101        }
102    }
103}
104
105/// The result of compiling a WebAssembly function.
106///
107/// This structure only have the compiled information data
108/// (function bytecode body, relocations, traps, jump tables
109/// and unwind information).
110#[cfg_attr(feature = "enable-serde", derive(Deserialize, Serialize))]
111#[derive(RkyvSerialize, RkyvDeserialize, Archive, Debug, Clone, PartialEq, Eq)]
112#[rkyv(derive(Debug))]
113pub struct CompiledFunction {
114    /// The function body.
115    pub body: FunctionBody,
116
117    /// The relocations (in the body)
118    pub relocations: Vec<Relocation>,
119
120    /// The frame information.
121    pub frame_info: CompiledFunctionFrameInfo,
122
123    /// The maximum stack allocation directly connected to the function itself
124    /// if tracked (does not include any potential function calls).
125    pub maximum_stack_usage: Option<usize>,
126}
127
128/// The compiled functions map (index in the Wasm -> function)
129pub type Functions = PrimaryMap<LocalFunctionIndex, CompiledFunction>;
130
131/// The custom sections for a Compilation.
132pub type CustomSections = PrimaryMap<SectionIndex, CustomSection>;
133
134/// The unwinding information for this Compilation.
135///
136/// It is used for retrieving the unwind information once an exception
137/// happens.
138/// In the future this structure may also hold other information useful
139/// for debugging.
140#[cfg_attr(feature = "enable-serde", derive(Deserialize, Serialize))]
141#[cfg_attr(feature = "artifact-size", derive(loupe::MemoryUsage))]
142#[derive(RkyvSerialize, RkyvDeserialize, Archive, Debug, PartialEq, Eq, Clone, Default)]
143#[rkyv(derive(Debug), compare(PartialEq))]
144pub struct UnwindInfo {
145    /// The section index in the [`Compilation`] that corresponds to the exception frames.
146    /// [Learn
147    /// more](https://refspecs.linuxfoundation.org/LSB_3.0.0/LSB-PDA/LSB-PDA/ehframechpt.html).
148    pub eh_frame: Option<SectionIndex>,
149    pub compact_unwind: Option<SectionIndex>,
150}
151
152impl UnwindInfo {
153    /// Creates a `Dwarf` struct with the corresponding indices for its sections
154    pub fn new(eh_frame: SectionIndex) -> Self {
155        Self {
156            eh_frame: Some(eh_frame),
157            compact_unwind: None,
158        }
159    }
160
161    pub fn new_cu(compact_unwind: SectionIndex) -> Self {
162        Self {
163            eh_frame: None,
164            compact_unwind: Some(compact_unwind),
165        }
166    }
167}
168
169/// The GOT - Global Offset Table - for this Compilation.
170///
171/// The GOT is but a list of pointers to objects (functions, data, sections..); in our context the
172/// GOT is represented simply as a custom section.
173#[cfg_attr(feature = "enable-serde", derive(Deserialize, Serialize))]
174#[cfg_attr(feature = "artifact-size", derive(loupe::MemoryUsage))]
175#[derive(RkyvSerialize, RkyvDeserialize, Archive, Debug, PartialEq, Eq, Clone, Default)]
176#[rkyv(derive(Debug))]
177pub struct GOT {
178    /// The section index in the [`Compilation`] that corresponds to the GOT.
179    pub index: Option<SectionIndex>,
180}
181
182impl GOT {
183    pub fn empty() -> Self {
184        Self { index: None }
185    }
186}
187/// The result of compiling a WebAssembly module's functions.
188#[cfg_attr(feature = "enable-serde", derive(Deserialize, Serialize))]
189#[derive(Debug, PartialEq, Eq)]
190pub struct RkyvCompilation {
191    /// Compiled code for the function bodies.
192    pub functions: Functions,
193
194    /// Custom sections for the module.
195    /// It will hold the data, for example, for constants used in a
196    /// function, global variables, rodata_64, hot/cold function partitioning, ...
197    pub custom_sections: CustomSections,
198
199    /// Trampolines to call a function defined locally in the wasm via a
200    /// provided `Vec` of values.
201    ///
202    /// This allows us to call easily Wasm functions, such as:
203    ///
204    /// ```ignore
205    /// let func = instance.exports.get_function("my_func");
206    /// func.call(&[Value::I32(1)]);
207    /// ```
208    pub function_call_trampolines: PrimaryMap<SignatureIndex, FunctionBody>,
209
210    /// Trampolines to call a dynamic function defined in
211    /// a host, from a Wasm module.
212    ///
213    /// This allows us to create dynamic Wasm functions, such as:
214    ///
215    /// ```ignore
216    /// fn my_func(values: &[Val]) -> Result<Vec<Val>, RuntimeError> {
217    ///     // do something
218    /// }
219    ///
220    /// let my_func_type = FunctionType::new(vec![Type::I32], vec![Type::I32]);
221    /// let imports = imports!{
222    ///     "namespace" => {
223    ///         "my_func" => Function::new(&store, my_func_type, my_func),
224    ///     }
225    /// }
226    /// ```
227    ///
228    /// Note: Dynamic function trampolines are only compiled for imported function types.
229    pub dynamic_function_trampolines: PrimaryMap<FunctionIndex, FunctionBody>,
230
231    /// Section ids corresponding to the unwind information.
232    pub unwind_info: UnwindInfo,
233
234    /// A reference to the [`GOT`] instance for the compilation.
235    pub got: GOT,
236}
237
238/// The result of compiling a WebAssembly module's functions can be either an RKYV-based data structure
239/// or relocatable ELF image bytes.
240#[cfg_attr(feature = "enable-serde", derive(Deserialize, Serialize))]
241#[derive(Debug, PartialEq, Eq)]
242pub enum Compilation {
243    Rkyv {
244        compilation: RkyvCompilation,
245        function_max_stack_usage: PrimaryMap<LocalFunctionIndex, Option<usize>>,
246    },
247    Elf {
248        data: Vec<u8>,
249        function_max_stack_usage: PrimaryMap<LocalFunctionIndex, Option<usize>>,
250    },
251}