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