summaryrefslogtreecommitdiffstats
path: root/third_party/rust/cranelift-codegen-meta/src/cdsl/isa.rs
diff options
context:
space:
mode:
Diffstat (limited to 'third_party/rust/cranelift-codegen-meta/src/cdsl/isa.rs')
-rw-r--r--third_party/rust/cranelift-codegen-meta/src/cdsl/isa.rs99
1 files changed, 99 insertions, 0 deletions
diff --git a/third_party/rust/cranelift-codegen-meta/src/cdsl/isa.rs b/third_party/rust/cranelift-codegen-meta/src/cdsl/isa.rs
new file mode 100644
index 0000000000..512105d09a
--- /dev/null
+++ b/third_party/rust/cranelift-codegen-meta/src/cdsl/isa.rs
@@ -0,0 +1,99 @@
+use std::collections::HashSet;
+use std::iter::FromIterator;
+
+use crate::cdsl::cpu_modes::CpuMode;
+use crate::cdsl::instructions::{InstructionGroup, InstructionPredicateMap};
+use crate::cdsl::recipes::Recipes;
+use crate::cdsl::regs::IsaRegs;
+use crate::cdsl::settings::SettingGroup;
+use crate::cdsl::xform::{TransformGroupIndex, TransformGroups};
+
+pub(crate) struct TargetIsa {
+ pub name: &'static str,
+ pub instructions: InstructionGroup,
+ pub settings: SettingGroup,
+ pub regs: IsaRegs,
+ pub recipes: Recipes,
+ pub cpu_modes: Vec<CpuMode>,
+ pub encodings_predicates: InstructionPredicateMap,
+
+ /// TransformGroupIndex are global to all the ISAs, while we want to have indices into the
+ /// local array of transform groups that are directly used. We use this map to get this
+ /// information.
+ pub local_transform_groups: Vec<TransformGroupIndex>,
+}
+
+impl TargetIsa {
+ pub fn new(
+ name: &'static str,
+ instructions: InstructionGroup,
+ settings: SettingGroup,
+ regs: IsaRegs,
+ recipes: Recipes,
+ cpu_modes: Vec<CpuMode>,
+ encodings_predicates: InstructionPredicateMap,
+ ) -> Self {
+ // Compute the local TransformGroup index.
+ let mut local_transform_groups = Vec::new();
+ for cpu_mode in &cpu_modes {
+ let transform_groups = cpu_mode.direct_transform_groups();
+ for group_index in transform_groups {
+ // find() is fine here: the number of transform group is < 5 as of June 2019.
+ if local_transform_groups
+ .iter()
+ .find(|&val| group_index == *val)
+ .is_none()
+ {
+ local_transform_groups.push(group_index);
+ }
+ }
+ }
+
+ Self {
+ name,
+ instructions,
+ settings,
+ regs,
+ recipes,
+ cpu_modes,
+ encodings_predicates,
+ local_transform_groups,
+ }
+ }
+
+ /// Returns a deterministically ordered, deduplicated list of TransformGroupIndex for the
+ /// transitive set of TransformGroup this TargetIsa uses.
+ pub fn transitive_transform_groups(
+ &self,
+ all_groups: &TransformGroups,
+ ) -> Vec<TransformGroupIndex> {
+ let mut set = HashSet::new();
+
+ for &root in self.local_transform_groups.iter() {
+ set.insert(root);
+ let mut base = root;
+ // Follow the chain of chain_with.
+ while let Some(chain_with) = &all_groups.get(base).chain_with {
+ set.insert(*chain_with);
+ base = *chain_with;
+ }
+ }
+
+ let mut vec = Vec::from_iter(set);
+ vec.sort();
+ vec
+ }
+
+ /// Returns a deterministically ordered, deduplicated list of TransformGroupIndex for the directly
+ /// reachable set of TransformGroup this TargetIsa uses.
+ pub fn direct_transform_groups(&self) -> &Vec<TransformGroupIndex> {
+ &self.local_transform_groups
+ }
+
+ pub fn translate_group_index(&self, group_index: TransformGroupIndex) -> usize {
+ self.local_transform_groups
+ .iter()
+ .position(|&val| val == group_index)
+ .expect("TransformGroup unused by this TargetIsa!")
+ }
+}