Add support for setting presets.
Fixes #11. Presets are groups of settings and values applied at once. This is used as a shorthand in test files, so for example "isa intel nehalem" enables all of the CPUID bits that the Nehalem micro-architecture provides.
This commit is contained in:
@@ -7,3 +7,27 @@ use std::fmt;
|
||||
// `Flags` struct with an impl for all of the settings defined in
|
||||
// `lib/cretonne/meta/cretonne/settings.py`.
|
||||
include!(concat!(env!("OUT_DIR"), "/settings-intel.rs"));
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::{builder, Flags};
|
||||
use settings::{self, Configurable};
|
||||
|
||||
#[test]
|
||||
fn presets() {
|
||||
let shared = settings::Flags::new(&settings::builder());
|
||||
|
||||
// Nehalem has SSE4.1 but not BMI1.
|
||||
let mut b1 = builder();
|
||||
b1.enable("nehalem").unwrap();
|
||||
let f1 = Flags::new(&shared, &b1);
|
||||
assert_eq!(f1.has_sse41(), true);
|
||||
assert_eq!(f1.has_bmi1(), false);
|
||||
|
||||
let mut b2 = builder();
|
||||
b2.enable("haswell").unwrap();
|
||||
let f2 = Flags::new(&shared, &b2);
|
||||
assert_eq!(f2.has_sse41(), true);
|
||||
assert_eq!(f2.has_bmi1(), true);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -108,8 +108,8 @@ impl settings::Configurable for Builder {
|
||||
self.setup.set(name, value)
|
||||
}
|
||||
|
||||
fn set_bool(&mut self, name: &str, value: bool) -> settings::Result<()> {
|
||||
self.setup.set_bool(name, value)
|
||||
fn enable(&mut self, name: &str) -> settings::Result<()> {
|
||||
self.setup.enable(name)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -114,7 +114,7 @@ mod tests {
|
||||
#[test]
|
||||
fn test_64bitenc() {
|
||||
let mut shared_builder = settings::builder();
|
||||
shared_builder.set_bool("is_64bit", true).unwrap();
|
||||
shared_builder.enable("is_64bit").unwrap();
|
||||
let shared_flags = settings::Flags::new(&shared_builder);
|
||||
let isa = isa::lookup("riscv").unwrap().finish(shared_flags);
|
||||
|
||||
@@ -161,7 +161,7 @@ mod tests {
|
||||
#[test]
|
||||
fn test_32bitenc() {
|
||||
let mut shared_builder = settings::builder();
|
||||
shared_builder.set_bool("is_64bit", false).unwrap();
|
||||
shared_builder.set("is_64bit", "false").unwrap();
|
||||
let shared_flags = settings::Flags::new(&shared_builder);
|
||||
let isa = isa::lookup("riscv").unwrap().finish(shared_flags);
|
||||
|
||||
@@ -216,13 +216,13 @@ mod tests {
|
||||
#[test]
|
||||
fn test_rv32m() {
|
||||
let mut shared_builder = settings::builder();
|
||||
shared_builder.set_bool("is_64bit", false).unwrap();
|
||||
shared_builder.set("is_64bit", "false").unwrap();
|
||||
let shared_flags = settings::Flags::new(&shared_builder);
|
||||
|
||||
// Set the supports_m stting which in turn enables the use_m predicate that unlocks
|
||||
// encodings for imul.
|
||||
let mut isa_builder = isa::lookup("riscv").unwrap();
|
||||
isa_builder.set_bool("supports_m", true).unwrap();
|
||||
isa_builder.enable("supports_m").unwrap();
|
||||
|
||||
let isa = isa_builder.finish(shared_flags);
|
||||
|
||||
|
||||
@@ -34,17 +34,17 @@ mod tests {
|
||||
fn predicates() {
|
||||
let shared = settings::Flags::new(&settings::builder());
|
||||
let mut b = builder();
|
||||
b.set_bool("supports_f", true).unwrap();
|
||||
b.set_bool("supports_d", true).unwrap();
|
||||
b.enable("supports_f").unwrap();
|
||||
b.enable("supports_d").unwrap();
|
||||
let f = Flags::new(&shared, &b);
|
||||
assert_eq!(f.full_float(), true);
|
||||
|
||||
let mut sb = settings::builder();
|
||||
sb.set_bool("enable_simd", false).unwrap();
|
||||
sb.set("enable_simd", "false").unwrap();
|
||||
let shared = settings::Flags::new(&sb);
|
||||
let mut b = builder();
|
||||
b.set_bool("supports_f", true).unwrap();
|
||||
b.set_bool("supports_d", true).unwrap();
|
||||
b.enable("supports_f").unwrap();
|
||||
b.enable("supports_d").unwrap();
|
||||
let f = Flags::new(&shared, &b);
|
||||
assert_eq!(f.full_float(), false);
|
||||
}
|
||||
|
||||
@@ -35,10 +35,10 @@ pub trait Configurable {
|
||||
/// This can set any type of setting whether it is numeric, boolean, or enumerated.
|
||||
fn set(&mut self, name: &str, value: &str) -> Result<()>;
|
||||
|
||||
/// Set the value of a boolean setting by name.
|
||||
/// Enable a boolean setting or apply a preset.
|
||||
///
|
||||
/// If the identified setting isn't a boolean, a `BadType` error is returned.
|
||||
fn set_bool(&mut self, name: &str, value: bool) -> Result<()>;
|
||||
/// If the identified setting isn't a boolean or a preset, a `BadType` error is returned.
|
||||
fn enable(&mut self, name: &str) -> Result<()>;
|
||||
}
|
||||
|
||||
/// Collect settings values based on a template.
|
||||
@@ -73,6 +73,13 @@ impl Builder {
|
||||
}
|
||||
}
|
||||
|
||||
/// Apply a preset. The argument is a slice of (mask, value) bytes.
|
||||
fn apply_preset(&mut self, values: &[(u8, u8)]) {
|
||||
for (byte, &(mask, value)) in self.bytes.iter_mut().zip(values) {
|
||||
*byte = (*byte & !mask) | value;
|
||||
}
|
||||
}
|
||||
|
||||
/// Look up a descriptor by name.
|
||||
fn lookup(&self, name: &str) -> Result<(usize, detail::Detail)> {
|
||||
match probe(self.template, name, simple_hash(name)) {
|
||||
@@ -101,14 +108,19 @@ fn parse_enum_value(value: &str, choices: &[&str]) -> Result<u8> {
|
||||
}
|
||||
|
||||
impl Configurable for Builder {
|
||||
fn set_bool(&mut self, name: &str, value: bool) -> Result<()> {
|
||||
fn enable(&mut self, name: &str) -> Result<()> {
|
||||
use self::detail::Detail;
|
||||
let (offset, detail) = self.lookup(name)?;
|
||||
if let Detail::Bool { bit } = detail {
|
||||
self.set_bit(offset, bit, value);
|
||||
Ok(())
|
||||
} else {
|
||||
Err(Error::BadType)
|
||||
match detail {
|
||||
Detail::Bool { bit } => {
|
||||
self.set_bit(offset, bit, true);
|
||||
Ok(())
|
||||
}
|
||||
Detail::Preset => {
|
||||
self.apply_preset(&self.template.presets[offset..]);
|
||||
Ok(())
|
||||
}
|
||||
_ => Err(Error::BadType),
|
||||
}
|
||||
}
|
||||
|
||||
@@ -128,6 +140,7 @@ impl Configurable for Builder {
|
||||
self.bytes[offset] = parse_enum_value(value,
|
||||
self.template.enums(last, enumerators))?;
|
||||
}
|
||||
Detail::Preset => return Err(Error::BadName),
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
@@ -169,6 +182,8 @@ pub mod detail {
|
||||
pub hash_table: &'static [u16],
|
||||
/// Default values.
|
||||
pub defaults: &'static [u8],
|
||||
/// Pairs of (mask, value) for presets.
|
||||
pub presets: &'static [(u8, u8)],
|
||||
}
|
||||
|
||||
impl Template {
|
||||
@@ -197,6 +212,8 @@ pub mod detail {
|
||||
write!(f, "{}", byte)
|
||||
}
|
||||
}
|
||||
// Presets aren't printed. They are reflected in the other settings.
|
||||
Detail::Preset { .. } => Ok(()),
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -251,6 +268,11 @@ pub mod detail {
|
||||
/// First enumerator in the ENUMERATORS table.
|
||||
enumerators: u16,
|
||||
},
|
||||
|
||||
/// A preset is not an individual setting, it is a collection of settings applied at once.
|
||||
///
|
||||
/// The `Descriptor::offset` field refers to the `PRESETS` table.
|
||||
Preset,
|
||||
}
|
||||
}
|
||||
|
||||
@@ -284,9 +306,9 @@ mod tests {
|
||||
#[test]
|
||||
fn modify_bool() {
|
||||
let mut b = builder();
|
||||
assert_eq!(b.set_bool("not_there", true), Err(BadName));
|
||||
assert_eq!(b.set_bool("enable_simd", true), Ok(()));
|
||||
assert_eq!(b.set_bool("enable_simd", false), Ok(()));
|
||||
assert_eq!(b.enable("not_there"), Err(BadName));
|
||||
assert_eq!(b.enable("enable_simd"), Ok(()));
|
||||
assert_eq!(b.set("enable_simd", "false"), Ok(()));
|
||||
|
||||
let f = Flags::new(&b);
|
||||
assert_eq!(f.enable_simd(), false);
|
||||
|
||||
Reference in New Issue
Block a user