cranelift_assembler_x64_meta/generate/
inst.rs1use super::{fmtln, generate_derive, generate_derive_arbitrary_bounds, Formatter};
2use crate::dsl;
3
4impl dsl::Inst {
5 pub fn generate_struct(&self, f: &mut Formatter) {
7 let struct_name = self.struct_name_with_generic();
8 let where_clause = if self.requires_generic() {
9 "where R: Registers"
10 } else {
11 ""
12 };
13
14 fmtln!(f, "/// `{self}`");
15 generate_derive(f);
16 if self.requires_generic() {
17 generate_derive_arbitrary_bounds(f);
18 }
19 f.add_block(&format!("pub struct {struct_name} {where_clause}"), |f| {
20 for k in &self.format.operands {
21 if let Some(ty) = k.generate_type() {
22 let loc = k.location;
23 fmtln!(f, "pub {loc}: {ty},");
24 }
25 }
26 });
27 }
28
29 fn requires_generic(&self) -> bool {
30 self.format.uses_variable_register()
31 }
32
33 pub(crate) fn struct_name_with_generic(&self) -> String {
35 let struct_name = self.name();
36 if self.requires_generic() {
37 format!("{struct_name}<R>")
38 } else {
39 struct_name
40 }
41 }
42
43 fn generate_impl_block_start(&self) -> &str {
45 if self.requires_generic() {
46 "impl<R: Registers>"
47 } else {
48 "impl"
49 }
50 }
51
52 pub fn generate_struct_impl(&self, f: &mut Formatter) {
54 let impl_block = self.generate_impl_block_start();
55 let struct_name = self.struct_name_with_generic();
56 f.add_block(&format!("{impl_block} {struct_name}"), |f| {
57 self.generate_new_function(f);
58 f.empty_line();
59 self.generate_encode_function(f);
60 f.empty_line();
61 self.generate_visit_function(f);
62 f.empty_line();
63 self.generate_features_function(f);
64 });
65 }
66
67 pub fn generate_new_function(&self, f: &mut Formatter) {
69 let params = comma_join(
70 self.format
71 .operands
72 .iter()
73 .filter_map(|o| o.generate_type().map(|t| format!("{}: {}", o.location, t))),
74 );
75 let args = comma_join(
76 self.format
77 .operands
78 .iter()
79 .filter(|o| !matches!(o.location.kind(), dsl::OperandKind::FixedReg(_)))
80 .map(|o| o.location.to_string()),
81 );
82
83 fmtln!(f, "#[must_use]");
84 f.add_block(&format!("pub fn new({params}) -> Self"), |f| {
85 fmtln!(f, "Self {{ {args} }}",);
86 });
87 }
88
89 fn generate_encode_function(&self, f: &mut Formatter) {
91 let off = if self.format.uses_memory().is_some() {
92 "off"
93 } else {
94 "_"
95 };
96 f.add_block(
97 &format!("pub fn encode(&self, buf: &mut impl CodeSink, {off}: &impl KnownOffsetTable)"),
98 |f| {
99 if let Some(op) = self.format.uses_memory() {
101 f.empty_line();
102 f.comment("Emit trap.");
103 match op {
104 crate::dsl::Location::rm128 => {
105 fmtln!(f, "if let XmmMem::Mem({op}) = &self.{op} {{");
106 }
107 _ => {
108 fmtln!(f, "if let GprMem::Mem({op}) = &self.{op} {{");
109 }
110 }
111 f.indent(|f| {
112 f.add_block(&format!("if let Some(trap_code) = {op}.trap_code()"), |f| {
113 fmtln!(f, "buf.add_trap(trap_code);");
114 });
115 });
116 fmtln!(f, "}}");
117 }
118
119 match &self.encoding {
120 dsl::Encoding::Rex(rex) => self.format.generate_rex_encoding(f, rex),
121 dsl::Encoding::Vex(_) => todo!(),
122 }
123 },
124 );
125 }
126
127 fn generate_visit_function(&self, f: &mut Formatter) {
129 use dsl::OperandKind::*;
130 let extra_generic_bound = if self.requires_generic() {
131 ""
132 } else {
133 "<R: Registers>"
134 };
135 f.add_block(&format!("pub fn visit{extra_generic_bound}(&mut self, visitor: &mut impl RegisterVisitor<R>)"), |f| {
136 for o in &self.format.operands {
137 match o.location.kind() {
138 Imm(_) => {
139 }
141 FixedReg(_) => {
142 let call = o.mutability.generate_regalloc_call();
143 let ty = o.mutability.generate_type();
144 let Some(fixed) = o.location.generate_fixed_reg() else {
145 unreachable!()
146 };
147 fmtln!(f, "visitor.fixed_{call}(&R::{ty}Gpr::new({fixed}));");
148 }
149 Reg(reg) => {
150 match reg.bits() {
151 128 => {
152 let call = o.mutability.generate_xmm_regalloc_call();
153 fmtln!(f, "visitor.{call}(self.{reg}.as_mut());");
154 }
155 _ => {
156 let call = o.mutability.generate_regalloc_call();
157 fmtln!(f, "visitor.{call}(self.{reg}.as_mut());");
158 }
159 };
160 }
161 RegMem(rm) => {
162 match rm.bits() {
163 128 => {
164 let call = o.mutability.generate_xmm_regalloc_call();
165 f.add_block(&format!("match &mut self.{rm}"), |f| {
166 fmtln!(f, "XmmMem::Xmm(r) => visitor.{call}(r),");
167 fmtln!(
168 f,
169 "XmmMem::Mem(m) => m.registers_mut().iter_mut().for_each(|r| visitor.read(r)),"
170 );
171 });
172 }
173 _ => {
174 let call = o.mutability.generate_regalloc_call();
175 f.add_block(&format!("match &mut self.{rm}"), |f| {
176 fmtln!(f, "GprMem::Gpr(r) => visitor.{call}(r),");
177 fmtln!(
178 f,
179 "GprMem::Mem(m) => m.registers_mut().iter_mut().for_each(|r| visitor.read(r)),"
180 );
181 });
182 }
183 };
184 }
185 }
186 }
187 });
188 }
189
190 fn generate_features_function(&self, f: &mut Formatter) {
192 fmtln!(f, "#[must_use]");
193 f.add_block("pub fn features(&self) -> Vec<Feature>", |f| {
194 let flags = self
195 .features
196 .iter()
197 .map(|f| format!("Feature::{f}"))
198 .collect::<Vec<_>>();
199 fmtln!(f, "vec![{}]", flags.join(", "));
200 });
201 }
202
203 pub fn generate_display_impl(&self, f: &mut Formatter) {
205 let impl_block = self.generate_impl_block_start();
206 let struct_name = self.struct_name_with_generic();
207 f.add_block(&format!("{impl_block} std::fmt::Display for {struct_name}"), |f| {
208 f.add_block("fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result", |f| {
209 for op in &self.format.operands {
210 let location = op.location;
211 let to_string = location.generate_to_string(op.extension);
212 fmtln!(f, "let {location} = {to_string};");
213 }
214 let inst_name = &self.mnemonic;
215 let ordered_ops = self.format.generate_att_style_operands();
216 fmtln!(f, "write!(f, \"{inst_name} {ordered_ops}\")");
217 });
218 });
219 }
220
221 pub fn generate_from_impl(&self, f: &mut Formatter) {
223 let struct_name_r = self.struct_name_with_generic();
224 let variant_name = self.name();
225 f.add_block(&format!("impl<R: Registers> From<{struct_name_r}> for Inst<R>"), |f| {
226 f.add_block(&format!("fn from(inst: {struct_name_r}) -> Self"), |f| {
227 fmtln!(f, "Self::{variant_name}(inst)");
228 });
229 });
230 }
231}
232
233fn comma_join<I: Into<String>>(items: impl Iterator<Item = I>) -> String {
234 items.map(Into::into).collect::<Vec<_>>().join(", ")
235}