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