wasmtime_cranelift/
builder.rs

1//! Implementation of a "compiler builder" for cranelift
2//!
3//! This module contains the implementation of how Cranelift is configured, as
4//! well as providing a function to return the default configuration to build.
5
6use anyhow::Result;
7use cranelift_codegen::{
8    isa::{self, OwnedTargetIsa},
9    CodegenResult,
10};
11use std::fmt;
12use std::sync::Arc;
13use wasmtime_cranelift_shared::isa_builder::IsaBuilder;
14use wasmtime_environ::{CacheStore, CompilerBuilder, Setting};
15
16struct Builder {
17    inner: IsaBuilder<CodegenResult<OwnedTargetIsa>>,
18    linkopts: LinkOptions,
19    cache_store: Option<Arc<dyn CacheStore>>,
20}
21
22#[derive(Clone, Default)]
23pub struct LinkOptions {
24    /// A debug-only setting used to synthetically insert 0-byte padding between
25    /// compiled functions to simulate huge compiled artifacts and exercise
26    /// logic related to jump veneers.
27    pub padding_between_functions: usize,
28
29    /// A debug-only setting used to force inter-function calls in a wasm module
30    /// to always go through "jump veneers" which are typically only generated
31    /// when functions are very far from each other.
32    pub force_jump_veneers: bool,
33}
34
35pub fn builder() -> Box<dyn CompilerBuilder> {
36    Box::new(Builder {
37        inner: IsaBuilder::new(|triple| isa::lookup(triple).map_err(|e| e.into())),
38        linkopts: LinkOptions::default(),
39        cache_store: None,
40    })
41}
42
43impl CompilerBuilder for Builder {
44    fn triple(&self) -> &target_lexicon::Triple {
45        self.inner.triple()
46    }
47
48    fn target(&mut self, target: target_lexicon::Triple) -> Result<()> {
49        self.inner.target(target)?;
50        Ok(())
51    }
52
53    fn set(&mut self, name: &str, value: &str) -> Result<()> {
54        // Special wasmtime-cranelift-only settings first
55        if name == "wasmtime_linkopt_padding_between_functions" {
56            self.linkopts.padding_between_functions = value.parse()?;
57            return Ok(());
58        }
59        if name == "wasmtime_linkopt_force_jump_veneer" {
60            self.linkopts.force_jump_veneers = value.parse()?;
61            return Ok(());
62        }
63
64        self.inner.set(name, value)
65    }
66
67    fn enable(&mut self, name: &str) -> Result<()> {
68        self.inner.enable(name)
69    }
70
71    fn build(&self) -> Result<Box<dyn wasmtime_environ::Compiler>> {
72        let isa = self.inner.build()?;
73        Ok(Box::new(crate::compiler::Compiler::new(
74            isa,
75            self.cache_store.clone(),
76            self.linkopts.clone(),
77        )))
78    }
79
80    fn settings(&self) -> Vec<Setting> {
81        self.inner.settings()
82    }
83
84    fn enable_incremental_compilation(
85        &mut self,
86        cache_store: Arc<dyn wasmtime_environ::CacheStore>,
87    ) -> Result<()> {
88        self.cache_store = Some(cache_store);
89        Ok(())
90    }
91}
92
93impl fmt::Debug for Builder {
94    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
95        f.debug_struct("Builder")
96            .field("shared_flags", &self.inner.shared_flags().to_string())
97            .finish()
98    }
99}