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