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