1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
pub use wasmer_compiler::{
    Artifact, BaseTunables, CompilerConfig, Engine, EngineBuilder, Tunables,
};
#[cfg(feature = "compiler")]
use wasmer_types::Features;
use wasmer_types::Target;

/// Returns the default engine for the Sys engine
pub(crate) fn default_engine() -> Engine {
    // We store them on a function that returns to make
    // sure this function doesn't emit a compile error even if
    // more than one compiler is enabled.
    #[allow(unreachable_code)]
    #[cfg(any(feature = "cranelift", feature = "llvm", feature = "singlepass"))]
    fn get_config() -> impl wasmer_compiler::CompilerConfig + 'static {
        cfg_if::cfg_if! {
            if #[cfg(feature = "cranelift")] {
                wasmer_compiler_cranelift::Cranelift::default()
            } else if #[cfg(feature = "llvm")] {
                wasmer_compiler_llvm::LLVM::default()
            } else if #[cfg(feature = "singlepass")] {
                wasmer_compiler_singlepass::Singlepass::default()
            } else {
                compile_error!("No default compiler chosen")
            }
        }
    }

    #[allow(unreachable_code, unused_mut)]
    fn get_engine() -> Engine {
        cfg_if::cfg_if! {
            if #[cfg(feature = "compiler")] {
                cfg_if::cfg_if! {
                    if #[cfg(any(feature = "cranelift", feature = "llvm", feature = "singlepass"))]
                    {
                        let config = get_config();
                        EngineBuilder::new(Box::new(config) as Box<dyn wasmer_compiler::CompilerConfig>)
                            .engine()
                    } else {
                        EngineBuilder::headless()
                            .engine()
                    }
                }
            } else {
                EngineBuilder::headless().engine()
            }
        }
    }

    let mut engine = get_engine();
    let tunables = BaseTunables::for_target(engine.target());
    engine.set_tunables(tunables);
    engine
}

/// The custom trait to access to all the `sys` function in the common
/// engine.
pub trait NativeEngineExt {
    /// Create a new `Engine` with the given config
    #[cfg(feature = "compiler")]
    fn new(compiler_config: Box<dyn CompilerConfig>, target: Target, features: Features) -> Self;

    /// Create a headless `Engine`
    ///
    /// A headless engine is an engine without any compiler attached.
    /// This is useful for assuring a minimal runtime for running
    /// WebAssembly modules.
    ///
    /// For example, for running in IoT devices where compilers are very
    /// expensive, or also to optimize startup speed.
    ///
    /// # Important
    ///
    /// Headless engines can't compile or validate any modules,
    /// they just take already processed Modules (via `Module::serialize`).
    fn headless() -> Self;

    /// Gets the target
    fn target(&self) -> &Target;

    /// Attach a Tunable to this engine
    fn set_tunables(&mut self, tunables: impl Tunables + Send + Sync + 'static);

    /// Get a reference to attached Tunable of this engine
    fn tunables(&self) -> &dyn Tunables;
}

impl NativeEngineExt for crate::engine::Engine {
    #[cfg(feature = "compiler")]
    fn new(compiler_config: Box<dyn CompilerConfig>, target: Target, features: Features) -> Self {
        Self(Engine::new(compiler_config, target, features))
    }

    fn headless() -> Self {
        Self(Engine::headless())
    }

    fn target(&self) -> &Target {
        self.0.target()
    }

    fn set_tunables(&mut self, tunables: impl Tunables + Send + Sync + 'static) {
        self.0.set_tunables(tunables)
    }

    fn tunables(&self) -> &dyn Tunables {
        self.0.tunables()
    }
}