1 use std::collections::HashSet;
2 use std::iter::FromIterator;
3 
4 use crate::cdsl::cpu_modes::CpuMode;
5 use crate::cdsl::instructions::{InstructionGroup, InstructionPredicateMap};
6 use crate::cdsl::recipes::Recipes;
7 use crate::cdsl::regs::IsaRegs;
8 use crate::cdsl::settings::SettingGroup;
9 use crate::cdsl::xform::{TransformGroupIndex, TransformGroups};
10 
11 pub(crate) struct TargetIsa {
12     pub name: &'static str,
13     pub instructions: InstructionGroup,
14     pub settings: SettingGroup,
15     pub regs: IsaRegs,
16     pub recipes: Recipes,
17     pub cpu_modes: Vec<CpuMode>,
18     pub encodings_predicates: InstructionPredicateMap,
19 
20     /// TransformGroupIndex are global to all the ISAs, while we want to have indices into the
21     /// local array of transform groups that are directly used. We use this map to get this
22     /// information.
23     pub local_transform_groups: Vec<TransformGroupIndex>,
24 }
25 
26 impl TargetIsa {
new( name: &'static str, instructions: InstructionGroup, settings: SettingGroup, regs: IsaRegs, recipes: Recipes, cpu_modes: Vec<CpuMode>, encodings_predicates: InstructionPredicateMap, ) -> Self27     pub fn new(
28         name: &'static str,
29         instructions: InstructionGroup,
30         settings: SettingGroup,
31         regs: IsaRegs,
32         recipes: Recipes,
33         cpu_modes: Vec<CpuMode>,
34         encodings_predicates: InstructionPredicateMap,
35     ) -> Self {
36         // Compute the local TransformGroup index.
37         let mut local_transform_groups = Vec::new();
38         for cpu_mode in &cpu_modes {
39             let transform_groups = cpu_mode.direct_transform_groups();
40             for group_index in transform_groups {
41                 // find() is fine here: the number of transform group is < 5 as of June 2019.
42                 if local_transform_groups
43                     .iter()
44                     .find(|&val| group_index == *val)
45                     .is_none()
46                 {
47                     local_transform_groups.push(group_index);
48                 }
49             }
50         }
51 
52         Self {
53             name,
54             instructions,
55             settings,
56             regs,
57             recipes,
58             cpu_modes,
59             encodings_predicates,
60             local_transform_groups,
61         }
62     }
63 
64     /// Returns a deterministically ordered, deduplicated list of TransformGroupIndex for the
65     /// transitive set of TransformGroup this TargetIsa uses.
transitive_transform_groups( &self, all_groups: &TransformGroups, ) -> Vec<TransformGroupIndex>66     pub fn transitive_transform_groups(
67         &self,
68         all_groups: &TransformGroups,
69     ) -> Vec<TransformGroupIndex> {
70         let mut set = HashSet::new();
71 
72         for &root in self.local_transform_groups.iter() {
73             set.insert(root);
74             let mut base = root;
75             // Follow the chain of chain_with.
76             while let Some(chain_with) = &all_groups.get(base).chain_with {
77                 set.insert(*chain_with);
78                 base = *chain_with;
79             }
80         }
81 
82         let mut vec = Vec::from_iter(set);
83         vec.sort();
84         vec
85     }
86 
87     /// Returns a deterministically ordered, deduplicated list of TransformGroupIndex for the directly
88     /// reachable set of TransformGroup this TargetIsa uses.
direct_transform_groups(&self) -> &Vec<TransformGroupIndex>89     pub fn direct_transform_groups(&self) -> &Vec<TransformGroupIndex> {
90         &self.local_transform_groups
91     }
92 
translate_group_index(&self, group_index: TransformGroupIndex) -> usize93     pub fn translate_group_index(&self, group_index: TransformGroupIndex) -> usize {
94         self.local_transform_groups
95             .iter()
96             .position(|&val| val == group_index)
97             .expect("TransformGroup unused by this TargetIsa!")
98     }
99 }
100