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