Skip to main content

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        Self::has_rkyv_header(bytes) || bytes.starts_with(&object::elf::ELFMAG)
57    }
58
59    pub(crate) fn has_rkyv_header(bytes: &[u8]) -> bool {
60        bytes.starts_with(Self::MAGIC_HEADER)
61    }
62
63    /// Compile a data buffer into a `ArtifactBuild`, which may then be instantiated.
64    #[cfg(feature = "compiler")]
65    pub fn new(
66        inner_engine: &mut EngineInner,
67        data: &[u8],
68        target: &Target,
69        memory_styles: PrimaryMap<MemoryIndex, MemoryStyle>,
70        table_styles: PrimaryMap<TableIndex, TableStyle>,
71        progress_callback: Option<&CompilationProgressCallback>,
72    ) -> Result<Self, CompileError> {
73        use crate::types::function::Compilation;
74
75        let environ = ModuleEnvironment::new();
76        let features = inner_engine.features().clone();
77
78        let translation = environ.translate(data).map_err(CompileError::Wasm)?;
79
80        let compiler = inner_engine.compiler()?;
81
82        // We try to apply the middleware first
83        let mut module = translation.module;
84        let middlewares = compiler.get_middlewares();
85        middlewares
86            .apply_on_module_info(&mut module)
87            .map_err(|err| CompileError::MiddlewareError(err.to_string()))?;
88        #[cfg(feature = "translator")]
89        if compiler.enable_readonly_funcref_table()
90            && let Some(table_index) =
91                analyze_readonly_funcref_table(&module, &translation.function_body_inputs)?
92        {
93            module.tables[table_index].readonly = true;
94        }
95
96        module.hash = Some(ModuleHash::new(data));
97        let compile_info = CompileModuleInfo {
98            module: Arc::new(module),
99            features,
100            memory_styles,
101            table_styles,
102            function_max_stack_usage: PrimaryMap::new(),
103        };
104        let cpu_features = compiler.get_cpu_features_used(target.cpu_features());
105        let mut serializable = SerializableModule {
106            // The native ELF image does not exist yet. This placeholder is only
107            // used for the metadata copy embedded in that image.
108            compilation: SerializableCompilation::Elf(Vec::new()),
109            compile_info,
110            data_initializers: translation
111                .data_initializers
112                .iter()
113                .map(OwnedDataInitializer::new)
114                .collect::<Vec<_>>()
115                .into_boxed_slice(),
116            cpu_features: cpu_features.as_u64(),
117        };
118        let compile_info_blob = serializable
119            .serialize()
120            .map_err(|e| CompileError::Codegen(format!("cannot serialize SerializeModule: {e}")))?;
121
122        // Compile the Module
123        let compilation = compiler.compile_module(
124            target,
125            &serializable.compile_info,
126            &compile_info_blob,
127            // SAFETY: Calling `unwrap` is correct since
128            // `environ.translate()` above will write some data into
129            // `module_translation_state`.
130            translation.module_translation_state.as_ref().unwrap(),
131            translation.function_body_inputs,
132            progress_callback,
133        )?;
134
135        let compilation = match compilation {
136            Compilation::Rkyv {
137                compilation,
138                function_max_stack_usage,
139            } => {
140                serializable.compile_info.function_max_stack_usage = function_max_stack_usage;
141                // Synthesize a custom section to hold the libcall trampolines.
142
143                let mut function_frame_info =
144                    PrimaryMap::with_capacity(compilation.functions.len());
145                let mut function_bodies = PrimaryMap::with_capacity(compilation.functions.len());
146                let mut function_relocations =
147                    PrimaryMap::with_capacity(compilation.functions.len());
148                for (_, func) in compilation.functions.into_iter() {
149                    function_bodies.push(func.body);
150                    function_relocations.push(func.relocations);
151                    function_frame_info.push(func.frame_info);
152                }
153                let mut custom_sections = compilation.custom_sections.clone();
154                let mut custom_section_relocations = compilation
155                    .custom_sections
156                    .iter()
157                    .map(|(_, section)| section.relocations.clone())
158                    .collect::<PrimaryMap<SectionIndex, _>>();
159                let libcall_trampolines_section = make_libcall_trampolines(target);
160                custom_section_relocations.push(libcall_trampolines_section.relocations.clone());
161                let libcall_trampolines = custom_sections.push(libcall_trampolines_section);
162                let libcall_trampoline_len = libcall_trampoline_len(target) as u32;
163
164                SerializableCompilation::Rkyv(RkyvSerializableCompilation {
165                    function_bodies,
166                    function_relocations,
167                    function_frame_info,
168                    function_call_trampolines: compilation.function_call_trampolines,
169                    dynamic_function_trampolines: compilation.dynamic_function_trampolines,
170                    custom_sections,
171                    custom_section_relocations,
172                    unwind_info: compilation.unwind_info,
173                    libcall_trampolines,
174                    libcall_trampoline_len,
175                    got: compilation.got,
176                })
177            }
178            Compilation::Elf {
179                data,
180                function_max_stack_usage,
181            } => {
182                serializable.compile_info.function_max_stack_usage = function_max_stack_usage;
183                SerializableCompilation::Elf(data)
184            }
185        };
186
187        serializable.compilation = compilation;
188        Ok(Self { serializable })
189    }
190
191    /// Create a new ArtifactBuild from a SerializableModule
192    pub fn from_serializable(serializable: SerializableModule) -> Self {
193        Self { serializable }
194    }
195
196    /// Get Functions Bodies ref
197    pub fn get_function_bodies_ref(&self) -> Option<&PrimaryMap<LocalFunctionIndex, FunctionBody>> {
198        if let SerializableCompilation::Rkyv(compilation) = &self.serializable.compilation {
199            Some(&compilation.function_bodies)
200        } else {
201            None
202        }
203    }
204
205    /// Get Functions Call Trampolines ref
206    pub fn get_function_call_trampolines_ref(
207        &self,
208    ) -> Option<&PrimaryMap<SignatureIndex, FunctionBody>> {
209        if let SerializableCompilation::Rkyv(compilation) = &self.serializable.compilation {
210            Some(&compilation.function_call_trampolines)
211        } else {
212            None
213        }
214    }
215
216    /// Get Dynamic Functions Call Trampolines ref
217    pub fn get_dynamic_function_trampolines_ref(
218        &self,
219    ) -> Option<&PrimaryMap<FunctionIndex, FunctionBody>> {
220        if let SerializableCompilation::Rkyv(compilation) = &self.serializable.compilation {
221            Some(&compilation.dynamic_function_trampolines)
222        } else {
223            None
224        }
225    }
226
227    /// Get Custom Sections ref
228    pub fn get_custom_sections_ref(&self) -> Option<&PrimaryMap<SectionIndex, CustomSection>> {
229        if let SerializableCompilation::Rkyv(compilation) = &self.serializable.compilation {
230            Some(&compilation.custom_sections)
231        } else {
232            None
233        }
234    }
235
236    /// Get Function Relocations
237    pub fn get_function_relocations(
238        &self,
239    ) -> Option<&PrimaryMap<LocalFunctionIndex, Vec<Relocation>>> {
240        if let SerializableCompilation::Rkyv(compilation) = &self.serializable.compilation {
241            Some(&compilation.function_relocations)
242        } else {
243            None
244        }
245    }
246
247    /// Get Function Relocations ref
248    pub fn get_custom_section_relocations_ref(
249        &self,
250    ) -> Option<&PrimaryMap<SectionIndex, Vec<Relocation>>> {
251        if let SerializableCompilation::Rkyv(compilation) = &self.serializable.compilation {
252            Some(&compilation.custom_section_relocations)
253        } else {
254            None
255        }
256    }
257
258    /// Get LibCall Trampoline Section Index
259    pub fn get_libcall_trampolines(&self) -> Option<SectionIndex> {
260        if let SerializableCompilation::Rkyv(compilation) = &self.serializable.compilation {
261            Some(compilation.libcall_trampolines)
262        } else {
263            None
264        }
265    }
266
267    /// Get LibCall Trampoline Length
268    pub fn get_libcall_trampoline_len(&self) -> Option<usize> {
269        if let SerializableCompilation::Rkyv(compilation) = &self.serializable.compilation {
270            Some(compilation.libcall_trampoline_len as usize)
271        } else {
272            None
273        }
274    }
275
276    /// Get a reference to the [`UnwindInfo`].
277    pub fn get_unwind_info(&self) -> Option<&UnwindInfo> {
278        if let SerializableCompilation::Rkyv(compilation) = &self.serializable.compilation {
279            Some(&compilation.unwind_info)
280        } else {
281            None
282        }
283    }
284
285    /// Get a reference to the [`GOT`].
286    pub fn get_got_ref(&self) -> Option<&GOT> {
287        if let SerializableCompilation::Rkyv(compilation) = &self.serializable.compilation {
288            Some(&compilation.got)
289        } else {
290            None
291        }
292    }
293
294    /// Get Function Relocations ref
295    pub fn get_frame_info_ref(
296        &self,
297    ) -> Option<&PrimaryMap<LocalFunctionIndex, CompiledFunctionFrameInfo>> {
298        if let SerializableCompilation::Rkyv(compilation) = &self.serializable.compilation {
299            Some(&compilation.function_frame_info)
300        } else {
301            None
302        }
303    }
304
305    /// The maximum stack allocation directly connected to the function itself
306    /// if tracked (does not include any potential function calls).
307    /// Available only for the Singlepass compiler
308    pub fn get_function_max_stack_usage(
309        &self,
310    ) -> Option<&PrimaryMap<LocalFunctionIndex, Option<usize>>> {
311        Some(&self.serializable.compile_info.function_max_stack_usage)
312    }
313}
314
315impl<'a> ArtifactCreate<'a> for ArtifactBuild {
316    type OwnedDataInitializer = &'a OwnedDataInitializer;
317    type OwnedDataInitializerIterator = core::slice::Iter<'a, OwnedDataInitializer>;
318
319    fn create_module_info(&self) -> Arc<ModuleInfo> {
320        self.serializable.compile_info.module.clone()
321    }
322
323    fn set_module_info_name(&mut self, name: String) -> bool {
324        Arc::get_mut(&mut self.serializable.compile_info.module).is_some_and(|module_info| {
325            module_info.name = Some(name.to_string());
326            true
327        })
328    }
329
330    fn module_info(&self) -> &ModuleInfo {
331        &self.serializable.compile_info.module
332    }
333
334    fn features(&self) -> &Features {
335        &self.serializable.compile_info.features
336    }
337
338    fn cpu_features(&self) -> EnumSet<CpuFeature> {
339        EnumSet::from_u64(self.serializable.cpu_features)
340    }
341
342    fn data_initializers(&'a self) -> Self::OwnedDataInitializerIterator {
343        self.serializable.data_initializers.iter()
344    }
345
346    fn memory_styles(&self) -> &PrimaryMap<MemoryIndex, MemoryStyle> {
347        &self.serializable.compile_info.memory_styles
348    }
349
350    fn table_styles(&self) -> &PrimaryMap<TableIndex, TableStyle> {
351        &self.serializable.compile_info.table_styles
352    }
353
354    fn serialize(&self) -> Result<Vec<u8>, SerializeError> {
355        match &self.serializable.compilation {
356            SerializableCompilation::Elf(data) => Ok(data.clone()),
357            SerializableCompilation::Rkyv(_) => serialize_module(&self.serializable),
358        }
359    }
360}
361
362/// Module loaded from an archive. Since `CompileModuleInfo` is part of the public
363/// interface of this crate and has to be mutable, it has to be deserialized completely.
364#[derive(Debug)]
365pub struct ModuleFromArchive<'a> {
366    /// The main serializable compilation object
367    pub compilation: &'a ArchivedSerializableCompilation,
368    /// Data initializers
369    pub data_initializers: &'a rkyv::Archived<Box<[OwnedDataInitializer]>>,
370    /// CPU Feature flags for this compilation
371    pub cpu_features: u64,
372
373    // Keep the original module around for re-serialization
374    original_module: &'a ArchivedSerializableModule,
375}
376
377impl<'a> ModuleFromArchive<'a> {
378    /// Create a new `ModuleFromArchive` from the archived version of a `SerializableModule`
379    pub fn from_serializable_module(
380        module: &'a ArchivedSerializableModule,
381    ) -> Result<Self, DeserializeError> {
382        Ok(Self {
383            compilation: &module.compilation,
384            data_initializers: &module.data_initializers,
385            cpu_features: module.cpu_features.to_native(),
386            original_module: module,
387        })
388    }
389}
390
391self_cell!(
392    struct ArtifactBuildFromArchiveCell {
393        owner: OwnedBuffer,
394
395        #[covariant]
396        dependent: ModuleFromArchive,
397    }
398
399    impl {Debug}
400);
401
402#[cfg(feature = "artifact-size")]
403impl loupe::MemoryUsage for ArtifactBuildFromArchiveCell {
404    fn size_of_val(&self, _tracker: &mut dyn loupe::MemoryUsageTracker) -> usize {
405        std::mem::size_of_val(self.borrow_owner()) + std::mem::size_of_val(self.borrow_dependent())
406    }
407}
408
409/// A compiled wasm module that was loaded from a serialized archive.
410#[derive(Clone, Debug)]
411#[cfg_attr(feature = "artifact-size", derive(loupe::MemoryUsage))]
412pub struct ArtifactBuildFromArchive {
413    cell: Arc<ArtifactBuildFromArchiveCell>,
414
415    /// Compilation information
416    compile_info: CompileModuleInfo,
417}
418
419impl ArtifactBuildFromArchive {
420    #[allow(unused)]
421    pub(crate) fn try_new(
422        buffer: OwnedBuffer,
423        module_builder: impl FnOnce(
424            &OwnedBuffer,
425        ) -> Result<&ArchivedSerializableModule, DeserializeError>,
426    ) -> Result<Self, DeserializeError> {
427        let mut compile_info = MaybeUninit::uninit();
428
429        let cell = ArtifactBuildFromArchiveCell::try_new(buffer, |buffer| {
430            let module = module_builder(buffer)?;
431            compile_info = MaybeUninit::new(
432                rkyv::deserialize::<_, RkyvError>(&module.compile_info)
433                    .map_err(|e| DeserializeError::CorruptedBinary(format!("{e:?}")))?,
434            );
435            ModuleFromArchive::from_serializable_module(module)
436        })?;
437
438        // Safety: we know the lambda will execute before getting here and assign both values
439        let compile_info = unsafe { compile_info.assume_init() };
440        Ok(Self {
441            cell: Arc::new(cell),
442            compile_info,
443        })
444    }
445
446    /// Gets the owned buffer
447    pub fn owned_buffer(&self) -> &OwnedBuffer {
448        self.cell.borrow_owner()
449    }
450
451    /// Get Functions Bodies ref
452    pub fn get_function_bodies_ref(
453        &self,
454    ) -> Option<&ArchivedPrimaryMap<LocalFunctionIndex, FunctionBody>> {
455        if let ArchivedSerializableCompilation::Rkyv(compilation) =
456            self.cell.borrow_dependent().compilation
457        {
458            Some(&compilation.function_bodies)
459        } else {
460            None
461        }
462    }
463
464    /// Get Functions Call Trampolines ref
465    pub fn get_function_call_trampolines_ref(
466        &self,
467    ) -> Option<&ArchivedPrimaryMap<SignatureIndex, FunctionBody>> {
468        if let ArchivedSerializableCompilation::Rkyv(compilation) =
469            self.cell.borrow_dependent().compilation
470        {
471            Some(&compilation.function_call_trampolines)
472        } else {
473            None
474        }
475    }
476
477    /// Get Dynamic Functions Call Trampolines ref
478    pub fn get_dynamic_function_trampolines_ref(
479        &self,
480    ) -> Option<&ArchivedPrimaryMap<FunctionIndex, FunctionBody>> {
481        if let ArchivedSerializableCompilation::Rkyv(compilation) =
482            self.cell.borrow_dependent().compilation
483        {
484            Some(&compilation.dynamic_function_trampolines)
485        } else {
486            None
487        }
488    }
489
490    /// Get Custom Sections ref
491    pub fn get_custom_sections_ref(
492        &self,
493    ) -> Option<&ArchivedPrimaryMap<SectionIndex, CustomSection>> {
494        if let ArchivedSerializableCompilation::Rkyv(compilation) =
495            self.cell.borrow_dependent().compilation
496        {
497            Some(&compilation.custom_sections)
498        } else {
499            None
500        }
501    }
502
503    /// Get Function Relocations
504    pub fn get_function_relocations(
505        &self,
506    ) -> Option<&ArchivedPrimaryMap<LocalFunctionIndex, Vec<Relocation>>> {
507        if let ArchivedSerializableCompilation::Rkyv(compilation) =
508            self.cell.borrow_dependent().compilation
509        {
510            Some(&compilation.function_relocations)
511        } else {
512            None
513        }
514    }
515
516    /// Get Function Relocations ref
517    pub fn get_custom_section_relocations_ref(
518        &self,
519    ) -> Option<&ArchivedPrimaryMap<SectionIndex, Vec<Relocation>>> {
520        if let ArchivedSerializableCompilation::Rkyv(compilation) =
521            self.cell.borrow_dependent().compilation
522        {
523            Some(&compilation.custom_section_relocations)
524        } else {
525            None
526        }
527    }
528
529    /// Get LibCall Trampoline Section Index
530    pub fn get_libcall_trampolines(&self) -> Option<SectionIndex> {
531        if let ArchivedSerializableCompilation::Rkyv(compilation) =
532            self.cell.borrow_dependent().compilation
533        {
534            Some(rkyv::deserialize::<_, RkyvError>(&compilation.libcall_trampolines).unwrap())
535        } else {
536            None
537        }
538    }
539
540    /// Get LibCall Trampoline Length
541    pub fn get_libcall_trampoline_len(&self) -> Option<usize> {
542        if let ArchivedSerializableCompilation::Rkyv(compilation) =
543            self.cell.borrow_dependent().compilation
544        {
545            Some(compilation.libcall_trampoline_len.to_native() as usize)
546        } else {
547            None
548        }
549    }
550
551    /// Get an unarchived [`UnwindInfo`].
552    pub fn get_unwind_info(&self) -> Option<UnwindInfo> {
553        if let ArchivedSerializableCompilation::Rkyv(compilation) =
554            self.cell.borrow_dependent().compilation
555        {
556            Some(rkyv::deserialize::<_, rkyv::rancor::Error>(&compilation.unwind_info).unwrap())
557        } else {
558            None
559        }
560    }
561
562    /// Get an unarchived [`GOT`].
563    pub fn get_got_ref(&self) -> Option<GOT> {
564        if let ArchivedSerializableCompilation::Rkyv(compilation) =
565            self.cell.borrow_dependent().compilation
566        {
567            Some(rkyv::deserialize::<_, rkyv::rancor::Error>(&compilation.got).unwrap())
568        } else {
569            None
570        }
571    }
572
573    /// Get Function Relocations ref
574    pub fn get_frame_info_ref(
575        &self,
576    ) -> Option<&ArchivedPrimaryMap<LocalFunctionIndex, CompiledFunctionFrameInfo>> {
577        if let ArchivedSerializableCompilation::Rkyv(compilation) =
578            self.cell.borrow_dependent().compilation
579        {
580            Some(&compilation.function_frame_info)
581        } else {
582            None
583        }
584    }
585
586    /// Get Function Relocations ref
587    pub fn deserialize_frame_info_ref(
588        &self,
589    ) -> Result<PrimaryMap<LocalFunctionIndex, CompiledFunctionFrameInfo>, DeserializeError> {
590        if let ArchivedSerializableCompilation::Rkyv(compilation) =
591            self.cell.borrow_dependent().compilation
592        {
593            rkyv::deserialize::<_, RkyvError>(&compilation.function_frame_info)
594                .map_err(|e| DeserializeError::CorruptedBinary(format!("{e:?}")))
595        } else {
596            Err(DeserializeError::CorruptedBinary(
597                "expected RKYV compilation".to_string(),
598            ))
599        }
600    }
601
602    /// The maximum stack allocation directly connected to the function itself
603    /// if tracked (does not include any potential function calls).
604    /// Available only for the Singlepass compiler
605    pub fn get_function_max_stack_usage(
606        &self,
607    ) -> Option<&PrimaryMap<LocalFunctionIndex, Option<usize>>> {
608        Some(&self.compile_info.function_max_stack_usage)
609    }
610
611    /// Get compiled ELF file data.
612    pub fn get_elf_file(&self) -> Option<&[u8]> {
613        if let ArchivedSerializableCompilation::Elf(data) = self.cell.borrow_dependent().compilation
614        {
615            Some(data)
616        } else {
617            None
618        }
619    }
620}
621
622impl<'a> ArtifactCreate<'a> for ArtifactBuildFromArchive {
623    type OwnedDataInitializer = &'a ArchivedOwnedDataInitializer;
624    type OwnedDataInitializerIterator = core::slice::Iter<'a, ArchivedOwnedDataInitializer>;
625
626    fn create_module_info(&self) -> Arc<ModuleInfo> {
627        self.compile_info.module.clone()
628    }
629
630    fn set_module_info_name(&mut self, name: String) -> bool {
631        Arc::get_mut(&mut self.compile_info.module).is_some_and(|module_info| {
632            module_info.name = Some(name.to_string());
633            true
634        })
635    }
636
637    fn module_info(&self) -> &ModuleInfo {
638        &self.compile_info.module
639    }
640
641    fn features(&self) -> &Features {
642        &self.compile_info.features
643    }
644
645    fn cpu_features(&self) -> EnumSet<CpuFeature> {
646        EnumSet::from_u64(self.cell.borrow_dependent().cpu_features)
647    }
648
649    fn data_initializers(&'a self) -> Self::OwnedDataInitializerIterator {
650        self.cell.borrow_dependent().data_initializers.iter()
651    }
652
653    fn memory_styles(&self) -> &PrimaryMap<MemoryIndex, MemoryStyle> {
654        &self.compile_info.memory_styles
655    }
656
657    fn table_styles(&self) -> &PrimaryMap<TableIndex, TableStyle> {
658        &self.compile_info.table_styles
659    }
660
661    fn serialize(&self) -> Result<Vec<u8>, SerializeError> {
662        if let ArchivedSerializableCompilation::Elf(data) = self.cell.borrow_dependent().compilation
663        {
664            return Ok(data.to_vec());
665        }
666
667        // We could have stored the original bytes, but since the module info name
668        // is mutable, we have to assume the data may have changed and serialize
669        // everything all over again. Also, to be able to serialize, first we have
670        // to deserialize completely. Luckily, serializing a module that was already
671        // deserialized from a file makes little sense, so hopefully, this is not a
672        // common use-case.
673
674        let mut module: SerializableModule =
675            rkyv::deserialize::<_, RkyvError>(self.cell.borrow_dependent().original_module)
676                .map_err(|e| SerializeError::Generic(e.to_string()))?;
677        module.compile_info = self.compile_info.clone();
678        serialize_module(&module)
679    }
680}
681
682fn serialize_module(module: &SerializableModule) -> Result<Vec<u8>, SerializeError> {
683    let serialized_data = module.serialize()?;
684    assert!(std::mem::align_of::<SerializableModule>() <= MetadataHeader::ALIGN);
685
686    let mut metadata_binary = vec![];
687    metadata_binary.extend(ArtifactBuild::MAGIC_HEADER);
688    metadata_binary.extend(MetadataHeader::new(serialized_data.len()).into_bytes());
689    metadata_binary.extend(serialized_data);
690    Ok(metadata_binary)
691}