wasmer_compiler/artifact_builders/
artifact_builder.rs

1//! Define `ArtifactBuild` to allow compiling and instantiating to be
2//! done as separate steps.
3
4#[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// Not every compiler backend uses these.
41#[allow(unused)]
42use wasmer_types::*;
43
44/// A compiled wasm module, ready to be instantiated.
45#[cfg_attr(feature = "artifact-size", derive(loupe::MemoryUsage))]
46pub struct ArtifactBuild {
47    pub(crate) serializable: SerializableModule,
48}
49
50impl ArtifactBuild {
51    /// Header signature for wasmu binary
52    pub const MAGIC_HEADER: &'static [u8; 16] = b"wasmer-universal";
53
54    /// Check if the provided bytes look like a serialized `ArtifactBuild`.
55    pub fn is_deserializable(bytes: &[u8]) -> bool {
56        bytes.starts_with(Self::MAGIC_HEADER)
57    }
58
59    /// Compile a data buffer into a `ArtifactBuild`, which may then be instantiated.
60    #[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        // We try to apply the middleware first
79        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            // The native ELF image does not exist yet. This placeholder is only
103            // used for the metadata copy embedded in that image.
104            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        // Compile the Module
119        let compilation = compiler.compile_module(
120            target,
121            &serializable.compile_info,
122            &compile_info_blob,
123            // SAFETY: Calling `unwrap` is correct since
124            // `environ.translate()` above will write some data into
125            // `module_translation_state`.
126            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                // Synthesize a custom section to hold the libcall trampolines.
138
139                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    /// Create a new ArtifactBuild from a SerializableModule
188    pub fn from_serializable(serializable: SerializableModule) -> Self {
189        Self { serializable }
190    }
191
192    /// Get Functions Bodies ref
193    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    /// Get Functions Call Trampolines ref
202    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    /// Get Dynamic Functions Call Trampolines ref
213    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    /// Get Custom Sections ref
224    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    /// Get Function Relocations
233    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    /// Get Function Relocations ref
244    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    /// Get LibCall Trampoline Section Index
255    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    /// Get LibCall Trampoline Length
264    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    /// Get a reference to the [`UnwindInfo`].
273    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    /// Get a reference to the [`GOT`].
282    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    /// Get Function Relocations ref
291    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    /// The maximum stack allocation directly connected to the function itself
302    /// if tracked (does not include any potential function calls).
303    /// Available only for the Singlepass compiler
304    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/// Module loaded from an archive. Since `CompileModuleInfo` is part of the public
359/// interface of this crate and has to be mutable, it has to be deserialized completely.
360#[derive(Debug)]
361pub struct ModuleFromArchive<'a> {
362    /// The main serializable compilation object
363    pub compilation: &'a ArchivedSerializableCompilation,
364    /// Data initializers
365    pub data_initializers: &'a rkyv::Archived<Box<[OwnedDataInitializer]>>,
366    /// CPU Feature flags for this compilation
367    pub cpu_features: u64,
368
369    // Keep the original module around for re-serialization
370    original_module: &'a ArchivedSerializableModule,
371}
372
373impl<'a> ModuleFromArchive<'a> {
374    /// Create a new `ModuleFromArchive` from the archived version of a `SerializableModule`
375    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/// A compiled wasm module that was loaded from a serialized archive.
406#[derive(Clone, Debug)]
407#[cfg_attr(feature = "artifact-size", derive(loupe::MemoryUsage))]
408pub struct ArtifactBuildFromArchive {
409    cell: Arc<ArtifactBuildFromArchiveCell>,
410
411    /// Compilation information
412    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        // Safety: we know the lambda will execute before getting here and assign both values
435        let compile_info = unsafe { compile_info.assume_init() };
436        Ok(Self {
437            cell: Arc::new(cell),
438            compile_info,
439        })
440    }
441
442    /// Gets the owned buffer
443    pub fn owned_buffer(&self) -> &OwnedBuffer {
444        self.cell.borrow_owner()
445    }
446
447    /// Get Functions Bodies ref
448    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    /// Get Functions Call Trampolines ref
461    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    /// Get Dynamic Functions Call Trampolines ref
474    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    /// Get Custom Sections ref
487    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    /// Get Function Relocations
500    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    /// Get Function Relocations ref
513    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    /// Get LibCall Trampoline Section Index
526    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    /// Get LibCall Trampoline Length
537    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    /// Get an unarchived [`UnwindInfo`].
548    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    /// Get an unarchived [`GOT`].
559    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    /// Get Function Relocations ref
570    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    /// Get Function Relocations ref
583    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    /// The maximum stack allocation directly connected to the function itself
599    /// if tracked (does not include any potential function calls).
600    /// Available only for the Singlepass compiler
601    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    /// Get compiled ELF file data.
608    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        // We could have stored the original bytes, but since the module info name
664        // is mutable, we have to assume the data may have changed and serialize
665        // everything all over again. Also, to be able to serialize, first we have
666        // to deserialize completely. Luckily, serializing a module that was already
667        // deserialized from a file makes little sense, so hopefully, this is not a
668        // common use-case.
669
670        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}