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 for (_, func) in compilation.functions.into_iter() {
122 function_bodies.push(func.body);
123 function_relocations.push(func.relocations);
124 function_frame_info.push(func.frame_info);
125 }
126 let mut custom_sections = compilation.custom_sections.clone();
127 let mut custom_section_relocations = compilation
128 .custom_sections
129 .iter()
130 .map(|(_, section)| section.relocations.clone())
131 .collect::<PrimaryMap<SectionIndex, _>>();
132 let libcall_trampolines_section = make_libcall_trampolines(target);
133 custom_section_relocations.push(libcall_trampolines_section.relocations.clone());
134 let libcall_trampolines = custom_sections.push(libcall_trampolines_section);
135 let libcall_trampoline_len = libcall_trampoline_len(target) as u32;
136 let cpu_features = compiler.get_cpu_features_used(target.cpu_features());
137
138 let serializable_compilation = SerializableCompilation {
139 function_bodies,
140 function_relocations,
141 function_frame_info,
142 function_call_trampolines: compilation.function_call_trampolines,
143 dynamic_function_trampolines: compilation.dynamic_function_trampolines,
144 custom_sections,
145 custom_section_relocations,
146 unwind_info: compilation.unwind_info,
147 libcall_trampolines,
148 libcall_trampoline_len,
149 got: compilation.got,
150 };
151 let serializable = SerializableModule {
152 compilation: serializable_compilation,
153 compile_info,
154 data_initializers,
155 cpu_features: cpu_features.as_u64(),
156 };
157 Ok(Self { serializable })
158 }
159
160 pub fn from_serializable(serializable: SerializableModule) -> Self {
162 Self { serializable }
163 }
164
165 pub fn get_function_bodies_ref(&self) -> &PrimaryMap<LocalFunctionIndex, FunctionBody> {
167 &self.serializable.compilation.function_bodies
168 }
169
170 pub fn get_function_call_trampolines_ref(&self) -> &PrimaryMap<SignatureIndex, FunctionBody> {
172 &self.serializable.compilation.function_call_trampolines
173 }
174
175 pub fn get_dynamic_function_trampolines_ref(&self) -> &PrimaryMap<FunctionIndex, FunctionBody> {
177 &self.serializable.compilation.dynamic_function_trampolines
178 }
179
180 pub fn get_custom_sections_ref(&self) -> &PrimaryMap<SectionIndex, CustomSection> {
182 &self.serializable.compilation.custom_sections
183 }
184
185 pub fn get_function_relocations(&self) -> &PrimaryMap<LocalFunctionIndex, Vec<Relocation>> {
187 &self.serializable.compilation.function_relocations
188 }
189
190 pub fn get_custom_section_relocations_ref(&self) -> &PrimaryMap<SectionIndex, Vec<Relocation>> {
192 &self.serializable.compilation.custom_section_relocations
193 }
194
195 pub fn get_libcall_trampolines(&self) -> SectionIndex {
197 self.serializable.compilation.libcall_trampolines
198 }
199
200 pub fn get_libcall_trampoline_len(&self) -> usize {
202 self.serializable.compilation.libcall_trampoline_len as usize
203 }
204
205 pub fn get_unwind_info(&self) -> &UnwindInfo {
207 &self.serializable.compilation.unwind_info
208 }
209
210 pub fn get_got_ref(&self) -> &GOT {
212 &self.serializable.compilation.got
213 }
214
215 pub fn get_frame_info_ref(&self) -> &PrimaryMap<LocalFunctionIndex, CompiledFunctionFrameInfo> {
217 &self.serializable.compilation.function_frame_info
218 }
219}
220
221impl<'a> ArtifactCreate<'a> for ArtifactBuild {
222 type OwnedDataInitializer = &'a OwnedDataInitializer;
223 type OwnedDataInitializerIterator = core::slice::Iter<'a, OwnedDataInitializer>;
224
225 fn create_module_info(&self) -> Arc<ModuleInfo> {
226 self.serializable.compile_info.module.clone()
227 }
228
229 fn set_module_info_name(&mut self, name: String) -> bool {
230 Arc::get_mut(&mut self.serializable.compile_info.module).is_some_and(|module_info| {
231 module_info.name = Some(name.to_string());
232 true
233 })
234 }
235
236 fn module_info(&self) -> &ModuleInfo {
237 &self.serializable.compile_info.module
238 }
239
240 fn features(&self) -> &Features {
241 &self.serializable.compile_info.features
242 }
243
244 fn cpu_features(&self) -> EnumSet<CpuFeature> {
245 EnumSet::from_u64(self.serializable.cpu_features)
246 }
247
248 fn data_initializers(&'a self) -> Self::OwnedDataInitializerIterator {
249 self.serializable.data_initializers.iter()
250 }
251
252 fn memory_styles(&self) -> &PrimaryMap<MemoryIndex, MemoryStyle> {
253 &self.serializable.compile_info.memory_styles
254 }
255
256 fn table_styles(&self) -> &PrimaryMap<TableIndex, TableStyle> {
257 &self.serializable.compile_info.table_styles
258 }
259
260 fn serialize(&self) -> Result<Vec<u8>, SerializeError> {
261 serialize_module(&self.serializable)
262 }
263}
264
265#[derive(Debug)]
268pub struct ModuleFromArchive<'a> {
269 pub compilation: &'a ArchivedSerializableCompilation,
271 pub data_initializers: &'a rkyv::Archived<Box<[OwnedDataInitializer]>>,
273 pub cpu_features: u64,
275
276 original_module: &'a ArchivedSerializableModule,
278}
279
280impl<'a> ModuleFromArchive<'a> {
281 pub fn from_serializable_module(
283 module: &'a ArchivedSerializableModule,
284 ) -> Result<Self, DeserializeError> {
285 Ok(Self {
286 compilation: &module.compilation,
287 data_initializers: &module.data_initializers,
288 cpu_features: module.cpu_features.to_native(),
289 original_module: module,
290 })
291 }
292}
293
294self_cell!(
295 struct ArtifactBuildFromArchiveCell {
296 owner: OwnedBuffer,
297
298 #[covariant]
299 dependent: ModuleFromArchive,
300 }
301
302 impl {Debug}
303);
304
305#[cfg(feature = "artifact-size")]
306impl loupe::MemoryUsage for ArtifactBuildFromArchiveCell {
307 fn size_of_val(&self, _tracker: &mut dyn loupe::MemoryUsageTracker) -> usize {
308 std::mem::size_of_val(self.borrow_owner()) + std::mem::size_of_val(self.borrow_dependent())
309 }
310}
311
312#[derive(Clone, Debug)]
314#[cfg_attr(feature = "artifact-size", derive(loupe::MemoryUsage))]
315pub struct ArtifactBuildFromArchive {
316 cell: Arc<ArtifactBuildFromArchiveCell>,
317
318 compile_info: CompileModuleInfo,
320}
321
322impl ArtifactBuildFromArchive {
323 #[allow(unused)]
324 pub(crate) fn try_new(
325 buffer: OwnedBuffer,
326 module_builder: impl FnOnce(
327 &OwnedBuffer,
328 ) -> Result<&ArchivedSerializableModule, DeserializeError>,
329 ) -> Result<Self, DeserializeError> {
330 let mut compile_info = MaybeUninit::uninit();
331
332 let cell = ArtifactBuildFromArchiveCell::try_new(buffer, |buffer| {
333 let module = module_builder(buffer)?;
334 compile_info = MaybeUninit::new(
335 rkyv::deserialize::<_, RkyvError>(&module.compile_info)
336 .map_err(|e| DeserializeError::CorruptedBinary(format!("{e:?}")))?,
337 );
338 ModuleFromArchive::from_serializable_module(module)
339 })?;
340
341 let compile_info = unsafe { compile_info.assume_init() };
343 Ok(Self {
344 cell: Arc::new(cell),
345 compile_info,
346 })
347 }
348
349 pub fn owned_buffer(&self) -> &OwnedBuffer {
351 self.cell.borrow_owner()
352 }
353
354 pub fn get_function_bodies_ref(&self) -> &ArchivedPrimaryMap<LocalFunctionIndex, FunctionBody> {
356 &self.cell.borrow_dependent().compilation.function_bodies
357 }
358
359 pub fn get_function_call_trampolines_ref(
361 &self,
362 ) -> &ArchivedPrimaryMap<SignatureIndex, FunctionBody> {
363 &self
364 .cell
365 .borrow_dependent()
366 .compilation
367 .function_call_trampolines
368 }
369
370 pub fn get_dynamic_function_trampolines_ref(
372 &self,
373 ) -> &ArchivedPrimaryMap<FunctionIndex, FunctionBody> {
374 &self
375 .cell
376 .borrow_dependent()
377 .compilation
378 .dynamic_function_trampolines
379 }
380
381 pub fn get_custom_sections_ref(&self) -> &ArchivedPrimaryMap<SectionIndex, CustomSection> {
383 &self.cell.borrow_dependent().compilation.custom_sections
384 }
385
386 pub fn get_function_relocations(
388 &self,
389 ) -> &ArchivedPrimaryMap<LocalFunctionIndex, Vec<Relocation>> {
390 &self
391 .cell
392 .borrow_dependent()
393 .compilation
394 .function_relocations
395 }
396
397 pub fn get_custom_section_relocations_ref(
399 &self,
400 ) -> &ArchivedPrimaryMap<SectionIndex, Vec<Relocation>> {
401 &self
402 .cell
403 .borrow_dependent()
404 .compilation
405 .custom_section_relocations
406 }
407
408 pub fn get_libcall_trampolines(&self) -> SectionIndex {
410 rkyv::deserialize::<_, RkyvError>(
411 &self.cell.borrow_dependent().compilation.libcall_trampolines,
412 )
413 .unwrap()
414 }
415
416 pub fn get_libcall_trampoline_len(&self) -> usize {
418 self.cell
419 .borrow_dependent()
420 .compilation
421 .libcall_trampoline_len
422 .to_native() as usize
423 }
424
425 pub fn get_unwind_info(&self) -> UnwindInfo {
427 rkyv::deserialize::<_, rkyv::rancor::Error>(
428 &self.cell.borrow_dependent().compilation.unwind_info,
429 )
430 .unwrap()
431 }
432
433 pub fn get_got_ref(&self) -> GOT {
435 rkyv::deserialize::<_, rkyv::rancor::Error>(&self.cell.borrow_dependent().compilation.got)
436 .unwrap()
437 }
438
439 pub fn get_frame_info_ref(
441 &self,
442 ) -> &ArchivedPrimaryMap<LocalFunctionIndex, CompiledFunctionFrameInfo> {
443 &self.cell.borrow_dependent().compilation.function_frame_info
444 }
445
446 pub fn deserialize_frame_info_ref(
448 &self,
449 ) -> Result<PrimaryMap<LocalFunctionIndex, CompiledFunctionFrameInfo>, DeserializeError> {
450 rkyv::deserialize::<_, RkyvError>(
451 &self.cell.borrow_dependent().compilation.function_frame_info,
452 )
453 .map_err(|e| DeserializeError::CorruptedBinary(format!("{e:?}")))
454 }
455}
456
457impl<'a> ArtifactCreate<'a> for ArtifactBuildFromArchive {
458 type OwnedDataInitializer = &'a ArchivedOwnedDataInitializer;
459 type OwnedDataInitializerIterator = core::slice::Iter<'a, ArchivedOwnedDataInitializer>;
460
461 fn create_module_info(&self) -> Arc<ModuleInfo> {
462 self.compile_info.module.clone()
463 }
464
465 fn set_module_info_name(&mut self, name: String) -> bool {
466 Arc::get_mut(&mut self.compile_info.module).is_some_and(|module_info| {
467 module_info.name = Some(name.to_string());
468 true
469 })
470 }
471
472 fn module_info(&self) -> &ModuleInfo {
473 &self.compile_info.module
474 }
475
476 fn features(&self) -> &Features {
477 &self.compile_info.features
478 }
479
480 fn cpu_features(&self) -> EnumSet<CpuFeature> {
481 EnumSet::from_u64(self.cell.borrow_dependent().cpu_features)
482 }
483
484 fn data_initializers(&'a self) -> Self::OwnedDataInitializerIterator {
485 self.cell.borrow_dependent().data_initializers.iter()
486 }
487
488 fn memory_styles(&self) -> &PrimaryMap<MemoryIndex, MemoryStyle> {
489 &self.compile_info.memory_styles
490 }
491
492 fn table_styles(&self) -> &PrimaryMap<TableIndex, TableStyle> {
493 &self.compile_info.table_styles
494 }
495
496 fn serialize(&self) -> Result<Vec<u8>, SerializeError> {
497 let mut module: SerializableModule =
505 rkyv::deserialize::<_, RkyvError>(self.cell.borrow_dependent().original_module)
506 .map_err(|e| SerializeError::Generic(e.to_string()))?;
507 module.compile_info = self.compile_info.clone();
508 serialize_module(&module)
509 }
510}
511
512fn serialize_module(module: &SerializableModule) -> Result<Vec<u8>, SerializeError> {
513 let serialized_data = module.serialize()?;
514 assert!(std::mem::align_of::<SerializableModule>() <= MetadataHeader::ALIGN);
515
516 let mut metadata_binary = vec![];
517 metadata_binary.extend(ArtifactBuild::MAGIC_HEADER);
518 metadata_binary.extend(MetadataHeader::new(serialized_data.len()).into_bytes());
519 metadata_binary.extend(serialized_data);
520 Ok(metadata_binary)
521}