wasmtime_cranelift/
isa_builder.rs1use anyhow::Result;
2use cranelift_codegen::isa::IsaBuilder as Builder;
3use cranelift_codegen::settings::{self, Configurable, Flags, SetError};
4use target_lexicon::Triple;
5use wasmtime_environ::{Setting, SettingKind};
6
7pub struct IsaBuilder<T> {
13 shared_flags: settings::Builder,
15 inner: Builder<T>,
17 pub lookup: fn(Triple) -> Result<Builder<T>>,
19}
20
21impl<T> IsaBuilder<T> {
22 pub fn new(triple: Option<Triple>, lookup: fn(Triple) -> Result<Builder<T>>) -> Result<Self> {
24 let mut flags = settings::builder();
25
26 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
45 pub fn triple(&self) -> &target_lexicon::Triple {
46 self.inner.triple()
47 }
48
49 pub fn target(&mut self, target: target_lexicon::Triple) -> Result<()> {
50 self.inner = (self.lookup)(target)?;
51 Ok(())
52 }
53
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
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
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 self.inner.enable(name)?;
89 }
90 _ => return Err(err.into()),
91 }
92 }
93 Ok(())
94 }
95
96 pub fn build(&self) -> T {
97 self.inner
98 .finish(settings::Flags::new(self.shared_flags.clone()))
99 }
100
101 pub fn shared_flags(&self) -> Flags {
102 settings::Flags::new(self.shared_flags.clone())
103 }
104}