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 });
72 }
73
74 pub fn generate_new_function(&self, f: &mut Formatter) {
76 let params = comma_join(
77 self.format
78 .operands
79 .iter()
80 .map(|o| format!("{}: impl Into<{}>", o.location, o.generate_type()))
81 .chain(if self.has_trap {
82 Some("trap: impl Into<TrapCode>".to_string())
83 } else {
84 None
85 }),
86 );
87 fmtln!(f, "#[must_use]");
88 f.add_block(&format!("pub fn new({params}) -> Self"), |f| {
89 f.add_block("Self", |f| {
90 for o in &self.format.operands {
91 let loc = o.location;
92 fmtln!(f, "{loc}: {loc}.into(),");
93 }
94 if self.has_trap {
95 fmtln!(f, "trap: trap.into(),");
96 }
97 });
98 });
99 }
100
101 pub fn generate_mnemonic_function(&self, f: &mut Formatter) {
103 use dsl::Customization::*;
104
105 fmtln!(f, "#[must_use]");
106 fmtln!(f, "#[inline]");
107 f.add_block(
108 &format!("pub fn mnemonic(&self) -> std::borrow::Cow<'static, str>"),
109 |f| {
110 if self.custom.contains(Mnemonic) {
111 fmtln!(f, "crate::custom::mnemonic::{}(self)", self.name());
112 } else {
113 fmtln!(f, "std::borrow::Cow::Borrowed(\"{}\")", self.mnemonic);
114 }
115 },
116 );
117 }
118
119 fn generate_encode_function(&self, f: &mut Formatter) {
121 use dsl::Customization::*;
122
123 f.add_block(
124 &format!("pub fn encode(&self, buf: &mut impl CodeSink)"),
125 |f| {
126 if self.custom.contains(Encode) {
127 fmtln!(f, "crate::custom::encode::{}(self, buf);", self.name());
128 } else {
129 self.generate_possible_trap(f);
130 match &self.encoding {
131 dsl::Encoding::Rex(rex) => self.format.generate_rex_encoding(f, rex),
132 dsl::Encoding::Vex(vex) => self.format.generate_vex_encoding(f, vex),
133 dsl::Encoding::Evex(evex) => self.format.generate_evex_encoding(f, evex),
134 }
135 }
136 },
137 );
138 }
139
140 fn generate_possible_trap(&self, f: &mut Formatter) {
142 if self.has_trap {
143 f.comment("Emit trap.");
144 fmtln!(f, "buf.add_trap(self.trap);");
145 } else if let Some(op) = self.format.uses_memory() {
146 use dsl::OperandKind::*;
147 f.comment("Emit trap.");
148 match op.kind() {
149 Mem(_) => {
150 f.add_block(
151 &format!("if let Some(trap_code) = self.{op}.trap_code()"),
152 |f| {
153 fmtln!(f, "buf.add_trap(trap_code);");
154 },
155 );
156 }
157 RegMem(_) => {
158 let ty = op.reg_class().unwrap();
159 f.add_block(&format!("if let {ty}Mem::Mem({op}) = &self.{op}"), |f| {
160 f.add_block(&format!("if let Some(trap_code) = {op}.trap_code()"), |f| {
161 fmtln!(f, "buf.add_trap(trap_code);");
162 });
163 });
164 }
165 _ => unreachable!(),
166 }
167 }
168 }
169
170 fn generate_visit_function(&self, f: &mut Formatter) {
172 use dsl::{Customization::*, OperandKind::*};
173 let extra_generic_bound = if self.requires_generic() {
174 ""
175 } else {
176 "<R: Registers>"
177 };
178 let visitor = if self.format.operands.is_empty() && !self.custom.contains(Visit) {
179 "_"
180 } else {
181 "visitor"
182 };
183 f.add_block(&format!("pub fn visit{extra_generic_bound}(&mut self, {visitor}: &mut impl RegisterVisitor<R>)"), |f| {
184 if self.custom.contains(Visit) {
185 fmtln!(f, "crate::custom::visit::{}(self, visitor)", self.name());
186 return;
187 }
188 for o in &self.format.operands {
189 let mutability = o.mutability.generate_snake_case();
190 let reg = o.location.reg_class();
191 match o.location.kind() {
192 Imm(_) => {
193 fmtln!(f, "let _ = visitor;");
199 }
200 FixedReg(loc) => {
201 let reg_lower = reg.unwrap().to_string().to_lowercase();
202 fmtln!(f, "let enc = self.{loc}.expected_enc();");
203 fmtln!(f, "visitor.fixed_{mutability}_{reg_lower}(&mut self.{loc}.0, enc);");
204 }
205 Reg(loc) => {
206 let reg_lower = reg.unwrap().to_string().to_lowercase();
207 fmtln!(f, "visitor.{mutability}_{reg_lower}(self.{loc}.as_mut());");
208 }
209 RegMem(loc) => {
210 let reg = reg.unwrap();
211 let reg_lower = reg.to_string().to_lowercase();
212 fmtln!(f, "visitor.{mutability}_{reg_lower}_mem(&mut self.{loc});");
213 }
214 Mem(loc) => {
215 fmtln!(f, "visitor.read_amode(&mut self.{loc});");
220 }
221
222 }
223 }
224 });
225 }
226
227 fn generate_is_available_function(&self, f: &mut Formatter) {
229 fmtln!(f, "#[must_use]");
230 f.add_block(
231 "pub fn is_available(&self, features: &impl AvailableFeatures) -> bool",
232 |f| {
233 let expr = self.features.generate_boolean_expr("features");
234 fmtln!(f, "{expr}");
235 },
236 );
237 }
238
239 fn generate_features_function(&self, f: &mut Formatter) {
241 fmtln!(f, "#[must_use]");
242 f.add_block("pub fn features(&self) -> &'static Features", |f| {
243 self.features.generate_constructor_expr(f);
244 });
245 }
246
247 pub fn generate_display_impl(&self, f: &mut Formatter) {
249 use crate::dsl::Customization::*;
250 let impl_block = self.generate_impl_block_start();
251 let struct_name = self.struct_name_with_generic();
252 f.add_block(
253 &format!("{impl_block} std::fmt::Display for {struct_name}"),
254 |f| {
255 f.add_block(
256 "fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result",
257 |f| {
258 if self.custom.contains(Display) {
259 fmtln!(f, "crate::custom::display::{}(f, self)", self.name());
260 return;
261 }
262
263 fmtln!(f, "let name = self.mnemonic();");
264 if self.format.operands.is_empty() {
265 fmtln!(f, "f.write_str(&name)");
266 return;
267 }
268 for op in self.format.operands.iter() {
269 let location = op.location;
270 let to_string = location.generate_to_string(op.extension);
271 fmtln!(f, "let {location} = {to_string};");
272 }
273 let ordered_ops = self.format.generate_att_style_operands();
274 let mut implicit_ops = self.format.generate_implicit_operands();
275 if self.has_trap {
276 fmtln!(f, "let trap = self.trap;");
277 if implicit_ops.is_empty() {
278 implicit_ops.push_str(" ;; {trap}");
279 } else {
280 implicit_ops.push_str(", {trap}");
281 }
282 }
283 fmtln!(f, "write!(f, \"{{name}} {ordered_ops}{implicit_ops}\")");
284 },
285 );
286 },
287 );
288 }
289
290 pub fn generate_from_impl(&self, f: &mut Formatter) {
292 let struct_name_r = self.struct_name_with_generic();
293 let variant_name = self.name();
294 f.add_block(
295 &format!("impl<R: Registers> From<{struct_name_r}> for Inst<R>"),
296 |f| {
297 f.add_block(&format!("fn from(inst: {struct_name_r}) -> Self"), |f| {
298 fmtln!(f, "Self::{variant_name}(inst)");
299 });
300 },
301 );
302 }
303}
304
305fn comma_join<S: Into<String>>(items: impl Iterator<Item = S>) -> String {
306 items.map(Into::into).collect::<Vec<_>>().join(", ")
307}