diff --git a/cranelift/codegen/meta/src/cdsl/mod.rs b/cranelift/codegen/meta/src/cdsl/mod.rs index 516b04d0b2..2d7f545dd2 100644 --- a/cranelift/codegen/meta/src/cdsl/mod.rs +++ b/cranelift/codegen/meta/src/cdsl/mod.rs @@ -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() }; diff --git a/cranelift/codegen/meta/src/cdsl/settings.rs b/cranelift/codegen/meta/src/cdsl/settings.rs index 805dfd2a7a..3983946225 100644 --- a/cranelift/codegen/meta/src/cdsl/settings.rs +++ b/cranelift/codegen/meta/src/cdsl/settings.rs @@ -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), And(Box, Box), } @@ -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, presets: Vec, - predicates: Vec, - predicate_number: u8, + predicates: Vec, } 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) -> 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 diff --git a/cranelift/codegen/meta/src/isa/x86/mod.rs b/cranelift/codegen/meta/src/isa/x86/mod.rs index 8080ea5d43..c0a35a8e1d 100644 --- a/cranelift/codegen/meta/src/isa/x86/mod.rs +++ b/cranelift/codegen/meta/src/isa/x86/mod.rs @@ -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",