1 //! This crate generates Rust sources for use by
2 //! [`cranelift_codegen`](../cranelift_codegen/index.html).
3 #[macro_use]
4 mod cdsl;
5 mod srcgen;
6 
7 pub mod error;
8 pub mod isa;
9 
10 mod gen_binemit;
11 mod gen_encodings;
12 mod gen_inst;
13 mod gen_legalizer;
14 mod gen_registers;
15 mod gen_settings;
16 mod gen_types;
17 
18 mod default_map;
19 mod shared;
20 mod unique_table;
21 
22 /// Generate an ISA from an architecture string (e.g. "x86_64").
isa_from_arch(arch: &str) -> Result<isa::Isa, String>23 pub fn isa_from_arch(arch: &str) -> Result<isa::Isa, String> {
24     isa::Isa::from_arch(arch).ok_or_else(|| format!("no supported isa found for arch `{}`", arch))
25 }
26 
27 /// Generates all the Rust source files used in Cranelift from the meta-language.
generate( old_backend_isas: &[isa::Isa], new_backend_isas: &[isa::Isa], out_dir: &str, ) -> Result<(), error::Error>28 pub fn generate(
29     old_backend_isas: &[isa::Isa],
30     new_backend_isas: &[isa::Isa],
31     out_dir: &str,
32 ) -> Result<(), error::Error> {
33     // Create all the definitions:
34     // - common definitions.
35     let mut shared_defs = shared::define();
36 
37     gen_settings::generate(
38         &shared_defs.settings,
39         gen_settings::ParentGroup::None,
40         "settings.rs",
41         &out_dir,
42     )?;
43     gen_types::generate("types.rs", &out_dir)?;
44 
45     // - per ISA definitions.
46     let target_isas = isa::define(old_backend_isas, &mut shared_defs);
47 
48     // At this point, all definitions are done.
49     let all_formats = shared_defs.verify_instruction_formats();
50 
51     // Generate all the code.
52     gen_inst::generate(
53         all_formats,
54         &shared_defs.all_instructions,
55         "opcodes.rs",
56         "inst_builder.rs",
57         &out_dir,
58     )?;
59 
60     let extra_legalization_groups: &[&'static str] = if !new_backend_isas.is_empty() {
61         // The new backend only requires the "expand" legalization group.
62         &["expand"]
63     } else {
64         &[]
65     };
66 
67     gen_legalizer::generate(
68         &target_isas,
69         &shared_defs.transform_groups,
70         extra_legalization_groups,
71         "legalize",
72         &out_dir,
73     )?;
74 
75     for isa in target_isas {
76         gen_registers::generate(&isa, &format!("registers-{}.rs", isa.name), &out_dir)?;
77 
78         gen_settings::generate(
79             &isa.settings,
80             gen_settings::ParentGroup::Shared,
81             &format!("settings-{}.rs", isa.name),
82             &out_dir,
83         )?;
84 
85         gen_encodings::generate(
86             &shared_defs,
87             &isa,
88             &format!("encoding-{}.rs", isa.name),
89             &out_dir,
90         )?;
91 
92         gen_binemit::generate(
93             &isa.name,
94             &isa.recipes,
95             &format!("binemit-{}.rs", isa.name),
96             &out_dir,
97         )?;
98     }
99 
100     for isa in new_backend_isas {
101         match isa {
102             isa::Isa::X86 => {
103                 // If the old backend ISAs contained x86, this file has already been generated.
104                 if old_backend_isas.iter().any(|isa| *isa == isa::Isa::X86) {
105                     continue;
106                 }
107 
108                 let settings = crate::isa::x86::settings::define(&shared_defs.settings);
109                 gen_settings::generate(
110                     &settings,
111                     gen_settings::ParentGroup::Shared,
112                     "settings-x86.rs",
113                     &out_dir,
114                 )?;
115             }
116             isa::Isa::Arm64 => {
117                 // aarch64 doesn't have platform-specific settings.
118             }
119             isa::Isa::S390x => {
120                 // s390x doesn't have platform-specific settings.
121             }
122             isa::Isa::Arm32 | isa::Isa::Riscv => todo!(),
123         }
124     }
125 
126     Ok(())
127 }
128