wasmer_compiler/
serialize.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
7use crate::types::{
8    function::{CompiledFunctionFrameInfo, FunctionBody, GOT, UnwindInfo},
9    module::CompileModuleInfo,
10    relocation::Relocation,
11    section::{CustomSection, SectionIndex},
12};
13use enumset::EnumSet;
14use rkyv::{Archive, Deserialize as RkyvDeserialize, Serialize as RkyvSerialize};
15use wasmer_types::{
16    DeserializeError, Features, FunctionIndex, LocalFunctionIndex, MemoryIndex, MemoryStyle,
17    ModuleInfo, OwnedDataInitializer, SerializeError, SignatureIndex, TableIndex, TableStyle,
18    entity::PrimaryMap, target::CpuFeature,
19};
20
21pub use wasmer_types::MetadataHeader;
22
23/// The compilation related data for a serialized modules
24#[derive(Archive, Default, RkyvDeserialize, RkyvSerialize)]
25#[cfg_attr(feature = "artifact-size", derive(loupe::MemoryUsage))]
26#[allow(missing_docs)]
27#[rkyv(derive(Debug))]
28pub struct SerializableCompilation {
29    pub function_bodies: PrimaryMap<LocalFunctionIndex, FunctionBody>,
30    pub function_relocations: PrimaryMap<LocalFunctionIndex, Vec<Relocation>>,
31    pub function_frame_info: PrimaryMap<LocalFunctionIndex, CompiledFunctionFrameInfo>,
32    pub function_call_trampolines: PrimaryMap<SignatureIndex, FunctionBody>,
33    pub dynamic_function_trampolines: PrimaryMap<FunctionIndex, FunctionBody>,
34    pub custom_sections: PrimaryMap<SectionIndex, CustomSection>,
35    pub custom_section_relocations: PrimaryMap<SectionIndex, Vec<Relocation>>,
36    // The section indices corresponding to the Dwarf debug info
37    pub unwind_info: UnwindInfo,
38    pub got: GOT,
39    // Custom section containing libcall trampolines.
40    pub libcall_trampolines: SectionIndex,
41    // Length of each libcall trampoline.
42    pub libcall_trampoline_len: u32,
43    // The maximum stack size used for each function (available only for the Singlepass compiler).
44    pub function_max_stack_usage: PrimaryMap<LocalFunctionIndex, Option<usize>>,
45}
46
47impl SerializableCompilation {
48    /// Serialize a Compilation into bytes
49    /// The bytes will have the following format:
50    /// RKYV serialization (any length) + POS (8 bytes)
51    pub fn serialize(&self) -> Result<Vec<u8>, SerializeError> {
52        rkyv::to_bytes::<rkyv::rancor::Error>(self)
53            .map(|v| v.into_vec())
54            .map_err(|e| SerializeError::Generic(e.to_string()))
55    }
56}
57
58/// Serializable struct that is able to serialize from and to a `ArtifactInfo`.
59#[derive(Archive, RkyvDeserialize, RkyvSerialize)]
60#[cfg_attr(feature = "artifact-size", derive(loupe::MemoryUsage))]
61#[allow(missing_docs)]
62#[rkyv(derive(Debug))]
63pub struct SerializableModule {
64    /// The main serializable compilation object
65    pub compilation: SerializableCompilation,
66    /// Compilation information
67    pub compile_info: CompileModuleInfo,
68    /// Data initializers
69    pub data_initializers: Box<[OwnedDataInitializer]>,
70    /// CPU Feature flags for this compilation
71    pub cpu_features: u64,
72}
73
74impl SerializableModule {
75    /// Serialize a Module into bytes
76    /// The bytes will have the following format:
77    /// RKYV serialization (any length) + POS (8 bytes)
78    pub fn serialize(&self) -> Result<Vec<u8>, SerializeError> {
79        rkyv::to_bytes::<rkyv::rancor::Error>(self)
80            .map(|v| v.into_vec())
81            .map_err(|e| SerializeError::Generic(e.to_string()))
82    }
83
84    /// Deserialize a Module from a slice.
85    /// The slice must have the following format:
86    /// RKYV serialization (any length) + POS (8 bytes)
87    ///
88    /// # Safety
89    ///
90    /// This method is unsafe since it deserializes data directly
91    /// from memory.
92    /// Right now we are not doing any extra work for validation, but
93    /// `rkyv` has an option to do bytecheck on the serialized data before
94    /// serializing (via `rkyv::check_archived_value`).
95    pub unsafe fn deserialize_unchecked(metadata_slice: &[u8]) -> Result<Self, DeserializeError> {
96        unsafe {
97            let archived = Self::archive_from_slice(metadata_slice)?;
98            Self::deserialize_from_archive(archived)
99        }
100    }
101
102    /// Deserialize a Module from a slice.
103    /// The slice must have the following format:
104    /// RKYV serialization (any length) + POS (8 bytes)
105    ///
106    /// Unlike [`Self::deserialize`], this function will validate the data.
107    ///
108    /// # Safety
109    /// Unsafe because it loads executable code into memory.
110    /// The loaded bytes must be trusted.
111    pub unsafe fn deserialize(metadata_slice: &[u8]) -> Result<Self, DeserializeError> {
112        let archived = Self::archive_from_slice_checked(metadata_slice)?;
113        Self::deserialize_from_archive(archived)
114    }
115
116    /// # Safety
117    ///
118    /// This method is unsafe.
119    /// Please check `SerializableModule::deserialize` for more details.
120    pub unsafe fn archive_from_slice(
121        metadata_slice: &[u8],
122    ) -> Result<&ArchivedSerializableModule, DeserializeError> {
123        unsafe { Ok(rkyv::access_unchecked(metadata_slice)) }
124    }
125
126    /// Deserialize an archived module.
127    ///
128    /// In contrast to [`Self::deserialize`], this method performs validation
129    /// and is not unsafe.
130    pub fn archive_from_slice_checked(
131        metadata_slice: &[u8],
132    ) -> Result<&ArchivedSerializableModule, DeserializeError> {
133        rkyv::access::<_, rkyv::rancor::Error>(metadata_slice)
134            .map_err(|e| DeserializeError::CorruptedBinary(e.to_string()))
135    }
136
137    /// Deserialize a compilation module from an archive
138    pub fn deserialize_from_archive(
139        archived: &ArchivedSerializableModule,
140    ) -> Result<Self, DeserializeError> {
141        rkyv::deserialize::<_, rkyv::rancor::Error>(archived)
142            .map_err(|e| DeserializeError::CorruptedBinary(e.to_string()))
143    }
144
145    /// Create a `ModuleInfo` for instantiation
146    pub fn create_module_info(&self) -> ModuleInfo {
147        self.compile_info.module.as_ref().clone()
148    }
149
150    /// Returns the `ModuleInfo` for instantiation
151    pub fn module_info(&self) -> &ModuleInfo {
152        &self.compile_info.module
153    }
154
155    /// Returns the features for this Artifact
156    pub fn features(&self) -> &Features {
157        &self.compile_info.features
158    }
159
160    /// Returns the CPU features for this Artifact
161    pub fn cpu_features(&self) -> EnumSet<CpuFeature> {
162        EnumSet::from_u64(self.cpu_features)
163    }
164
165    /// Returns data initializers to pass to `VMInstance::initialize`
166    pub fn data_initializers(&self) -> &[OwnedDataInitializer] {
167        &self.data_initializers
168    }
169
170    /// Returns the memory styles associated with this `Artifact`.
171    pub fn memory_styles(&self) -> &PrimaryMap<MemoryIndex, MemoryStyle> {
172        &self.compile_info.memory_styles
173    }
174
175    /// Returns the table plans associated with this `Artifact`.
176    pub fn table_styles(&self) -> &PrimaryMap<TableIndex, TableStyle> {
177        &self.compile_info.table_styles
178    }
179}