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
518                if let Some(num_threads) = self.compiler_threads {
519                    config.num_threads(num_threads);
520                }
521
522                if let Some(mut debug_dir) = self.compiler_debug_dir.clone() {
523                    debug_dir.push("llvm");
524                    config.callbacks(Some(LLVMCallbacks::new(debug_dir)?));
525                    config.verbose_asm(true);
526                }
527                if self.enable_verifier {
528                    config.enable_verifier();
529                }
530                if self.enable_nan_canonicalization {
531                    config.canonicalize_nans(true);
532                }
533                if let Some(p) = &self.profiler {
534                    match p {
535                        Profiler::Perfmap => config.enable_perfmap(),
536                    }
537                }
538
539                Box::new(config)
540            }
541            BackendType::V8 | BackendType::Wamr | BackendType::Wasmi => unreachable!(),
542            #[cfg(not(all(feature = "singlepass", feature = "cranelift", feature = "llvm")))]
543            compiler => {
544                bail!("The `{compiler}` compiler is not included in this binary.")
545            }
546        };
547
548        #[allow(unreachable_code)]
549        Ok(compiler_config)
550    }
551}
552
553/// The compiler used for the store
554#[derive(Debug, PartialEq, Eq, Clone, Copy)]
555#[allow(clippy::upper_case_acronyms, dead_code)]
556pub enum BackendType {
557    /// Singlepass compiler
558    Singlepass,
559
560    /// Cranelift compiler
561    Cranelift,
562
563    /// LLVM compiler
564    LLVM,
565
566    /// V8 runtime
567    V8,
568
569    /// Wamr runtime
570    Wamr,
571
572    /// Wasmi runtime
573    Wasmi,
574
575    /// Headless compiler
576    #[allow(dead_code)]
577    Headless,
578}
579
580impl BackendType {
581    /// Return all enabled compilers
582    pub fn enabled() -> Vec<Self> {
583        vec![
584            #[cfg(feature = "cranelift")]
585            Self::Cranelift,
586            #[cfg(feature = "llvm")]
587            Self::LLVM,
588            #[cfg(feature = "singlepass")]
589            Self::Singlepass,
590            #[cfg(feature = "v8")]
591            Self::V8,
592            #[cfg(feature = "wamr")]
593            Self::Wamr,
594            #[cfg(feature = "wasmi")]
595            Self::Wasmi,
596        ]
597    }
598
599    /// Returns an engine for this backend type.
600    /// We enable every feature the engine supports, since the same engine may later be used
601    /// with a module that requires more features than the one used during engine detection.
602    pub fn get_engine(&self, target: &Target, runtime_opts: &RuntimeOptions) -> Result<Engine> {
603        match self {
604            #[cfg(feature = "singlepass")]
605            Self::Singlepass => {
606                let mut config = wasmer_compiler_singlepass::Singlepass::new();
607                let supported_features = config.supported_features_for_target(target);
608                if runtime_opts.enable_verifier {
609                    config.enable_verifier();
610                }
611                if runtime_opts.enable_nan_canonicalization {
612                    config.canonicalize_nans(true);
613                }
614                if let Some(p) = &runtime_opts.profiler {
615                    match p {
616                        Profiler::Perfmap => config.enable_perfmap(),
617                    }
618                }
619                if let Some(mut debug_dir) = runtime_opts.compiler_debug_dir.clone() {
620                    use wasmer_compiler_singlepass::SinglepassCallbacks;
621
622                    debug_dir.push("singlepass");
623                    config.callbacks(Some(SinglepassCallbacks::new(debug_dir)?));
624                }
625                if let Some(num_threads) = runtime_opts.compiler_threads {
626                    config.num_threads(num_threads);
627                }
628                let engine = wasmer_compiler::EngineBuilder::new(config)
629                    .set_features(Some(supported_features))
630                    .set_target(Some(target.clone()))
631                    .engine()
632                    .into();
633                Ok(engine)
634            }
635            #[cfg(feature = "cranelift")]
636            Self::Cranelift => {
637                let mut config = wasmer_compiler_cranelift::Cranelift::new();
638                let supported_features = config.supported_features_for_target(target);
639                if runtime_opts.enable_verifier {
640                    config.enable_verifier();
641                }
642                if runtime_opts.enable_nan_canonicalization {
643                    config.canonicalize_nans(true);
644                }
645                if let Some(p) = &runtime_opts.profiler {
646                    match p {
647                        Profiler::Perfmap => config.enable_perfmap(),
648                    }
649                }
650                if let Some(mut debug_dir) = runtime_opts.compiler_debug_dir.clone() {
651                    use wasmer_compiler_cranelift::CraneliftCallbacks;
652
653                    debug_dir.push("cranelift");
654                    config.callbacks(Some(CraneliftCallbacks::new(debug_dir)?));
655                }
656                if let Some(num_threads) = runtime_opts.compiler_threads {
657                    config.num_threads(num_threads);
658                }
659                let engine = wasmer_compiler::EngineBuilder::new(config)
660                    .set_features(Some(supported_features))
661                    .set_target(Some(target.clone()))
662                    .engine()
663                    .into();
664                Ok(engine)
665            }
666            #[cfg(feature = "llvm")]
667            Self::LLVM => {
668                use wasmer_compiler_llvm::LLVMCallbacks;
669                use wasmer_types::entity::EntityRef;
670
671                let mut config = wasmer_compiler_llvm::LLVM::new();
672                config.enable_non_volatile_memops();
673
674                let supported_features = config.supported_features_for_target(target);
675                if let Some(mut debug_dir) = runtime_opts.compiler_debug_dir.clone() {
676                    debug_dir.push("llvm");
677                    config.callbacks(Some(LLVMCallbacks::new(debug_dir)?));
678                    config.verbose_asm(true);
679                }
680                if runtime_opts.enable_verifier {
681                    config.enable_verifier();
682                }
683                if runtime_opts.enable_nan_canonicalization {
684                    config.canonicalize_nans(true);
685                }
686
687                if let Some(num_threads) = runtime_opts.compiler_threads {
688                    config.num_threads(num_threads);
689                }
690
691                if let Some(p) = &runtime_opts.profiler {
692                    match p {
693                        Profiler::Perfmap => config.enable_perfmap(),
694                    }
695                }
696
697                let engine = wasmer_compiler::EngineBuilder::new(config)
698                    .set_features(Some(supported_features))
699                    .set_target(Some(target.clone()))
700                    .engine()
701                    .into();
702                Ok(engine)
703            }
704            #[cfg(feature = "v8")]
705            Self::V8 => Ok(wasmer::v8::V8::new().into()),
706            #[cfg(feature = "wamr")]
707            Self::Wamr => Ok(wasmer::wamr::Wamr::new().into()),
708            #[cfg(feature = "wasmi")]
709            Self::Wasmi => Ok(wasmer::wasmi::Wasmi::new().into()),
710            Self::Headless => bail!("Headless is not a valid runtime to instantiate directly"),
711            #[allow(unreachable_patterns)]
712            _ => bail!("Unsupported backend type"),
713        }
714    }
715
716    /// Check if this backend supports all the required WebAssembly features
717    #[allow(unreachable_code)]
718    pub fn supports_features(&self, required_features: &Features, target: &Target) -> bool {
719        // Map BackendType to the corresponding wasmer::BackendKind
720        let backend_kind = match self {
721            #[cfg(feature = "singlepass")]
722            Self::Singlepass => wasmer::BackendKind::Singlepass,
723            #[cfg(feature = "cranelift")]
724            Self::Cranelift => wasmer::BackendKind::Cranelift,
725            #[cfg(feature = "llvm")]
726            Self::LLVM => wasmer::BackendKind::LLVM,
727            #[cfg(feature = "v8")]
728            Self::V8 => wasmer::BackendKind::V8,
729            #[cfg(feature = "wamr")]
730            Self::Wamr => wasmer::BackendKind::Wamr,
731            #[cfg(feature = "wasmi")]
732            Self::Wasmi => wasmer::BackendKind::Wasmi,
733            Self::Headless => return false, // Headless can't compile
734            #[allow(unreachable_patterns)]
735            _ => return false,
736        };
737
738        // Get the supported features from the backend
739        let supported = wasmer::Engine::supported_features_for_backend(&backend_kind, target);
740
741        // Check if the backend supports all required features
742        if !supported.contains_features(required_features) {
743            return false;
744        }
745
746        true
747    }
748}
749
750impl From<&BackendType> for wasmer::BackendKind {
751    fn from(backend_type: &BackendType) -> Self {
752        match backend_type {
753            #[cfg(feature = "singlepass")]
754            BackendType::Singlepass => wasmer::BackendKind::Singlepass,
755            #[cfg(feature = "cranelift")]
756            BackendType::Cranelift => wasmer::BackendKind::Cranelift,
757            #[cfg(feature = "llvm")]
758            BackendType::LLVM => wasmer::BackendKind::LLVM,
759            #[cfg(feature = "v8")]
760            BackendType::V8 => wasmer::BackendKind::V8,
761            #[cfg(feature = "wamr")]
762            BackendType::Wamr => wasmer::BackendKind::Wamr,
763            #[cfg(feature = "wasmi")]
764            BackendType::Wasmi => wasmer::BackendKind::Wasmi,
765            _ => {
766                #[cfg(feature = "sys")]
767                {
768                    wasmer::BackendKind::Headless
769                }
770                #[cfg(not(feature = "sys"))]
771                {
772                    unreachable!("No backend enabled!")
773                }
774            }
775        }
776    }
777}
778
779impl std::fmt::Display for BackendType {
780    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
781        write!(
782            f,
783            "{}",
784            match self {
785                Self::Singlepass => "singlepass",
786                Self::Cranelift => "cranelift",
787                Self::LLVM => "llvm",
788                Self::V8 => "v8",
789                Self::Wamr => "wamr",
790                Self::Wasmi => "wasmi",
791                Self::Headless => "headless",
792            }
793        )
794    }
795}