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