wasmer_compiler/engine/
artifact.rs

1//! Define `Artifact`, based on `ArtifactBuild`
2//! to allow compiling and instantiating to be done as separate steps.
3
4use std::sync::{
5    Arc,
6    atomic::{AtomicUsize, Ordering::SeqCst},
7};
8
9#[cfg(feature = "compiler")]
10use crate::ModuleEnvironment;
11use crate::{
12    ArtifactBuild, ArtifactBuildFromArchive, ArtifactCreate, Engine, EngineInner, Features,
13    FrameInfosVariant, FunctionExtent, GlobalFrameInfoRegistration, InstantiationError, Tunables,
14    engine::{link::link_module, resolver::resolve_tags},
15    lib::std::vec::IntoIter,
16    register_frame_info, resolve_imports,
17    serialize::{MetadataHeader, SerializableModule},
18    types::relocation::{RelocationLike, RelocationTarget},
19};
20#[cfg(feature = "static-artifact-create")]
21use crate::{Compiler, FunctionBodyData, ModuleTranslationState, types::module::CompileModuleInfo};
22#[cfg(any(feature = "static-artifact-create", feature = "static-artifact-load"))]
23use crate::{serialize::SerializableCompilation, types::symbols::ModuleMetadata};
24
25use enumset::EnumSet;
26use shared_buffer::OwnedBuffer;
27
28#[cfg(any(feature = "static-artifact-create", feature = "static-artifact-load"))]
29use std::mem;
30
31#[cfg(feature = "static-artifact-create")]
32use crate::object::{
33    Object, ObjectMetadataBuilder, emit_compilation, emit_data, get_object_for_target,
34};
35
36#[cfg(feature = "compiler")]
37use wasmer_types::HashAlgorithm;
38use wasmer_types::{
39    ArchivedDataInitializerLocation, ArchivedOwnedDataInitializer, CompileError, DataInitializer,
40    DataInitializerLike, DataInitializerLocation, DataInitializerLocationLike, DeserializeError,
41    FunctionIndex, LocalFunctionIndex, MemoryIndex, ModuleInfo, OwnedDataInitializer,
42    SerializeError, SignatureIndex, TableIndex,
43    entity::{BoxedSlice, PrimaryMap},
44    target::{CpuFeature, Target},
45};
46
47use wasmer_vm::{
48    FunctionBodyPtr, InstanceAllocator, MemoryStyle, StoreObjects, TableStyle, TrapHandlerFn,
49    VMConfig, VMExtern, VMInstance, VMSharedSignatureIndex, VMTrampoline,
50};
51
52#[cfg_attr(feature = "artifact-size", derive(loupe::MemoryUsage))]
53pub struct AllocatedArtifact {
54    // This shows if the frame info has been regestered already or not.
55    // Because the 'GlobalFrameInfoRegistration' ownership can be transfered to EngineInner
56    // this bool is needed to track the status, as 'frame_info_registration' will be None
57    // after the ownership is transfered.
58    frame_info_registered: bool,
59    // frame_info_registered is not staying there but transfered to CodeMemory from EngineInner
60    // using 'Artifact::take_frame_info_registration' method
61    // so the GloabelFrameInfo and MMap stays in sync and get dropped at the same time
62    frame_info_registration: Option<GlobalFrameInfoRegistration>,
63    finished_functions: BoxedSlice<LocalFunctionIndex, FunctionBodyPtr>,
64
65    #[cfg_attr(feature = "artifact-size", loupe(skip))]
66    finished_function_call_trampolines: BoxedSlice<SignatureIndex, VMTrampoline>,
67    finished_dynamic_function_trampolines: BoxedSlice<FunctionIndex, FunctionBodyPtr>,
68    signatures: BoxedSlice<SignatureIndex, VMSharedSignatureIndex>,
69    finished_function_lengths: BoxedSlice<LocalFunctionIndex, usize>,
70}
71
72#[derive(Debug, PartialEq, Eq, PartialOrd, Ord)]
73#[cfg_attr(feature = "artifact-size", derive(loupe::MemoryUsage))]
74#[repr(transparent)]
75/// A unique identifier for an Artifact.
76pub struct ArtifactId {
77    id: usize,
78}
79
80impl ArtifactId {
81    /// Format this identifier as a string.
82    pub fn id(&self) -> String {
83        format!("{}", &self.id)
84    }
85}
86
87impl Clone for ArtifactId {
88    fn clone(&self) -> Self {
89        Self::default()
90    }
91}
92
93impl Default for ArtifactId {
94    fn default() -> Self {
95        static NEXT_ID: AtomicUsize = AtomicUsize::new(0);
96        Self {
97            id: NEXT_ID.fetch_add(1, SeqCst),
98        }
99    }
100}
101
102/// A compiled wasm module, ready to be instantiated.
103#[cfg_attr(feature = "artifact-size", derive(loupe::MemoryUsage))]
104pub struct Artifact {
105    id: ArtifactId,
106    artifact: ArtifactBuildVariant,
107    // The artifact will only be allocated in memory in case we can execute it
108    // (that means, if the target != host then this will be None).
109    allocated: Option<AllocatedArtifact>,
110}
111
112/// Artifacts may be created as the result of the compilation of a wasm
113/// module, corresponding to `ArtifactBuildVariant::Plain`, or loaded
114/// from an archive, corresponding to `ArtifactBuildVariant::Archived`.
115#[cfg_attr(feature = "artifact-size", derive(loupe::MemoryUsage))]
116#[allow(clippy::large_enum_variant)]
117pub enum ArtifactBuildVariant {
118    Plain(ArtifactBuild),
119    Archived(ArtifactBuildFromArchive),
120}
121
122impl Artifact {
123    /// Compile a data buffer into a `ArtifactBuild`, which may then be instantiated.
124    #[cfg(feature = "compiler")]
125    pub fn new(
126        engine: &Engine,
127        data: &[u8],
128        tunables: &dyn Tunables,
129        hash_algorithm: Option<HashAlgorithm>,
130    ) -> Result<Self, CompileError> {
131        let mut inner_engine = engine.inner_mut();
132        let environ = ModuleEnvironment::new();
133        let translation = environ.translate(data).map_err(CompileError::Wasm)?;
134        let module = translation.module;
135        let memory_styles: PrimaryMap<MemoryIndex, MemoryStyle> = module
136            .memories
137            .values()
138            .map(|memory_type| tunables.memory_style(memory_type))
139            .collect();
140        let table_styles: PrimaryMap<TableIndex, TableStyle> = module
141            .tables
142            .values()
143            .map(|table_type| tunables.table_style(table_type))
144            .collect();
145
146        let artifact = ArtifactBuild::new(
147            &mut inner_engine,
148            data,
149            engine.target(),
150            memory_styles,
151            table_styles,
152            hash_algorithm,
153        )?;
154
155        Self::from_parts(
156            &mut inner_engine,
157            ArtifactBuildVariant::Plain(artifact),
158            engine.target(),
159        )
160        .map_err(|e| match e {
161            DeserializeError::Compiler(c) => c,
162
163            // `from_parts` only ever returns `CompileError`s when an
164            // `ArtifactBuildVariant::Plain` is passed in. Other cases
165            // of `DeserializeError` can only happen when an
166            // `ArtifactBuildVariant::Archived` is passed in. We don't
167            // wish to change the return type of this method because
168            // a. it makes no sense and b. it would be a breaking change,
169            // hence this match block and the other cases being
170            // unreachable.
171            _ => unreachable!(),
172        })
173    }
174
175    /// This indicates if the Artifact is allocated and can be run by the current
176    /// host. In case it can't be run (for example, if the artifact is cross compiled to
177    /// other architecture), it will return false.
178    pub fn allocated(&self) -> bool {
179        self.allocated.is_some()
180    }
181
182    /// A unique identifier for this object.
183    ///
184    /// This exists to allow us to compare two Artifacts for equality. Otherwise,
185    /// comparing two trait objects unsafely relies on implementation details
186    /// of trait representation.
187    pub fn id(&self) -> &ArtifactId {
188        &self.id
189    }
190
191    /// Compile a data buffer into a `ArtifactBuild`, which may then be instantiated.
192    #[cfg(not(feature = "compiler"))]
193    pub fn new(_engine: &Engine, _data: &[u8]) -> Result<Self, CompileError> {
194        Err(CompileError::Codegen(
195            "Compilation is not enabled in the engine".to_string(),
196        ))
197    }
198
199    /// Deserialize a serialized artifact.
200    ///
201    /// # Safety
202    /// This function loads executable code into memory.
203    /// You must trust the loaded bytes to be valid for the chosen engine and
204    /// for the host CPU architecture.
205    /// In contrast to [`Self::deserialize_unchecked`] the artifact layout is
206    /// validated, which increases safety.
207    pub unsafe fn deserialize(
208        engine: &Engine,
209        bytes: OwnedBuffer,
210    ) -> Result<Self, DeserializeError> {
211        unsafe {
212            if !ArtifactBuild::is_deserializable(bytes.as_ref()) {
213                let static_artifact = Self::deserialize_object(engine, bytes);
214                match static_artifact {
215                    Ok(v) => {
216                        return Ok(v);
217                    }
218                    Err(e) => {
219                        return Err(DeserializeError::Incompatible(format!(
220                            "The provided bytes are not wasmer-universal: {e}"
221                        )));
222                    }
223                }
224            }
225
226            let artifact = ArtifactBuildFromArchive::try_new(bytes, |bytes| {
227                let bytes =
228                    Self::get_byte_slice(bytes, ArtifactBuild::MAGIC_HEADER.len(), bytes.len())?;
229
230                let metadata_len = MetadataHeader::parse(bytes)?;
231                let metadata_slice = Self::get_byte_slice(bytes, MetadataHeader::LEN, bytes.len())?;
232                let metadata_slice = Self::get_byte_slice(metadata_slice, 0, metadata_len)?;
233
234                SerializableModule::archive_from_slice_checked(metadata_slice)
235            })?;
236
237            let mut inner_engine = engine.inner_mut();
238            Self::from_parts(
239                &mut inner_engine,
240                ArtifactBuildVariant::Archived(artifact),
241                engine.target(),
242            )
243        }
244    }
245
246    /// Deserialize a serialized artifact.
247    ///
248    /// NOTE: You should prefer [`Self::deserialize`].
249    ///
250    /// # Safety
251    /// See [`Self::deserialize`].
252    /// In contrast to the above, this function skips artifact layout validation,
253    /// which increases the risk of loading invalid artifacts.
254    pub unsafe fn deserialize_unchecked(
255        engine: &Engine,
256        bytes: OwnedBuffer,
257    ) -> Result<Self, DeserializeError> {
258        unsafe {
259            if !ArtifactBuild::is_deserializable(bytes.as_ref()) {
260                let static_artifact = Self::deserialize_object(engine, bytes);
261                match static_artifact {
262                    Ok(v) => {
263                        return Ok(v);
264                    }
265                    Err(e) => {
266                        return Err(DeserializeError::Incompatible(format!(
267                            "The provided bytes are not wasmer-universal: {e}"
268                        )));
269                    }
270                }
271            }
272
273            let artifact = ArtifactBuildFromArchive::try_new(bytes, |bytes| {
274                let bytes =
275                    Self::get_byte_slice(bytes, ArtifactBuild::MAGIC_HEADER.len(), bytes.len())?;
276
277                let metadata_len = MetadataHeader::parse(bytes)?;
278                let metadata_slice = Self::get_byte_slice(bytes, MetadataHeader::LEN, bytes.len())?;
279                let metadata_slice = Self::get_byte_slice(metadata_slice, 0, metadata_len)?;
280
281                SerializableModule::archive_from_slice(metadata_slice)
282            })?;
283
284            let mut inner_engine = engine.inner_mut();
285            Self::from_parts(
286                &mut inner_engine,
287                ArtifactBuildVariant::Archived(artifact),
288                engine.target(),
289            )
290        }
291    }
292
293    /// Construct a `ArtifactBuild` from component parts.
294    pub fn from_parts(
295        engine_inner: &mut EngineInner,
296        artifact: ArtifactBuildVariant,
297        target: &Target,
298    ) -> Result<Self, DeserializeError> {
299        if !target.is_native() {
300            return Ok(Self {
301                id: Default::default(),
302                artifact,
303                allocated: None,
304            });
305        } else {
306            // check if cpu features are compatible before anything else
307            let cpu_features = artifact.cpu_features();
308            if !target.cpu_features().is_superset(cpu_features) {
309                return Err(DeserializeError::Incompatible(format!(
310                    "Some CPU Features needed for the artifact are missing: {:?}",
311                    cpu_features.difference(*target.cpu_features())
312                )));
313            }
314        }
315        let module_info = artifact.module_info();
316        let (
317            finished_functions,
318            finished_function_call_trampolines,
319            finished_dynamic_function_trampolines,
320            custom_sections,
321        ) = match &artifact {
322            ArtifactBuildVariant::Plain(p) => engine_inner.allocate(
323                module_info,
324                p.get_function_bodies_ref().values(),
325                p.get_function_call_trampolines_ref().values(),
326                p.get_dynamic_function_trampolines_ref().values(),
327                p.get_custom_sections_ref().values(),
328            )?,
329            ArtifactBuildVariant::Archived(a) => engine_inner.allocate(
330                module_info,
331                a.get_function_bodies_ref().values(),
332                a.get_function_call_trampolines_ref().values(),
333                a.get_dynamic_function_trampolines_ref().values(),
334                a.get_custom_sections_ref().values(),
335            )?,
336        };
337
338        let get_got_address: Box<dyn Fn(RelocationTarget) -> Option<usize>> = match &artifact {
339            ArtifactBuildVariant::Plain(p) => {
340                if let Some(got) = p.get_got_ref().index {
341                    let relocs: Vec<_> = p.get_custom_section_relocations_ref()[got]
342                        .iter()
343                        .map(|v| (v.reloc_target, v.offset))
344                        .collect();
345                    let got_base = custom_sections[got].0 as usize;
346                    Box::new(move |t: RelocationTarget| {
347                        relocs
348                            .iter()
349                            .find(|(v, _)| v == &t)
350                            .map(|(_, o)| got_base + (*o as usize))
351                    })
352                } else {
353                    Box::new(|_: RelocationTarget| None)
354                }
355            }
356
357            ArtifactBuildVariant::Archived(p) => {
358                if let Some(got) = p.get_got_ref().index {
359                    let relocs: Vec<_> = p.get_custom_section_relocations_ref()[got]
360                        .iter()
361                        .map(|v| (v.reloc_target(), v.offset))
362                        .collect();
363                    let got_base = custom_sections[got].0 as usize;
364                    Box::new(move |t: RelocationTarget| {
365                        relocs
366                            .iter()
367                            .find(|(v, _)| v == &t)
368                            .map(|(_, o)| got_base + (o.to_native() as usize))
369                    })
370                } else {
371                    Box::new(|_: RelocationTarget| None)
372                }
373            }
374        };
375
376        match &artifact {
377            ArtifactBuildVariant::Plain(p) => link_module(
378                module_info,
379                &finished_functions,
380                &finished_dynamic_function_trampolines,
381                p.get_function_relocations()
382                    .iter()
383                    .map(|(k, v)| (k, v.iter())),
384                &custom_sections,
385                p.get_custom_section_relocations_ref()
386                    .iter()
387                    .map(|(k, v)| (k, v.iter())),
388                p.get_libcall_trampolines(),
389                p.get_libcall_trampoline_len(),
390                &get_got_address,
391            ),
392            ArtifactBuildVariant::Archived(a) => link_module(
393                module_info,
394                &finished_functions,
395                &finished_dynamic_function_trampolines,
396                a.get_function_relocations()
397                    .iter()
398                    .map(|(k, v)| (k, v.iter())),
399                &custom_sections,
400                a.get_custom_section_relocations_ref()
401                    .iter()
402                    .map(|(k, v)| (k, v.iter())),
403                a.get_libcall_trampolines(),
404                a.get_libcall_trampoline_len(),
405                &get_got_address,
406            ),
407        };
408
409        // Compute indices into the shared signature table.
410        let signatures = {
411            let signature_registry = engine_inner.signatures();
412            module_info
413                .signatures
414                .values()
415                .map(|sig| signature_registry.register(sig))
416                .collect::<PrimaryMap<_, _>>()
417        };
418
419        let eh_frame = match &artifact {
420            ArtifactBuildVariant::Plain(p) => p.get_unwind_info().eh_frame.map(|v| unsafe {
421                std::slice::from_raw_parts(
422                    *custom_sections[v],
423                    p.get_custom_sections_ref()[v].bytes.len(),
424                )
425            }),
426            ArtifactBuildVariant::Archived(a) => a.get_unwind_info().eh_frame.map(|v| unsafe {
427                std::slice::from_raw_parts(
428                    *custom_sections[v],
429                    a.get_custom_sections_ref()[v].bytes.len(),
430                )
431            }),
432        };
433
434        let compact_unwind = match &artifact {
435            ArtifactBuildVariant::Plain(p) => p.get_unwind_info().compact_unwind.map(|v| unsafe {
436                std::slice::from_raw_parts(
437                    *custom_sections[v],
438                    p.get_custom_sections_ref()[v].bytes.len(),
439                )
440            }),
441            ArtifactBuildVariant::Archived(a) => {
442                a.get_unwind_info().compact_unwind.map(|v| unsafe {
443                    std::slice::from_raw_parts(
444                        *custom_sections[v],
445                        a.get_custom_sections_ref()[v].bytes.len(),
446                    )
447                })
448            }
449        };
450
451        // This needs to be called before publishing the `eh_frame`.
452        engine_inner.register_compact_unwind(
453            compact_unwind,
454            get_got_address(RelocationTarget::LibCall(wasmer_vm::LibCall::EHPersonality)),
455        )?;
456
457        #[cfg(not(target_arch = "wasm32"))]
458        {
459            engine_inner.register_perfmap(&finished_functions, module_info)?;
460        }
461
462        // Make all code compiled thus far executable.
463        engine_inner.publish_compiled_code();
464
465        engine_inner.publish_eh_frame(eh_frame)?;
466
467        drop(get_got_address);
468
469        let finished_function_lengths = finished_functions
470            .values()
471            .map(|extent| extent.length)
472            .collect::<PrimaryMap<LocalFunctionIndex, usize>>()
473            .into_boxed_slice();
474        let finished_functions = finished_functions
475            .values()
476            .map(|extent| extent.ptr)
477            .collect::<PrimaryMap<LocalFunctionIndex, FunctionBodyPtr>>()
478            .into_boxed_slice();
479        let finished_function_call_trampolines =
480            finished_function_call_trampolines.into_boxed_slice();
481        let finished_dynamic_function_trampolines =
482            finished_dynamic_function_trampolines.into_boxed_slice();
483        let signatures = signatures.into_boxed_slice();
484
485        let mut artifact = Self {
486            id: Default::default(),
487            artifact,
488            allocated: Some(AllocatedArtifact {
489                frame_info_registered: false,
490                frame_info_registration: None,
491                finished_functions,
492                finished_function_call_trampolines,
493                finished_dynamic_function_trampolines,
494                signatures,
495                finished_function_lengths,
496            }),
497        };
498
499        artifact
500            .internal_register_frame_info()
501            .map_err(|e| DeserializeError::CorruptedBinary(format!("{e:?}")))?;
502        if let Some(frame_info) = artifact.internal_take_frame_info_registration() {
503            engine_inner.register_frame_info(frame_info);
504        }
505
506        Ok(artifact)
507    }
508
509    /// Check if the provided bytes look like a serialized `ArtifactBuild`.
510    pub fn is_deserializable(bytes: &[u8]) -> bool {
511        ArtifactBuild::is_deserializable(bytes)
512    }
513}
514
515impl PartialEq for Artifact {
516    fn eq(&self, other: &Self) -> bool {
517        self.id == other.id
518    }
519}
520impl Eq for Artifact {}
521
522impl std::fmt::Debug for Artifact {
523    fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
524        f.debug_struct("Artifact")
525            .field("artifact_id", &self.id)
526            .field("module_info", &self.module_info())
527            .finish()
528    }
529}
530
531impl<'a> ArtifactCreate<'a> for Artifact {
532    type OwnedDataInitializer = <ArtifactBuildVariant as ArtifactCreate<'a>>::OwnedDataInitializer;
533    type OwnedDataInitializerIterator =
534        <ArtifactBuildVariant as ArtifactCreate<'a>>::OwnedDataInitializerIterator;
535
536    fn set_module_info_name(&mut self, name: String) -> bool {
537        self.artifact.set_module_info_name(name)
538    }
539
540    fn create_module_info(&self) -> Arc<ModuleInfo> {
541        self.artifact.create_module_info()
542    }
543
544    fn module_info(&self) -> &ModuleInfo {
545        self.artifact.module_info()
546    }
547
548    fn features(&self) -> &Features {
549        self.artifact.features()
550    }
551
552    fn cpu_features(&self) -> EnumSet<CpuFeature> {
553        self.artifact.cpu_features()
554    }
555
556    fn data_initializers(&'a self) -> Self::OwnedDataInitializerIterator {
557        self.artifact.data_initializers()
558    }
559
560    fn memory_styles(&self) -> &PrimaryMap<MemoryIndex, MemoryStyle> {
561        self.artifact.memory_styles()
562    }
563
564    fn table_styles(&self) -> &PrimaryMap<TableIndex, TableStyle> {
565        self.artifact.table_styles()
566    }
567
568    fn serialize(&self) -> Result<Vec<u8>, SerializeError> {
569        self.artifact.serialize()
570    }
571}
572
573impl<'a> ArtifactCreate<'a> for ArtifactBuildVariant {
574    type OwnedDataInitializer = OwnedDataInitializerVariant<'a>;
575    type OwnedDataInitializerIterator = IntoIter<Self::OwnedDataInitializer>;
576
577    fn create_module_info(&self) -> Arc<ModuleInfo> {
578        match self {
579            Self::Plain(artifact) => artifact.create_module_info(),
580            Self::Archived(artifact) => artifact.create_module_info(),
581        }
582    }
583
584    fn set_module_info_name(&mut self, name: String) -> bool {
585        match self {
586            Self::Plain(artifact) => artifact.set_module_info_name(name),
587            Self::Archived(artifact) => artifact.set_module_info_name(name),
588        }
589    }
590
591    fn module_info(&self) -> &ModuleInfo {
592        match self {
593            Self::Plain(artifact) => artifact.module_info(),
594            Self::Archived(artifact) => artifact.module_info(),
595        }
596    }
597
598    fn features(&self) -> &Features {
599        match self {
600            Self::Plain(artifact) => artifact.features(),
601            Self::Archived(artifact) => artifact.features(),
602        }
603    }
604
605    fn cpu_features(&self) -> EnumSet<CpuFeature> {
606        match self {
607            Self::Plain(artifact) => artifact.cpu_features(),
608            Self::Archived(artifact) => artifact.cpu_features(),
609        }
610    }
611
612    fn memory_styles(&self) -> &PrimaryMap<MemoryIndex, MemoryStyle> {
613        match self {
614            Self::Plain(artifact) => artifact.memory_styles(),
615            Self::Archived(artifact) => artifact.memory_styles(),
616        }
617    }
618
619    fn table_styles(&self) -> &PrimaryMap<TableIndex, TableStyle> {
620        match self {
621            Self::Plain(artifact) => artifact.table_styles(),
622            Self::Archived(artifact) => artifact.table_styles(),
623        }
624    }
625
626    fn data_initializers(&'a self) -> Self::OwnedDataInitializerIterator {
627        match self {
628            Self::Plain(artifact) => artifact
629                .data_initializers()
630                .map(OwnedDataInitializerVariant::Plain)
631                .collect::<Vec<_>>()
632                .into_iter(),
633            Self::Archived(artifact) => artifact
634                .data_initializers()
635                .map(OwnedDataInitializerVariant::Archived)
636                .collect::<Vec<_>>()
637                .into_iter(),
638        }
639    }
640
641    fn serialize(&self) -> Result<Vec<u8>, SerializeError> {
642        match self {
643            Self::Plain(artifact) => artifact.serialize(),
644            Self::Archived(artifact) => artifact.serialize(),
645        }
646    }
647}
648
649#[derive(Clone, Copy)]
650pub enum OwnedDataInitializerVariant<'a> {
651    Plain(&'a OwnedDataInitializer),
652    Archived(&'a ArchivedOwnedDataInitializer),
653}
654
655impl<'a> DataInitializerLike<'a> for OwnedDataInitializerVariant<'a> {
656    type Location = DataInitializerLocationVariant<'a>;
657
658    fn location(&self) -> Self::Location {
659        match self {
660            Self::Plain(plain) => DataInitializerLocationVariant::Plain(plain.location()),
661            Self::Archived(archived) => {
662                DataInitializerLocationVariant::Archived(archived.location())
663            }
664        }
665    }
666
667    fn data(&self) -> &'a [u8] {
668        match self {
669            Self::Plain(plain) => plain.data(),
670            Self::Archived(archived) => archived.data(),
671        }
672    }
673}
674
675#[derive(Clone, Copy)]
676pub enum DataInitializerLocationVariant<'a> {
677    Plain(&'a DataInitializerLocation),
678    Archived(&'a ArchivedDataInitializerLocation),
679}
680
681impl DataInitializerLocationVariant<'_> {
682    pub fn clone_to_plain(&self) -> DataInitializerLocation {
683        match self {
684            Self::Plain(p) => (*p).clone(),
685            Self::Archived(a) => DataInitializerLocation {
686                memory_index: a.memory_index(),
687                base: a.base(),
688                offset: a.offset(),
689            },
690        }
691    }
692}
693
694impl DataInitializerLocationLike for DataInitializerLocationVariant<'_> {
695    fn memory_index(&self) -> MemoryIndex {
696        match self {
697            Self::Plain(plain) => plain.memory_index(),
698            Self::Archived(archived) => archived.memory_index(),
699        }
700    }
701
702    fn base(&self) -> Option<wasmer_types::GlobalIndex> {
703        match self {
704            Self::Plain(plain) => plain.base(),
705            Self::Archived(archived) => archived.base(),
706        }
707    }
708
709    fn offset(&self) -> usize {
710        match self {
711            Self::Plain(plain) => plain.offset(),
712            Self::Archived(archived) => archived.offset(),
713        }
714    }
715}
716
717impl Artifact {
718    fn internal_register_frame_info(&mut self) -> Result<(), DeserializeError> {
719        if self
720            .allocated
721            .as_ref()
722            .expect("It must be allocated")
723            .frame_info_registered
724        {
725            return Ok(()); // already done
726        }
727
728        let finished_function_extents = self
729            .allocated
730            .as_ref()
731            .expect("It must be allocated")
732            .finished_functions
733            .values()
734            .copied()
735            .zip(
736                self.allocated
737                    .as_ref()
738                    .expect("It must be allocated")
739                    .finished_function_lengths
740                    .values()
741                    .copied(),
742            )
743            .map(|(ptr, length)| FunctionExtent { ptr, length })
744            .collect::<PrimaryMap<LocalFunctionIndex, _>>()
745            .into_boxed_slice();
746
747        let frame_info_registration = &mut self
748            .allocated
749            .as_mut()
750            .expect("It must be allocated")
751            .frame_info_registration;
752
753        *frame_info_registration = register_frame_info(
754            self.artifact.create_module_info(),
755            &finished_function_extents,
756            match &self.artifact {
757                ArtifactBuildVariant::Plain(p) => {
758                    FrameInfosVariant::Owned(p.get_frame_info_ref().clone())
759                }
760                ArtifactBuildVariant::Archived(a) => FrameInfosVariant::Archived(a.clone()),
761            },
762        );
763
764        self.allocated
765            .as_mut()
766            .expect("It must be allocated")
767            .frame_info_registered = true;
768
769        Ok(())
770    }
771
772    fn internal_take_frame_info_registration(&mut self) -> Option<GlobalFrameInfoRegistration> {
773        let frame_info_registration = &mut self
774            .allocated
775            .as_mut()
776            .expect("It must be allocated")
777            .frame_info_registration;
778
779        frame_info_registration.take()
780    }
781
782    /// Returns the functions allocated in memory or this `Artifact`
783    /// ready to be run.
784    pub fn finished_functions(&self) -> &BoxedSlice<LocalFunctionIndex, FunctionBodyPtr> {
785        &self
786            .allocated
787            .as_ref()
788            .expect("It must be allocated")
789            .finished_functions
790    }
791
792    /// Returns the function call trampolines allocated in memory of this
793    /// `Artifact`, ready to be run.
794    pub fn finished_function_call_trampolines(&self) -> &BoxedSlice<SignatureIndex, VMTrampoline> {
795        &self
796            .allocated
797            .as_ref()
798            .expect("It must be allocated")
799            .finished_function_call_trampolines
800    }
801
802    /// Returns the dynamic function trampolines allocated in memory
803    /// of this `Artifact`, ready to be run.
804    pub fn finished_dynamic_function_trampolines(
805        &self,
806    ) -> &BoxedSlice<FunctionIndex, FunctionBodyPtr> {
807        &self
808            .allocated
809            .as_ref()
810            .expect("It must be allocated")
811            .finished_dynamic_function_trampolines
812    }
813
814    /// Returns the associated VM signatures for this `Artifact`.
815    pub fn signatures(&self) -> &BoxedSlice<SignatureIndex, VMSharedSignatureIndex> {
816        &self
817            .allocated
818            .as_ref()
819            .expect("It must be allocated")
820            .signatures
821    }
822
823    /// Do preinstantiation logic that is executed before instantiating
824    #[allow(clippy::result_large_err)]
825    pub fn preinstantiate(&self) -> Result<(), InstantiationError> {
826        Ok(())
827    }
828
829    /// Crate an `Instance` from this `Artifact`.
830    ///
831    /// # Safety
832    ///
833    /// See [`VMInstance::new`].
834    #[allow(clippy::result_large_err)]
835    pub unsafe fn instantiate(
836        &self,
837        tunables: &dyn Tunables,
838        imports: &[VMExtern],
839        context: &mut StoreObjects,
840    ) -> Result<VMInstance, InstantiationError> {
841        unsafe {
842            // Validate the CPU features this module was compiled with against the
843            // host CPU features.
844            let host_cpu_features = CpuFeature::for_host();
845            if !host_cpu_features.is_superset(self.cpu_features()) {
846                return Err(InstantiationError::CpuFeature(format!(
847                    "{:?}",
848                    self.cpu_features().difference(host_cpu_features)
849                )));
850            }
851
852            self.preinstantiate()?;
853
854            let module = self.create_module_info();
855
856            let tags = resolve_tags(&module, imports, context).map_err(InstantiationError::Link)?;
857
858            let imports = resolve_imports(
859                &module,
860                imports,
861                context,
862                self.finished_dynamic_function_trampolines(),
863                self.memory_styles(),
864                self.table_styles(),
865            )
866            .map_err(InstantiationError::Link)?;
867
868            // Get pointers to where metadata about local memories should live in VM memory.
869            // Get pointers to where metadata about local tables should live in VM memory.
870
871            let (allocator, memory_definition_locations, table_definition_locations) =
872                InstanceAllocator::new(&module);
873            let finished_memories = tunables
874                .create_memories(
875                    context,
876                    &module,
877                    self.memory_styles(),
878                    &memory_definition_locations,
879                )
880                .map_err(InstantiationError::Link)?
881                .into_boxed_slice();
882            let finished_tables = tunables
883                .create_tables(
884                    context,
885                    &module,
886                    self.table_styles(),
887                    &table_definition_locations,
888                )
889                .map_err(InstantiationError::Link)?
890                .into_boxed_slice();
891            let finished_globals = tunables
892                .create_globals(context, &module)
893                .map_err(InstantiationError::Link)?
894                .into_boxed_slice();
895
896            let handle = VMInstance::new(
897                allocator,
898                module,
899                context,
900                self.finished_functions().clone(),
901                self.finished_function_call_trampolines().clone(),
902                finished_memories,
903                finished_tables,
904                finished_globals,
905                tags,
906                imports,
907                self.signatures().clone(),
908            )
909            .map_err(InstantiationError::Start)?;
910            Ok(handle)
911        }
912    }
913
914    /// Finishes the instantiation of a just created `VMInstance`.
915    ///
916    /// # Safety
917    ///
918    /// See [`VMInstance::finish_instantiation`].
919    #[allow(clippy::result_large_err)]
920    pub unsafe fn finish_instantiation(
921        &self,
922        config: &VMConfig,
923        trap_handler: Option<*const TrapHandlerFn<'static>>,
924        handle: &mut VMInstance,
925    ) -> Result<(), InstantiationError> {
926        unsafe {
927            let data_initializers = self
928                .data_initializers()
929                .map(|init| DataInitializer {
930                    location: init.location().clone_to_plain(),
931                    data: init.data(),
932                })
933                .collect::<Vec<_>>();
934            handle
935                .finish_instantiation(config, trap_handler, &data_initializers)
936                .map_err(InstantiationError::Start)
937        }
938    }
939
940    #[allow(clippy::type_complexity)]
941    #[cfg(feature = "static-artifact-create")]
942    /// Generate a compilation
943    pub fn generate_metadata<'data>(
944        data: &'data [u8],
945        compiler: &dyn Compiler,
946        tunables: &dyn Tunables,
947        features: &Features,
948    ) -> Result<
949        (
950            CompileModuleInfo,
951            PrimaryMap<LocalFunctionIndex, FunctionBodyData<'data>>,
952            Vec<DataInitializer<'data>>,
953            Option<ModuleTranslationState>,
954        ),
955        CompileError,
956    > {
957        let environ = ModuleEnvironment::new();
958        let translation = environ.translate(data).map_err(CompileError::Wasm)?;
959
960        // We try to apply the middleware first
961        use crate::translator::ModuleMiddlewareChain;
962        let mut module = translation.module;
963        let middlewares = compiler.get_middlewares();
964        middlewares
965            .apply_on_module_info(&mut module)
966            .map_err(|e| CompileError::MiddlewareError(e.to_string()))?;
967
968        let memory_styles: PrimaryMap<MemoryIndex, MemoryStyle> = module
969            .memories
970            .values()
971            .map(|memory_type| tunables.memory_style(memory_type))
972            .collect();
973        let table_styles: PrimaryMap<TableIndex, TableStyle> = module
974            .tables
975            .values()
976            .map(|table_type| tunables.table_style(table_type))
977            .collect();
978
979        let compile_info = CompileModuleInfo {
980            module: Arc::new(module),
981            features: features.clone(),
982            memory_styles,
983            table_styles,
984        };
985        Ok((
986            compile_info,
987            translation.function_body_inputs,
988            translation.data_initializers,
989            translation.module_translation_state,
990        ))
991    }
992
993    /// Generate the metadata object for the module
994    #[cfg(feature = "static-artifact-create")]
995    #[allow(clippy::type_complexity)]
996    pub fn metadata<'a>(
997        compiler: &dyn Compiler,
998        data: &'a [u8],
999        metadata_prefix: Option<&str>,
1000        target: &Target,
1001        tunables: &dyn Tunables,
1002        features: &Features,
1003    ) -> Result<
1004        (
1005            ModuleMetadata,
1006            Option<ModuleTranslationState>,
1007            PrimaryMap<LocalFunctionIndex, FunctionBodyData<'a>>,
1008        ),
1009        CompileError,
1010    > {
1011        #[allow(dead_code)]
1012        let (compile_info, function_body_inputs, data_initializers, module_translation) =
1013            Self::generate_metadata(data, compiler, tunables, features)?;
1014
1015        let data_initializers = data_initializers
1016            .iter()
1017            .map(OwnedDataInitializer::new)
1018            .collect::<Vec<_>>()
1019            .into_boxed_slice();
1020
1021        // TODO: we currently supply all-zero function body lengths.
1022        // We don't know the lengths until they're compiled, yet we have to
1023        // supply the metadata as an input to the compile.
1024        let function_body_lengths = function_body_inputs
1025            .keys()
1026            .map(|_function_body| 0u64)
1027            .collect::<PrimaryMap<LocalFunctionIndex, u64>>();
1028
1029        let metadata = ModuleMetadata {
1030            compile_info,
1031            prefix: metadata_prefix.map(|s| s.to_string()).unwrap_or_default(),
1032            data_initializers,
1033            function_body_lengths,
1034            cpu_features: target.cpu_features().as_u64(),
1035        };
1036
1037        Ok((metadata, module_translation, function_body_inputs))
1038    }
1039
1040    /// Compile a module into an object file, which can be statically linked against.
1041    ///
1042    /// The `metadata_prefix` is an optional prefix for the object name to make the
1043    /// function names in the object file unique. When set, the function names will
1044    /// be `wasmer_function_{prefix}_{id}` and the object metadata will be addressable
1045    /// using `WASMER_METADATA_{prefix}_LENGTH` and `WASMER_METADATA_{prefix}_DATA`.
1046    ///
1047    #[cfg(feature = "static-artifact-create")]
1048    pub fn generate_object<'data>(
1049        compiler: &dyn Compiler,
1050        data: &[u8],
1051        metadata_prefix: Option<&str>,
1052        target: &'data Target,
1053        tunables: &dyn Tunables,
1054        features: &Features,
1055    ) -> Result<
1056        (
1057            ModuleInfo,
1058            Object<'data>,
1059            usize,
1060            Box<dyn crate::types::symbols::SymbolRegistry>,
1061        ),
1062        CompileError,
1063    > {
1064        use crate::types::symbols::{ModuleMetadataSymbolRegistry, SymbolRegistry};
1065
1066        fn to_compile_error(err: impl std::error::Error) -> CompileError {
1067            CompileError::Codegen(format!("{err}"))
1068        }
1069
1070        let target_triple = target.triple();
1071        let (mut metadata, module_translation, function_body_inputs) =
1072            Self::metadata(compiler, data, metadata_prefix, target, tunables, features)
1073                .map_err(to_compile_error)?;
1074
1075        /*
1076        In the C file we need:
1077        - imports
1078        - exports
1079
1080        to construct an api::Module which is a Store (can be passed in via argument) and an
1081        Arc<dyn Artifact> which means this struct which includes:
1082        - CompileModuleInfo
1083        - Features
1084        - ModuleInfo
1085        - MemoryIndex -> MemoryStyle
1086        - TableIndex -> TableStyle
1087        - LocalFunctionIndex -> FunctionBodyPtr // finished functions
1088        - FunctionIndex -> FunctionBodyPtr // finished dynamic function trampolines
1089        - SignatureIndex -> VMSharedSignatureindextureIndex // signatures
1090         */
1091
1092        let mut metadata_builder =
1093            ObjectMetadataBuilder::new(&metadata, target_triple).map_err(to_compile_error)?;
1094
1095        let (_compile_info, symbol_registry) = metadata.split();
1096
1097        let compilation: crate::types::function::Compilation = compiler.compile_module(
1098            target,
1099            &metadata.compile_info,
1100            module_translation.as_ref().unwrap(),
1101            function_body_inputs,
1102        )?;
1103        let mut obj = get_object_for_target(target_triple).map_err(to_compile_error)?;
1104
1105        let object_name = ModuleMetadataSymbolRegistry {
1106            prefix: metadata_prefix.unwrap_or_default().to_string(),
1107        }
1108        .symbol_to_name(crate::types::symbols::Symbol::Metadata);
1109
1110        let default_align = match target_triple.architecture {
1111            target_lexicon::Architecture::Aarch64(_) => {
1112                if matches!(
1113                    target_triple.operating_system,
1114                    target_lexicon::OperatingSystem::Darwin(_)
1115                ) {
1116                    8
1117                } else {
1118                    4
1119                }
1120            }
1121            _ => 1,
1122        };
1123
1124        let offset = emit_data(
1125            &mut obj,
1126            object_name.as_bytes(),
1127            metadata_builder.placeholder_data(),
1128            default_align,
1129        )
1130        .map_err(to_compile_error)?;
1131        metadata_builder.set_section_offset(offset);
1132
1133        emit_compilation(
1134            &mut obj,
1135            compilation,
1136            &symbol_registry,
1137            target_triple,
1138            &metadata_builder,
1139        )
1140        .map_err(to_compile_error)?;
1141        Ok((
1142            Arc::try_unwrap(metadata.compile_info.module).unwrap(),
1143            obj,
1144            metadata_builder.placeholder_data().len(),
1145            Box::new(symbol_registry),
1146        ))
1147    }
1148
1149    /// Deserialize a ArtifactBuild from an object file
1150    ///
1151    /// # Safety
1152    /// The object must be a valid static object generated by wasmer.
1153    #[cfg(not(feature = "static-artifact-load"))]
1154    pub unsafe fn deserialize_object(
1155        _engine: &Engine,
1156        _bytes: OwnedBuffer,
1157    ) -> Result<Self, DeserializeError> {
1158        Err(DeserializeError::Compiler(
1159            CompileError::UnsupportedFeature("static load is not compiled in".to_string()),
1160        ))
1161    }
1162
1163    fn get_byte_slice(input: &[u8], start: usize, end: usize) -> Result<&[u8], DeserializeError> {
1164        if (start == end && input.len() > start)
1165            || (start < end && input.len() > start && input.len() >= end)
1166        {
1167            Ok(&input[start..end])
1168        } else {
1169            Err(DeserializeError::InvalidByteLength {
1170                expected: end - start,
1171                got: input.len(),
1172            })
1173        }
1174    }
1175
1176    /// Deserialize a ArtifactBuild from an object file
1177    ///
1178    /// # Safety
1179    /// The object must be a valid static object generated by wasmer.
1180    #[cfg(feature = "static-artifact-load")]
1181    pub unsafe fn deserialize_object(
1182        engine: &Engine,
1183        bytes: OwnedBuffer,
1184    ) -> Result<Self, DeserializeError> {
1185        unsafe {
1186            let bytes = bytes.as_slice();
1187            let metadata_len = MetadataHeader::parse(bytes)?;
1188            let metadata_slice = Self::get_byte_slice(bytes, MetadataHeader::LEN, bytes.len())?;
1189            let metadata_slice = Self::get_byte_slice(metadata_slice, 0, metadata_len)?;
1190            let metadata: ModuleMetadata = ModuleMetadata::deserialize(metadata_slice)?;
1191
1192            const WORD_SIZE: usize = mem::size_of::<usize>();
1193            let mut byte_buffer = [0u8; WORD_SIZE];
1194
1195            let mut cur_offset = MetadataHeader::LEN + metadata_len;
1196
1197            let byte_buffer_slice =
1198                Self::get_byte_slice(bytes, cur_offset, cur_offset + WORD_SIZE)?;
1199            byte_buffer[0..WORD_SIZE].clone_from_slice(byte_buffer_slice);
1200            cur_offset += WORD_SIZE;
1201
1202            let num_finished_functions = usize::from_ne_bytes(byte_buffer);
1203            let mut finished_functions: PrimaryMap<LocalFunctionIndex, FunctionBodyPtr> =
1204                PrimaryMap::new();
1205
1206            let engine_inner = engine.inner();
1207            let signature_registry = engine_inner.signatures();
1208
1209            // read finished functions in order now...
1210            for _i in 0..num_finished_functions {
1211                let byte_buffer_slice =
1212                    Self::get_byte_slice(bytes, cur_offset, cur_offset + WORD_SIZE)?;
1213                byte_buffer[0..WORD_SIZE].clone_from_slice(byte_buffer_slice);
1214                let fp = FunctionBodyPtr(usize::from_ne_bytes(byte_buffer) as _);
1215                cur_offset += WORD_SIZE;
1216
1217                // TODO: we can read back the length here if we serialize it. This will improve debug output.
1218                finished_functions.push(fp);
1219            }
1220
1221            // We register all the signatures
1222            let signatures = {
1223                metadata
1224                    .compile_info
1225                    .module
1226                    .signatures
1227                    .values()
1228                    .map(|sig| signature_registry.register(sig))
1229                    .collect::<PrimaryMap<_, _>>()
1230            };
1231
1232            // read trampolines in order
1233            let mut finished_function_call_trampolines = PrimaryMap::new();
1234
1235            let byte_buffer_slice =
1236                Self::get_byte_slice(bytes, cur_offset, cur_offset + WORD_SIZE)?;
1237            byte_buffer[0..WORD_SIZE].clone_from_slice(byte_buffer_slice);
1238            cur_offset += WORD_SIZE;
1239            let num_function_trampolines = usize::from_ne_bytes(byte_buffer);
1240            for _ in 0..num_function_trampolines {
1241                let byte_buffer_slice =
1242                    Self::get_byte_slice(bytes, cur_offset, cur_offset + WORD_SIZE)?;
1243                byte_buffer[0..WORD_SIZE].clone_from_slice(byte_buffer_slice);
1244                cur_offset += WORD_SIZE;
1245                let trampoline_ptr_bytes = usize::from_ne_bytes(byte_buffer);
1246                let trampoline = mem::transmute::<usize, VMTrampoline>(trampoline_ptr_bytes);
1247                finished_function_call_trampolines.push(trampoline);
1248                // TODO: we can read back the length here if we serialize it. This will improve debug output.
1249            }
1250
1251            // read dynamic function trampolines in order now...
1252            let mut finished_dynamic_function_trampolines = PrimaryMap::new();
1253            let byte_buffer_slice =
1254                Self::get_byte_slice(bytes, cur_offset, cur_offset + WORD_SIZE)?;
1255            byte_buffer[0..WORD_SIZE].clone_from_slice(byte_buffer_slice);
1256            cur_offset += WORD_SIZE;
1257            let num_dynamic_trampoline_functions = usize::from_ne_bytes(byte_buffer);
1258            for _i in 0..num_dynamic_trampoline_functions {
1259                let byte_buffer_slice =
1260                    Self::get_byte_slice(bytes, cur_offset, cur_offset + WORD_SIZE)?;
1261                byte_buffer[0..WORD_SIZE].clone_from_slice(byte_buffer_slice);
1262                let fp = FunctionBodyPtr(usize::from_ne_bytes(byte_buffer) as _);
1263                cur_offset += WORD_SIZE;
1264
1265                // TODO: we can read back the length here if we serialize it. This will improve debug output.
1266
1267                finished_dynamic_function_trampolines.push(fp);
1268            }
1269
1270            let artifact = ArtifactBuild::from_serializable(SerializableModule {
1271                compilation: SerializableCompilation::default(),
1272                compile_info: metadata.compile_info,
1273                data_initializers: metadata.data_initializers,
1274                cpu_features: metadata.cpu_features,
1275            });
1276
1277            let finished_function_lengths = finished_functions
1278                .values()
1279                .map(|_| 0)
1280                .collect::<PrimaryMap<LocalFunctionIndex, usize>>()
1281                .into_boxed_slice();
1282
1283            Ok(Self {
1284                id: Default::default(),
1285                artifact: ArtifactBuildVariant::Plain(artifact),
1286                allocated: Some(AllocatedArtifact {
1287                    frame_info_registered: false,
1288                    frame_info_registration: None,
1289                    finished_functions: finished_functions.into_boxed_slice(),
1290                    finished_function_call_trampolines: finished_function_call_trampolines
1291                        .into_boxed_slice(),
1292                    finished_dynamic_function_trampolines: finished_dynamic_function_trampolines
1293                        .into_boxed_slice(),
1294                    signatures: signatures.into_boxed_slice(),
1295                    finished_function_lengths,
1296                }),
1297            })
1298        }
1299    }
1300}