Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
bytecodealliance
GitHub Repository: bytecodealliance/wasmtime
Path: blob/main/crates/cranelift/src/isa_builder.rs
1692 views
1
use anyhow::Result;
2
use cranelift_codegen::isa::IsaBuilder as Builder;
3
use cranelift_codegen::settings::{self, Configurable, Flags, SetError};
4
use target_lexicon::Triple;
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.
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
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
// Try the target-specific flags.
88
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
}
105
106