1 use crate::compiler::Compiler; 2 use anyhow::{Result, bail}; 3 use std::sync::Arc; 4 use target_lexicon::Triple; 5 use wasmtime_cranelift::isa_builder::IsaBuilder; 6 use wasmtime_environ::{CompilerBuilder, Setting, Tunables}; 7 use winch_codegen::{TargetIsa, isa}; 8 9 /// Compiler builder. 10 struct Builder { 11 inner: IsaBuilder<Result<Box<dyn TargetIsa>>>, 12 cranelift: Box<dyn CompilerBuilder>, 13 tunables: Option<Tunables>, 14 } 15 16 pub fn builder(triple: Option<Triple>) -> Result<Box<dyn CompilerBuilder>> { 17 let inner = IsaBuilder::new(triple.clone(), |triple| isa::lookup(triple))?; 18 let cranelift = wasmtime_cranelift::builder(triple)?; 19 Ok(Box::new(Builder { 20 inner, 21 cranelift, 22 tunables: None, 23 })) 24 } 25 26 impl CompilerBuilder for Builder { 27 fn triple(&self) -> &target_lexicon::Triple { 28 self.inner.triple() 29 } 30 31 fn target(&mut self, target: target_lexicon::Triple) -> Result<()> { 32 self.inner.target(target.clone())?; 33 self.cranelift.target(target)?; 34 Ok(()) 35 } 36 37 fn set(&mut self, name: &str, value: &str) -> Result<()> { 38 self.inner.set(name, value)?; 39 self.cranelift.set(name, value)?; 40 Ok(()) 41 } 42 43 fn enable(&mut self, name: &str) -> Result<()> { 44 self.inner.enable(name)?; 45 self.cranelift.enable(name)?; 46 Ok(()) 47 } 48 49 fn settings(&self) -> Vec<Setting> { 50 self.inner.settings() 51 } 52 53 fn set_tunables(&mut self, tunables: Tunables) -> Result<()> { 54 if !tunables.winch_callable { 55 bail!("Winch requires the winch calling convention"); 56 } 57 58 if !tunables.table_lazy_init { 59 bail!("Winch requires the table-lazy-init option to be enabled"); 60 } 61 62 if !tunables.signals_based_traps { 63 bail!("Winch requires the signals-based-traps option to be enabled"); 64 } 65 66 if tunables.debug_native { 67 bail!("Winch does not currently support generating native debug information"); 68 } 69 70 if tunables.debug_guest { 71 bail!("Winch does not currently support guest-level debugging"); 72 } 73 74 self.tunables = Some(tunables.clone()); 75 self.cranelift.set_tunables(tunables)?; 76 Ok(()) 77 } 78 79 fn tunables(&self) -> Option<&Tunables> { 80 self.cranelift.tunables() 81 } 82 83 fn build(&self) -> Result<Box<dyn wasmtime_environ::Compiler>> { 84 let isa = self.inner.build()?; 85 let cranelift = self.cranelift.build()?; 86 let tunables = self 87 .tunables 88 .as_ref() 89 .expect("set_tunables not called") 90 .clone(); 91 Ok(Box::new(Compiler::new(isa, cranelift, tunables))) 92 } 93 94 fn enable_incremental_compilation( 95 &mut self, 96 _cache_store: Arc<dyn wasmtime_environ::CacheStore>, 97 ) -> Result<()> { 98 bail!("incremental compilation is not supported on this platform"); 99 } 100 } 101 102 impl std::fmt::Debug for Builder { 103 fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result { 104 write!(f, "Builder: {{ triple: {:?} }}", self.triple()) 105 } 106 } 107