decodetree/
gen.rs

1//! Code generator for decodetree.
2
3use 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    /// Collect field usage statistics.
22    ///
23    /// Returns the number of processed patterns.
24    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/// Helper to align generated code.
135#[derive(Copy, Clone, Default)]
136pub struct Pad(usize);
137
138impl Pad {
139    /// Shift padding to the right.
140    pub fn shift(self) -> Self {
141        Self(self.0 + 4)
142    }
143
144    /// Shift padding to the right in-place.
145    pub fn right(&mut self) -> Self {
146        self.0 += 4;
147        *self
148    }
149
150    /// Shift padding to the left in-place.
151    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/// Hooks to generate custom code.
169#[allow(unused_variables)]
170pub trait Gen<T, S = Str> {
171    /// Additional attributes for argument sets.
172    fn sets_attrs(&self) -> &[&str] {
173        &[]
174    }
175
176    /// Additional attributes for trait.
177    fn trait_attrs(&self) -> &[&str] {
178        &[]
179    }
180
181    /// Additional parent traits.
182    fn trait_parents(&self) -> &[&str] {
183        &[]
184    }
185
186    /// Use to generate code inside trait.
187    fn trait_body<W: Write>(&mut self, out: &mut W, pad: Pad) -> io::Result<()> {
188        Ok(())
189    }
190
191    /// Additional arguments to pass to decode function.
192    fn decode_args(&self) -> &[(&str, &str)] {
193        &[]
194    }
195
196    /// Additional attributes for condition functions.
197    #[allow(unused_variables)]
198    fn cond_attrs(&self, name: &str) -> &[&str] {
199        &[]
200    }
201
202    /// Additional arguments for condition functions.
203    #[allow(unused_variables)]
204    fn cond_args(&self, name: &str) -> &[(&str, &str)] {
205        &[]
206    }
207
208    /// Filter wich trans function prototypes should be generated.
209    #[allow(unused_variables)]
210    fn trans_proto_check(&self, name: &str) -> bool {
211        true
212    }
213
214    /// Filter wich trans function calls should be generated.
215    #[allow(unused_variables)]
216    fn trans_call_check(&self, name: &str) -> bool {
217        self.trans_proto_check(name)
218    }
219
220    /// Additional attributes for trans functions.
221    #[allow(unused_variables)]
222    fn trans_attrs(&self, name: &str) -> &[&str] {
223        &[]
224    }
225
226    /// Filter arguments to trans functions.
227    #[allow(unused_variables)]
228    fn trans_check_arg(&self, name: &str, arg: &str) -> bool {
229        true
230    }
231
232    /// Additional arguments to pass to trans functions.
233    #[allow(unused_variables)]
234    fn trans_args(&self, name: &str) -> &[(&str, &str)] {
235        &[]
236    }
237
238    /// Use to generate default implementation of trans functions.
239    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    /// Use to generate code after successful trans function.
249    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    /// Use to generate code outside of the Decode trait.
259    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
266/// Generator builder.
267pub 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    /// Override Decode trait name.
303    pub fn trait_name(mut self, name: &str) -> Self {
304        self.trait_name = name.into();
305        self
306    }
307
308    /// Override instruction type.
309    pub fn insn_type(mut self, ty: &str) -> Self {
310        self.insn_type = Some(ty.into());
311        self
312    }
313
314    /// Override type for pattern values.
315    pub fn value_type(mut self, ty: &str) -> Self {
316        self.value_type = Some(ty.into());
317        self
318    }
319
320    /// Override zero-extend extract function.
321    pub fn zextract(mut self, name: &str) -> Self {
322        self.zextract = name.into();
323        self
324    }
325
326    /// Override sign-extend extract function.
327    pub fn sextract(mut self, name: &str) -> Self {
328        self.sextract = name.into();
329        self
330    }
331
332    /// Generate default functions implementations.
333    pub fn stubs(mut self, stubs: bool) -> Self {
334        self.stubs = stubs;
335        self
336    }
337
338    /// Generate `type Error` in Decode trait.
339    pub fn error_type(mut self, error_type: bool) -> Self {
340        self.error_type = error_type;
341        self
342    }
343
344    /// Generate instruction size checks.
345    pub fn variable_size(mut self, variable_size: bool) -> Self {
346        self.variable_size = variable_size;
347        self
348    }
349
350    /// Pass `args_name` to trans function by reference.
351    pub fn args_by_ref(mut self, by_ref: bool) -> Self {
352        self.args_by_ref = by_ref;
353        self
354    }
355
356    /// Do not preload fields if required instruction size is not checked.
357    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    /// Set how many fields can be preloaded at once.
363    ///
364    /// Set `0` to disable fields preloading.
365    pub fn preload_field_max(mut self, count: u32) -> Self {
366        self.preload_field_max = count;
367        self
368    }
369
370    /// Only fields used by `usage`% patterns will be preloaded.
371    ///
372    /// Set `0.0` to disable this filter.
373    pub fn preload_field_usage(mut self, usage: f64) -> Self {
374        self.preload_field_usage = usage;
375        self
376    }
377
378    /// Build the `Generator`.
379    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    // The bitmask checked in a parent scope.
415    mask: T,
416    // The instruction size checked in a parent scope.
417    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        // writeln!(out, "{pad}// Fields usage statistics:")?;
464        // writeln!(out, "{pad}// ")?;
465        // writeln!(out, "{pad}//  count | patterns | field")?;
466        // writeln!(out, "{pad}//--------|----------|-------------")?;
467        // for (count, field) in &fields {
468        //     let usage = *count as f64 / pattern_count * 100.0;
469        //     writeln!(out, "{pad}//  {count:>5} | {usage:7.1}% | {}", field.name())?;
470        // }
471        // writeln!(out)?;
472
473        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                // required instruction size is not checked yet
482                continue;
483            }
484            if self.is_preloaded_field(name) {
485                // already preloaded
486                continue;
487            }
488            n += 1;
489            if n > self.preload_field_max {
490                // no more preloads
491                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
510/// Decodetree generator.
511pub 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    /// Create builder object for `Generator`.
532    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    /// Generate code.
1217    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}