wasmer_compiler/
compiler.rs

1//! This module mainly outputs the `Compiler` trait that custom
2//! compilers will need to implement.
3
4use crate::types::{module::CompileModuleInfo, symbols::SymbolRegistry};
5use crate::{
6    lib::std::{boxed::Box, sync::Arc},
7    translator::ModuleMiddleware,
8    types::function::Compilation,
9    FunctionBodyData, ModuleTranslationState,
10};
11use enumset::EnumSet;
12use wasmer_types::{
13    entity::PrimaryMap,
14    error::CompileError,
15    target::{CpuFeature, Target, UserCompilerOptimizations},
16    Features, LocalFunctionIndex,
17};
18#[cfg(feature = "translator")]
19use wasmparser::{Validator, WasmFeatures};
20
21/// The compiler configuration options.
22pub trait CompilerConfig {
23    /// Enable Position Independent Code (PIC).
24    ///
25    /// This is required for shared object generation (Native Engine),
26    /// but will make the JIT Engine to fail, since PIC is not yet
27    /// supported in the JIT linking phase.
28    fn enable_pic(&mut self) {
29        // By default we do nothing, each backend will need to customize this
30        // in case they do something special for emitting PIC code.
31    }
32
33    /// Enable compiler IR verification.
34    ///
35    /// For compilers capable of doing so, this enables internal consistency
36    /// checking.
37    fn enable_verifier(&mut self) {
38        // By default we do nothing, each backend will need to customize this
39        // in case they create an IR that they can verify.
40    }
41
42    /// Enable generation of perfmaps to sample the JIT compiled frames.
43    fn enable_perfmap(&mut self) {
44        // By default we do nothing, each backend will need to customize this
45        // in case they create an IR that they can verify.
46    }
47
48    /// Enable NaN canonicalization.
49    ///
50    /// NaN canonicalization is useful when trying to run WebAssembly
51    /// deterministically across different architectures.
52    fn canonicalize_nans(&mut self, _enable: bool) {
53        // By default we do nothing, each backend will need to customize this
54        // in case they create an IR that they can verify.
55    }
56
57    /// Gets the custom compiler config
58    fn compiler(self: Box<Self>) -> Box<dyn Compiler>;
59
60    /// Gets the default features for this compiler in the given target
61    fn default_features_for_target(&self, target: &Target) -> Features {
62        self.supported_features_for_target(target)
63    }
64
65    /// Gets the supported features for this compiler in the given target
66    fn supported_features_for_target(&self, _target: &Target) -> Features {
67        Features::default()
68    }
69
70    /// Pushes a middleware onto the back of the middleware chain.
71    fn push_middleware(&mut self, middleware: Arc<dyn ModuleMiddleware>);
72}
73
74impl<T> From<T> for Box<dyn CompilerConfig + 'static>
75where
76    T: CompilerConfig + 'static,
77{
78    fn from(other: T) -> Self {
79        Box::new(other)
80    }
81}
82
83/// An implementation of a Compiler from parsed WebAssembly module to Compiled native code.
84pub trait Compiler: Send + std::fmt::Debug {
85    /// Returns a descriptive name for this compiler.
86    ///
87    /// Note that this is an API breaking change since 3.0
88    fn name(&self) -> &str;
89
90    /// Returns the deterministic id of this compiler. Same compilers with different
91    /// optimizations map to different deterministic IDs.
92    fn deterministic_id(&self) -> String;
93
94    /// Add suggested optimizations to this compiler.
95    ///
96    /// # Note
97    ///
98    /// Not every compiler supports every optimization. This function may fail (i.e. not set the
99    /// suggested optimizations) silently if the underlying compiler does not support one or
100    /// more optimizations.
101    fn with_opts(
102        &mut self,
103        suggested_compiler_opts: &UserCompilerOptimizations,
104    ) -> Result<(), CompileError> {
105        _ = suggested_compiler_opts;
106        Ok(())
107    }
108
109    /// Validates a module.
110    ///
111    /// It returns the a succesful Result in case is valid, `CompileError` in case is not.
112    #[cfg(feature = "translator")]
113    fn validate_module(&self, features: &Features, data: &[u8]) -> Result<(), CompileError> {
114        let mut wasm_features = WasmFeatures::default();
115        wasm_features.set(WasmFeatures::BULK_MEMORY, features.bulk_memory);
116        wasm_features.set(WasmFeatures::THREADS, features.threads);
117        wasm_features.set(WasmFeatures::REFERENCE_TYPES, features.reference_types);
118        wasm_features.set(WasmFeatures::MULTI_VALUE, features.multi_value);
119        wasm_features.set(WasmFeatures::SIMD, features.simd);
120        wasm_features.set(WasmFeatures::TAIL_CALL, features.tail_call);
121        wasm_features.set(WasmFeatures::MULTI_MEMORY, features.multi_memory);
122        wasm_features.set(WasmFeatures::MEMORY64, features.memory64);
123        wasm_features.set(WasmFeatures::EXCEPTIONS, features.exceptions);
124        wasm_features.set(WasmFeatures::EXTENDED_CONST, features.extended_const);
125        wasm_features.set(WasmFeatures::RELAXED_SIMD, features.relaxed_simd);
126        wasm_features.set(WasmFeatures::MUTABLE_GLOBAL, true);
127        wasm_features.set(WasmFeatures::SATURATING_FLOAT_TO_INT, true);
128        wasm_features.set(WasmFeatures::FLOATS, true);
129        wasm_features.set(WasmFeatures::SIGN_EXTENSION, true);
130        wasm_features.set(WasmFeatures::GC_TYPES, true);
131
132        // Not supported
133        wasm_features.set(WasmFeatures::COMPONENT_MODEL, false);
134        wasm_features.set(WasmFeatures::FUNCTION_REFERENCES, false);
135        wasm_features.set(WasmFeatures::MEMORY_CONTROL, false);
136        wasm_features.set(WasmFeatures::GC, false);
137        wasm_features.set(WasmFeatures::COMPONENT_MODEL_VALUES, false);
138        wasm_features.set(WasmFeatures::COMPONENT_MODEL_NESTED_NAMES, false);
139
140        let mut validator = Validator::new_with_features(wasm_features);
141        validator
142            .validate_all(data)
143            .map_err(|e| CompileError::Validate(format!("{e}")))?;
144        Ok(())
145    }
146
147    /// Compiles a parsed module.
148    ///
149    /// It returns the [`Compilation`] or a [`CompileError`].
150    fn compile_module(
151        &self,
152        target: &Target,
153        module: &CompileModuleInfo,
154        module_translation: &ModuleTranslationState,
155        // The list of function bodies
156        function_body_inputs: PrimaryMap<LocalFunctionIndex, FunctionBodyData<'_>>,
157    ) -> Result<Compilation, CompileError>;
158
159    /// Compiles a module into a native object file.
160    ///
161    /// It returns the bytes as a `&[u8]` or a [`CompileError`].
162    fn experimental_native_compile_module(
163        &self,
164        _target: &Target,
165        _module: &CompileModuleInfo,
166        _module_translation: &ModuleTranslationState,
167        // The list of function bodies
168        _function_body_inputs: &PrimaryMap<LocalFunctionIndex, FunctionBodyData<'_>>,
169        _symbol_registry: &dyn SymbolRegistry,
170        // The metadata to inject into the wasmer_metadata section of the object file.
171        _wasmer_metadata: &[u8],
172    ) -> Option<Result<Vec<u8>, CompileError>> {
173        None
174    }
175
176    /// Get the middlewares for this compiler
177    fn get_middlewares(&self) -> &[Arc<dyn ModuleMiddleware>];
178
179    /// Get the CpuFeatues used by the compiler
180    fn get_cpu_features_used(&self, cpu_features: &EnumSet<CpuFeature>) -> EnumSet<CpuFeature> {
181        *cpu_features
182    }
183
184    /// Get whether `perfmap` is enabled or not.
185    fn get_perfmap_enabled(&self) -> bool {
186        false
187    }
188}