Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
bytecodealliance
GitHub Repository: bytecodealliance/wasmtime
Path: blob/main/cranelift/reader/src/isaspec.rs
2451 views
1
//! Parsed representation of `set` and `isa` commands.
2
//!
3
//! A test case file can contain `set` commands that set ISA-independent settings, and it can
4
//! contain `isa` commands that select an ISA and applies ISA-specific settings.
5
//!
6
//! If a test case file contains `isa` commands, the tests will only be run against the specified
7
//! ISAs. If the file contains no `isa` commands, the tests will be run against all supported ISAs.
8
9
use crate::error::{Location, ParseError};
10
use crate::testcommand::TestOption;
11
use cranelift_codegen::isa::{OwnedTargetIsa, TargetIsa};
12
use cranelift_codegen::settings::{Configurable, Flags, SetError};
13
14
/// The ISA specifications in a `.clif` file.
15
pub enum IsaSpec {
16
/// The parsed file does not contain any `isa` commands, but it may contain `set` commands
17
/// which are reflected in the finished `Flags` object.
18
None(Flags),
19
20
/// The parsed file does contain `isa` commands.
21
/// Each `isa` command is used to configure a `TargetIsa` trait object.
22
Some(Vec<OwnedTargetIsa>),
23
}
24
25
impl IsaSpec {
26
/// If the `IsaSpec` contains exactly 1 `TargetIsa` we return a reference to it
27
pub fn unique_isa(&self) -> Option<&dyn TargetIsa> {
28
if let Self::Some(ref isa_vec) = *self {
29
if isa_vec.len() == 1 {
30
return Some(&*isa_vec[0]);
31
}
32
}
33
None
34
}
35
}
36
37
/// An error type returned by `parse_options`.
38
pub enum ParseOptionError {
39
/// A generic ParseError.
40
Generic(ParseError),
41
42
/// An unknown flag was used, with the given name at the given location.
43
UnknownFlag {
44
/// Location where the flag was given.
45
loc: Location,
46
/// Name of the unknown flag.
47
name: String,
48
},
49
50
/// An unknown value was used, with the given name at the given location.
51
UnknownValue {
52
/// Location where the flag was given.
53
loc: Location,
54
/// Name of the unknown value.
55
name: String,
56
/// Value of the unknown value.
57
value: String,
58
},
59
}
60
61
impl From<ParseOptionError> for ParseError {
62
fn from(err: ParseOptionError) -> Self {
63
match err {
64
ParseOptionError::Generic(err) => err,
65
ParseOptionError::UnknownFlag { loc, name } => Self {
66
location: loc,
67
message: format!("unknown setting '{name}'"),
68
is_warning: false,
69
},
70
ParseOptionError::UnknownValue { loc, name, value } => Self {
71
location: loc,
72
message: format!("unknown setting '{name}={value}'"),
73
is_warning: false,
74
},
75
}
76
}
77
}
78
79
macro_rules! option_err {
80
( $loc:expr, $fmt:expr, $( $arg:expr ),+ ) => {
81
Err($crate::ParseOptionError::Generic($crate::ParseError {
82
location: $loc.clone(),
83
message: format!( $fmt, $( $arg ),+ ),
84
is_warning: false,
85
}))
86
};
87
}
88
89
/// Parse an iterator of command line options and apply them to `config`.
90
///
91
/// Note that parsing terminates after the first error is encountered.
92
pub fn parse_options<'a, I>(
93
iter: I,
94
config: &mut dyn Configurable,
95
loc: Location,
96
) -> Result<(), ParseOptionError>
97
where
98
I: Iterator<Item = &'a str>,
99
{
100
for opt in iter {
101
parse_option(opt, config, loc)?;
102
}
103
Ok(())
104
}
105
106
/// Parse an single command line options and apply it to `config`.
107
pub fn parse_option(
108
opt: &str,
109
config: &mut dyn Configurable,
110
loc: Location,
111
) -> Result<(), ParseOptionError> {
112
match TestOption::new(opt) {
113
TestOption::Flag(name) => match config.enable(name) {
114
Ok(_) => Ok(()),
115
Err(SetError::BadName(name)) => Err(ParseOptionError::UnknownFlag { loc, name }),
116
Err(_) => option_err!(loc, "not a boolean flag: '{}'", opt),
117
},
118
TestOption::Value(name, value) => match config.set(name, value) {
119
Ok(_) => Ok(()),
120
Err(SetError::BadName(name)) => Err(ParseOptionError::UnknownValue {
121
loc,
122
name,
123
value: value.to_string(),
124
}),
125
Err(SetError::BadType) => option_err!(loc, "invalid setting type: '{}'", opt),
126
Err(SetError::BadValue(expected)) => {
127
option_err!(
128
loc,
129
"invalid setting value for '{}', expected {}",
130
opt,
131
expected
132
)
133
}
134
},
135
}
136
}
137
138