1f78a61b9SBenjamin Bouvier //! Shared definitions for the Cranelift intermediate language.
2f78a61b9SBenjamin Bouvier
30a1bb3baSbjorn3 pub mod entities;
4d59bef19SBenjamin Bouvier pub mod formats;
5d59bef19SBenjamin Bouvier pub mod immediates;
686430abcSBenjamin Bouvier pub mod instructions;
7f78a61b9SBenjamin Bouvier pub mod settings;
8f78a61b9SBenjamin Bouvier pub mod types;
9d59bef19SBenjamin Bouvier
100243b642SBenjamin Bouvier use crate::cdsl::formats::{FormatStructure, InstructionFormat};
1153ec12d5Sbjorn3 use crate::cdsl::instructions::AllInstructions;
12d59bef19SBenjamin Bouvier use crate::cdsl::settings::SettingGroup;
13d59bef19SBenjamin Bouvier
148fba449bSBenjamin Bouvier use crate::shared::entities::EntityRefs;
150243b642SBenjamin Bouvier use crate::shared::formats::Formats;
1629e3ec51SBenjamin Bouvier use crate::shared::immediates::Immediates;
1729e3ec51SBenjamin Bouvier
180243b642SBenjamin Bouvier use std::collections::HashMap;
190243b642SBenjamin Bouvier use std::rc::Rc;
200243b642SBenjamin Bouvier
21d1d2e790SBenjamin Bouvier pub(crate) struct Definitions {
22d59bef19SBenjamin Bouvier pub settings: SettingGroup,
23f1d1d1e9SBenjamin Bouvier pub all_instructions: AllInstructions,
24*7e66ed24Sbjorn3 pub all_formats: Vec<Rc<InstructionFormat>>,
25d59bef19SBenjamin Bouvier }
26d59bef19SBenjamin Bouvier
define() -> Definitions27d1d2e790SBenjamin Bouvier pub(crate) fn define() -> Definitions {
28f1d1d1e9SBenjamin Bouvier let mut all_instructions = AllInstructions::new();
29f1d1d1e9SBenjamin Bouvier
3029e3ec51SBenjamin Bouvier let immediates = Immediates::new();
319b8e7b51SNick Fitzgerald let entities = EntityRefs::new();
320243b642SBenjamin Bouvier let formats = Formats::new(&immediates, &entities);
330243b642SBenjamin Bouvier instructions::define(&mut all_instructions, &formats, &immediates, &entities);
34*7e66ed24Sbjorn3 let all_formats = verify_instruction_formats(&all_instructions);
35d00e42edSBenjamin Bouvier
36d59bef19SBenjamin Bouvier Definitions {
37d59bef19SBenjamin Bouvier settings: settings::define(),
38f1d1d1e9SBenjamin Bouvier all_instructions,
39*7e66ed24Sbjorn3 all_formats,
40d59bef19SBenjamin Bouvier }
41d59bef19SBenjamin Bouvier }
420243b642SBenjamin Bouvier
430243b642SBenjamin Bouvier /// Verifies certain properties of formats.
440243b642SBenjamin Bouvier ///
450243b642SBenjamin Bouvier /// - Formats must be uniquely named: if two formats have the same name, they must refer to the
460243b642SBenjamin Bouvier /// same data. Otherwise, two format variants in the codegen crate would have the same name.
470243b642SBenjamin Bouvier /// - Formats must be structurally different from each other. Otherwise, this would lead to
480243b642SBenjamin Bouvier /// code duplicate in the codegen crate.
490243b642SBenjamin Bouvier ///
500243b642SBenjamin Bouvier /// Returns a list of all the instruction formats effectively used.
verify_instruction_formats(all_instructions: &AllInstructions) -> Vec<Rc<InstructionFormat>>51*7e66ed24Sbjorn3 fn verify_instruction_formats(all_instructions: &AllInstructions) -> Vec<Rc<InstructionFormat>> {
520243b642SBenjamin Bouvier let mut format_names: HashMap<&'static str, &Rc<InstructionFormat>> = HashMap::new();
530243b642SBenjamin Bouvier
540243b642SBenjamin Bouvier // A structure is: number of input value operands / whether there's varargs or not / names
550243b642SBenjamin Bouvier // of immediate fields.
56*7e66ed24Sbjorn3 let mut format_structures: HashMap<FormatStructure, Rc<InstructionFormat>> = HashMap::new();
570243b642SBenjamin Bouvier
58*7e66ed24Sbjorn3 for inst in all_instructions {
590243b642SBenjamin Bouvier // Check name.
600243b642SBenjamin Bouvier if let Some(existing_format) = format_names.get(&inst.format.name) {
610243b642SBenjamin Bouvier assert!(
6285118c8cSkevaundray Rc::ptr_eq(existing_format, &inst.format),
630243b642SBenjamin Bouvier "formats must uniquely named; there's a\
640243b642SBenjamin Bouvier conflict on the name '{}', please make sure it is used only once.",
650243b642SBenjamin Bouvier existing_format.name
660243b642SBenjamin Bouvier );
670243b642SBenjamin Bouvier } else {
680243b642SBenjamin Bouvier format_names.insert(inst.format.name, &inst.format);
690243b642SBenjamin Bouvier }
700243b642SBenjamin Bouvier
710243b642SBenjamin Bouvier // Check structure.
720243b642SBenjamin Bouvier let key = inst.format.structure();
730243b642SBenjamin Bouvier if let Some(existing_format) = format_structures.get(&key) {
740243b642SBenjamin Bouvier assert_eq!(
750243b642SBenjamin Bouvier existing_format.name, inst.format.name,
760243b642SBenjamin Bouvier "duplicate instruction formats {} and {}; please remove one.",
770243b642SBenjamin Bouvier existing_format.name, inst.format.name
780243b642SBenjamin Bouvier );
790243b642SBenjamin Bouvier } else {
80*7e66ed24Sbjorn3 format_structures.insert(key, inst.format.clone());
810243b642SBenjamin Bouvier }
820243b642SBenjamin Bouvier }
830243b642SBenjamin Bouvier
8485118c8cSkevaundray let mut result = Vec::from_iter(format_structures.into_values());
85b342cbddSMike Hommey result.sort_by_key(|format| format.name);
86b342cbddSMike Hommey result
870243b642SBenjamin Bouvier }
88