wasmer_compiler/artifact_builders/
artifact_builder.rs1#[cfg(feature = "compiler")]
5use super::trampoline::{libcall_trampoline_len, make_libcall_trampolines};
6#[cfg(feature = "compiler")]
7use crate::translator::analyze_readonly_funcref_table;
8use crate::{
9 ArtifactCreate, Features,
10 serialize::{
11 ArchivedSerializableCompilation, ArchivedSerializableModule, MetadataHeader,
12 SerializableCompilation, SerializableModule,
13 },
14 types::{
15 function::{CompiledFunctionFrameInfo, FunctionBody, GOT, UnwindInfo},
16 module::CompileModuleInfo,
17 relocation::Relocation,
18 section::{CustomSection, SectionIndex},
19 },
20};
21#[cfg(feature = "compiler")]
22use crate::{
23 EngineInner, ModuleEnvironment, ModuleMiddlewareChain, serialize::RkyvSerializableCompilation,
24};
25#[cfg(feature = "compiler")]
26use wasmer_types::{CompilationProgressCallback, target::Target};
27
28use core::mem::MaybeUninit;
29use enumset::EnumSet;
30use rkyv::rancor::Error as RkyvError;
31use self_cell::self_cell;
32use shared_buffer::OwnedBuffer;
33use std::sync::Arc;
34use wasmer_types::{
35 DeserializeError,
36 entity::{ArchivedPrimaryMap, PrimaryMap},
37 target::CpuFeature,
38};
39
40#[allow(unused)]
42use wasmer_types::*;
43
44#[cfg_attr(feature = "artifact-size", derive(loupe::MemoryUsage))]
46pub struct ArtifactBuild {
47 pub(crate) serializable: SerializableModule,
48}
49
50impl ArtifactBuild {
51 pub const MAGIC_HEADER: &'static [u8; 16] = b"wasmer-universal";
53
54 pub fn is_deserializable(bytes: &[u8]) -> bool {
56 Self::has_rkyv_header(bytes) || bytes.starts_with(&object::elf::ELFMAG)
57 }
58
59 pub(crate) fn has_rkyv_header(bytes: &[u8]) -> bool {
60 bytes.starts_with(Self::MAGIC_HEADER)
61 }
62
63 #[cfg(feature = "compiler")]
65 pub fn new(
66 inner_engine: &mut EngineInner,
67 data: &[u8],
68 target: &Target,
69 memory_styles: PrimaryMap<MemoryIndex, MemoryStyle>,
70 table_styles: PrimaryMap<TableIndex, TableStyle>,
71 progress_callback: Option<&CompilationProgressCallback>,
72 ) -> Result<Self, CompileError> {
73 use crate::types::function::Compilation;
74
75 let environ = ModuleEnvironment::new();
76 let features = inner_engine.features().clone();
77
78 let translation = environ.translate(data).map_err(CompileError::Wasm)?;
79
80 let compiler = inner_engine.compiler()?;
81
82 let mut module = translation.module;
84 let middlewares = compiler.get_middlewares();
85 middlewares
86 .apply_on_module_info(&mut module)
87 .map_err(|err| CompileError::MiddlewareError(err.to_string()))?;
88 #[cfg(feature = "translator")]
89 if compiler.enable_readonly_funcref_table()
90 && let Some(table_index) =
91 analyze_readonly_funcref_table(&module, &translation.function_body_inputs)?
92 {
93 module.tables[table_index].readonly = true;
94 }
95
96 module.hash = Some(ModuleHash::new(data));
97 let compile_info = CompileModuleInfo {
98 module: Arc::new(module),
99 features,
100 memory_styles,
101 table_styles,
102 function_max_stack_usage: PrimaryMap::new(),
103 };
104 let cpu_features = compiler.get_cpu_features_used(target.cpu_features());
105 let mut serializable = SerializableModule {
106 compilation: SerializableCompilation::Elf(Vec::new()),
109 compile_info,
110 data_initializers: translation
111 .data_initializers
112 .iter()
113 .map(OwnedDataInitializer::new)
114 .collect::<Vec<_>>()
115 .into_boxed_slice(),
116 cpu_features: cpu_features.as_u64(),
117 };
118 let compile_info_blob = serializable
119 .serialize()
120 .map_err(|e| CompileError::Codegen(format!("cannot serialize SerializeModule: {e}")))?;
121
122 let compilation = compiler.compile_module(
124 target,
125 &serializable.compile_info,
126 &compile_info_blob,
127 translation.module_translation_state.as_ref().unwrap(),
131 translation.function_body_inputs,
132 progress_callback,
133 )?;
134
135 let compilation = match compilation {
136 Compilation::Rkyv {
137 compilation,
138 function_max_stack_usage,
139 } => {
140 serializable.compile_info.function_max_stack_usage = function_max_stack_usage;
141 let mut function_frame_info =
144 PrimaryMap::with_capacity(compilation.functions.len());
145 let mut function_bodies = PrimaryMap::with_capacity(compilation.functions.len());
146 let mut function_relocations =
147 PrimaryMap::with_capacity(compilation.functions.len());
148 for (_, func) in compilation.functions.into_iter() {
149 function_bodies.push(func.body);
150 function_relocations.push(func.relocations);
151 function_frame_info.push(func.frame_info);
152 }
153 let mut custom_sections = compilation.custom_sections.clone();
154 let mut custom_section_relocations = compilation
155 .custom_sections
156 .iter()
157 .map(|(_, section)| section.relocations.clone())
158 .collect::<PrimaryMap<SectionIndex, _>>();
159 let libcall_trampolines_section = make_libcall_trampolines(target);
160 custom_section_relocations.push(libcall_trampolines_section.relocations.clone());
161 let libcall_trampolines = custom_sections.push(libcall_trampolines_section);
162 let libcall_trampoline_len = libcall_trampoline_len(target) as u32;
163
164 SerializableCompilation::Rkyv(RkyvSerializableCompilation {
165 function_bodies,
166 function_relocations,
167 function_frame_info,
168 function_call_trampolines: compilation.function_call_trampolines,
169 dynamic_function_trampolines: compilation.dynamic_function_trampolines,
170 custom_sections,
171 custom_section_relocations,
172 unwind_info: compilation.unwind_info,
173 libcall_trampolines,
174 libcall_trampoline_len,
175 got: compilation.got,
176 })
177 }
178 Compilation::Elf {
179 data,
180 function_max_stack_usage,
181 } => {
182 serializable.compile_info.function_max_stack_usage = function_max_stack_usage;
183 SerializableCompilation::Elf(data)
184 }
185 };
186
187 serializable.compilation = compilation;
188 Ok(Self { serializable })
189 }
190
191 pub fn from_serializable(serializable: SerializableModule) -> Self {
193 Self { serializable }
194 }
195
196 pub fn get_function_bodies_ref(&self) -> Option<&PrimaryMap<LocalFunctionIndex, FunctionBody>> {
198 if let SerializableCompilation::Rkyv(compilation) = &self.serializable.compilation {
199 Some(&compilation.function_bodies)
200 } else {
201 None
202 }
203 }
204
205 pub fn get_function_call_trampolines_ref(
207 &self,
208 ) -> Option<&PrimaryMap<SignatureIndex, FunctionBody>> {
209 if let SerializableCompilation::Rkyv(compilation) = &self.serializable.compilation {
210 Some(&compilation.function_call_trampolines)
211 } else {
212 None
213 }
214 }
215
216 pub fn get_dynamic_function_trampolines_ref(
218 &self,
219 ) -> Option<&PrimaryMap<FunctionIndex, FunctionBody>> {
220 if let SerializableCompilation::Rkyv(compilation) = &self.serializable.compilation {
221 Some(&compilation.dynamic_function_trampolines)
222 } else {
223 None
224 }
225 }
226
227 pub fn get_custom_sections_ref(&self) -> Option<&PrimaryMap<SectionIndex, CustomSection>> {
229 if let SerializableCompilation::Rkyv(compilation) = &self.serializable.compilation {
230 Some(&compilation.custom_sections)
231 } else {
232 None
233 }
234 }
235
236 pub fn get_function_relocations(
238 &self,
239 ) -> Option<&PrimaryMap<LocalFunctionIndex, Vec<Relocation>>> {
240 if let SerializableCompilation::Rkyv(compilation) = &self.serializable.compilation {
241 Some(&compilation.function_relocations)
242 } else {
243 None
244 }
245 }
246
247 pub fn get_custom_section_relocations_ref(
249 &self,
250 ) -> Option<&PrimaryMap<SectionIndex, Vec<Relocation>>> {
251 if let SerializableCompilation::Rkyv(compilation) = &self.serializable.compilation {
252 Some(&compilation.custom_section_relocations)
253 } else {
254 None
255 }
256 }
257
258 pub fn get_libcall_trampolines(&self) -> Option<SectionIndex> {
260 if let SerializableCompilation::Rkyv(compilation) = &self.serializable.compilation {
261 Some(compilation.libcall_trampolines)
262 } else {
263 None
264 }
265 }
266
267 pub fn get_libcall_trampoline_len(&self) -> Option<usize> {
269 if let SerializableCompilation::Rkyv(compilation) = &self.serializable.compilation {
270 Some(compilation.libcall_trampoline_len as usize)
271 } else {
272 None
273 }
274 }
275
276 pub fn get_unwind_info(&self) -> Option<&UnwindInfo> {
278 if let SerializableCompilation::Rkyv(compilation) = &self.serializable.compilation {
279 Some(&compilation.unwind_info)
280 } else {
281 None
282 }
283 }
284
285 pub fn get_got_ref(&self) -> Option<&GOT> {
287 if let SerializableCompilation::Rkyv(compilation) = &self.serializable.compilation {
288 Some(&compilation.got)
289 } else {
290 None
291 }
292 }
293
294 pub fn get_frame_info_ref(
296 &self,
297 ) -> Option<&PrimaryMap<LocalFunctionIndex, CompiledFunctionFrameInfo>> {
298 if let SerializableCompilation::Rkyv(compilation) = &self.serializable.compilation {
299 Some(&compilation.function_frame_info)
300 } else {
301 None
302 }
303 }
304
305 pub fn get_function_max_stack_usage(
309 &self,
310 ) -> Option<&PrimaryMap<LocalFunctionIndex, Option<usize>>> {
311 Some(&self.serializable.compile_info.function_max_stack_usage)
312 }
313}
314
315impl<'a> ArtifactCreate<'a> for ArtifactBuild {
316 type OwnedDataInitializer = &'a OwnedDataInitializer;
317 type OwnedDataInitializerIterator = core::slice::Iter<'a, OwnedDataInitializer>;
318
319 fn create_module_info(&self) -> Arc<ModuleInfo> {
320 self.serializable.compile_info.module.clone()
321 }
322
323 fn set_module_info_name(&mut self, name: String) -> bool {
324 Arc::get_mut(&mut self.serializable.compile_info.module).is_some_and(|module_info| {
325 module_info.name = Some(name.to_string());
326 true
327 })
328 }
329
330 fn module_info(&self) -> &ModuleInfo {
331 &self.serializable.compile_info.module
332 }
333
334 fn features(&self) -> &Features {
335 &self.serializable.compile_info.features
336 }
337
338 fn cpu_features(&self) -> EnumSet<CpuFeature> {
339 EnumSet::from_u64(self.serializable.cpu_features)
340 }
341
342 fn data_initializers(&'a self) -> Self::OwnedDataInitializerIterator {
343 self.serializable.data_initializers.iter()
344 }
345
346 fn memory_styles(&self) -> &PrimaryMap<MemoryIndex, MemoryStyle> {
347 &self.serializable.compile_info.memory_styles
348 }
349
350 fn table_styles(&self) -> &PrimaryMap<TableIndex, TableStyle> {
351 &self.serializable.compile_info.table_styles
352 }
353
354 fn serialize(&self) -> Result<Vec<u8>, SerializeError> {
355 match &self.serializable.compilation {
356 SerializableCompilation::Elf(data) => Ok(data.clone()),
357 SerializableCompilation::Rkyv(_) => serialize_module(&self.serializable),
358 }
359 }
360}
361
362#[derive(Debug)]
365pub struct ModuleFromArchive<'a> {
366 pub compilation: &'a ArchivedSerializableCompilation,
368 pub data_initializers: &'a rkyv::Archived<Box<[OwnedDataInitializer]>>,
370 pub cpu_features: u64,
372
373 original_module: &'a ArchivedSerializableModule,
375}
376
377impl<'a> ModuleFromArchive<'a> {
378 pub fn from_serializable_module(
380 module: &'a ArchivedSerializableModule,
381 ) -> Result<Self, DeserializeError> {
382 Ok(Self {
383 compilation: &module.compilation,
384 data_initializers: &module.data_initializers,
385 cpu_features: module.cpu_features.to_native(),
386 original_module: module,
387 })
388 }
389}
390
391self_cell!(
392 struct ArtifactBuildFromArchiveCell {
393 owner: OwnedBuffer,
394
395 #[covariant]
396 dependent: ModuleFromArchive,
397 }
398
399 impl {Debug}
400);
401
402#[cfg(feature = "artifact-size")]
403impl loupe::MemoryUsage for ArtifactBuildFromArchiveCell {
404 fn size_of_val(&self, _tracker: &mut dyn loupe::MemoryUsageTracker) -> usize {
405 std::mem::size_of_val(self.borrow_owner()) + std::mem::size_of_val(self.borrow_dependent())
406 }
407}
408
409#[derive(Clone, Debug)]
411#[cfg_attr(feature = "artifact-size", derive(loupe::MemoryUsage))]
412pub struct ArtifactBuildFromArchive {
413 cell: Arc<ArtifactBuildFromArchiveCell>,
414
415 compile_info: CompileModuleInfo,
417}
418
419impl ArtifactBuildFromArchive {
420 #[allow(unused)]
421 pub(crate) fn try_new(
422 buffer: OwnedBuffer,
423 module_builder: impl FnOnce(
424 &OwnedBuffer,
425 ) -> Result<&ArchivedSerializableModule, DeserializeError>,
426 ) -> Result<Self, DeserializeError> {
427 let mut compile_info = MaybeUninit::uninit();
428
429 let cell = ArtifactBuildFromArchiveCell::try_new(buffer, |buffer| {
430 let module = module_builder(buffer)?;
431 compile_info = MaybeUninit::new(
432 rkyv::deserialize::<_, RkyvError>(&module.compile_info)
433 .map_err(|e| DeserializeError::CorruptedBinary(format!("{e:?}")))?,
434 );
435 ModuleFromArchive::from_serializable_module(module)
436 })?;
437
438 let compile_info = unsafe { compile_info.assume_init() };
440 Ok(Self {
441 cell: Arc::new(cell),
442 compile_info,
443 })
444 }
445
446 pub fn owned_buffer(&self) -> &OwnedBuffer {
448 self.cell.borrow_owner()
449 }
450
451 pub fn get_function_bodies_ref(
453 &self,
454 ) -> Option<&ArchivedPrimaryMap<LocalFunctionIndex, FunctionBody>> {
455 if let ArchivedSerializableCompilation::Rkyv(compilation) =
456 self.cell.borrow_dependent().compilation
457 {
458 Some(&compilation.function_bodies)
459 } else {
460 None
461 }
462 }
463
464 pub fn get_function_call_trampolines_ref(
466 &self,
467 ) -> Option<&ArchivedPrimaryMap<SignatureIndex, FunctionBody>> {
468 if let ArchivedSerializableCompilation::Rkyv(compilation) =
469 self.cell.borrow_dependent().compilation
470 {
471 Some(&compilation.function_call_trampolines)
472 } else {
473 None
474 }
475 }
476
477 pub fn get_dynamic_function_trampolines_ref(
479 &self,
480 ) -> Option<&ArchivedPrimaryMap<FunctionIndex, FunctionBody>> {
481 if let ArchivedSerializableCompilation::Rkyv(compilation) =
482 self.cell.borrow_dependent().compilation
483 {
484 Some(&compilation.dynamic_function_trampolines)
485 } else {
486 None
487 }
488 }
489
490 pub fn get_custom_sections_ref(
492 &self,
493 ) -> Option<&ArchivedPrimaryMap<SectionIndex, CustomSection>> {
494 if let ArchivedSerializableCompilation::Rkyv(compilation) =
495 self.cell.borrow_dependent().compilation
496 {
497 Some(&compilation.custom_sections)
498 } else {
499 None
500 }
501 }
502
503 pub fn get_function_relocations(
505 &self,
506 ) -> Option<&ArchivedPrimaryMap<LocalFunctionIndex, Vec<Relocation>>> {
507 if let ArchivedSerializableCompilation::Rkyv(compilation) =
508 self.cell.borrow_dependent().compilation
509 {
510 Some(&compilation.function_relocations)
511 } else {
512 None
513 }
514 }
515
516 pub fn get_custom_section_relocations_ref(
518 &self,
519 ) -> Option<&ArchivedPrimaryMap<SectionIndex, Vec<Relocation>>> {
520 if let ArchivedSerializableCompilation::Rkyv(compilation) =
521 self.cell.borrow_dependent().compilation
522 {
523 Some(&compilation.custom_section_relocations)
524 } else {
525 None
526 }
527 }
528
529 pub fn get_libcall_trampolines(&self) -> Option<SectionIndex> {
531 if let ArchivedSerializableCompilation::Rkyv(compilation) =
532 self.cell.borrow_dependent().compilation
533 {
534 Some(rkyv::deserialize::<_, RkyvError>(&compilation.libcall_trampolines).unwrap())
535 } else {
536 None
537 }
538 }
539
540 pub fn get_libcall_trampoline_len(&self) -> Option<usize> {
542 if let ArchivedSerializableCompilation::Rkyv(compilation) =
543 self.cell.borrow_dependent().compilation
544 {
545 Some(compilation.libcall_trampoline_len.to_native() as usize)
546 } else {
547 None
548 }
549 }
550
551 pub fn get_unwind_info(&self) -> Option<UnwindInfo> {
553 if let ArchivedSerializableCompilation::Rkyv(compilation) =
554 self.cell.borrow_dependent().compilation
555 {
556 Some(rkyv::deserialize::<_, rkyv::rancor::Error>(&compilation.unwind_info).unwrap())
557 } else {
558 None
559 }
560 }
561
562 pub fn get_got_ref(&self) -> Option<GOT> {
564 if let ArchivedSerializableCompilation::Rkyv(compilation) =
565 self.cell.borrow_dependent().compilation
566 {
567 Some(rkyv::deserialize::<_, rkyv::rancor::Error>(&compilation.got).unwrap())
568 } else {
569 None
570 }
571 }
572
573 pub fn get_frame_info_ref(
575 &self,
576 ) -> Option<&ArchivedPrimaryMap<LocalFunctionIndex, CompiledFunctionFrameInfo>> {
577 if let ArchivedSerializableCompilation::Rkyv(compilation) =
578 self.cell.borrow_dependent().compilation
579 {
580 Some(&compilation.function_frame_info)
581 } else {
582 None
583 }
584 }
585
586 pub fn deserialize_frame_info_ref(
588 &self,
589 ) -> Result<PrimaryMap<LocalFunctionIndex, CompiledFunctionFrameInfo>, DeserializeError> {
590 if let ArchivedSerializableCompilation::Rkyv(compilation) =
591 self.cell.borrow_dependent().compilation
592 {
593 rkyv::deserialize::<_, RkyvError>(&compilation.function_frame_info)
594 .map_err(|e| DeserializeError::CorruptedBinary(format!("{e:?}")))
595 } else {
596 Err(DeserializeError::CorruptedBinary(
597 "expected RKYV compilation".to_string(),
598 ))
599 }
600 }
601
602 pub fn get_function_max_stack_usage(
606 &self,
607 ) -> Option<&PrimaryMap<LocalFunctionIndex, Option<usize>>> {
608 Some(&self.compile_info.function_max_stack_usage)
609 }
610
611 pub fn get_elf_file(&self) -> Option<&[u8]> {
613 if let ArchivedSerializableCompilation::Elf(data) = self.cell.borrow_dependent().compilation
614 {
615 Some(data)
616 } else {
617 None
618 }
619 }
620}
621
622impl<'a> ArtifactCreate<'a> for ArtifactBuildFromArchive {
623 type OwnedDataInitializer = &'a ArchivedOwnedDataInitializer;
624 type OwnedDataInitializerIterator = core::slice::Iter<'a, ArchivedOwnedDataInitializer>;
625
626 fn create_module_info(&self) -> Arc<ModuleInfo> {
627 self.compile_info.module.clone()
628 }
629
630 fn set_module_info_name(&mut self, name: String) -> bool {
631 Arc::get_mut(&mut self.compile_info.module).is_some_and(|module_info| {
632 module_info.name = Some(name.to_string());
633 true
634 })
635 }
636
637 fn module_info(&self) -> &ModuleInfo {
638 &self.compile_info.module
639 }
640
641 fn features(&self) -> &Features {
642 &self.compile_info.features
643 }
644
645 fn cpu_features(&self) -> EnumSet<CpuFeature> {
646 EnumSet::from_u64(self.cell.borrow_dependent().cpu_features)
647 }
648
649 fn data_initializers(&'a self) -> Self::OwnedDataInitializerIterator {
650 self.cell.borrow_dependent().data_initializers.iter()
651 }
652
653 fn memory_styles(&self) -> &PrimaryMap<MemoryIndex, MemoryStyle> {
654 &self.compile_info.memory_styles
655 }
656
657 fn table_styles(&self) -> &PrimaryMap<TableIndex, TableStyle> {
658 &self.compile_info.table_styles
659 }
660
661 fn serialize(&self) -> Result<Vec<u8>, SerializeError> {
662 if let ArchivedSerializableCompilation::Elf(data) = self.cell.borrow_dependent().compilation
663 {
664 return Ok(data.to_vec());
665 }
666
667 let mut module: SerializableModule =
675 rkyv::deserialize::<_, RkyvError>(self.cell.borrow_dependent().original_module)
676 .map_err(|e| SerializeError::Generic(e.to_string()))?;
677 module.compile_info = self.compile_info.clone();
678 serialize_module(&module)
679 }
680}
681
682fn serialize_module(module: &SerializableModule) -> Result<Vec<u8>, SerializeError> {
683 let serialized_data = module.serialize()?;
684 assert!(std::mem::align_of::<SerializableModule>() <= MetadataHeader::ALIGN);
685
686 let mut metadata_binary = vec![];
687 metadata_binary.extend(ArtifactBuild::MAGIC_HEADER);
688 metadata_binary.extend(MetadataHeader::new(serialized_data.len()).into_bytes());
689 metadata_binary.extend(serialized_data);
690 Ok(metadata_binary)
691}