wasmer_compiler/artifact_builders/
artifact_builder.rs1#[cfg(feature = "compiler")]
5use super::trampoline::{libcall_trampoline_len, make_libcall_trampolines};
6
7use crate::{
8 ArtifactCreate, Features,
9 serialize::{
10 ArchivedSerializableCompilation, ArchivedSerializableModule, MetadataHeader,
11 SerializableModule,
12 },
13 types::{
14 function::{CompiledFunctionFrameInfo, FunctionBody, GOT, UnwindInfo},
15 module::CompileModuleInfo,
16 relocation::Relocation,
17 section::{CustomSection, SectionIndex},
18 },
19};
20#[cfg(feature = "compiler")]
21use crate::{
22 EngineInner, ModuleEnvironment, ModuleMiddlewareChain, serialize::SerializableCompilation,
23};
24#[cfg(feature = "compiler")]
25use wasmer_types::target::Target;
26
27use core::mem::MaybeUninit;
28use enumset::EnumSet;
29use rkyv::rancor::Error as RkyvError;
30use self_cell::self_cell;
31use shared_buffer::OwnedBuffer;
32use std::sync::Arc;
33use wasmer_types::{
34 CompilationProgressCallback, DeserializeError,
35 entity::{ArchivedPrimaryMap, PrimaryMap},
36 target::CpuFeature,
37};
38
39#[allow(unused)]
41use wasmer_types::*;
42
43#[cfg_attr(feature = "artifact-size", derive(loupe::MemoryUsage))]
45pub struct ArtifactBuild {
46 serializable: SerializableModule,
47}
48
49impl ArtifactBuild {
50 pub const MAGIC_HEADER: &'static [u8; 16] = b"wasmer-universal";
52
53 pub fn is_deserializable(bytes: &[u8]) -> bool {
55 bytes.starts_with(Self::MAGIC_HEADER)
56 }
57
58 #[cfg(feature = "compiler")]
60 pub fn new(
61 inner_engine: &mut EngineInner,
62 data: &[u8],
63 target: &Target,
64 memory_styles: PrimaryMap<MemoryIndex, MemoryStyle>,
65 table_styles: PrimaryMap<TableIndex, TableStyle>,
66 progress_callback: Option<&CompilationProgressCallback>,
67 ) -> Result<Self, CompileError> {
68 let environ = ModuleEnvironment::new();
69 let features = inner_engine.features().clone();
70
71 let translation = environ.translate(data).map_err(CompileError::Wasm)?;
72
73 let compiler = inner_engine.compiler()?;
74
75 let mut module = translation.module;
77 let middlewares = compiler.get_middlewares();
78 middlewares
79 .apply_on_module_info(&mut module)
80 .map_err(|err| CompileError::MiddlewareError(err.to_string()))?;
81 module.hash = Some(ModuleHash::new(data));
82
83 let compile_info = CompileModuleInfo {
84 module: Arc::new(module),
85 features,
86 memory_styles,
87 table_styles,
88 };
89
90 let compilation = compiler.compile_module(
92 target,
93 &compile_info,
94 translation.module_translation_state.as_ref().unwrap(),
98 translation.function_body_inputs,
99 progress_callback,
100 )?;
101
102 let data_initializers = translation
103 .data_initializers
104 .iter()
105 .map(OwnedDataInitializer::new)
106 .collect::<Vec<_>>()
107 .into_boxed_slice();
108
109 let mut function_frame_info = PrimaryMap::with_capacity(compilation.functions.len());
111 let mut function_bodies = PrimaryMap::with_capacity(compilation.functions.len());
112 let mut function_relocations = PrimaryMap::with_capacity(compilation.functions.len());
113 for (_, func) in compilation.functions.into_iter() {
114 function_bodies.push(func.body);
115 function_relocations.push(func.relocations);
116 function_frame_info.push(func.frame_info);
117 }
118 let mut custom_sections = compilation.custom_sections.clone();
119 let mut custom_section_relocations = compilation
120 .custom_sections
121 .iter()
122 .map(|(_, section)| section.relocations.clone())
123 .collect::<PrimaryMap<SectionIndex, _>>();
124 let libcall_trampolines_section = make_libcall_trampolines(target);
125 custom_section_relocations.push(libcall_trampolines_section.relocations.clone());
126 let libcall_trampolines = custom_sections.push(libcall_trampolines_section);
127 let libcall_trampoline_len = libcall_trampoline_len(target) as u32;
128 let cpu_features = compiler.get_cpu_features_used(target.cpu_features());
129
130 let serializable_compilation = SerializableCompilation {
131 function_bodies,
132 function_relocations,
133 function_frame_info,
134 function_call_trampolines: compilation.function_call_trampolines,
135 dynamic_function_trampolines: compilation.dynamic_function_trampolines,
136 custom_sections,
137 custom_section_relocations,
138 unwind_info: compilation.unwind_info,
139 libcall_trampolines,
140 libcall_trampoline_len,
141 got: compilation.got,
142 };
143 let serializable = SerializableModule {
144 compilation: serializable_compilation,
145 compile_info,
146 data_initializers,
147 cpu_features: cpu_features.as_u64(),
148 };
149 Ok(Self { serializable })
150 }
151
152 pub fn from_serializable(serializable: SerializableModule) -> Self {
154 Self { serializable }
155 }
156
157 pub fn get_function_bodies_ref(&self) -> &PrimaryMap<LocalFunctionIndex, FunctionBody> {
159 &self.serializable.compilation.function_bodies
160 }
161
162 pub fn get_function_call_trampolines_ref(&self) -> &PrimaryMap<SignatureIndex, FunctionBody> {
164 &self.serializable.compilation.function_call_trampolines
165 }
166
167 pub fn get_dynamic_function_trampolines_ref(&self) -> &PrimaryMap<FunctionIndex, FunctionBody> {
169 &self.serializable.compilation.dynamic_function_trampolines
170 }
171
172 pub fn get_custom_sections_ref(&self) -> &PrimaryMap<SectionIndex, CustomSection> {
174 &self.serializable.compilation.custom_sections
175 }
176
177 pub fn get_function_relocations(&self) -> &PrimaryMap<LocalFunctionIndex, Vec<Relocation>> {
179 &self.serializable.compilation.function_relocations
180 }
181
182 pub fn get_custom_section_relocations_ref(&self) -> &PrimaryMap<SectionIndex, Vec<Relocation>> {
184 &self.serializable.compilation.custom_section_relocations
185 }
186
187 pub fn get_libcall_trampolines(&self) -> SectionIndex {
189 self.serializable.compilation.libcall_trampolines
190 }
191
192 pub fn get_libcall_trampoline_len(&self) -> usize {
194 self.serializable.compilation.libcall_trampoline_len as usize
195 }
196
197 pub fn get_unwind_info(&self) -> &UnwindInfo {
199 &self.serializable.compilation.unwind_info
200 }
201
202 pub fn get_got_ref(&self) -> &GOT {
204 &self.serializable.compilation.got
205 }
206
207 pub fn get_frame_info_ref(&self) -> &PrimaryMap<LocalFunctionIndex, CompiledFunctionFrameInfo> {
209 &self.serializable.compilation.function_frame_info
210 }
211}
212
213impl<'a> ArtifactCreate<'a> for ArtifactBuild {
214 type OwnedDataInitializer = &'a OwnedDataInitializer;
215 type OwnedDataInitializerIterator = core::slice::Iter<'a, OwnedDataInitializer>;
216
217 fn create_module_info(&self) -> Arc<ModuleInfo> {
218 self.serializable.compile_info.module.clone()
219 }
220
221 fn set_module_info_name(&mut self, name: String) -> bool {
222 Arc::get_mut(&mut self.serializable.compile_info.module).is_some_and(|module_info| {
223 module_info.name = Some(name.to_string());
224 true
225 })
226 }
227
228 fn module_info(&self) -> &ModuleInfo {
229 &self.serializable.compile_info.module
230 }
231
232 fn features(&self) -> &Features {
233 &self.serializable.compile_info.features
234 }
235
236 fn cpu_features(&self) -> EnumSet<CpuFeature> {
237 EnumSet::from_u64(self.serializable.cpu_features)
238 }
239
240 fn data_initializers(&'a self) -> Self::OwnedDataInitializerIterator {
241 self.serializable.data_initializers.iter()
242 }
243
244 fn memory_styles(&self) -> &PrimaryMap<MemoryIndex, MemoryStyle> {
245 &self.serializable.compile_info.memory_styles
246 }
247
248 fn table_styles(&self) -> &PrimaryMap<TableIndex, TableStyle> {
249 &self.serializable.compile_info.table_styles
250 }
251
252 fn serialize(&self) -> Result<Vec<u8>, SerializeError> {
253 serialize_module(&self.serializable)
254 }
255}
256
257#[derive(Debug)]
260pub struct ModuleFromArchive<'a> {
261 pub compilation: &'a ArchivedSerializableCompilation,
263 pub data_initializers: &'a rkyv::Archived<Box<[OwnedDataInitializer]>>,
265 pub cpu_features: u64,
267
268 original_module: &'a ArchivedSerializableModule,
270}
271
272impl<'a> ModuleFromArchive<'a> {
273 pub fn from_serializable_module(
275 module: &'a ArchivedSerializableModule,
276 ) -> Result<Self, DeserializeError> {
277 Ok(Self {
278 compilation: &module.compilation,
279 data_initializers: &module.data_initializers,
280 cpu_features: module.cpu_features.to_native(),
281 original_module: module,
282 })
283 }
284}
285
286self_cell!(
287 struct ArtifactBuildFromArchiveCell {
288 owner: OwnedBuffer,
289
290 #[covariant]
291 dependent: ModuleFromArchive,
292 }
293
294 impl {Debug}
295);
296
297#[cfg(feature = "artifact-size")]
298impl loupe::MemoryUsage for ArtifactBuildFromArchiveCell {
299 fn size_of_val(&self, _tracker: &mut dyn loupe::MemoryUsageTracker) -> usize {
300 std::mem::size_of_val(self.borrow_owner()) + std::mem::size_of_val(self.borrow_dependent())
301 }
302}
303
304#[derive(Clone, Debug)]
306#[cfg_attr(feature = "artifact-size", derive(loupe::MemoryUsage))]
307pub struct ArtifactBuildFromArchive {
308 cell: Arc<ArtifactBuildFromArchiveCell>,
309
310 compile_info: CompileModuleInfo,
312}
313
314impl ArtifactBuildFromArchive {
315 #[allow(unused)]
316 pub(crate) fn try_new(
317 buffer: OwnedBuffer,
318 module_builder: impl FnOnce(
319 &OwnedBuffer,
320 ) -> Result<&ArchivedSerializableModule, DeserializeError>,
321 ) -> Result<Self, DeserializeError> {
322 let mut compile_info = MaybeUninit::uninit();
323
324 let cell = ArtifactBuildFromArchiveCell::try_new(buffer, |buffer| {
325 let module = module_builder(buffer)?;
326 compile_info = MaybeUninit::new(
327 rkyv::deserialize::<_, RkyvError>(&module.compile_info)
328 .map_err(|e| DeserializeError::CorruptedBinary(format!("{e:?}")))?,
329 );
330 ModuleFromArchive::from_serializable_module(module)
331 })?;
332
333 let compile_info = unsafe { compile_info.assume_init() };
335 Ok(Self {
336 cell: Arc::new(cell),
337 compile_info,
338 })
339 }
340
341 pub fn owned_buffer(&self) -> &OwnedBuffer {
343 self.cell.borrow_owner()
344 }
345
346 pub fn get_function_bodies_ref(&self) -> &ArchivedPrimaryMap<LocalFunctionIndex, FunctionBody> {
348 &self.cell.borrow_dependent().compilation.function_bodies
349 }
350
351 pub fn get_function_call_trampolines_ref(
353 &self,
354 ) -> &ArchivedPrimaryMap<SignatureIndex, FunctionBody> {
355 &self
356 .cell
357 .borrow_dependent()
358 .compilation
359 .function_call_trampolines
360 }
361
362 pub fn get_dynamic_function_trampolines_ref(
364 &self,
365 ) -> &ArchivedPrimaryMap<FunctionIndex, FunctionBody> {
366 &self
367 .cell
368 .borrow_dependent()
369 .compilation
370 .dynamic_function_trampolines
371 }
372
373 pub fn get_custom_sections_ref(&self) -> &ArchivedPrimaryMap<SectionIndex, CustomSection> {
375 &self.cell.borrow_dependent().compilation.custom_sections
376 }
377
378 pub fn get_function_relocations(
380 &self,
381 ) -> &ArchivedPrimaryMap<LocalFunctionIndex, Vec<Relocation>> {
382 &self
383 .cell
384 .borrow_dependent()
385 .compilation
386 .function_relocations
387 }
388
389 pub fn get_custom_section_relocations_ref(
391 &self,
392 ) -> &ArchivedPrimaryMap<SectionIndex, Vec<Relocation>> {
393 &self
394 .cell
395 .borrow_dependent()
396 .compilation
397 .custom_section_relocations
398 }
399
400 pub fn get_libcall_trampolines(&self) -> SectionIndex {
402 rkyv::deserialize::<_, RkyvError>(
403 &self.cell.borrow_dependent().compilation.libcall_trampolines,
404 )
405 .unwrap()
406 }
407
408 pub fn get_libcall_trampoline_len(&self) -> usize {
410 self.cell
411 .borrow_dependent()
412 .compilation
413 .libcall_trampoline_len
414 .to_native() as usize
415 }
416
417 pub fn get_unwind_info(&self) -> UnwindInfo {
419 rkyv::deserialize::<_, rkyv::rancor::Error>(
420 &self.cell.borrow_dependent().compilation.unwind_info,
421 )
422 .unwrap()
423 }
424
425 pub fn get_got_ref(&self) -> GOT {
427 rkyv::deserialize::<_, rkyv::rancor::Error>(&self.cell.borrow_dependent().compilation.got)
428 .unwrap()
429 }
430
431 pub fn get_frame_info_ref(
433 &self,
434 ) -> &ArchivedPrimaryMap<LocalFunctionIndex, CompiledFunctionFrameInfo> {
435 &self.cell.borrow_dependent().compilation.function_frame_info
436 }
437
438 pub fn deserialize_frame_info_ref(
440 &self,
441 ) -> Result<PrimaryMap<LocalFunctionIndex, CompiledFunctionFrameInfo>, DeserializeError> {
442 rkyv::deserialize::<_, RkyvError>(
443 &self.cell.borrow_dependent().compilation.function_frame_info,
444 )
445 .map_err(|e| DeserializeError::CorruptedBinary(format!("{e:?}")))
446 }
447}
448
449impl<'a> ArtifactCreate<'a> for ArtifactBuildFromArchive {
450 type OwnedDataInitializer = &'a ArchivedOwnedDataInitializer;
451 type OwnedDataInitializerIterator = core::slice::Iter<'a, ArchivedOwnedDataInitializer>;
452
453 fn create_module_info(&self) -> Arc<ModuleInfo> {
454 self.compile_info.module.clone()
455 }
456
457 fn set_module_info_name(&mut self, name: String) -> bool {
458 Arc::get_mut(&mut self.compile_info.module).is_some_and(|module_info| {
459 module_info.name = Some(name.to_string());
460 true
461 })
462 }
463
464 fn module_info(&self) -> &ModuleInfo {
465 &self.compile_info.module
466 }
467
468 fn features(&self) -> &Features {
469 &self.compile_info.features
470 }
471
472 fn cpu_features(&self) -> EnumSet<CpuFeature> {
473 EnumSet::from_u64(self.cell.borrow_dependent().cpu_features)
474 }
475
476 fn data_initializers(&'a self) -> Self::OwnedDataInitializerIterator {
477 self.cell.borrow_dependent().data_initializers.iter()
478 }
479
480 fn memory_styles(&self) -> &PrimaryMap<MemoryIndex, MemoryStyle> {
481 &self.compile_info.memory_styles
482 }
483
484 fn table_styles(&self) -> &PrimaryMap<TableIndex, TableStyle> {
485 &self.compile_info.table_styles
486 }
487
488 fn serialize(&self) -> Result<Vec<u8>, SerializeError> {
489 let mut module: SerializableModule =
497 rkyv::deserialize::<_, RkyvError>(self.cell.borrow_dependent().original_module)
498 .map_err(|e| SerializeError::Generic(e.to_string()))?;
499 module.compile_info = self.compile_info.clone();
500 serialize_module(&module)
501 }
502}
503
504fn serialize_module(module: &SerializableModule) -> Result<Vec<u8>, SerializeError> {
505 let serialized_data = module.serialize()?;
506 assert!(std::mem::align_of::<SerializableModule>() <= MetadataHeader::ALIGN);
507
508 let mut metadata_binary = vec![];
509 metadata_binary.extend(ArtifactBuild::MAGIC_HEADER);
510 metadata_binary.extend(MetadataHeader::new(serialized_data.len()).into_bytes());
511 metadata_binary.extend(serialized_data);
512 Ok(metadata_binary)
513}