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