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 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::SerializableCompilation,
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 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 let environ = ModuleEnvironment::new();
70 let features = inner_engine.features().clone();
71
72 let translation = environ.translate(data).map_err(CompileError::Wasm)?;
73
74 let compiler = inner_engine.compiler()?;
75
76 let mut module = translation.module;
78 let middlewares = compiler.get_middlewares();
79 middlewares
80 .apply_on_module_info(&mut module)
81 .map_err(|err| CompileError::MiddlewareError(err.to_string()))?;
82 #[cfg(feature = "translator")]
83 if compiler.enable_readonly_funcref_table()
84 && let Some(table_index) =
85 analyze_readonly_funcref_table(&module, &translation.function_body_inputs)?
86 {
87 module.tables[table_index].readonly = true;
88 }
89
90 module.hash = Some(ModuleHash::new(data));
91 let compile_info = CompileModuleInfo {
92 module: Arc::new(module),
93 features,
94 memory_styles,
95 table_styles,
96 };
97
98 let compilation = compiler.compile_module(
100 target,
101 &compile_info,
102 translation.module_translation_state.as_ref().unwrap(),
106 translation.function_body_inputs,
107 progress_callback,
108 )?;
109
110 let data_initializers = translation
111 .data_initializers
112 .iter()
113 .map(OwnedDataInitializer::new)
114 .collect::<Vec<_>>()
115 .into_boxed_slice();
116
117 let mut function_frame_info = PrimaryMap::with_capacity(compilation.functions.len());
119 let mut function_bodies = PrimaryMap::with_capacity(compilation.functions.len());
120 let mut function_relocations = PrimaryMap::with_capacity(compilation.functions.len());
121 let mut function_max_stack_usage = PrimaryMap::with_capacity(compilation.functions.len());
122 for (_, func) in compilation.functions.into_iter() {
123 function_bodies.push(func.body);
124 function_relocations.push(func.relocations);
125 function_frame_info.push(func.frame_info);
126 function_max_stack_usage.push(func.maximum_stack_usage);
127 }
128 let mut custom_sections = compilation.custom_sections.clone();
129 let mut custom_section_relocations = compilation
130 .custom_sections
131 .iter()
132 .map(|(_, section)| section.relocations.clone())
133 .collect::<PrimaryMap<SectionIndex, _>>();
134 let libcall_trampolines_section = make_libcall_trampolines(target);
135 custom_section_relocations.push(libcall_trampolines_section.relocations.clone());
136 let libcall_trampolines = custom_sections.push(libcall_trampolines_section);
137 let libcall_trampoline_len = libcall_trampoline_len(target) as u32;
138 let cpu_features = compiler.get_cpu_features_used(target.cpu_features());
139
140 let serializable_compilation = SerializableCompilation {
141 function_bodies,
142 function_relocations,
143 function_frame_info,
144 function_max_stack_usage,
145 function_call_trampolines: compilation.function_call_trampolines,
146 dynamic_function_trampolines: compilation.dynamic_function_trampolines,
147 custom_sections,
148 custom_section_relocations,
149 unwind_info: compilation.unwind_info,
150 libcall_trampolines,
151 libcall_trampoline_len,
152 got: compilation.got,
153 };
154 let serializable = SerializableModule {
155 compilation: serializable_compilation,
156 compile_info,
157 data_initializers,
158 cpu_features: cpu_features.as_u64(),
159 };
160 Ok(Self { serializable })
161 }
162
163 pub fn from_serializable(serializable: SerializableModule) -> Self {
165 Self { serializable }
166 }
167
168 pub fn get_function_bodies_ref(&self) -> &PrimaryMap<LocalFunctionIndex, FunctionBody> {
170 &self.serializable.compilation.function_bodies
171 }
172
173 pub fn get_function_call_trampolines_ref(&self) -> &PrimaryMap<SignatureIndex, FunctionBody> {
175 &self.serializable.compilation.function_call_trampolines
176 }
177
178 pub fn get_dynamic_function_trampolines_ref(&self) -> &PrimaryMap<FunctionIndex, FunctionBody> {
180 &self.serializable.compilation.dynamic_function_trampolines
181 }
182
183 pub fn get_custom_sections_ref(&self) -> &PrimaryMap<SectionIndex, CustomSection> {
185 &self.serializable.compilation.custom_sections
186 }
187
188 pub fn get_function_relocations(&self) -> &PrimaryMap<LocalFunctionIndex, Vec<Relocation>> {
190 &self.serializable.compilation.function_relocations
191 }
192
193 pub fn get_custom_section_relocations_ref(&self) -> &PrimaryMap<SectionIndex, Vec<Relocation>> {
195 &self.serializable.compilation.custom_section_relocations
196 }
197
198 pub fn get_libcall_trampolines(&self) -> SectionIndex {
200 self.serializable.compilation.libcall_trampolines
201 }
202
203 pub fn get_libcall_trampoline_len(&self) -> usize {
205 self.serializable.compilation.libcall_trampoline_len as usize
206 }
207
208 pub fn get_unwind_info(&self) -> &UnwindInfo {
210 &self.serializable.compilation.unwind_info
211 }
212
213 pub fn get_got_ref(&self) -> &GOT {
215 &self.serializable.compilation.got
216 }
217
218 pub fn get_frame_info_ref(&self) -> &PrimaryMap<LocalFunctionIndex, CompiledFunctionFrameInfo> {
220 &self.serializable.compilation.function_frame_info
221 }
222
223 pub fn get_function_max_stack_usage(&self) -> &PrimaryMap<LocalFunctionIndex, Option<usize>> {
227 &self.serializable.compilation.function_max_stack_usage
228 }
229}
230
231impl<'a> ArtifactCreate<'a> for ArtifactBuild {
232 type OwnedDataInitializer = &'a OwnedDataInitializer;
233 type OwnedDataInitializerIterator = core::slice::Iter<'a, OwnedDataInitializer>;
234
235 fn create_module_info(&self) -> Arc<ModuleInfo> {
236 self.serializable.compile_info.module.clone()
237 }
238
239 fn set_module_info_name(&mut self, name: String) -> bool {
240 Arc::get_mut(&mut self.serializable.compile_info.module).is_some_and(|module_info| {
241 module_info.name = Some(name.to_string());
242 true
243 })
244 }
245
246 fn module_info(&self) -> &ModuleInfo {
247 &self.serializable.compile_info.module
248 }
249
250 fn features(&self) -> &Features {
251 &self.serializable.compile_info.features
252 }
253
254 fn cpu_features(&self) -> EnumSet<CpuFeature> {
255 EnumSet::from_u64(self.serializable.cpu_features)
256 }
257
258 fn data_initializers(&'a self) -> Self::OwnedDataInitializerIterator {
259 self.serializable.data_initializers.iter()
260 }
261
262 fn memory_styles(&self) -> &PrimaryMap<MemoryIndex, MemoryStyle> {
263 &self.serializable.compile_info.memory_styles
264 }
265
266 fn table_styles(&self) -> &PrimaryMap<TableIndex, TableStyle> {
267 &self.serializable.compile_info.table_styles
268 }
269
270 fn serialize(&self) -> Result<Vec<u8>, SerializeError> {
271 serialize_module(&self.serializable)
272 }
273}
274
275#[derive(Debug)]
278pub struct ModuleFromArchive<'a> {
279 pub compilation: &'a ArchivedSerializableCompilation,
281 pub data_initializers: &'a rkyv::Archived<Box<[OwnedDataInitializer]>>,
283 pub cpu_features: u64,
285
286 original_module: &'a ArchivedSerializableModule,
288}
289
290impl<'a> ModuleFromArchive<'a> {
291 pub fn from_serializable_module(
293 module: &'a ArchivedSerializableModule,
294 ) -> Result<Self, DeserializeError> {
295 Ok(Self {
296 compilation: &module.compilation,
297 data_initializers: &module.data_initializers,
298 cpu_features: module.cpu_features.to_native(),
299 original_module: module,
300 })
301 }
302}
303
304self_cell!(
305 struct ArtifactBuildFromArchiveCell {
306 owner: OwnedBuffer,
307
308 #[covariant]
309 dependent: ModuleFromArchive,
310 }
311
312 impl {Debug}
313);
314
315#[cfg(feature = "artifact-size")]
316impl loupe::MemoryUsage for ArtifactBuildFromArchiveCell {
317 fn size_of_val(&self, _tracker: &mut dyn loupe::MemoryUsageTracker) -> usize {
318 std::mem::size_of_val(self.borrow_owner()) + std::mem::size_of_val(self.borrow_dependent())
319 }
320}
321
322#[derive(Clone, Debug)]
324#[cfg_attr(feature = "artifact-size", derive(loupe::MemoryUsage))]
325pub struct ArtifactBuildFromArchive {
326 cell: Arc<ArtifactBuildFromArchiveCell>,
327
328 compile_info: CompileModuleInfo,
330}
331
332impl ArtifactBuildFromArchive {
333 #[allow(unused)]
334 pub(crate) fn try_new(
335 buffer: OwnedBuffer,
336 module_builder: impl FnOnce(
337 &OwnedBuffer,
338 ) -> Result<&ArchivedSerializableModule, DeserializeError>,
339 ) -> Result<Self, DeserializeError> {
340 let mut compile_info = MaybeUninit::uninit();
341
342 let cell = ArtifactBuildFromArchiveCell::try_new(buffer, |buffer| {
343 let module = module_builder(buffer)?;
344 compile_info = MaybeUninit::new(
345 rkyv::deserialize::<_, RkyvError>(&module.compile_info)
346 .map_err(|e| DeserializeError::CorruptedBinary(format!("{e:?}")))?,
347 );
348 ModuleFromArchive::from_serializable_module(module)
349 })?;
350
351 let compile_info = unsafe { compile_info.assume_init() };
353 Ok(Self {
354 cell: Arc::new(cell),
355 compile_info,
356 })
357 }
358
359 pub fn owned_buffer(&self) -> &OwnedBuffer {
361 self.cell.borrow_owner()
362 }
363
364 pub fn get_function_bodies_ref(&self) -> &ArchivedPrimaryMap<LocalFunctionIndex, FunctionBody> {
366 &self.cell.borrow_dependent().compilation.function_bodies
367 }
368
369 pub fn get_function_call_trampolines_ref(
371 &self,
372 ) -> &ArchivedPrimaryMap<SignatureIndex, FunctionBody> {
373 &self
374 .cell
375 .borrow_dependent()
376 .compilation
377 .function_call_trampolines
378 }
379
380 pub fn get_dynamic_function_trampolines_ref(
382 &self,
383 ) -> &ArchivedPrimaryMap<FunctionIndex, FunctionBody> {
384 &self
385 .cell
386 .borrow_dependent()
387 .compilation
388 .dynamic_function_trampolines
389 }
390
391 pub fn get_custom_sections_ref(&self) -> &ArchivedPrimaryMap<SectionIndex, CustomSection> {
393 &self.cell.borrow_dependent().compilation.custom_sections
394 }
395
396 pub fn get_function_relocations(
398 &self,
399 ) -> &ArchivedPrimaryMap<LocalFunctionIndex, Vec<Relocation>> {
400 &self
401 .cell
402 .borrow_dependent()
403 .compilation
404 .function_relocations
405 }
406
407 pub fn get_custom_section_relocations_ref(
409 &self,
410 ) -> &ArchivedPrimaryMap<SectionIndex, Vec<Relocation>> {
411 &self
412 .cell
413 .borrow_dependent()
414 .compilation
415 .custom_section_relocations
416 }
417
418 pub fn get_libcall_trampolines(&self) -> SectionIndex {
420 rkyv::deserialize::<_, RkyvError>(
421 &self.cell.borrow_dependent().compilation.libcall_trampolines,
422 )
423 .unwrap()
424 }
425
426 pub fn get_libcall_trampoline_len(&self) -> usize {
428 self.cell
429 .borrow_dependent()
430 .compilation
431 .libcall_trampoline_len
432 .to_native() as usize
433 }
434
435 pub fn get_unwind_info(&self) -> UnwindInfo {
437 rkyv::deserialize::<_, rkyv::rancor::Error>(
438 &self.cell.borrow_dependent().compilation.unwind_info,
439 )
440 .unwrap()
441 }
442
443 pub fn get_got_ref(&self) -> GOT {
445 rkyv::deserialize::<_, rkyv::rancor::Error>(&self.cell.borrow_dependent().compilation.got)
446 .unwrap()
447 }
448
449 pub fn get_frame_info_ref(
451 &self,
452 ) -> &ArchivedPrimaryMap<LocalFunctionIndex, CompiledFunctionFrameInfo> {
453 &self.cell.borrow_dependent().compilation.function_frame_info
454 }
455
456 pub fn deserialize_frame_info_ref(
458 &self,
459 ) -> Result<PrimaryMap<LocalFunctionIndex, CompiledFunctionFrameInfo>, DeserializeError> {
460 rkyv::deserialize::<_, RkyvError>(
461 &self.cell.borrow_dependent().compilation.function_frame_info,
462 )
463 .map_err(|e| DeserializeError::CorruptedBinary(format!("{e:?}")))
464 }
465
466 pub fn get_function_max_stack_usage(
470 &self,
471 ) -> &ArchivedPrimaryMap<LocalFunctionIndex, Option<usize>> {
472 &self
473 .cell
474 .borrow_dependent()
475 .compilation
476 .function_max_stack_usage
477 }
478}
479
480impl<'a> ArtifactCreate<'a> for ArtifactBuildFromArchive {
481 type OwnedDataInitializer = &'a ArchivedOwnedDataInitializer;
482 type OwnedDataInitializerIterator = core::slice::Iter<'a, ArchivedOwnedDataInitializer>;
483
484 fn create_module_info(&self) -> Arc<ModuleInfo> {
485 self.compile_info.module.clone()
486 }
487
488 fn set_module_info_name(&mut self, name: String) -> bool {
489 Arc::get_mut(&mut self.compile_info.module).is_some_and(|module_info| {
490 module_info.name = Some(name.to_string());
491 true
492 })
493 }
494
495 fn module_info(&self) -> &ModuleInfo {
496 &self.compile_info.module
497 }
498
499 fn features(&self) -> &Features {
500 &self.compile_info.features
501 }
502
503 fn cpu_features(&self) -> EnumSet<CpuFeature> {
504 EnumSet::from_u64(self.cell.borrow_dependent().cpu_features)
505 }
506
507 fn data_initializers(&'a self) -> Self::OwnedDataInitializerIterator {
508 self.cell.borrow_dependent().data_initializers.iter()
509 }
510
511 fn memory_styles(&self) -> &PrimaryMap<MemoryIndex, MemoryStyle> {
512 &self.compile_info.memory_styles
513 }
514
515 fn table_styles(&self) -> &PrimaryMap<TableIndex, TableStyle> {
516 &self.compile_info.table_styles
517 }
518
519 fn serialize(&self) -> Result<Vec<u8>, SerializeError> {
520 let mut module: SerializableModule =
528 rkyv::deserialize::<_, RkyvError>(self.cell.borrow_dependent().original_module)
529 .map_err(|e| SerializeError::Generic(e.to_string()))?;
530 module.compile_info = self.compile_info.clone();
531 serialize_module(&module)
532 }
533}
534
535fn serialize_module(module: &SerializableModule) -> Result<Vec<u8>, SerializeError> {
536 let serialized_data = module.serialize()?;
537 assert!(std::mem::align_of::<SerializableModule>() <= MetadataHeader::ALIGN);
538
539 let mut metadata_binary = vec![];
540 metadata_binary.extend(ArtifactBuild::MAGIC_HEADER);
541 metadata_binary.extend(MetadataHeader::new(serialized_data.len()).into_bytes());
542 metadata_binary.extend(serialized_data);
543 Ok(metadata_binary)
544}