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