cranelift_assembler_x64_meta/
generate.rs1mod features;
4mod format;
5mod inst;
6mod operand;
7
8use crate::dsl;
9use cranelift_srcgen::{Formatter, fmtln};
10
11pub fn rust_assembler(f: &mut Formatter, insts: &[dsl::Inst]) {
13 generate_inst_enum(f, insts);
15 generate_inst_display_impl(f, insts);
16 generate_inst_encode_impl(f, insts);
17 generate_inst_visit_impl(f, insts);
18 generate_inst_is_available_impl(f, insts);
19 generate_inst_features_impl(f, insts);
20
21 f.empty_line();
23 for inst in insts {
24 inst.generate_struct(f);
25 inst.generate_struct_impl(f);
26 inst.generate_display_impl(f);
27 inst.generate_from_impl(f);
28 f.empty_line();
29 }
30
31 dsl::Feature::generate_macro(f);
33}
34
35fn generate_inst_enum(f: &mut Formatter, insts: &[dsl::Inst]) {
37 fmtln!(f, "#[doc(hidden)]");
38 generate_derive(f);
39 generate_derive_arbitrary_bounds(f);
40 f.add_block("pub enum Inst<R: Registers>", |f| {
41 for inst in insts {
42 let variant_name = inst.name();
43 let struct_name = inst.struct_name_with_generic();
44 fmtln!(f, "{variant_name}({struct_name}),");
45 }
46 });
47}
48
49fn generate_derive(f: &mut Formatter) {
51 fmtln!(f, "#[derive(Copy, Clone, Debug)]");
52 fmtln!(
53 f,
54 "#[cfg_attr(any(test, feature = \"fuzz\"), derive(arbitrary::Arbitrary))]"
55 );
56}
57
58fn generate_derive_arbitrary_bounds(f: &mut Formatter) {
61 fmtln!(
62 f,
63 "#[cfg_attr(any(test, feature = \"fuzz\"), arbitrary(bound = \"R: crate::fuzz::RegistersArbitrary\"))]"
64 );
65}
66
67fn generate_inst_display_impl(f: &mut Formatter, insts: &[dsl::Inst]) {
69 f.add_block("impl<R: Registers> std::fmt::Display for Inst<R>", |f| {
70 f.add_block(
71 "fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result",
72 |f| {
73 f.add_block("match self", |f| {
74 for inst in insts {
75 let variant_name = inst.name();
76 fmtln!(f, "Self::{variant_name}(i) => i.fmt(f),");
77 }
78 });
79 },
80 );
81 });
82}
83
84fn generate_inst_encode_impl(f: &mut Formatter, insts: &[dsl::Inst]) {
86 f.add_block("impl<R: Registers> Inst<R>", |f| {
87 f.add_block("pub fn encode(&self, b: &mut impl CodeSink)", |f| {
88 f.add_block("match self", |f| {
89 for inst in insts {
90 let variant_name = inst.name();
91 fmtln!(f, "Self::{variant_name}(i) => i.encode(b),");
92 }
93 });
94 });
95 });
96}
97
98fn generate_inst_visit_impl(f: &mut Formatter, insts: &[dsl::Inst]) {
100 fmtln!(f, "impl<R: Registers> Inst<R> {{");
101 f.indent(|f| {
102 fmtln!(
103 f,
104 "pub fn visit(&mut self, v: &mut impl RegisterVisitor<R>) {{"
105 );
106 f.indent(|f| {
107 fmtln!(f, "match self {{");
108 f.indent_push();
109 for inst in insts {
110 let variant_name = inst.name();
111 fmtln!(f, "Self::{variant_name}(i) => i.visit(v),");
112 }
113 f.indent_pop();
114 fmtln!(f, "}}");
115 });
116 fmtln!(f, "}}");
117 });
118 fmtln!(f, "}}");
119}
120
121fn generate_inst_is_available_impl(f: &mut Formatter, insts: &[dsl::Inst]) {
123 f.add_block("impl<R: Registers> Inst<R>", |f| {
124 f.add_block(
125 "pub fn is_available(&self, f: &impl AvailableFeatures) -> bool",
126 |f| {
127 f.add_block("match self", |f| {
128 for inst in insts {
129 let variant_name = inst.name();
130 fmtln!(f, "Self::{variant_name}(i) => i.is_available(f),");
131 }
132 });
133 },
134 );
135 });
136}
137
138fn generate_inst_features_impl(f: &mut Formatter, insts: &[dsl::Inst]) {
140 f.add_block("impl<R: Registers> Inst<R>", |f| {
141 f.add_block("pub fn features(&self) -> &'static Features", |f| {
142 f.add_block("match self", |f| {
143 for inst in insts {
144 let variant_name = inst.name();
145 fmtln!(f, "Self::{variant_name}(i) => i.features(),");
146 }
147 });
148 });
149 });
150}