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 let off = if self.format.uses_memory().is_some() || self.custom.contains(Encode) {
122 "off"
123 } else {
124 "_"
125 };
126 f.add_block(
127 &format!(
128 "pub fn encode(&self, buf: &mut impl CodeSink, {off}: &impl KnownOffsetTable)"
129 ),
130 |f| {
131 if self.custom.contains(Encode) {
132 fmtln!(f, "crate::custom::encode::{}(self, buf, off);", self.name());
133 } else {
134 self.generate_possible_trap(f);
135 match &self.encoding {
136 dsl::Encoding::Rex(rex) => self.format.generate_rex_encoding(f, rex),
137 dsl::Encoding::Vex(vex) => self.format.generate_vex_encoding(f, vex),
138 }
139 }
140 },
141 );
142 }
143
144 fn generate_possible_trap(&self, f: &mut Formatter) {
146 if self.has_trap {
147 f.comment("Emit trap.");
148 fmtln!(f, "buf.add_trap(self.trap);");
149 } else if let Some(op) = self.format.uses_memory() {
150 use dsl::OperandKind::*;
151 f.comment("Emit trap.");
152 match op.kind() {
153 Mem(_) => {
154 f.add_block(
155 &format!("if let Some(trap_code) = self.{op}.trap_code()"),
156 |f| {
157 fmtln!(f, "buf.add_trap(trap_code);");
158 },
159 );
160 }
161 RegMem(_) => {
162 let ty = op.reg_class().unwrap();
163 f.add_block(&format!("if let {ty}Mem::Mem({op}) = &self.{op}"), |f| {
164 f.add_block(&format!("if let Some(trap_code) = {op}.trap_code()"), |f| {
165 fmtln!(f, "buf.add_trap(trap_code);");
166 });
167 });
168 }
169 _ => unreachable!(),
170 }
171 }
172 }
173
174 fn generate_visit_function(&self, f: &mut Formatter) {
176 use dsl::{Customization::*, OperandKind::*};
177 let extra_generic_bound = if self.requires_generic() {
178 ""
179 } else {
180 "<R: Registers>"
181 };
182 let visitor = if self.format.operands.is_empty() && !self.custom.contains(Visit) {
183 "_"
184 } else {
185 "visitor"
186 };
187 f.add_block(&format!("pub fn visit{extra_generic_bound}(&mut self, {visitor}: &mut impl RegisterVisitor<R>)"), |f| {
188 if self.custom.contains(Visit) {
189 fmtln!(f, "crate::custom::visit::{}(self, visitor)", self.name());
190 return;
191 }
192 for o in &self.format.operands {
193 let mutability = o.mutability.generate_snake_case();
194 let reg = o.location.reg_class();
195 match o.location.kind() {
196 Imm(_) => {
197 fmtln!(f, "let _ = visitor;");
203 }
204 FixedReg(loc) => {
205 let reg_lower = reg.unwrap().to_string().to_lowercase();
206 fmtln!(f, "let enc = self.{loc}.expected_enc();");
207 fmtln!(f, "visitor.fixed_{mutability}_{reg_lower}(&mut self.{loc}.0, enc);");
208 }
209 Reg(loc) => {
210 let reg_lower = reg.unwrap().to_string().to_lowercase();
211 fmtln!(f, "visitor.{mutability}_{reg_lower}(self.{loc}.as_mut());");
212 }
213 RegMem(loc) => {
214 let reg = reg.unwrap();
215 let reg_lower = reg.to_string().to_lowercase();
216 fmtln!(f, "visitor.{mutability}_{reg_lower}_mem(&mut self.{loc});");
217 }
218 Mem(loc) => {
219 fmtln!(f, "visitor.read_amode(&mut self.{loc});");
224 }
225
226 }
227 }
228 });
229 }
230
231 fn generate_features_function(&self, f: &mut Formatter) {
233 fmtln!(f, "#[must_use]");
234 f.add_block("pub fn features(&self) -> Vec<Feature>", |f| {
235 let flags = self
236 .features
237 .iter()
238 .map(|f| format!("Feature::{f}"))
239 .collect::<Vec<_>>();
240 fmtln!(f, "vec![{}]", flags.join(", "));
241 });
242 }
243
244 pub fn generate_display_impl(&self, f: &mut Formatter) {
246 use crate::dsl::Customization::*;
247 let impl_block = self.generate_impl_block_start();
248 let struct_name = self.struct_name_with_generic();
249 f.add_block(
250 &format!("{impl_block} std::fmt::Display for {struct_name}"),
251 |f| {
252 f.add_block(
253 "fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result",
254 |f| {
255 if self.custom.contains(Display) {
256 fmtln!(f, "crate::custom::display::{}(f, self)", self.name());
257 return;
258 }
259
260 fmtln!(f, "let name = self.mnemonic();");
261 if self.format.operands.is_empty() {
262 fmtln!(f, "f.write_str(&name)");
263 return;
264 }
265 for op in self.format.operands.iter() {
266 let location = op.location;
267 let to_string = location.generate_to_string(op.extension);
268 fmtln!(f, "let {location} = {to_string};");
269 }
270 let ordered_ops = self.format.generate_att_style_operands();
271 let mut implicit_ops = self.format.generate_implicit_operands();
272 if self.has_trap {
273 fmtln!(f, "let trap = self.trap;");
274 if implicit_ops.is_empty() {
275 implicit_ops.push_str(" ;; {trap}");
276 } else {
277 implicit_ops.push_str(", {trap}");
278 }
279 }
280 fmtln!(f, "write!(f, \"{{name}} {ordered_ops}{implicit_ops}\")");
281 },
282 );
283 },
284 );
285 }
286 pub fn generate_from_impl(&self, f: &mut Formatter) {
288 let struct_name_r = self.struct_name_with_generic();
289 let variant_name = self.name();
290 f.add_block(
291 &format!("impl<R: Registers> From<{struct_name_r}> for Inst<R>"),
292 |f| {
293 f.add_block(&format!("fn from(inst: {struct_name_r}) -> Self"), |f| {
294 fmtln!(f, "Self::{variant_name}(inst)");
295 });
296 },
297 );
298 }
299}
300
301fn comma_join<S: Into<String>>(items: impl Iterator<Item = S>) -> String {
302 items.map(Into::into).collect::<Vec<_>>().join(", ")
303}