1 //! Shared definitions for the Cranelift intermediate language. 2 3 pub mod entities; 4 pub mod formats; 5 pub mod immediates; 6 pub mod instructions; 7 pub mod legalize; 8 pub mod settings; 9 pub mod types; 10 11 use crate::cdsl::formats::{FormatStructure, InstructionFormat}; 12 use crate::cdsl::instructions::{AllInstructions, InstructionGroup}; 13 use crate::cdsl::settings::SettingGroup; 14 use crate::cdsl::xform::TransformGroups; 15 16 use crate::shared::entities::EntityRefs; 17 use crate::shared::formats::Formats; 18 use crate::shared::immediates::Immediates; 19 20 use std::collections::HashMap; 21 use std::iter::FromIterator; 22 use std::rc::Rc; 23 24 pub(crate) struct Definitions { 25 pub settings: SettingGroup, 26 pub all_instructions: AllInstructions, 27 pub instructions: InstructionGroup, 28 pub imm: Immediates, 29 pub formats: Formats, 30 pub transform_groups: TransformGroups, 31 pub entities: EntityRefs, 32 } 33 34 pub(crate) fn define() -> Definitions { 35 let mut all_instructions = AllInstructions::new(); 36 37 let immediates = Immediates::new(); 38 let entities = EntityRefs::new(); 39 let formats = Formats::new(&immediates, &entities); 40 let instructions = 41 instructions::define(&mut all_instructions, &formats, &immediates, &entities); 42 let transform_groups = legalize::define(&instructions, &immediates); 43 44 Definitions { 45 settings: settings::define(), 46 all_instructions, 47 instructions, 48 imm: immediates, 49 formats, 50 transform_groups, 51 entities, 52 } 53 } 54 55 impl Definitions { 56 /// Verifies certain properties of formats. 57 /// 58 /// - Formats must be uniquely named: if two formats have the same name, they must refer to the 59 /// same data. Otherwise, two format variants in the codegen crate would have the same name. 60 /// - Formats must be structurally different from each other. Otherwise, this would lead to 61 /// code duplicate in the codegen crate. 62 /// 63 /// Returns a list of all the instruction formats effectively used. 64 pub fn verify_instruction_formats(&self) -> Vec<&InstructionFormat> { 65 let mut format_names: HashMap<&'static str, &Rc<InstructionFormat>> = HashMap::new(); 66 67 // A structure is: number of input value operands / whether there's varargs or not / names 68 // of immediate fields. 69 let mut format_structures: HashMap<FormatStructure, &InstructionFormat> = HashMap::new(); 70 71 for inst in self.all_instructions.values() { 72 // Check name. 73 if let Some(existing_format) = format_names.get(&inst.format.name) { 74 assert!( 75 Rc::ptr_eq(&existing_format, &inst.format), 76 "formats must uniquely named; there's a\ 77 conflict on the name '{}', please make sure it is used only once.", 78 existing_format.name 79 ); 80 } else { 81 format_names.insert(inst.format.name, &inst.format); 82 } 83 84 // Check structure. 85 let key = inst.format.structure(); 86 if let Some(existing_format) = format_structures.get(&key) { 87 assert_eq!( 88 existing_format.name, inst.format.name, 89 "duplicate instruction formats {} and {}; please remove one.", 90 existing_format.name, inst.format.name 91 ); 92 } else { 93 format_structures.insert(key, &inst.format); 94 } 95 } 96 97 let mut result = Vec::from_iter(format_structures.into_iter().map(|(_, v)| v)); 98 result.sort_by_key(|format| format.name); 99 result 100 } 101 } 102