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