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