cranelift_assembler_x64_meta/generate/
inst.rs1use super::{Formatter, fmtln, generate_derive, generate_derive_arbitrary_bounds};
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 let loc = k.location;
22 let ty = k.generate_type();
23 fmtln!(f, "pub {loc}: {ty},");
24 }
25
26 if self.has_trap {
27 fmtln!(f, "pub trap: TrapCode,");
28 }
29 });
30 }
31
32 fn requires_generic(&self) -> bool {
33 self.format.uses_register()
34 }
35
36 pub(crate) fn struct_name_with_generic(&self) -> String {
38 let struct_name = self.name();
39 if self.requires_generic() {
40 format!("{struct_name}<R>")
41 } else {
42 struct_name
43 }
44 }
45
46 fn generate_impl_block_start(&self) -> &str {
48 if self.requires_generic() {
49 "impl<R: Registers>"
50 } else {
51 "impl"
52 }
53 }
54
55 pub fn generate_struct_impl(&self, f: &mut Formatter) {
57 let impl_block = self.generate_impl_block_start();
58 let struct_name = self.struct_name_with_generic();
59 f.add_block(&format!("{impl_block} {struct_name}"), |f| {
60 self.generate_new_function(f);
61 f.empty_line();
62 self.generate_mnemonic_function(f);
63 f.empty_line();
64 self.generate_encode_function(f);
65 f.empty_line();
66 self.generate_visit_function(f);
67 f.empty_line();
68 self.generate_is_available_function(f);
69 f.empty_line();
70 self.generate_features_function(f);
71 f.empty_line();
72 self.generate_num_registers_function(f);
73 });
74 }
75
76 pub fn generate_new_function(&self, f: &mut Formatter) {
78 let params = comma_join(
79 self.format
80 .operands
81 .iter()
82 .map(|o| format!("{}: impl Into<{}>", o.location, o.generate_type()))
83 .chain(if self.has_trap {
84 Some("trap: impl Into<TrapCode>".to_string())
85 } else {
86 None
87 }),
88 );
89 fmtln!(f, "#[must_use]");
90 f.add_block(&format!("pub fn new({params}) -> Self"), |f| {
91 f.add_block("Self", |f| {
92 for o in &self.format.operands {
93 let loc = o.location;
94 fmtln!(f, "{loc}: {loc}.into(),");
95 }
96 if self.has_trap {
97 fmtln!(f, "trap: trap.into(),");
98 }
99 });
100 });
101 }
102
103 pub fn generate_mnemonic_function(&self, f: &mut Formatter) {
105 use dsl::Customization::*;
106
107 fmtln!(f, "#[must_use]");
108 fmtln!(f, "#[inline]");
109 f.add_block(
110 &format!("pub fn mnemonic(&self) -> std::borrow::Cow<'static, str>"),
111 |f| {
112 if self.custom.contains(Mnemonic) {
113 fmtln!(f, "crate::custom::mnemonic::{}(self)", self.name());
114 } else {
115 fmtln!(f, "std::borrow::Cow::Borrowed(\"{}\")", self.mnemonic);
116 }
117 },
118 );
119 }
120
121 fn generate_encode_function(&self, f: &mut Formatter) {
123 use dsl::Customization::*;
124
125 f.add_block(
126 &format!("pub fn encode(&self, buf: &mut impl CodeSink)"),
127 |f| {
128 if self.custom.contains(Encode) {
129 fmtln!(f, "crate::custom::encode::{}(self, buf);", self.name());
130 } else {
131 self.generate_possible_trap(f);
132 match &self.encoding {
133 dsl::Encoding::Rex(rex) => self.format.generate_rex_encoding(f, rex),
134 dsl::Encoding::Vex(vex) => self.format.generate_vex_encoding(f, vex),
135 dsl::Encoding::Evex(evex) => self.format.generate_evex_encoding(f, evex),
136 }
137 }
138 },
139 );
140 }
141
142 fn generate_possible_trap(&self, f: &mut Formatter) {
144 if self.has_trap {
145 f.comment("Emit trap.");
146 fmtln!(f, "buf.add_trap(self.trap);");
147 } else if let Some(op) = self.format.uses_memory() {
148 use dsl::OperandKind::*;
149 f.comment("Emit trap.");
150 match op.kind() {
151 Mem(_) => {
152 f.add_block(
153 &format!("if let Some(trap_code) = self.{op}.trap_code()"),
154 |f| {
155 fmtln!(f, "buf.add_trap(trap_code);");
156 },
157 );
158 }
159 RegMem(_) => {
160 let ty = op.reg_class().unwrap();
161 f.add_block(&format!("if let {ty}Mem::Mem({op}) = &self.{op}"), |f| {
162 f.add_block(&format!("if let Some(trap_code) = {op}.trap_code()"), |f| {
163 fmtln!(f, "buf.add_trap(trap_code);");
164 });
165 });
166 }
167 _ => unreachable!(),
168 }
169 }
170 }
171
172 fn generate_visit_function(&self, f: &mut Formatter) {
174 use dsl::{Customization::*, OperandKind::*};
175 let extra_generic_bound = if self.requires_generic() {
176 ""
177 } else {
178 "<R: Registers>"
179 };
180 let visitor = if self.format.operands.is_empty() && !self.custom.contains(Visit) {
181 "_"
182 } else {
183 "visitor"
184 };
185 f.add_block(&format!("pub fn visit{extra_generic_bound}(&mut self, {visitor}: &mut impl RegisterVisitor<R>)"), |f| {
186 if self.custom.contains(Visit) {
187 fmtln!(f, "crate::custom::visit::{}(self, visitor)", self.name());
188 return;
189 }
190 for o in &self.format.operands {
191 let mutability = o.mutability.generate_snake_case();
192 let reg = o.location.reg_class();
193 match o.location.kind() {
194 Imm(_) => {
195 fmtln!(f, "let _ = visitor;");
201 }
202 FixedReg(loc) => {
203 let reg_lower = reg.unwrap().to_string().to_lowercase();
204 fmtln!(f, "let enc = self.{loc}.expected_enc();");
205 fmtln!(f, "visitor.fixed_{mutability}_{reg_lower}(&mut self.{loc}.0, enc);");
206 }
207 Reg(loc) => {
208 let reg_lower = reg.unwrap().to_string().to_lowercase();
209 fmtln!(f, "visitor.{mutability}_{reg_lower}(self.{loc}.as_mut());");
210 }
211 RegMem(loc) => {
212 let reg = reg.unwrap();
213 let reg_lower = reg.to_string().to_lowercase();
214 fmtln!(f, "visitor.{mutability}_{reg_lower}_mem(&mut self.{loc});");
215 }
216 Mem(loc) => {
217 fmtln!(f, "visitor.read_amode(&mut self.{loc});");
222 }
223
224 }
225 }
226 });
227 }
228
229 fn generate_is_available_function(&self, f: &mut Formatter) {
231 fmtln!(f, "#[must_use]");
232 f.add_block(
233 "pub fn is_available(&self, features: &impl AvailableFeatures) -> bool",
234 |f| {
235 let expr = self.features.generate_boolean_expr("features");
236 fmtln!(f, "{expr}");
237 },
238 );
239 }
240
241 fn generate_features_function(&self, f: &mut Formatter) {
243 fmtln!(f, "#[must_use]");
244 f.add_block("pub fn features(&self) -> &'static Features", |f| {
245 self.features.generate_constructor_expr(f);
246 });
247 }
248
249 fn generate_num_registers_function(&self, f: &mut Formatter) {
251 fmtln!(f, "#[must_use]");
252 f.add_block("pub fn num_registers_available(&self) -> usize", |f| {
253 use dsl::Encoding::*;
254 let n = match self.encoding {
255 Rex(_) | Vex(_) => 16,
256 Evex(_) => 32,
257 };
258 fmtln!(f, "{n}")
259 });
260 }
261
262 pub fn generate_display_impl(&self, f: &mut Formatter) {
264 use crate::dsl::Customization::*;
265 let impl_block = self.generate_impl_block_start();
266 let struct_name = self.struct_name_with_generic();
267 f.add_block(
268 &format!("{impl_block} std::fmt::Display for {struct_name}"),
269 |f| {
270 f.add_block(
271 "fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result",
272 |f| {
273 if self.custom.contains(Display) {
274 fmtln!(f, "crate::custom::display::{}(f, self)", self.name());
275 return;
276 }
277
278 fmtln!(f, "let name = self.mnemonic();");
279 if self.format.operands.is_empty() {
280 fmtln!(f, "f.write_str(&name)");
281 return;
282 }
283 for op in self.format.operands.iter() {
284 let location = op.location;
285 let to_string = location.generate_to_string(op.extension);
286 fmtln!(f, "let {location} = {to_string};");
287 }
288 let ordered_ops = self.format.generate_att_style_operands();
289 let mut implicit_ops = self.format.generate_implicit_operands();
290 if self.has_trap {
291 fmtln!(f, "let trap = self.trap;");
292 if implicit_ops.is_empty() {
293 implicit_ops.push_str(" ;; {trap}");
294 } else {
295 implicit_ops.push_str(", {trap}");
296 }
297 }
298 fmtln!(f, "write!(f, \"{{name}} {ordered_ops}{implicit_ops}\")");
299 },
300 );
301 },
302 );
303 }
304
305 pub fn generate_from_impl(&self, f: &mut Formatter) {
307 let struct_name_r = self.struct_name_with_generic();
308 let variant_name = self.name();
309 f.add_block(
310 &format!("impl<R: Registers> From<{struct_name_r}> for Inst<R>"),
311 |f| {
312 f.add_block(&format!("fn from(inst: {struct_name_r}) -> Self"), |f| {
313 fmtln!(f, "Self::{variant_name}(inst)");
314 });
315 },
316 );
317 }
318}
319
320fn comma_join<S: Into<String>>(items: impl Iterator<Item = S>) -> String {
321 items.map(Into::into).collect::<Vec<_>>().join(", ")
322}