hc_wasmer_types/compilation/
function.rs

1// This file contains code from external sources.
2// Attributions: https://github.com/wasmerio/wasmer/blob/main/docs/ATTRIBUTIONS.md
3
4//! A `Compilation` contains the compiled function bodies for a WebAssembly
5//! module (`CompiledFunction`).
6
7use crate::entity::PrimaryMap;
8use crate::lib::std::vec::Vec;
9use crate::{ArchivedCompiledFunctionUnwindInfo, TrapInformation};
10use crate::{CompiledFunctionUnwindInfo, FunctionAddressMap};
11use crate::{
12    CustomSection, FunctionIndex, LocalFunctionIndex, Relocation, SectionIndex, SignatureIndex,
13};
14use rkyv::option::ArchivedOption;
15use rkyv::{Archive, Deserialize as RkyvDeserialize, Serialize as RkyvSerialize};
16#[cfg(feature = "enable-serde")]
17use serde::{Deserialize, Serialize};
18
19use super::unwind::CompiledFunctionUnwindInfoLike;
20
21/// The frame info for a Compiled function.
22///
23/// This structure is only used for reconstructing
24/// the frame information after a `Trap`.
25#[cfg_attr(feature = "enable-serde", derive(Deserialize, Serialize))]
26#[derive(RkyvSerialize, RkyvDeserialize, Archive, Debug, Clone, PartialEq, Eq, Default)]
27#[archive_attr(derive(rkyv::CheckBytes, Debug))]
28pub struct CompiledFunctionFrameInfo {
29    /// The traps (in the function body).
30    ///
31    /// Code offsets of the traps MUST be in ascending order.
32    pub traps: Vec<TrapInformation>,
33
34    /// The address map.
35    pub address_map: FunctionAddressMap,
36}
37
38/// The function body.
39#[cfg_attr(feature = "enable-serde", derive(Deserialize, Serialize))]
40#[derive(RkyvSerialize, RkyvDeserialize, Archive, Debug, Clone, PartialEq, Eq)]
41#[archive_attr(derive(rkyv::CheckBytes, Debug))]
42pub struct FunctionBody {
43    /// The function body bytes.
44    #[cfg_attr(feature = "enable-serde", serde(with = "serde_bytes"))]
45    pub body: Vec<u8>,
46
47    /// The function unwind info
48    pub unwind_info: Option<CompiledFunctionUnwindInfo>,
49}
50
51/// Any struct that acts like a `FunctionBody`.
52#[allow(missing_docs)]
53pub trait FunctionBodyLike<'a> {
54    type UnwindInfo: CompiledFunctionUnwindInfoLike<'a>;
55
56    fn body(&'a self) -> &'a [u8];
57    fn unwind_info(&'a self) -> Option<&Self::UnwindInfo>;
58}
59
60impl<'a> FunctionBodyLike<'a> for FunctionBody {
61    type UnwindInfo = CompiledFunctionUnwindInfo;
62
63    fn body(&'a self) -> &'a [u8] {
64        self.body.as_ref()
65    }
66
67    fn unwind_info(&'a self) -> Option<&Self::UnwindInfo> {
68        self.unwind_info.as_ref()
69    }
70}
71
72impl<'a> FunctionBodyLike<'a> for ArchivedFunctionBody {
73    type UnwindInfo = ArchivedCompiledFunctionUnwindInfo;
74
75    fn body(&'a self) -> &'a [u8] {
76        self.body.as_ref()
77    }
78
79    fn unwind_info(&'a self) -> Option<&Self::UnwindInfo> {
80        match self.unwind_info {
81            ArchivedOption::Some(ref x) => Some(x),
82            ArchivedOption::None => None,
83        }
84    }
85}
86
87/// The result of compiling a WebAssembly function.
88///
89/// This structure only have the compiled information data
90/// (function bytecode body, relocations, traps, jump tables
91/// and unwind information).
92#[cfg_attr(feature = "enable-serde", derive(Deserialize, Serialize))]
93#[derive(RkyvSerialize, RkyvDeserialize, Archive, Debug, Clone, PartialEq, Eq)]
94#[archive_attr(derive(rkyv::CheckBytes, Debug))]
95pub struct CompiledFunction {
96    /// The function body.
97    pub body: FunctionBody,
98
99    /// The relocations (in the body)
100    pub relocations: Vec<Relocation>,
101
102    /// The frame information.
103    pub frame_info: CompiledFunctionFrameInfo,
104}
105
106/// The compiled functions map (index in the Wasm -> function)
107pub type Functions = PrimaryMap<LocalFunctionIndex, CompiledFunction>;
108
109/// The custom sections for a Compilation.
110pub type CustomSections = PrimaryMap<SectionIndex, CustomSection>;
111
112/// The DWARF information for this Compilation.
113///
114/// It is used for retrieving the unwind information once an exception
115/// happens.
116/// In the future this structure may also hold other information useful
117/// for debugging.
118#[cfg_attr(feature = "enable-serde", derive(Deserialize, Serialize))]
119#[derive(
120    RkyvSerialize, RkyvDeserialize, Archive, rkyv::CheckBytes, Debug, PartialEq, Eq, Clone,
121)]
122#[archive(as = "Self")]
123pub struct Dwarf {
124    /// The section index in the [`Compilation`] that corresponds to the exception frames.
125    /// [Learn
126    /// more](https://refspecs.linuxfoundation.org/LSB_3.0.0/LSB-PDA/LSB-PDA/ehframechpt.html).
127    pub eh_frame: SectionIndex,
128}
129
130impl Dwarf {
131    /// Creates a `Dwarf` struct with the corresponding indices for its sections
132    pub fn new(eh_frame: SectionIndex) -> Self {
133        Self { eh_frame }
134    }
135}
136
137/// The result of compiling a WebAssembly module's functions.
138#[cfg_attr(feature = "enable-serde", derive(Deserialize, Serialize))]
139#[derive(Debug, PartialEq, Eq)]
140pub struct Compilation {
141    /// Compiled code for the function bodies.
142    pub functions: Functions,
143
144    /// Custom sections for the module.
145    /// It will hold the data, for example, for constants used in a
146    /// function, global variables, rodata_64, hot/cold function partitioning, ...
147    pub custom_sections: CustomSections,
148
149    /// Trampolines to call a function defined locally in the wasm via a
150    /// provided `Vec` of values.
151    ///
152    /// This allows us to call easily Wasm functions, such as:
153    ///
154    /// ```ignore
155    /// let func = instance.exports.get_function("my_func");
156    /// func.call(&[Value::I32(1)]);
157    /// ```
158    pub function_call_trampolines: PrimaryMap<SignatureIndex, FunctionBody>,
159
160    /// Trampolines to call a dynamic function defined in
161    /// a host, from a Wasm module.
162    ///
163    /// This allows us to create dynamic Wasm functions, such as:
164    ///
165    /// ```ignore
166    /// fn my_func(values: &[Val]) -> Result<Vec<Val>, RuntimeError> {
167    ///     // do something
168    /// }
169    ///
170    /// let my_func_type = FunctionType::new(vec![Type::I32], vec![Type::I32]);
171    /// let imports = imports!{
172    ///     "namespace" => {
173    ///         "my_func" => Function::new(&store, my_func_type, my_func),
174    ///     }
175    /// }
176    /// ```
177    ///
178    /// Note: Dynamic function trampolines are only compiled for imported function types.
179    pub dynamic_function_trampolines: PrimaryMap<FunctionIndex, FunctionBody>,
180
181    /// Section ids corresponding to the Dwarf debug info
182    pub debug: Option<Dwarf>,
183}