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