1 //! This crate generates Rust sources for use by
2 //! [`cranelift_codegen`](../cranelift_codegen/index.html).
3
4 use cranelift_srcgen::{Formatter, Language, error};
5 use shared::Definitions;
6
7 #[macro_use]
8 mod cdsl;
9
10 pub mod isa;
11 pub mod isle;
12
13 mod gen_asm;
14 mod gen_inst;
15 mod gen_isle;
16 mod gen_settings;
17 mod gen_types;
18
19 mod constant_hash;
20 mod shared;
21 mod unique_table;
22
23 #[cfg(feature = "pulley")]
24 mod pulley;
25
26 /// Generate an ISA from an architecture string (e.g. "x86_64").
isa_from_arch(arch: &str) -> Result<isa::Isa, String>27 pub fn isa_from_arch(arch: &str) -> Result<isa::Isa, String> {
28 isa::Isa::from_arch(arch).ok_or_else(|| format!("no supported isa found for arch `{arch}`"))
29 }
30
31 /// Generates all the Rust source files used in Cranelift from the meta-language.
generate_rust(isas: &[isa::Isa], out_dir: &std::path::Path) -> Result<(), error::Error>32 pub fn generate_rust(isas: &[isa::Isa], out_dir: &std::path::Path) -> Result<(), error::Error> {
33 let shared_defs = shared::define();
34 generate_rust_for_shared_defs(&shared_defs, isas, out_dir)
35 }
36
generate_rust_for_shared_defs( shared_defs: &Definitions, isas: &[isa::Isa], out_dir: &std::path::Path, ) -> Result<(), error::Error>37 fn generate_rust_for_shared_defs(
38 shared_defs: &Definitions,
39 isas: &[isa::Isa],
40 out_dir: &std::path::Path,
41 ) -> Result<(), error::Error> {
42 gen_settings::generate(
43 &shared_defs.settings,
44 gen_settings::ParentGroup::None,
45 "settings.rs",
46 out_dir,
47 )?;
48
49 gen_types::generate("types.rs", out_dir)?;
50
51 gen_inst::generate(
52 &shared_defs.all_formats,
53 &shared_defs.all_instructions,
54 "opcodes.rs",
55 "inst_builder.rs",
56 out_dir,
57 )?;
58
59 // Per ISA definitions.
60 for isa in isa::define(isas) {
61 gen_settings::generate(
62 &isa.settings,
63 gen_settings::ParentGroup::Shared,
64 &format!("settings-{}.rs", isa.name),
65 out_dir,
66 )?;
67 }
68
69 #[cfg(feature = "pulley")]
70 if isas.contains(&isa::Isa::Pulley32) || isas.contains(&isa::Isa::Pulley64) {
71 pulley::generate_rust("pulley_inst_gen.rs", out_dir)?;
72 }
73
74 Ok(())
75 }
76
77 /// Generates all the ISLE source files used in Cranelift from the meta-language.
generate_isle(isle_dir: &std::path::Path) -> Result<(), error::Error>78 pub fn generate_isle(isle_dir: &std::path::Path) -> Result<(), error::Error> {
79 let shared_defs = shared::define();
80 generate_isle_for_shared_defs(&shared_defs, isle_dir)
81 }
82
generate_isle_for_shared_defs( shared_defs: &Definitions, isle_dir: &std::path::Path, ) -> Result<(), error::Error>83 fn generate_isle_for_shared_defs(
84 shared_defs: &Definitions,
85 isle_dir: &std::path::Path,
86 ) -> Result<(), error::Error> {
87 gen_isle::generate(
88 &shared_defs.all_formats,
89 &shared_defs.all_instructions,
90 "numerics.isle",
91 "isle_numerics.rs",
92 "clif_opt.isle",
93 "clif_lower.isle",
94 isle_dir,
95 )?;
96
97 #[cfg(feature = "pulley")]
98 pulley::generate_isle("pulley_gen.isle", isle_dir)?;
99
100 Ok(())
101 }
102
103 /// Generate the ISLE definitions; this provides ISLE glue to access the
104 /// assembler instructions in [cranelift_assembler_x64_meta].
generate_isle_for_assembler( insts: &[cranelift_assembler_x64_meta::dsl::Inst], isle_dir: &std::path::Path, ) -> Result<(), error::Error>105 fn generate_isle_for_assembler(
106 insts: &[cranelift_assembler_x64_meta::dsl::Inst],
107 isle_dir: &std::path::Path,
108 ) -> Result<(), error::Error> {
109 let mut fmt = Formatter::new(Language::Isle);
110 gen_asm::generate_isle(&mut fmt, insts);
111 fmt.write("assembler.isle", isle_dir)
112 }
113
114 /// Generate a macro containing builder functions for the assembler's ISLE
115 /// constructors; this provides Rust implementations backing up the ISLE
116 /// definitions in [generate_isle_for_assembler].
generate_rust_macro_for_assembler( insts: &[cranelift_assembler_x64_meta::dsl::Inst], out_dir: &std::path::Path, ) -> Result<(), error::Error>117 fn generate_rust_macro_for_assembler(
118 insts: &[cranelift_assembler_x64_meta::dsl::Inst],
119 out_dir: &std::path::Path,
120 ) -> Result<(), error::Error> {
121 let mut fmt = Formatter::new(Language::Rust);
122 gen_asm::generate_rust_macro(&mut fmt, insts);
123 fmt.write("assembler-isle-macro.rs", out_dir)
124 }
125
126 /// Generates all the source files used in Cranelift from the meta-language.
generate( isas: &[isa::Isa], out_dir: &std::path::Path, isle_dir: &std::path::Path, ) -> Result<(), error::Error>127 pub fn generate(
128 isas: &[isa::Isa],
129 out_dir: &std::path::Path,
130 isle_dir: &std::path::Path,
131 ) -> Result<(), error::Error> {
132 let shared_defs = shared::define();
133 generate_rust_for_shared_defs(&shared_defs, isas, out_dir)?;
134 generate_isle_for_shared_defs(&shared_defs, isle_dir)?;
135
136 let insts = cranelift_assembler_x64_meta::instructions::list();
137 generate_isle_for_assembler(&insts, isle_dir)?;
138 generate_rust_macro_for_assembler(&insts, out_dir)?;
139
140 Ok(())
141 }
142