1 use cranelift_codegen::isa::IsaBuilder as Builder; 2 use cranelift_codegen::settings::{self, Configurable, Flags, SetError}; 3 use target_lexicon::Triple; 4 use wasmtime_environ::error::Result; 5 use wasmtime_environ::{Setting, SettingKind}; 6 7 /// A helper to build an Isa for a compiler implementation. 8 /// Compiler builders can wrap this to provide better flexibility when setting flags. 9 /// 10 /// Most methods are mirrored from the `wasmtime_environ::CompilerBuilder` trait, so look there for more 11 /// information. 12 pub struct IsaBuilder<T> { 13 /// The shared flags that all targets share. 14 shared_flags: settings::Builder, 15 /// The internal ISA builder for the current target. 16 inner: Builder<T>, 17 /// A callback to lookup a new ISA builder for a target. 18 pub lookup: fn(Triple) -> Result<Builder<T>>, 19 } 20 21 impl<T> IsaBuilder<T> { 22 /// Create a new ISA builder with the given lookup function. new(triple: Option<Triple>, lookup: fn(Triple) -> Result<Builder<T>>) -> Result<Self>23 pub fn new(triple: Option<Triple>, lookup: fn(Triple) -> Result<Builder<T>>) -> Result<Self> { 24 let mut flags = settings::builder(); 25 26 // We don't use probestack as a stack limit mechanism 27 flags 28 .set("enable_probestack", "false") 29 .expect("should be valid flag"); 30 31 let triple_specified = triple.is_some(); 32 let triple = triple.unwrap_or_else(Triple::host); 33 let mut isa_flags = lookup(triple)?; 34 if !triple_specified { 35 cranelift_native::infer_native_flags(&mut isa_flags).unwrap(); 36 } 37 38 Ok(Self { 39 shared_flags: flags, 40 inner: isa_flags, 41 lookup, 42 }) 43 } 44 triple(&self) -> &target_lexicon::Triple45 pub fn triple(&self) -> &target_lexicon::Triple { 46 self.inner.triple() 47 } 48 target(&mut self, target: target_lexicon::Triple) -> Result<()>49 pub fn target(&mut self, target: target_lexicon::Triple) -> Result<()> { 50 self.inner = (self.lookup)(target)?; 51 Ok(()) 52 } 53 settings(&self) -> Vec<Setting>54 pub fn settings(&self) -> Vec<Setting> { 55 self.inner 56 .iter() 57 .map(|s| Setting { 58 description: s.description, 59 name: s.name, 60 values: s.values, 61 kind: match s.kind { 62 settings::SettingKind::Preset => SettingKind::Preset, 63 settings::SettingKind::Enum => SettingKind::Enum, 64 settings::SettingKind::Num => SettingKind::Num, 65 settings::SettingKind::Bool => SettingKind::Bool, 66 }, 67 }) 68 .collect() 69 } 70 set(&mut self, name: &str, value: &str) -> Result<()>71 pub fn set(&mut self, name: &str, value: &str) -> Result<()> { 72 if let Err(err) = self.shared_flags.set(name, value) { 73 match err { 74 SetError::BadName(_) => { 75 self.inner.set(name, value)?; 76 } 77 _ => return Err(err.into()), 78 } 79 } 80 Ok(()) 81 } 82 enable(&mut self, name: &str) -> Result<()>83 pub fn enable(&mut self, name: &str) -> Result<()> { 84 if let Err(err) = self.shared_flags.enable(name) { 85 match err { 86 SetError::BadName(_) => { 87 // Try the target-specific flags. 88 self.inner.enable(name)?; 89 } 90 _ => return Err(err.into()), 91 } 92 } 93 Ok(()) 94 } 95 build(&self) -> T96 pub fn build(&self) -> T { 97 self.inner 98 .finish(settings::Flags::new(self.shared_flags.clone())) 99 } 100 shared_flags(&self) -> Flags101 pub fn shared_flags(&self) -> Flags { 102 settings::Flags::new(self.shared_flags.clone()) 103 } 104 } 105