[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:
@@ -23,6 +23,15 @@ macro_rules! predicate {
|
|||||||
($a:ident && $($b:tt)*) => {
|
($a:ident && $($b:tt)*) => {
|
||||||
PredicateNode::And(Box::new($a.into()), Box::new(predicate!($($b)*)))
|
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:ident) => {
|
||||||
$a.into()
|
$a.into()
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -153,7 +153,7 @@ impl SettingGroup {
|
|||||||
/// This is the basic information needed to track the specific parts of a setting when building
|
/// This is the basic information needed to track the specific parts of a setting when building
|
||||||
/// them.
|
/// them.
|
||||||
pub enum ProtoSpecificSetting {
|
pub enum ProtoSpecificSetting {
|
||||||
Bool(bool, u8),
|
Bool(bool),
|
||||||
Enum(Vec<&'static str>),
|
Enum(Vec<&'static str>),
|
||||||
Num(u8),
|
Num(u8),
|
||||||
}
|
}
|
||||||
@@ -169,6 +169,7 @@ struct ProtoSetting {
|
|||||||
pub enum PredicateNode {
|
pub enum PredicateNode {
|
||||||
OwnedBool(BoolSettingIndex),
|
OwnedBool(BoolSettingIndex),
|
||||||
SharedBool(&'static str, &'static str),
|
SharedBool(&'static str, &'static str),
|
||||||
|
Not(Box<PredicateNode>),
|
||||||
And(Box<PredicateNode>, Box<PredicateNode>),
|
And(Box<PredicateNode>, Box<PredicateNode>),
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -198,10 +199,16 @@ impl PredicateNode {
|
|||||||
PredicateNode::And(ref lhs, ref rhs) => {
|
PredicateNode::And(ref lhs, ref rhs) => {
|
||||||
format!("{} && {}", lhs.render(group), rhs.render(group))
|
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 struct Predicate {
|
||||||
pub name: &'static str,
|
pub name: &'static str,
|
||||||
node: PredicateNode,
|
node: PredicateNode,
|
||||||
@@ -218,8 +225,7 @@ pub struct SettingGroupBuilder {
|
|||||||
name: &'static str,
|
name: &'static str,
|
||||||
settings: Vec<ProtoSetting>,
|
settings: Vec<ProtoSetting>,
|
||||||
presets: Vec<Preset>,
|
presets: Vec<Preset>,
|
||||||
predicates: Vec<Predicate>,
|
predicates: Vec<ProtoPredicate>,
|
||||||
predicate_number: u8,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl SettingGroupBuilder {
|
impl SettingGroupBuilder {
|
||||||
@@ -229,7 +235,6 @@ impl SettingGroupBuilder {
|
|||||||
settings: Vec::new(),
|
settings: Vec::new(),
|
||||||
presets: Vec::new(),
|
presets: Vec::new(),
|
||||||
predicates: Vec::new(),
|
predicates: Vec::new(),
|
||||||
predicate_number: 0,
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -256,13 +261,7 @@ impl SettingGroupBuilder {
|
|||||||
self.predicates.len() == 0,
|
self.predicates.len() == 0,
|
||||||
"predicates must be added after the boolean settings"
|
"predicates must be added after the boolean settings"
|
||||||
);
|
);
|
||||||
let predicate_number = self.predicate_number;
|
self.add_setting(name, comment, ProtoSpecificSetting::Bool(default));
|
||||||
self.predicate_number += 1;
|
|
||||||
self.add_setting(
|
|
||||||
name,
|
|
||||||
comment,
|
|
||||||
ProtoSpecificSetting::Bool(default, predicate_number),
|
|
||||||
);
|
|
||||||
BoolSettingIndex(self.settings.len() - 1)
|
BoolSettingIndex(self.settings.len() - 1)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -280,9 +279,7 @@ impl SettingGroupBuilder {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub fn add_predicate(&mut self, name: &'static str, node: PredicateNode) {
|
pub fn add_predicate(&mut self, name: &'static str, node: PredicateNode) {
|
||||||
let number = self.predicate_number;
|
self.predicates.push(ProtoPredicate { name, node });
|
||||||
self.predicate_number += 1;
|
|
||||||
self.predicates.push(Predicate { name, node, number });
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn add_preset(&mut self, name: &'static str, args: Vec<PresetType>) -> PresetIndex {
|
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`.
|
/// 1. Byte-sized settings like `NumSetting` and `EnumSetting`.
|
||||||
/// 2. `BoolSetting` settings.
|
/// 2. `BoolSetting` settings.
|
||||||
/// 3. Precomputed named predicates.
|
/// 3. Precomputed named predicates.
|
||||||
/// 4. Other numbered predicates, including anonymous predicates and parent
|
/// 4. Other numbered predicates, including parent predicates that need to be accessible by
|
||||||
/// predicates that need to be accessible by number.
|
/// number.
|
||||||
///
|
///
|
||||||
/// Set `self.settings_size` to the length of the byte vector prefix that
|
/// Set `self.settings_size` to the length of the byte vector prefix that
|
||||||
/// contains the settings. All bytes after that are computed, not
|
/// contains the settings. All bytes after that are computed, not
|
||||||
@@ -318,9 +315,6 @@ impl SettingGroupBuilder {
|
|||||||
/// 2. in the list above.
|
/// 2. in the list above.
|
||||||
///
|
///
|
||||||
/// Assign `byte_offset` and `bit_offset` fields in all settings.
|
/// 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 {
|
pub fn finish(self) -> SettingGroup {
|
||||||
let mut group = SettingGroup {
|
let mut group = SettingGroup {
|
||||||
name: self.name,
|
name: self.name,
|
||||||
@@ -353,12 +347,12 @@ impl SettingGroupBuilder {
|
|||||||
|
|
||||||
group.bool_start_byte_offset = byte_offset;
|
group.bool_start_byte_offset = byte_offset;
|
||||||
|
|
||||||
|
let mut predicate_number = 0;
|
||||||
|
|
||||||
// Then the boolean settings.
|
// Then the boolean settings.
|
||||||
for s in &self.settings {
|
for s in &self.settings {
|
||||||
let (default, predicate_number) = match s.specific {
|
let default = match s.specific {
|
||||||
ProtoSpecificSetting::Bool(default, predicate_number) => {
|
ProtoSpecificSetting::Bool(default) => default,
|
||||||
(default, predicate_number)
|
|
||||||
}
|
|
||||||
ProtoSpecificSetting::Enum(_) | ProtoSpecificSetting::Num(_) => continue,
|
ProtoSpecificSetting::Enum(_) | ProtoSpecificSetting::Num(_) => continue,
|
||||||
};
|
};
|
||||||
group.settings.push(Setting {
|
group.settings.push(Setting {
|
||||||
@@ -371,6 +365,7 @@ impl SettingGroupBuilder {
|
|||||||
predicate_number,
|
predicate_number,
|
||||||
}),
|
}),
|
||||||
});
|
});
|
||||||
|
predicate_number += 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
assert!(
|
assert!(
|
||||||
@@ -379,7 +374,22 @@ impl SettingGroupBuilder {
|
|||||||
);
|
);
|
||||||
group.settings_size = group.byte_size();
|
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.presets.extend(self.presets);
|
||||||
|
|
||||||
group
|
group
|
||||||
|
|||||||
@@ -11,7 +11,7 @@ use crate::shared::Definitions as SharedDefinitions;
|
|||||||
mod instructions;
|
mod instructions;
|
||||||
mod legalize;
|
mod legalize;
|
||||||
|
|
||||||
fn define_settings(_shared: &SettingGroup) -> SettingGroup {
|
fn define_settings(shared: &SettingGroup) -> SettingGroup {
|
||||||
let mut settings = SettingGroupBuilder::new("x86");
|
let mut settings = SettingGroupBuilder::new("x86");
|
||||||
|
|
||||||
// CPUID.01H:ECX
|
// 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_bmi1", predicate!(has_bmi1));
|
||||||
settings.add_predicate("use_lznct", predicate!(has_lzcnt));
|
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!());
|
settings.add_preset("baseline", preset!());
|
||||||
let nehalem = settings.add_preset(
|
let nehalem = settings.add_preset(
|
||||||
"nehalem",
|
"nehalem",
|
||||||
|
|||||||
Reference in New Issue
Block a user