wasmer_cli/
backend.rs

1//! Common module with common used structures across different
2//! commands.
3
4// NOTE: A lot of this code depends on feature flags.
5// To not go crazy with annotations, some lints are disabled for the whole
6// module.
7#![allow(dead_code, unused_imports, unused_variables)]
8
9use std::num::NonZero;
10use std::string::ToString;
11use std::sync::Arc;
12use std::{path::PathBuf, str::FromStr};
13
14use anyhow::{Context, Result, bail};
15#[cfg(feature = "sys")]
16use wasmer::sys::*;
17use wasmer::*;
18use wasmer_types::{Features, target::Target};
19
20#[cfg(feature = "compiler")]
21use wasmer_compiler::CompilerConfig;
22
23use wasmer::Engine;
24
25#[derive(Debug, clap::Parser, Clone, Default)]
26/// The WebAssembly features that can be passed through the
27/// Command Line args.
28pub struct WasmFeatures {
29    /// Enable support for the SIMD proposal.
30    #[clap(long = "enable-simd")]
31    pub simd: bool,
32
33    /// Disable support for the threads proposal.
34    #[clap(long = "disable-threads")]
35    pub disable_threads: bool,
36
37    /// Deprecated, threads are enabled by default.
38    #[clap(long = "enable-threads")]
39    pub _threads: bool,
40
41    /// Enable support for the reference types proposal.
42    #[clap(long = "enable-reference-types")]
43    pub reference_types: bool,
44
45    /// Enable support for the multi value proposal.
46    #[clap(long = "enable-multi-value")]
47    pub multi_value: bool,
48
49    /// Enable support for the bulk memory proposal.
50    #[clap(long = "enable-bulk-memory")]
51    pub bulk_memory: bool,
52
53    /// Enable support for the tail call proposal.
54    #[clap(long = "enable-tail-call")]
55    pub tail_call: bool,
56
57    /// Enable support for the module linking proposal.
58    #[clap(long = "enable-module-linking")]
59    pub module_linking: bool,
60
61    /// Enable support for the multi memory proposal.
62    #[clap(long = "enable-multi-memory")]
63    pub multi_memory: bool,
64
65    /// Enable support for the memory64 proposal.
66    #[clap(long = "enable-memory64")]
67    pub memory64: bool,
68
69    /// Enable support for the exceptions proposal.
70    #[clap(long = "enable-exceptions")]
71    pub exceptions: bool,
72
73    /// Enable support for the relaxed SIMD proposal.
74    #[clap(long = "enable-relaxed-simd")]
75    pub relaxed_simd: bool,
76
77    /// Enable support for the extended constant expressions proposal.
78    #[clap(long = "enable-extended-const")]
79    pub extended_const: bool,
80
81    /// Enable support for the wide arithmetic proposal.
82    #[clap(long = "wide-arithmetic")]
83    pub wide_arithmetic: bool,
84
85    /// Enable support for all pre-standard proposals.
86    #[clap(long = "enable-all")]
87    pub all: bool,
88}
89
90#[derive(Debug, Clone, clap::Parser, Default)]
91/// The compiler options
92pub struct RuntimeOptions {
93    /// Use Singlepass compiler.
94    #[cfg(feature = "singlepass")]
95    #[clap(short, long, conflicts_with_all = &Vec::<&str>::from_iter([
96        #[cfg(feature = "llvm")]
97        "llvm", 
98        #[cfg(feature = "v8")]
99        "v8", 
100        #[cfg(feature = "cranelift")]
101        "cranelift", 
102        #[cfg(feature = "wamr")]
103        "wamr", 
104        #[cfg(feature = "wasmi")]
105        "wasmi"
106    ]))]
107    singlepass: bool,
108
109    /// Use Cranelift compiler.
110    #[cfg(feature = "cranelift")]
111    #[clap(short, long, conflicts_with_all = &Vec::<&str>::from_iter([
112        #[cfg(feature = "llvm")]
113        "llvm", 
114        #[cfg(feature = "v8")]
115        "v8", 
116        #[cfg(feature = "singlepass")]
117        "singlepass", 
118        #[cfg(feature = "wamr")]
119        "wamr", 
120        #[cfg(feature = "wasmi")]
121        "wasmi"
122    ]))]
123    cranelift: bool,
124
125    /// Use LLVM compiler.
126    #[cfg(feature = "llvm")]
127    #[clap(short, long, conflicts_with_all = &Vec::<&str>::from_iter([
128        #[cfg(feature = "cranelift")]
129        "cranelift", 
130        #[cfg(feature = "v8")]
131        "v8", 
132        #[cfg(feature = "singlepass")]
133        "singlepass", 
134        #[cfg(feature = "wamr")]
135        "wamr", 
136        #[cfg(feature = "wasmi")]
137        "wasmi"
138    ]))]
139    llvm: bool,
140
141    /// Use the V8 runtime.
142    #[cfg(feature = "v8")]
143    #[clap(long, conflicts_with_all = &Vec::<&str>::from_iter([
144        #[cfg(feature = "cranelift")]
145        "cranelift", 
146        #[cfg(feature = "llvm")]
147        "llvm", 
148        #[cfg(feature = "singlepass")]
149        "singlepass", 
150        #[cfg(feature = "wamr")]
151        "wamr", 
152        #[cfg(feature = "wasmi")]
153        "wasmi"
154    ]))]
155    v8: bool,
156
157    /// Use the WAMR runtime.
158    #[cfg(feature = "wamr")]
159    #[clap(long, conflicts_with_all = &Vec::<&str>::from_iter([
160        #[cfg(feature = "cranelift")]
161        "cranelift", 
162        #[cfg(feature = "llvm")]
163        "llvm", 
164        #[cfg(feature = "singlepass")]
165        "singlepass", 
166        #[cfg(feature = "v8")]
167        "v8", 
168        #[cfg(feature = "wasmi")]
169        "wasmi"
170    ]))]
171    wamr: bool,
172
173    /// Use the Wasmi runtime.
174    #[cfg(feature = "wasmi")]
175    #[clap(long, conflicts_with_all = &Vec::<&str>::from_iter([
176        #[cfg(feature = "cranelift")]
177        "cranelift", 
178        #[cfg(feature = "llvm")]
179        "llvm", 
180        #[cfg(feature = "singlepass")]
181        "singlepass", 
182        #[cfg(feature = "v8")]
183        "v8", 
184        #[cfg(feature = "wamr")]
185        "wamr"
186    ]))]
187    wasmi: bool,
188
189    /// Enable compiler internal verification.
190    ///
191    /// Available for Cranelift, LLVM and Singlepass.
192    #[clap(long)]
193    enable_verifier: bool,
194
195    /// Debug directory, where IR and object files will be written to.
196    ///
197    /// Available for Cranelift, LLVM and Singlepass.
198    #[clap(long, alias = "llvm-debug-dir")]
199    pub(crate) compiler_debug_dir: Option<PathBuf>,
200
201    /// Enable a profiler.
202    ///
203    /// Available for Cranelift, LLVM and Singlepass.
204    #[clap(long, value_enum)]
205    profiler: Option<Profiler>,
206
207    /// Deprecated option as m0 optimization always play role if we use a static memory
208    #[cfg(feature = "llvm")]
209    #[clap(long, hide = true)]
210    _enable_pass_params_opt: bool,
211
212    /// Sets the number of threads used to compile the input module(s).
213    #[clap(long, alias = "llvm-num-threads")]
214    compiler_threads: Option<NonZero<usize>>,
215
216    /// Enable NaN canonicalization during compilation to produce deterministic
217    /// canonical quiet NaNs (QNaNs) across architectures.
218    #[clap(long = "enable-nan-canonicalization")]
219    enable_nan_canonicalization: bool,
220
221    #[clap(flatten)]
222    features: WasmFeatures,
223}
224
225#[derive(Clone, Debug)]
226pub enum Profiler {
227    /// Perfmap-based profilers.
228    Perfmap,
229}
230
231impl FromStr for Profiler {
232    type Err = anyhow::Error;
233
234    fn from_str(s: &str) -> std::result::Result<Self, Self::Err> {
235        match s.to_lowercase().as_str() {
236            "perfmap" => Ok(Self::Perfmap),
237            _ => Err(anyhow::anyhow!("Unrecognized profiler: {s}")),
238        }
239    }
240}
241
242impl RuntimeOptions {
243    pub fn get_available_backends(&self) -> Result<Vec<BackendType>> {
244        // If a specific backend is explicitly requested, use it
245        #[cfg(feature = "cranelift")]
246        {
247            if self.cranelift {
248                return Ok(vec![BackendType::Cranelift]);
249            }
250        }
251
252        #[cfg(feature = "llvm")]
253        {
254            if self.llvm {
255                return Ok(vec![BackendType::LLVM]);
256            }
257        }
258
259        #[cfg(feature = "singlepass")]
260        {
261            if self.singlepass {
262                return Ok(vec![BackendType::Singlepass]);
263            }
264        }
265
266        #[cfg(feature = "wamr")]
267        {
268            if self.wamr {
269                return Ok(vec![BackendType::Wamr]);
270            }
271        }
272
273        #[cfg(feature = "v8")]
274        {
275            if self.v8 {
276                return Ok(vec![BackendType::V8]);
277            }
278        }
279
280        #[cfg(feature = "wasmi")]
281        {
282            if self.wasmi {
283                return Ok(vec![BackendType::Wasmi]);
284            }
285        }
286
287        Ok(BackendType::enabled())
288    }
289
290    /// Filter enabled backends based on required WebAssembly features
291    pub fn filter_backends_by_features(
292        backends: Vec<BackendType>,
293        required_features: &Features,
294        target: &Target,
295    ) -> Vec<BackendType> {
296        backends
297            .into_iter()
298            .filter(|backend| backend.supports_features(required_features, target))
299            .collect()
300    }
301
302    pub fn get_store(&self) -> Result<Store> {
303        let engine = self.get_engine(&Target::default())?;
304        Ok(Store::new(engine))
305    }
306
307    pub fn get_engine(&self, target: &Target) -> Result<Engine> {
308        let backends = self.get_available_backends()?;
309        let backend = backends.first().context("no compiler backend enabled")?;
310        backend.get_engine(target, self)
311    }
312
313    pub fn get_engine_for_module(&self, module_contents: &[u8], target: &Target) -> Result<Engine> {
314        let required_features = self
315            .detect_features_from_wasm(module_contents)
316            .unwrap_or_default();
317
318        self.get_engine_for_features(&required_features, target)
319    }
320
321    pub fn get_engine_for_features(
322        &self,
323        required_features: &Features,
324        target: &Target,
325    ) -> Result<Engine> {
326        let backends = self.get_available_backends()?;
327        let filtered_backends =
328            Self::filter_backends_by_features(backends.clone(), required_features, target);
329
330        if filtered_backends.is_empty() {
331            let enabled_backends = BackendType::enabled();
332            if backends.len() == 1 && enabled_backends.len() > 1 {
333                // If the user has chosen an specific backend, we can suggest to use another one
334                let filtered_backends =
335                    Self::filter_backends_by_features(enabled_backends, required_features, target);
336                let extra_text: String = if !filtered_backends.is_empty() {
337                    format!(". You can use --{} instead", filtered_backends[0])
338                } else {
339                    "".to_string()
340                };
341                bail!(
342                    "The {} backend does not support the required features for the Wasm module{}",
343                    backends[0],
344                    extra_text
345                );
346            } else {
347                bail!(
348                    "No backends support the required features for the Wasm module. Feel free to open an issue at https://github.com/wasmerio/wasmer/issues"
349                );
350            }
351        }
352        filtered_backends.first().unwrap().get_engine(target, self)
353    }
354
355    #[cfg(feature = "compiler")]
356    /// Get the enabled Wasm features.
357    pub fn get_features(&self, default_features: &Features) -> Result<Features> {
358        if self.features.all {
359            return Ok(Features::all());
360        }
361
362        let mut result = default_features.clone();
363        if !self.features.disable_threads {
364            result.threads(true);
365        }
366        if self.features.disable_threads {
367            result.threads(false);
368        }
369        if self.features.multi_value {
370            result.multi_value(true);
371        }
372        if self.features.simd {
373            result.simd(true);
374        }
375        if self.features.bulk_memory {
376            result.bulk_memory(true);
377        }
378        if self.features.reference_types {
379            result.reference_types(true);
380        }
381        Ok(result)
382    }
383
384    #[cfg(feature = "compiler")]
385    /// Get a copy of the default features with user-configured options
386    pub fn get_configured_features(&self) -> Result<Features> {
387        let features = Features::default();
388        self.get_features(&features)
389    }
390
391    /// Detect features from a WebAssembly module binary.
392    pub fn detect_features_from_wasm(
393        &self,
394        wasm_bytes: &[u8],
395    ) -> Result<Features, wasmparser::BinaryReaderError> {
396        if self.features.all {
397            return Ok(Features::all());
398        }
399
400        let mut features = Features::detect_from_wasm(wasm_bytes)?;
401
402        // Merge with user-configured features
403        if !self.features.disable_threads {
404            features.threads(true);
405        }
406        if self.features.reference_types {
407            features.reference_types(true);
408        }
409        if self.features.simd {
410            features.simd(true);
411        }
412        if self.features.bulk_memory {
413            features.bulk_memory(true);
414        }
415        if self.features.multi_value {
416            features.multi_value(true);
417        }
418        if self.features.tail_call {
419            features.tail_call(true);
420        }
421        if self.features.module_linking {
422            features.module_linking(true);
423        }
424        if self.features.multi_memory {
425            features.multi_memory(true);
426        }
427        if self.features.memory64 {
428            features.memory64(true);
429        }
430        if self.features.exceptions {
431            features.exceptions(true);
432        }
433
434        Ok(features)
435    }
436
437    #[cfg(feature = "compiler")]
438    pub fn get_sys_compiler_engine_for_target(
439        &self,
440        target: Target,
441    ) -> std::result::Result<Engine, anyhow::Error> {
442        let backends = self.get_available_backends()?;
443        let compiler_config = self.get_sys_compiler_config(backends.first().unwrap())?;
444        let default_features = compiler_config.default_features_for_target(&target);
445        let features = self.get_features(&default_features)?;
446        Ok(wasmer_compiler::EngineBuilder::new(compiler_config)
447            .set_features(Some(features))
448            .set_target(Some(target))
449            .engine()
450            .into())
451    }
452
453    #[allow(unused_variables)]
454    #[cfg(feature = "compiler")]
455    pub(crate) fn get_sys_compiler_config(
456        &self,
457        rt: &BackendType,
458    ) -> Result<Box<dyn CompilerConfig>> {
459        let compiler_config: Box<dyn CompilerConfig> = match rt {
460            BackendType::Headless => bail!("The headless engine can't be chosen"),
461            #[cfg(feature = "singlepass")]
462            BackendType::Singlepass => {
463                let mut config = wasmer_compiler_singlepass::Singlepass::new();
464                if self.enable_verifier {
465                    config.enable_verifier();
466                }
467                if self.enable_nan_canonicalization {
468                    config.canonicalize_nans(true);
469                }
470                if let Some(p) = &self.profiler {
471                    match p {
472                        Profiler::Perfmap => config.enable_perfmap(),
473                    }
474                }
475                if let Some(mut debug_dir) = self.compiler_debug_dir.clone() {
476                    use wasmer_compiler_singlepass::SinglepassCallbacks;
477
478                    debug_dir.push("singlepass");
479                    config.callbacks(Some(SinglepassCallbacks::new(debug_dir)?));
480                }
481                if let Some(num_threads) = self.compiler_threads {
482                    config.num_threads(num_threads);
483                }
484                Box::new(config)
485            }
486            #[cfg(feature = "cranelift")]
487            BackendType::Cranelift => {
488                let mut config = wasmer_compiler_cranelift::Cranelift::new();
489                if self.enable_verifier {
490                    config.enable_verifier();
491                }
492                if self.enable_nan_canonicalization {
493                    config.canonicalize_nans(true);
494                }
495                if let Some(p) = &self.profiler {
496                    match p {
497                        Profiler::Perfmap => config.enable_perfmap(),
498                    }
499                }
500                if let Some(mut debug_dir) = self.compiler_debug_dir.clone() {
501                    use wasmer_compiler_cranelift::CraneliftCallbacks;
502
503                    debug_dir.push("cranelift");
504                    config.callbacks(Some(CraneliftCallbacks::new(debug_dir)?));
505                }
506                if let Some(num_threads) = self.compiler_threads {
507                    config.num_threads(num_threads);
508                }
509                Box::new(config)
510            }
511            #[cfg(feature = "llvm")]
512            BackendType::LLVM => {
513                use wasmer_compiler_llvm::LLVMCallbacks;
514                use wasmer_types::entity::EntityRef;
515                let mut config = LLVM::new();
516                config.enable_non_volatile_memops();
517                config.enable_readonly_funcref_table();
518
519                if let Some(num_threads) = self.compiler_threads {
520                    config.num_threads(num_threads);
521                }
522
523                if let Some(mut debug_dir) = self.compiler_debug_dir.clone() {
524                    debug_dir.push("llvm");
525                    config.callbacks(Some(LLVMCallbacks::new(debug_dir)?));
526                    config.verbose_asm(true);
527                }
528                if self.enable_verifier {
529                    config.enable_verifier();
530                }
531                if self.enable_nan_canonicalization {
532                    config.canonicalize_nans(true);
533                }
534                if let Some(p) = &self.profiler {
535                    match p {
536                        Profiler::Perfmap => config.enable_perfmap(),
537                    }
538                }
539
540                Box::new(config)
541            }
542            BackendType::V8 | BackendType::Wamr | BackendType::Wasmi => unreachable!(),
543            #[cfg(not(all(feature = "singlepass", feature = "cranelift", feature = "llvm")))]
544            compiler => {
545                bail!("The `{compiler}` compiler is not included in this binary.")
546            }
547        };
548
549        #[allow(unreachable_code)]
550        Ok(compiler_config)
551    }
552}
553
554/// The compiler used for the store
555#[derive(Debug, PartialEq, Eq, Clone, Copy)]
556#[allow(clippy::upper_case_acronyms, dead_code)]
557pub enum BackendType {
558    /// Singlepass compiler
559    Singlepass,
560
561    /// Cranelift compiler
562    Cranelift,
563
564    /// LLVM compiler
565    LLVM,
566
567    /// V8 runtime
568    V8,
569
570    /// Wamr runtime
571    Wamr,
572
573    /// Wasmi runtime
574    Wasmi,
575
576    /// Headless compiler
577    #[allow(dead_code)]
578    Headless,
579}
580
581impl BackendType {
582    /// Return all enabled compilers
583    pub fn enabled() -> Vec<Self> {
584        vec![
585            #[cfg(feature = "cranelift")]
586            Self::Cranelift,
587            #[cfg(feature = "llvm")]
588            Self::LLVM,
589            #[cfg(feature = "singlepass")]
590            Self::Singlepass,
591            #[cfg(feature = "v8")]
592            Self::V8,
593            #[cfg(feature = "wamr")]
594            Self::Wamr,
595            #[cfg(feature = "wasmi")]
596            Self::Wasmi,
597        ]
598    }
599
600    /// Returns an engine for this backend type.
601    /// We enable every feature the engine supports, since the same engine may later be used
602    /// with a module that requires more features than the one used during engine detection.
603    pub fn get_engine(&self, target: &Target, runtime_opts: &RuntimeOptions) -> Result<Engine> {
604        match self {
605            #[cfg(feature = "singlepass")]
606            Self::Singlepass => {
607                let mut config = wasmer_compiler_singlepass::Singlepass::new();
608                let supported_features = config.supported_features_for_target(target);
609                if runtime_opts.enable_verifier {
610                    config.enable_verifier();
611                }
612                if runtime_opts.enable_nan_canonicalization {
613                    config.canonicalize_nans(true);
614                }
615                if let Some(p) = &runtime_opts.profiler {
616                    match p {
617                        Profiler::Perfmap => config.enable_perfmap(),
618                    }
619                }
620                if let Some(mut debug_dir) = runtime_opts.compiler_debug_dir.clone() {
621                    use wasmer_compiler_singlepass::SinglepassCallbacks;
622
623                    debug_dir.push("singlepass");
624                    config.callbacks(Some(SinglepassCallbacks::new(debug_dir)?));
625                }
626                if let Some(num_threads) = runtime_opts.compiler_threads {
627                    config.num_threads(num_threads);
628                }
629                let engine = wasmer_compiler::EngineBuilder::new(config)
630                    .set_features(Some(supported_features))
631                    .set_target(Some(target.clone()))
632                    .engine()
633                    .into();
634                Ok(engine)
635            }
636            #[cfg(feature = "cranelift")]
637            Self::Cranelift => {
638                let mut config = wasmer_compiler_cranelift::Cranelift::new();
639                let supported_features = config.supported_features_for_target(target);
640                if runtime_opts.enable_verifier {
641                    config.enable_verifier();
642                }
643                if runtime_opts.enable_nan_canonicalization {
644                    config.canonicalize_nans(true);
645                }
646                if let Some(p) = &runtime_opts.profiler {
647                    match p {
648                        Profiler::Perfmap => config.enable_perfmap(),
649                    }
650                }
651                if let Some(mut debug_dir) = runtime_opts.compiler_debug_dir.clone() {
652                    use wasmer_compiler_cranelift::CraneliftCallbacks;
653
654                    debug_dir.push("cranelift");
655                    config.callbacks(Some(CraneliftCallbacks::new(debug_dir)?));
656                }
657                if let Some(num_threads) = runtime_opts.compiler_threads {
658                    config.num_threads(num_threads);
659                }
660                let engine = wasmer_compiler::EngineBuilder::new(config)
661                    .set_features(Some(supported_features))
662                    .set_target(Some(target.clone()))
663                    .engine()
664                    .into();
665                Ok(engine)
666            }
667            #[cfg(feature = "llvm")]
668            Self::LLVM => {
669                use wasmer_compiler_llvm::LLVMCallbacks;
670                use wasmer_types::entity::EntityRef;
671
672                let mut config = wasmer_compiler_llvm::LLVM::new();
673                config.enable_non_volatile_memops();
674                config.enable_readonly_funcref_table();
675
676                let supported_features = config.supported_features_for_target(target);
677                if let Some(mut debug_dir) = runtime_opts.compiler_debug_dir.clone() {
678                    debug_dir.push("llvm");
679                    config.callbacks(Some(LLVMCallbacks::new(debug_dir)?));
680                    config.verbose_asm(true);
681                }
682                if runtime_opts.enable_verifier {
683                    config.enable_verifier();
684                }
685                if runtime_opts.enable_nan_canonicalization {
686                    config.canonicalize_nans(true);
687                }
688
689                if let Some(num_threads) = runtime_opts.compiler_threads {
690                    config.num_threads(num_threads);
691                }
692
693                if let Some(p) = &runtime_opts.profiler {
694                    match p {
695                        Profiler::Perfmap => config.enable_perfmap(),
696                    }
697                }
698
699                let engine = wasmer_compiler::EngineBuilder::new(config)
700                    .set_features(Some(supported_features))
701                    .set_target(Some(target.clone()))
702                    .engine()
703                    .into();
704                Ok(engine)
705            }
706            #[cfg(feature = "v8")]
707            Self::V8 => Ok(wasmer::v8::V8::new().into()),
708            #[cfg(feature = "wamr")]
709            Self::Wamr => Ok(wasmer::wamr::Wamr::new().into()),
710            #[cfg(feature = "wasmi")]
711            Self::Wasmi => Ok(wasmer::wasmi::Wasmi::new().into()),
712            Self::Headless => bail!("Headless is not a valid runtime to instantiate directly"),
713            #[allow(unreachable_patterns)]
714            _ => bail!("Unsupported backend type"),
715        }
716    }
717
718    /// Check if this backend supports all the required WebAssembly features
719    #[allow(unreachable_code)]
720    pub fn supports_features(&self, required_features: &Features, target: &Target) -> bool {
721        // Map BackendType to the corresponding wasmer::BackendKind
722        let backend_kind = match self {
723            #[cfg(feature = "singlepass")]
724            Self::Singlepass => wasmer::BackendKind::Singlepass,
725            #[cfg(feature = "cranelift")]
726            Self::Cranelift => wasmer::BackendKind::Cranelift,
727            #[cfg(feature = "llvm")]
728            Self::LLVM => wasmer::BackendKind::LLVM,
729            #[cfg(feature = "v8")]
730            Self::V8 => wasmer::BackendKind::V8,
731            #[cfg(feature = "wamr")]
732            Self::Wamr => wasmer::BackendKind::Wamr,
733            #[cfg(feature = "wasmi")]
734            Self::Wasmi => wasmer::BackendKind::Wasmi,
735            Self::Headless => return false, // Headless can't compile
736            #[allow(unreachable_patterns)]
737            _ => return false,
738        };
739
740        // Get the supported features from the backend
741        let supported = wasmer::Engine::supported_features_for_backend(&backend_kind, target);
742
743        // Check if the backend supports all required features
744        if !supported.contains_features(required_features) {
745            return false;
746        }
747
748        true
749    }
750}
751
752impl From<&BackendType> for wasmer::BackendKind {
753    fn from(backend_type: &BackendType) -> Self {
754        match backend_type {
755            #[cfg(feature = "singlepass")]
756            BackendType::Singlepass => wasmer::BackendKind::Singlepass,
757            #[cfg(feature = "cranelift")]
758            BackendType::Cranelift => wasmer::BackendKind::Cranelift,
759            #[cfg(feature = "llvm")]
760            BackendType::LLVM => wasmer::BackendKind::LLVM,
761            #[cfg(feature = "v8")]
762            BackendType::V8 => wasmer::BackendKind::V8,
763            #[cfg(feature = "wamr")]
764            BackendType::Wamr => wasmer::BackendKind::Wamr,
765            #[cfg(feature = "wasmi")]
766            BackendType::Wasmi => wasmer::BackendKind::Wasmi,
767            _ => {
768                #[cfg(feature = "sys")]
769                {
770                    wasmer::BackendKind::Headless
771                }
772                #[cfg(not(feature = "sys"))]
773                {
774                    unreachable!("No backend enabled!")
775                }
776            }
777        }
778    }
779}
780
781impl std::fmt::Display for BackendType {
782    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
783        write!(
784            f,
785            "{}",
786            match self {
787                Self::Singlepass => "singlepass",
788                Self::Cranelift => "cranelift",
789                Self::LLVM => "llvm",
790                Self::V8 => "v8",
791                Self::Wamr => "wamr",
792                Self::Wasmi => "wasmi",
793                Self::Headless => "headless",
794            }
795        )
796    }
797}