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