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