[meta] Use named predicates for x86 settings in the Rust crate too;

And generate them using the same deterministic order that the Python
code uses.
This commit is contained in:
Benjamin Bouvier
2019-04-16 15:24:28 +02:00
parent 6a25354520
commit 390cfb37da
3 changed files with 62 additions and 25 deletions

View File

@@ -23,6 +23,15 @@ macro_rules! predicate {
($a:ident && $($b:tt)*) => {
PredicateNode::And(Box::new($a.into()), Box::new(predicate!($($b)*)))
};
(!$a:ident && $($b:tt)*) => {
PredicateNode::And(
Box::new(PredicateNode::Not(Box::new($a.into()))),
Box::new(predicate!($($b)*))
)
};
(!$a:ident) => {
PredicateNode::Not(Box::new($a.into()))
};
($a:ident) => {
$a.into()
};

View File

@@ -153,7 +153,7 @@ impl SettingGroup {
/// This is the basic information needed to track the specific parts of a setting when building
/// them.
pub enum ProtoSpecificSetting {
Bool(bool, u8),
Bool(bool),
Enum(Vec<&'static str>),
Num(u8),
}
@@ -169,6 +169,7 @@ struct ProtoSetting {
pub enum PredicateNode {
OwnedBool(BoolSettingIndex),
SharedBool(&'static str, &'static str),
Not(Box<PredicateNode>),
And(Box<PredicateNode>, Box<PredicateNode>),
}
@@ -198,10 +199,16 @@ impl PredicateNode {
PredicateNode::And(ref lhs, ref rhs) => {
format!("{} && {}", lhs.render(group), rhs.render(group))
}
PredicateNode::Not(ref node) => format!("!({})", node.render(group)),
}
}
}
struct ProtoPredicate {
pub name: &'static str,
node: PredicateNode,
}
pub struct Predicate {
pub name: &'static str,
node: PredicateNode,
@@ -218,8 +225,7 @@ pub struct SettingGroupBuilder {
name: &'static str,
settings: Vec<ProtoSetting>,
presets: Vec<Preset>,
predicates: Vec<Predicate>,
predicate_number: u8,
predicates: Vec<ProtoPredicate>,
}
impl SettingGroupBuilder {
@@ -229,7 +235,6 @@ impl SettingGroupBuilder {
settings: Vec::new(),
presets: Vec::new(),
predicates: Vec::new(),
predicate_number: 0,
}
}
@@ -256,13 +261,7 @@ impl SettingGroupBuilder {
self.predicates.len() == 0,
"predicates must be added after the boolean settings"
);
let predicate_number = self.predicate_number;
self.predicate_number += 1;
self.add_setting(
name,
comment,
ProtoSpecificSetting::Bool(default, predicate_number),
);
self.add_setting(name, comment, ProtoSpecificSetting::Bool(default));
BoolSettingIndex(self.settings.len() - 1)
}
@@ -280,9 +279,7 @@ impl SettingGroupBuilder {
}
pub fn add_predicate(&mut self, name: &'static str, node: PredicateNode) {
let number = self.predicate_number;
self.predicate_number += 1;
self.predicates.push(Predicate { name, node, number });
self.predicates.push(ProtoPredicate { name, node });
}
pub fn add_preset(&mut self, name: &'static str, args: Vec<PresetType>) -> PresetIndex {
@@ -307,8 +304,8 @@ impl SettingGroupBuilder {
/// 1. Byte-sized settings like `NumSetting` and `EnumSetting`.
/// 2. `BoolSetting` settings.
/// 3. Precomputed named predicates.
/// 4. Other numbered predicates, including anonymous predicates and parent
/// predicates that need to be accessible by number.
/// 4. Other numbered predicates, including parent predicates that need to be accessible by
/// number.
///
/// Set `self.settings_size` to the length of the byte vector prefix that
/// contains the settings. All bytes after that are computed, not
@@ -318,9 +315,6 @@ impl SettingGroupBuilder {
/// 2. in the list above.
///
/// Assign `byte_offset` and `bit_offset` fields in all settings.
///
/// After calling this method, no more settings can be added, but
/// additional predicates can be made accessible with `number_predicate()`.
pub fn finish(self) -> SettingGroup {
let mut group = SettingGroup {
name: self.name,
@@ -353,12 +347,12 @@ impl SettingGroupBuilder {
group.bool_start_byte_offset = byte_offset;
let mut predicate_number = 0;
// Then the boolean settings.
for s in &self.settings {
let (default, predicate_number) = match s.specific {
ProtoSpecificSetting::Bool(default, predicate_number) => {
(default, predicate_number)
}
let default = match s.specific {
ProtoSpecificSetting::Bool(default) => default,
ProtoSpecificSetting::Enum(_) | ProtoSpecificSetting::Num(_) => continue,
};
group.settings.push(Setting {
@@ -371,6 +365,7 @@ impl SettingGroupBuilder {
predicate_number,
}),
});
predicate_number += 1;
}
assert!(
@@ -379,7 +374,22 @@ impl SettingGroupBuilder {
);
group.settings_size = group.byte_size();
group.predicates.extend(self.predicates);
// Sort predicates by name to ensure the same order as the Python code.
let mut predicates = self.predicates;
predicates.sort_by_key(|predicate| predicate.name);
group
.predicates
.extend(predicates.into_iter().map(|predicate| {
let number = predicate_number;
predicate_number += 1;
return Predicate {
name: predicate.name,
node: predicate.node,
number,
};
}));
group.presets.extend(self.presets);
group

View File

@@ -11,7 +11,7 @@ use crate::shared::Definitions as SharedDefinitions;
mod instructions;
mod legalize;
fn define_settings(_shared: &SettingGroup) -> SettingGroup {
fn define_settings(shared: &SettingGroup) -> SettingGroup {
let mut settings = SettingGroupBuilder::new("x86");
// CPUID.01H:ECX
@@ -47,6 +47,24 @@ fn define_settings(_shared: &SettingGroup) -> SettingGroup {
settings.add_predicate("use_bmi1", predicate!(has_bmi1));
settings.add_predicate("use_lznct", predicate!(has_lzcnt));
// Some shared boolean values are used in x86 instruction predicates, so we need to group them
// in the same TargetIsa, for compabitibity with code generated by meta-python.
// TODO Once all the meta generation code has been migrated from Python to Rust, we can put it
// back in the shared SettingGroup, and use it in x86 instruction predicates.
let is_pic = shared.get_bool("is_pic");
let allones_funcaddrs = shared.get_bool("allones_funcaddrs");
settings.add_predicate("is_pic", predicate!(is_pic));
settings.add_predicate("not_is_pic", predicate!(!is_pic));
settings.add_predicate(
"all_ones_funcaddrs_and_not_is_pic",
predicate!(allones_funcaddrs && !is_pic),
);
settings.add_predicate(
"not_all_ones_funcaddrs_and_not_is_pic",
predicate!(!allones_funcaddrs && !is_pic),
);
settings.add_preset("baseline", preset!());
let nehalem = settings.add_preset(
"nehalem",