1use std::{
4 cmp,
5 collections::{HashMap, HashSet},
6 fmt,
7 hash::Hash,
8 io::{self, Write},
9 ops::Deref,
10 rc::Rc,
11};
12
13use crate::{
14 DecodeTree, Field, FieldDef, FieldItem, Group, Insn, Item, Overlap, OverlapItem, Pattern,
15 SetValue, SetValueKind, Str, ValueKind,
16};
17
18type FieldUsageInfo<S = Str> = HashMap<S, (usize, Rc<FieldDef<S>>)>;
19
20trait FieldUsage<S = Str> {
21 fn field_usage(&self, output: &mut FieldUsageInfo<S>) -> usize;
25}
26
27impl<S> FieldUsage<S> for Rc<FieldDef<S>>
28where
29 S: Clone + Eq + Hash,
30{
31 fn field_usage(&self, output: &mut FieldUsageInfo<S>) -> usize {
32 for item in self.items() {
33 if let FieldItem::FieldRef(field_ref) = item {
34 field_ref.field.field_usage(output);
35 }
36 }
37
38 match output.get_mut(&self.name) {
39 Some(entry) => {
40 entry.0 += 1;
41 }
42 None => {
43 output.insert(self.name.clone(), (1, self.clone()));
44 }
45 }
46
47 0
48 }
49}
50
51impl<S> FieldUsage<S> for Field<S>
52where
53 S: Clone + Eq + Hash,
54{
55 fn field_usage(&self, output: &mut FieldUsageInfo<S>) -> usize {
56 if let Self::FieldRef(def) = self {
57 for item in def.items() {
58 if let FieldItem::FieldRef(field_ref) = item {
59 field_ref.field.field_usage(output);
60 }
61 }
62
63 match output.get_mut(&def.name) {
64 Some(entry) => {
65 entry.0 += 1;
66 }
67 None => {
68 output.insert(def.name.clone(), (1, def.clone()));
69 }
70 }
71 }
72
73 0
74 }
75}
76
77impl<I, S> FieldUsage<S> for Pattern<I, S>
78where
79 S: Clone + Eq + Hash,
80{
81 fn field_usage(&self, output: &mut FieldUsageInfo<S>) -> usize {
82 for i in &self.args {
83 match i.kind() {
84 ValueKind::Set(_, values) => {
85 for i in values {
86 if let SetValueKind::Field(field) = i.kind() {
87 field.field_usage(output);
88 }
89 }
90 }
91 ValueKind::Field(field) => {
92 field.field_usage(output);
93 }
94 _ => {}
95 }
96 }
97 1
98 }
99}
100
101impl<I, S> FieldUsage<S> for Overlap<I, S>
102where
103 S: Clone + Eq + Hash,
104{
105 fn field_usage(&self, output: &mut HashMap<S, (usize, Rc<FieldDef<S>>)>) -> usize {
106 let mut count = 0;
107 for item in &self.items {
108 count += match item {
109 OverlapItem::Pattern(i) => i.field_usage(output),
110 OverlapItem::Group(i) => i.field_usage(output),
111 };
112 }
113 count
114 }
115}
116
117impl<I, S> FieldUsage<S> for Group<I, S>
118where
119 S: Clone + Eq + Hash,
120{
121 fn field_usage(&self, output: &mut FieldUsageInfo<S>) -> usize {
122 let mut count = 0;
123 for item in &self.items {
124 count += match item {
125 Item::Pattern(i) => i.field_usage(output),
126 Item::Overlap(i) => i.field_usage(output),
127 Item::Group(i) => i.field_usage(output),
128 };
129 }
130 count
131 }
132}
133
134#[derive(Copy, Clone, Default)]
136pub struct Pad(usize);
137
138impl Pad {
139 pub fn shift(self) -> Self {
141 Self(self.0 + 4)
142 }
143
144 pub fn right(&mut self) -> Self {
146 self.0 += 4;
147 *self
148 }
149
150 pub fn left(&mut self) -> Self {
152 assert!(self.0 >= 4);
153 self.0 -= 4;
154 *self
155 }
156}
157
158impl fmt::Display for Pad {
159 fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
160 if self.0 != 0 {
161 write!(fmt, "{1:0$}", self.0, ' ')
162 } else {
163 Ok(())
164 }
165 }
166}
167
168#[allow(unused_variables)]
170pub trait Gen<T, S = Str> {
171 fn sets_attrs(&self) -> &[&str] {
173 &[]
174 }
175
176 fn trait_attrs(&self) -> &[&str] {
178 &[]
179 }
180
181 fn trait_parents(&self) -> &[&str] {
183 &[]
184 }
185
186 fn trait_body<W: Write>(&mut self, out: &mut W, pad: Pad) -> io::Result<()> {
188 Ok(())
189 }
190
191 fn decode_args(&self) -> &[(&str, &str)] {
193 &[]
194 }
195
196 #[allow(unused_variables)]
198 fn cond_attrs(&self, name: &str) -> &[&str] {
199 &[]
200 }
201
202 #[allow(unused_variables)]
204 fn cond_args(&self, name: &str) -> &[(&str, &str)] {
205 &[]
206 }
207
208 #[allow(unused_variables)]
210 fn trans_proto_check(&self, name: &str) -> bool {
211 true
212 }
213
214 #[allow(unused_variables)]
216 fn trans_call_check(&self, name: &str) -> bool {
217 self.trans_proto_check(name)
218 }
219
220 #[allow(unused_variables)]
222 fn trans_attrs(&self, name: &str) -> &[&str] {
223 &[]
224 }
225
226 #[allow(unused_variables)]
228 fn trans_check_arg(&self, name: &str, arg: &str) -> bool {
229 true
230 }
231
232 #[allow(unused_variables)]
234 fn trans_args(&self, name: &str) -> &[(&str, &str)] {
235 &[]
236 }
237
238 fn trans_body<W: Write>(
240 &mut self,
241 out: &mut W,
242 pad: Pad,
243 pattern: &Pattern<T, S>,
244 ) -> io::Result<bool> {
245 Ok(false)
246 }
247
248 fn trans_success<W: Write>(
250 &mut self,
251 out: &mut W,
252 pad: Pad,
253 pattern: &Pattern<T, S>,
254 ) -> io::Result<()> {
255 Ok(())
256 }
257
258 fn end<W: Write>(&mut self, out: &mut W, pad: Pad, opcodes: &HashSet<&str>) -> io::Result<()> {
260 Ok(())
261 }
262}
263
264impl<T> Gen<T> for () {}
265
266pub struct GeneratorBuilder {
268 trait_name: Str,
269 insn_type: Option<Str>,
270 value_type: Option<Str>,
271 zextract: Str,
272 sextract: Str,
273 stubs: bool,
274 variable_size: bool,
275 error_type: bool,
276 args_by_ref: bool,
277 preload_field_check_size: bool,
278 preload_field_max: u32,
279 preload_field_usage: f64,
280}
281
282impl Default for GeneratorBuilder {
283 fn default() -> Self {
284 Self {
285 trait_name: Str::from("Decode"),
286 insn_type: None,
287 value_type: None,
288 zextract: Str::from("zextract"),
289 sextract: Str::from("sextract"),
290 stubs: false,
291 variable_size: false,
292 error_type: true,
293 args_by_ref: false,
294 preload_field_check_size: false,
295 preload_field_max: 5,
296 preload_field_usage: 33.0,
297 }
298 }
299}
300
301impl GeneratorBuilder {
302 pub fn trait_name(mut self, name: &str) -> Self {
304 self.trait_name = name.into();
305 self
306 }
307
308 pub fn insn_type(mut self, ty: &str) -> Self {
310 self.insn_type = Some(ty.into());
311 self
312 }
313
314 pub fn value_type(mut self, ty: &str) -> Self {
316 self.value_type = Some(ty.into());
317 self
318 }
319
320 pub fn zextract(mut self, name: &str) -> Self {
322 self.zextract = name.into();
323 self
324 }
325
326 pub fn sextract(mut self, name: &str) -> Self {
328 self.sextract = name.into();
329 self
330 }
331
332 pub fn stubs(mut self, stubs: bool) -> Self {
334 self.stubs = stubs;
335 self
336 }
337
338 pub fn error_type(mut self, error_type: bool) -> Self {
340 self.error_type = error_type;
341 self
342 }
343
344 pub fn variable_size(mut self, variable_size: bool) -> Self {
346 self.variable_size = variable_size;
347 self
348 }
349
350 pub fn args_by_ref(mut self, by_ref: bool) -> Self {
352 self.args_by_ref = by_ref;
353 self
354 }
355
356 pub fn preload_field_check_size(mut self, check_size: bool) -> Self {
358 self.preload_field_check_size = check_size;
359 self
360 }
361
362 pub fn preload_field_max(mut self, count: u32) -> Self {
366 self.preload_field_max = count;
367 self
368 }
369
370 pub fn preload_field_usage(mut self, usage: f64) -> Self {
374 self.preload_field_usage = usage;
375 self
376 }
377
378 pub fn build<T, S, G>(self, tree: &DecodeTree<T, S>, gen: G) -> Generator<T, S, G>
380 where
381 T: Insn,
382 G: Gen<T, S>,
383 {
384 let insn_type = self
385 .insn_type
386 .unwrap_or_else(|| format!("u{}", T::width()).into());
387 let value_type = self
388 .value_type
389 .unwrap_or_else(|| format!("i{}", T::width()).into());
390
391 Generator {
392 trait_name: self.trait_name,
393 insn_type,
394 value_type,
395 zextract: self.zextract,
396 sextract: self.sextract,
397 stubs: self.stubs,
398 variable_size: self.variable_size,
399 error_type: self.error_type,
400 args_by_ref: self.args_by_ref,
401 preload_field_check_size: self.preload_field_check_size,
402 preload_field_max: self.preload_field_max,
403 preload_field_usage: self.preload_field_usage,
404 gen,
405 tree,
406 opcodes: Default::default(),
407 conditions: Default::default(),
408 }
409 }
410}
411
412#[derive(Clone)]
413struct Scope<T, S> {
414 mask: T,
416 size: u32,
418
419 preload_field_check_size: bool,
420 preload_field_max: u32,
421 preload_field_usage: f64,
422 preloaded_fields: HashMap<S, Rc<FieldDef<S>>>,
423}
424
425impl<T, S> Scope<T, S>
426where
427 T: Insn,
428 S: Clone + Eq + Hash + fmt::Display,
429{
430 fn new<G>(generator: &Generator<T, S, G>) -> Self {
431 Self {
432 mask: T::zero(),
433 size: 0,
434 preload_field_check_size: generator.preload_field_check_size,
435 preload_field_max: generator.preload_field_max,
436 preload_field_usage: generator.preload_field_usage,
437 preloaded_fields: Default::default(),
438 }
439 }
440
441 fn child(&self, mask: T, size: u32) -> Self {
442 Self {
443 mask,
444 size,
445 preload_field_check_size: self.preload_field_check_size,
446 preload_field_max: self.preload_field_max,
447 preload_field_usage: self.preload_field_usage,
448 preloaded_fields: self.preloaded_fields.clone(),
449 }
450 }
451
452 fn preload_fields(
453 &mut self,
454 out: &mut impl Write,
455 pad: Pad,
456 item: &dyn FieldUsage<S>,
457 ) -> io::Result<()> {
458 let mut fields = Default::default();
459 let pattern_count = item.field_usage(&mut fields) as f64;
460 let mut fields: Vec<_> = fields.into_values().collect();
461 fields.sort_by(|(a, _), (b, _)| b.cmp(a));
462
463 let mut n = 0;
474 for (count, field) in &fields {
475 let usage = *count as f64 / pattern_count * 100.0;
476 if usage < self.preload_field_usage {
477 break;
478 }
479 let name = field.name();
480 if self.preload_field_check_size && self.size < field.required_size() {
481 continue;
483 }
484 if self.is_preloaded_field(name) {
485 continue;
487 }
488 n += 1;
489 if n > self.preload_field_max {
490 break;
492 }
493 writeln!(out, "{pad}// {count:} uses in {usage:.1}% patterns")?;
494 writeln!(out, "{pad}let {name} = self.extract_{name}(insn);")?;
495 self.preloaded_fields.insert(name.clone(), field.clone());
496 }
497
498 if n != 0 {
499 writeln!(out)?;
500 }
501
502 Ok(())
503 }
504
505 fn is_preloaded_field(&self, name: &S) -> bool {
506 self.preloaded_fields.contains_key(name)
507 }
508}
509
510pub struct Generator<'a, T = super::DefaultInsn, S = Str, G = ()> {
512 trait_name: Str,
513 insn_type: Str,
514 value_type: Str,
515 zextract: Str,
516 sextract: Str,
517 stubs: bool,
518 variable_size: bool,
519 error_type: bool,
520 args_by_ref: bool,
521 preload_field_max: u32,
522 preload_field_usage: f64,
523 preload_field_check_size: bool,
524 gen: G,
525 tree: &'a DecodeTree<T, S>,
526 opcodes: HashSet<&'a str>,
527 conditions: HashSet<&'a str>,
528}
529
530impl Generator<'_> {
531 pub fn builder() -> GeneratorBuilder {
533 GeneratorBuilder::default()
534 }
535}
536
537impl<'a, T, S: 'a, G> Generator<'a, T, S, G>
538where
539 T: Insn,
540 S: Clone + Eq + Hash + fmt::Display + Deref<Target = str>,
541 G: Gen<T, S>,
542{
543 fn gen_comment<W: Write>(&self, out: &mut W, pad: Pad, msg: &str) -> io::Result<()> {
544 let width = 60;
545 writeln!(out, "{pad}///{:/<width$}///", "")?;
546 writeln!(out, "{pad}// {msg:width$} //")?;
547 writeln!(out, "{pad}///{:/<width$}///", "")?;
548 writeln!(out)
549 }
550
551 fn gen_trans_proto_pattern<W: Write>(
552 &mut self,
553 out: &mut W,
554 pad: Pad,
555 pattern: &'a Pattern<T, S>,
556 ) -> io::Result<()> {
557 for i in &pattern.cond {
558 self.conditions.insert(&i.name);
559 }
560
561 if self.opcodes.contains(&*pattern.name) {
562 return Ok(());
563 }
564
565 self.opcodes.insert(&pattern.name);
566
567 if !self.gen.trans_proto_check(pattern.name()) {
568 return Ok(());
569 }
570
571 write!(out, "{pad}fn trans_{}(&mut self", pattern.name())?;
572 for (name, ty) in self.gen.trans_args(pattern.name()) {
573 write!(out, ", {name}: {ty}")?;
574 }
575 for value in pattern
576 .args
577 .iter()
578 .filter(|i| self.gen.trans_check_arg(pattern.name(), i.name().as_ref()))
579 {
580 let name = value.name();
581 write!(out, ", {name}: ")?;
582 match value.kind() {
583 ValueKind::Set(set, _) => write!(out, "args_{set}")?,
584 _ => write!(out, "{}", self.value_type)?,
585 }
586 }
587 write!(out, ") -> Result<bool, Self::Error>")?;
588
589 if self.gen.trans_body(out, pad, pattern)? {
590 writeln!(out)?;
591 return Ok(());
592 }
593
594 if self.stubs {
595 writeln!(out, "{{ todo!(\"trans_{}\") }}", pattern.name)?;
596 } else {
597 writeln!(out, ";")?;
598 }
599
600 Ok(())
601 }
602
603 fn gen_trans_proto_overlap_item<W: Write>(
604 &mut self,
605 out: &mut W,
606 pad: Pad,
607 item: &'a OverlapItem<T, S>,
608 ) -> io::Result<()> {
609 match &item {
610 OverlapItem::Pattern(p) => {
611 self.gen_trans_proto_pattern(out, pad, p)?;
612 }
613 OverlapItem::Group(g) => {
614 self.gen_trans_proto_group(out, pad, g)?;
615 }
616 }
617 Ok(())
618 }
619
620 fn gen_trans_proto_group_item<W: Write>(
621 &mut self,
622 out: &mut W,
623 pad: Pad,
624 item: &'a Item<T, S>,
625 ) -> io::Result<()> {
626 match &item {
627 Item::Pattern(p) => {
628 self.gen_trans_proto_pattern(out, pad, p)?;
629 }
630 Item::Overlap(g) => {
631 for i in &g.items {
632 self.gen_trans_proto_overlap_item(out, pad, i)?;
633 }
634 }
635 Item::Group(g) => {
636 for i in &g.items {
637 self.gen_trans_proto_group_item(out, pad, i)?;
638 }
639 }
640 }
641 Ok(())
642 }
643
644 fn gen_trans_proto_group<W: Write>(
645 &mut self,
646 out: &mut W,
647 pad: Pad,
648 group: &'a Group<T, S>,
649 ) -> io::Result<()> {
650 for i in &group.items {
651 self.gen_trans_proto_group_item(out, pad, i)?;
652 }
653 writeln!(out)
654 }
655
656 fn gen_cond_proto<W: Write>(&mut self, out: &mut W, pad: Pad) -> io::Result<()> {
657 if self.conditions.is_empty() {
658 return Ok(());
659 }
660
661 let mut list: Vec<_> = self.conditions.iter().collect();
662 list.sort();
663
664 self.gen_comment(out, pad, "Conditions")?;
665 for i in &list {
666 for attr in self.gen.cond_attrs(i) {
667 writeln!(out, "{attr}")?;
668 }
669 write!(out, "{pad}fn cond_{i}(&self")?;
670 for (arg, ty) in self.gen.cond_args(i) {
671 write!(out, ", {arg}: {ty}")?;
672 }
673 writeln!(out, ") -> bool;")?;
674 }
675 writeln!(out)
676 }
677
678 fn gen_args<W: Write>(&self, out: &mut W, pad: Pad) -> io::Result<()> {
679 self.gen_comment(out, pad, "Argument sets")?;
680 for args in self.tree.sets.iter().filter(|i| !i.is_extern) {
681 for attr in self.gen.sets_attrs() {
682 writeln!(out, "{attr}")?;
683 }
684 writeln!(out, "{pad}#[allow(non_camel_case_types)]")?;
685 if args.items.is_empty() {
686 writeln!(out, "{pad}pub struct args_{};", args.name)?;
687 } else {
688 writeln!(out, "{pad}pub struct args_{} {{", args.name)?;
689 for i in &args.items {
690 let ty = i.ty.as_deref().unwrap_or(&self.value_type);
691 writeln!(out, "{}pub {}: {ty},", pad.shift(), i.name)?;
692 }
693 writeln!(out, "{pad}}}")?;
694 }
695 writeln!(out)?;
696 }
697 Ok(())
698 }
699
700 fn gen_extern_func_proto<W: Write>(&self, out: &mut W, pad: Pad) -> io::Result<()> {
701 let mut set = HashSet::new();
702 let mut first = true;
703 for i in self.tree.fields.iter().filter_map(|i| i.func.as_deref()) {
704 if !set.contains(i) {
705 if first {
706 self.gen_comment(out, pad, "Extern functions")?;
707 first = false;
708 }
709
710 set.insert(i);
711 let ty = &self.value_type;
712 write!(out, "{pad}fn {i}(&self, value: {ty}) -> {ty}")?;
713 if self.stubs {
714 writeln!(out, " {{ todo!(\"{i}\") }}")?;
715 } else {
716 writeln!(out, ";")?;
717 }
718 }
719 }
720 if !first {
721 writeln!(out)?;
722 }
723 Ok(())
724 }
725
726 fn gen_extract_field_body<W: Write>(
727 &self,
728 out: &mut W,
729 field: &FieldDef<S>,
730 pad: Pad,
731 ) -> io::Result<()> {
732 let ty = &self.value_type;
733 if field.items.len() == 1 {
734 let f = &field.items[0];
735 write!(out, "{pad}")?;
736 if let Some(func) = field.func.as_deref() {
737 write!(out, "self.{func}(")?;
738 }
739 match f {
740 FieldItem::Field(f) => {
741 let (pos, len) = (f.pos(), f.len());
742 let func = if f.sxt() {
743 &self.sextract
744 } else {
745 &self.zextract
746 };
747 write!(out, "{func}(insn, {pos}, {len}) as {ty}")?;
748 }
749 FieldItem::FieldRef(f) => {
750 let (field, len) = (f.field(), f.len());
751 let func = if f.sxt() {
752 &self.sextract
753 } else {
754 &self.zextract
755 };
756 let name = field.name();
757 let insn_type = &self.insn_type;
758 write!(
759 out,
760 "{func}(self.extract_{name}(insn) as {insn_type}, 0, {len}) as {ty}"
761 )?;
762 }
763 }
764 if field.func.is_some() {
765 write!(out, ")")?;
766 }
767 writeln!(out)?;
768 } else {
769 writeln!(out, "{pad}let mut out = 0;")?;
770 for i in field.items() {
771 match i {
772 FieldItem::Field(f) => {
773 let (pos, len) = (f.pos(), f.len());
774 writeln!(out, "{pad}out <<= {};", len)?;
775 let func = if f.sxt() {
776 &self.sextract
777 } else {
778 &self.zextract
779 };
780 writeln!(out, "{pad}out |= {func}(insn, {pos}, {len}) as {ty};")?;
781 }
782 FieldItem::FieldRef(f) => {
783 let (field, len) = (f.field(), f.len());
784 writeln!(out, "{pad}out <<= {};", len)?;
785 let func = if f.sxt() {
786 &self.sextract
787 } else {
788 &self.zextract
789 };
790 let name = field.name();
791 writeln!(out, "{pad}let tmp0 = Self::extract_{name}(insn);")?;
792 writeln!(out, "{pad}out |= {func}(tmp0, 0, {len}) as {ty};")?;
793 }
794 }
795 }
796 if let Some(func) = &field.func {
797 writeln!(out, "{pad}self.{func}(out)")?;
798 } else {
799 writeln!(out, "{pad}out",)?;
800 }
801 }
802 Ok(())
803 }
804
805 fn gen_extract_fields<W: Write>(&self, out: &mut W, pad: Pad) -> io::Result<()> {
806 if self.tree.fields.is_empty() {
807 return Ok(());
808 }
809 self.gen_comment(out, pad, "Extract functions")?;
810 let insn_ty = &self.insn_type;
811 let val_ty = &self.value_type;
812 for field in &self.tree.fields {
813 let name = field.name();
814 writeln!(
815 out,
816 "{pad}fn extract_{name}(&self, insn: {insn_ty}) -> {val_ty} {{",
817 )?;
818 self.gen_extract_field_body(out, field, pad.shift())?;
819 writeln!(out, "{pad}}}",)?;
820 writeln!(out)?;
821 }
822 Ok(())
823 }
824
825 fn gen_extract_field<W: Write>(
826 &self,
827 out: &mut W,
828 scope: &Scope<T, S>,
829 arg: Option<&S>,
830 sep: char,
831 field: &Field<S>,
832 ) -> io::Result<()> {
833 match field {
834 Field::FieldRef(field) => {
835 let name = field.name();
836 if !scope.is_preloaded_field(name) {
837 write!(out, "{sep} self.extract_{name}(insn)")?;
838 } else if arg.map(|arg| arg != name).unwrap_or(true) {
839 write!(out, "{sep} {name}")?;
840 }
841 }
842 Field::Field(field) => {
843 let pos = field.pos();
844 let len = field.len();
845 let func = if field.sxt() {
846 &self.sextract
847 } else {
848 &self.zextract
849 };
850 write!(
851 out,
852 "{sep} {func}(insn, {pos}, {len}) as {}",
853 self.value_type
854 )?;
855 }
856 }
857 Ok(())
858 }
859
860 fn gen_extract_set<W: Write>(
861 &self,
862 out: &mut W,
863 pad: Pad,
864 scope: &Scope<T, S>,
865 name: &str,
866 set: &str,
867 items: &[SetValue<S>],
868 ) -> io::Result<()> {
869 writeln!(out, "{pad}let {name} = args_{set} {{")?;
870 let p = pad.shift();
871 for arg in items {
872 write!(out, "{p}{}", arg.name())?;
873 match arg.kind() {
874 SetValueKind::Field(f) => {
875 self.gen_extract_field(out, scope, Some(arg.name()), ':', f)?
876 }
877 SetValueKind::Const(v) => write!(out, ": {v}")?,
878 }
879 if let Some(ref ty) = arg.ty {
880 write!(out, " as {ty}")?;
881 }
882 writeln!(out, ",")?;
883 }
884 writeln!(out, "{pad}}};")?;
885 Ok(())
886 }
887
888 fn gen_extract_args<W: Write>(
889 &self,
890 out: &mut W,
891 pattern: &Pattern<T, S>,
892 pad: Pad,
893 scope: &Scope<T, S>,
894 ) -> io::Result<()> {
895 for arg in pattern
896 .args
897 .iter()
898 .filter(|i| self.gen.trans_check_arg(pattern.name(), i.name()))
899 {
900 let name = arg.name();
901 match arg.kind() {
902 ValueKind::Set(set, values) => {
903 self.gen_extract_set(out, pad, scope, name, set, values.as_slice())?;
904 }
905 ValueKind::Field(f) => match f {
906 Field::FieldRef(def)
907 if scope.is_preloaded_field(def.name()) && name == def.name() => {}
908 _ => {
909 write!(out, "{pad}let {name} ")?;
910 self.gen_extract_field(out, scope, None, '=', f)?;
911 writeln!(out, ";")?;
912 }
913 },
914 ValueKind::Const(v) => {
915 writeln!(out, "{pad}let {name} = {v};")?;
916 }
917 }
918 }
919 Ok(())
920 }
921
922 fn gen_pattern_comment<W: Write>(
923 &mut self,
924 out: &mut W,
925 pad: Pad,
926 pattern: &Pattern<T, S>,
927 ) -> io::Result<()> {
928 for line in pattern.raw().lines() {
929 writeln!(out, "{pad}// {line}")?;
930 }
931 Ok(())
932 }
933
934 fn gen_call_trans_func<W: Write>(
935 &mut self,
936 out: &mut W,
937 mut pad: Pad,
938 pattern: &Pattern<T, S>,
939 scope: &Scope<T, S>,
940 ) -> io::Result<()> {
941 self.gen_extract_args(out, pattern, pad, scope)?;
942
943 let gen_call = self.gen.trans_call_check(pattern.name());
944 if gen_call {
945 write!(out, "{pad}if Self::trans_{}(self", pattern.name)?;
946 for (name, _) in self.gen.trans_args(pattern.name()) {
947 write!(out, ", {name}")?;
948 }
949 for arg in pattern
950 .args
951 .iter()
952 .filter(|i| self.gen.trans_check_arg(pattern.name(), i.name()))
953 {
954 if self.args_by_ref && arg.is_set() {
955 write!(out, ", &{}", arg.name())?;
956 } else {
957 write!(out, ", {}", arg.name())?;
958 }
959 }
960 writeln!(out, ")? {{")?;
961 pad.right();
962 }
963
964 self.gen.trans_success(out, pad, pattern)?;
965
966 writeln!(out, "{pad}return Ok({});", pattern.size())?;
967
968 if gen_call {
969 pad.left();
970 writeln!(out, "{pad}}}")?;
971 }
972 Ok(())
973 }
974
975 fn gen_pattern_conditions<W: Write>(
976 &self,
977 out: &mut W,
978 _: Pad,
979 pat: &Pattern<T, S>,
980 ) -> io::Result<()> {
981 for (i, cond) in pat.cond.iter().enumerate() {
982 if i != 0 {
983 write!(out, " && ")?;
984 }
985 let inv = if cond.invert { "!" } else { "" };
986 write!(out, "{inv}self.cond_{}(", cond.name())?;
987 for (i, (arg, _)) in self.gen.cond_args(cond.name()).iter().enumerate() {
988 if i != 0 {
989 write!(out, ", ")?;
990 }
991 write!(out, "{arg}")?;
992 }
993 write!(out, ")")?;
994 }
995 Ok(())
996 }
997
998 fn gen_decode_overlap<W: Write>(
999 &mut self,
1000 out: &mut W,
1001 mut pad: Pad,
1002 group: &Overlap<T, S>,
1003 mut scope: Scope<T, S>,
1004 ) -> io::Result<()> {
1005 scope.preload_fields(out, pad, group)?;
1006
1007 for i in &group.items {
1008 match i {
1009 OverlapItem::Pattern(pat) => {
1010 let mask = pat.mask.bit_andn(&scope.mask);
1011
1012 scope.size = self.gen_check_insn_size(out, pad, scope.size, mask.size())?;
1013
1014 self.gen_pattern_comment(out, pad, pat)?;
1015 let is_mask_non_zero = mask != T::zero();
1016 if is_mask_non_zero || pat.has_conditions() {
1017 write!(out, "{pad}if ")?;
1018 if pat.has_conditions() {
1019 self.gen_pattern_conditions(out, pad, pat)?;
1020 }
1021 if is_mask_non_zero && pat.has_conditions() {
1022 write!(out, " && ")?;
1023 }
1024 if is_mask_non_zero {
1025 let opcode = pat.opcode.bit_andn(&scope.mask);
1026 write!(out, "insn & {mask:#x} == {opcode:#x}")?;
1027 }
1028 write!(out, " ")?;
1029 } else {
1030 write!(out, "{pad}")?;
1031 }
1032
1033 writeln!(out, "{{ ")?;
1034 pad.right();
1035 self.gen_check_insn_size(out, pad, scope.size, pat.size())?;
1036 self.gen_call_trans_func(out, pad, pat, &scope)?;
1037 pad.left();
1038 writeln!(out, "{pad}}}")?;
1039 }
1040 OverlapItem::Group(group) => {
1041 self.gen_decode_group(out, pad, group, scope.clone())?;
1042 }
1043 }
1044 }
1045 Ok(())
1046 }
1047
1048 fn gen_check_insn_size(
1049 &self,
1050 out: &mut impl Write,
1051 pad: Pad,
1052 old_size: u32,
1053 size: u32,
1054 ) -> io::Result<u32> {
1055 if self.variable_size && old_size < size {
1056 writeln!(out, "{pad}if insn_size < {size} {{")?;
1057 writeln!(out, "{}return Err(self.need_more({size}));", pad.shift())?;
1058 writeln!(out, "{pad}}}")?;
1059 Ok(size)
1060 } else {
1061 Ok(old_size)
1062 }
1063 }
1064
1065 fn gen_decode_group<W: Write>(
1066 &mut self,
1067 out: &mut W,
1068 mut pad: Pad,
1069 group: &Group<T, S>,
1070 mut scope: Scope<T, S>,
1071 ) -> io::Result<()> {
1072 let shared = group.shared_mask().bit_andn(&scope.mask);
1073 let shared_size = shared.size();
1074
1075 scope.size = self.gen_check_insn_size(out, pad, scope.size, shared_size)?;
1076
1077 scope.preload_fields(out, pad, group)?;
1078
1079 writeln!(out, "{pad}match insn & {shared:#x} {{")?;
1080 pad.right();
1081
1082 let mut item_sizes = HashMap::<T, u32>::new();
1083 if self.variable_size {
1084 for item in &group.items {
1085 let opcode = item.opcode().bit_and(&shared);
1086 let item_size = match item {
1087 Item::Pattern(pattern) => pattern.size(),
1088 _ => item.mask().size(),
1089 };
1090 if shared_size < item_size {
1091 let e = item_sizes.entry(opcode).or_default();
1092 *e = cmp::max(*e, item_size);
1093 }
1094 }
1095 }
1096
1097 for item in &group.items {
1098 if let Item::Pattern(pattern) = item {
1099 self.gen_pattern_comment(out, pad, pattern)?;
1100 }
1101
1102 let opcode = item.opcode().bit_and(&shared);
1103
1104 let mut item_size = scope.size;
1105 if self.variable_size {
1106 if let Some(size) = item_sizes.remove(&opcode) {
1107 if item_size < size {
1108 write!(out, "{pad}{opcode:#x} if insn_size < {size} => ")?;
1109 writeln!(out, "return Err(self.need_more({size})),")?;
1110 item_size = size;
1111 }
1112 }
1113 }
1114
1115 write!(out, "{pad}{opcode:#x}")?;
1116 let exclusive = item.mask().bit_andn(&shared).bit_andn(&scope.mask);
1117 if exclusive != T::zero() {
1118 let exclusive_opcode = item.opcode().bit_and(&exclusive);
1119 write!(out, " if insn & {exclusive:#x} == {exclusive_opcode:#x}")?;
1120 }
1121 writeln!(out, " => {{")?;
1122 pad.right();
1123
1124 match item {
1125 Item::Pattern(pattern) => {
1126 if pattern.has_conditions() {
1127 write!(out, "{pad}if ")?;
1128 self.gen_pattern_conditions(out, pad, pattern)?;
1129 writeln!(out, " {{")?;
1130 pad.right();
1131 }
1132 self.gen_call_trans_func(out, pad, pattern, &scope)?;
1133 if pattern.has_conditions() {
1134 pad.left();
1135 writeln!(out, "{pad}}}")?;
1136 }
1137 }
1138 Item::Overlap(overlap) => {
1139 let scope = scope.child(*item.mask(), item_size);
1140 self.gen_decode_overlap(out, pad, overlap, scope)?;
1141 }
1142 Item::Group(group) => {
1143 let scope = scope.child(*item.mask(), item_size);
1144 self.gen_decode_group(out, pad, group, scope)?;
1145 }
1146 }
1147
1148 pad.left();
1149 writeln!(out, "{pad}}}")?;
1150 }
1151
1152 writeln!(out, "{pad}_ => {{}}")?;
1153
1154 pad.left();
1155 writeln!(out, "{pad}}}")?;
1156
1157 Ok(())
1158 }
1159
1160 fn gen_decode<W: Write>(&mut self, out: &mut W, mut pad: Pad) -> io::Result<()> {
1161 self.gen_comment(out, pad, "Decode function")?;
1162 write!(out, "{pad}fn decode(&mut self, insn: {}", self.insn_type)?;
1163 if self.variable_size {
1164 write!(out, ", insn_size: usize")?;
1165 }
1166 for (name, ty) in self.gen.decode_args() {
1167 write!(out, ", {name}: {ty}")?;
1168 }
1169 writeln!(out, ") -> Result<usize, Self::Error> {{")?;
1170 pad.right();
1171 self.gen_decode_group(out, pad, &self.tree.root, Scope::new(self))?;
1172 writeln!(out)?;
1173 writeln!(out, "{pad}Err(self.fail())")?;
1174 pad.left();
1175 writeln!(out, "{pad}}}")
1176 }
1177
1178 fn gen_trait<W: Write>(&mut self, out: &mut W, mut pad: Pad) -> io::Result<()> {
1179 for attr in self.gen.trait_attrs() {
1180 writeln!(out, "{pad}{attr}")?;
1181 }
1182 if self.stubs {
1183 writeln!(out, "#[allow(unused_variables)]")?;
1184 }
1185 writeln!(out, "#[allow(clippy::unnecessary_cast)]")?;
1186 writeln!(out, "#[allow(clippy::collapsible_if)]")?;
1187 write!(out, "{pad}pub trait {}: Sized", self.trait_name)?;
1188 for parent in self.gen.trait_parents() {
1189 write!(out, " + {parent}")?;
1190 }
1191 writeln!(out, " {{")?;
1192 pad.right();
1193 if self.error_type {
1194 writeln!(out, "{pad}type Error;")?;
1195 writeln!(out)?;
1196 }
1197 if self.variable_size {
1198 writeln!(out, "{pad}fn need_more(&self, size: usize) -> Self::Error;")?;
1199 }
1200 writeln!(out, "{pad}fn fail(&self) -> Self::Error;")?;
1201 self.gen_extern_func_proto(out, pad)?;
1202 self.gen_extract_fields(out, pad)?;
1203 if !self.tree.root.as_slice().len() != 0 {
1204 self.gen_comment(out, pad, "Translation functions")?;
1205 self.gen_trans_proto_group(out, pad, &self.tree.root)?;
1206 self.gen_cond_proto(out, pad)?;
1207 self.gen_decode(out, pad)?;
1208 writeln!(out)?;
1209 }
1210 self.gen_comment(out, pad, "Generated user code for trait")?;
1211 self.gen.trait_body(out, pad)?;
1212 pad.left();
1213 writeln!(out, "{pad}}}")
1214 }
1215
1216 pub fn generate<W: Write>(&mut self, mut out: W) -> io::Result<()> {
1218 let pad = Pad(0);
1219 let out = &mut out;
1220 self.gen_args(out, pad)?;
1221 self.gen_trait(out, pad)?;
1222 writeln!(out)?;
1223 self.gen_comment(out, pad, "Generated user code")?;
1224 self.gen.end(out, pad, &self.opcodes)
1225 }
1226}