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