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 let loc = k.location;
22 let ty = k.generate_type();
23 fmtln!(f, "pub {loc}: {ty},");
24 }
25 });
26 }
27
28 fn requires_generic(&self) -> bool {
29 self.format.uses_register()
30 }
31
32 pub(crate) fn struct_name_with_generic(&self) -> String {
34 let struct_name = self.name();
35 if self.requires_generic() {
36 format!("{struct_name}<R>")
37 } else {
38 struct_name
39 }
40 }
41
42 fn generate_impl_block_start(&self) -> &str {
44 if self.requires_generic() {
45 "impl<R: Registers>"
46 } else {
47 "impl"
48 }
49 }
50
51 pub fn generate_struct_impl(&self, f: &mut Formatter) {
53 let impl_block = self.generate_impl_block_start();
54 let struct_name = self.struct_name_with_generic();
55 f.add_block(&format!("{impl_block} {struct_name}"), |f| {
56 self.generate_new_function(f);
57 f.empty_line();
58 self.generate_encode_function(f);
59 f.empty_line();
60 self.generate_visit_function(f);
61 f.empty_line();
62 self.generate_features_function(f);
63 });
64 }
65
66 pub fn generate_new_function(&self, f: &mut Formatter) {
68 let params = comma_join(
69 self.format
70 .operands
71 .iter()
72 .map(|o| format!("{}: impl Into<{}>", o.location, o.generate_type())),
73 );
74 fmtln!(f, "#[must_use]");
75 f.add_block(&format!("pub fn new({params}) -> Self"), |f| {
76 f.add_block("Self", |f| {
77 for o in &self.format.operands {
78 let loc = o.location;
79 fmtln!(f, "{loc}: {loc}.into(),");
80 }
81 });
82 });
83 }
84
85 fn generate_encode_function(&self, f: &mut Formatter) {
87 let off = if self.format.uses_memory().is_some() {
88 "off"
89 } else {
90 "_"
91 };
92 f.add_block(
93 &format!(
94 "pub fn encode(&self, buf: &mut impl CodeSink, {off}: &impl KnownOffsetTable)"
95 ),
96 |f| {
97 if let Some(op) = self.format.uses_memory() {
99 use dsl::OperandKind::*;
100 f.comment("Emit trap.");
101 match op.kind() {
102 Mem(_) => {
103 f.add_block(
104 &format!("if let Some(trap_code) = self.{op}.trap_code()"),
105 |f| {
106 fmtln!(f, "buf.add_trap(trap_code);");
107 },
108 );
109 }
110 RegMem(_) => {
111 let ty = op.reg_class().unwrap();
112 f.add_block(&format!("if let {ty}Mem::Mem({op}) = &self.{op}"), |f| {
113 f.add_block(
114 &format!("if let Some(trap_code) = {op}.trap_code()"),
115 |f| {
116 fmtln!(f, "buf.add_trap(trap_code);");
117 },
118 );
119 });
120 }
121 _ => unreachable!(),
122 }
123 }
124
125 match &self.encoding {
126 dsl::Encoding::Rex(rex) => self.format.generate_rex_encoding(f, rex),
127 dsl::Encoding::Vex(_) => todo!(),
128 }
129 },
130 );
131 }
132
133 fn generate_visit_function(&self, f: &mut Formatter) {
135 use dsl::OperandKind::*;
136 let extra_generic_bound = if self.requires_generic() {
137 ""
138 } else {
139 "<R: Registers>"
140 };
141 f.add_block(&format!("pub fn visit{extra_generic_bound}(&mut self, visitor: &mut impl RegisterVisitor<R>)"), |f| {
142 for o in &self.format.operands {
143 let mutability = o.mutability.generate_snake_case();
144 let reg = o.location.reg_class();
145 match o.location.kind() {
146 Imm(_) => {
147 }
149 FixedReg(loc) => {
150 let reg_lower = reg.unwrap().to_string().to_lowercase();
151 fmtln!(f, "let enc = self.{loc}.expected_enc();");
152 fmtln!(f, "visitor.fixed_{mutability}_{reg_lower}(&mut self.{loc}.0, enc);");
153 }
154 Reg(loc) => {
155 let reg_lower = reg.unwrap().to_string().to_lowercase();
156 fmtln!(f, "visitor.{mutability}_{reg_lower}(self.{loc}.as_mut());");
157 }
158 RegMem(loc) => {
159 let reg = reg.unwrap();
160 let reg_lower = reg.to_string().to_lowercase();
161 f.add_block(&format!("match &mut self.{loc}"), |f| {
162 fmtln!(f, "{reg}Mem::{reg}(r) => visitor.{mutability}_{reg_lower}(r),");
163 fmtln!(f, "{reg}Mem::Mem(m) => visit_amode(m, visitor),");
164 });
165 }
166 Mem(loc) => {
167 fmtln!(f, "visit_amode(&mut self.{loc}, visitor);");
168 }
169 }
170 }
171 });
172 }
173
174 fn generate_features_function(&self, f: &mut Formatter) {
176 fmtln!(f, "#[must_use]");
177 f.add_block("pub fn features(&self) -> Vec<Feature>", |f| {
178 let flags = self
179 .features
180 .iter()
181 .map(|f| format!("Feature::{f}"))
182 .collect::<Vec<_>>();
183 fmtln!(f, "vec![{}]", flags.join(", "));
184 });
185 }
186
187 pub fn generate_display_impl(&self, f: &mut Formatter) {
189 let impl_block = self.generate_impl_block_start();
190 let struct_name = self.struct_name_with_generic();
191 f.add_block(
192 &format!("{impl_block} std::fmt::Display for {struct_name}"),
193 |f| {
194 f.add_block(
195 "fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result",
196 |f| {
197 for op in &self.format.operands {
198 let location = op.location;
199 let to_string = location.generate_to_string(op.extension);
200 fmtln!(f, "let {location} = {to_string};");
201 }
202 let inst_name = if self.mnemonic.starts_with("lock_") {
205 &format!("lock {}", &self.mnemonic[5..])
206 } else {
207 &self.mnemonic
208 };
209 let ordered_ops = self.format.generate_att_style_operands();
210 fmtln!(f, "write!(f, \"{inst_name} {ordered_ops}\")");
211 },
212 );
213 },
214 );
215 }
216
217 pub fn generate_from_impl(&self, f: &mut Formatter) {
219 let struct_name_r = self.struct_name_with_generic();
220 let variant_name = self.name();
221 f.add_block(
222 &format!("impl<R: Registers> From<{struct_name_r}> for Inst<R>"),
223 |f| {
224 f.add_block(&format!("fn from(inst: {struct_name_r}) -> Self"), |f| {
225 fmtln!(f, "Self::{variant_name}(inst)");
226 });
227 },
228 );
229 }
230}
231
232fn comma_join<S: Into<String>>(items: impl Iterator<Item = S>) -> String {
233 items.map(Into::into).collect::<Vec<_>>().join(", ")
234}