regalloc2/ion/
reg_traversal.rs1use crate::{MachineEnv, PReg, RegClass};
2
3pub struct RegTraversalIter<'a> {
18 env: &'a MachineEnv,
19 class: usize,
20 hints: [Option<PReg>; 2],
21 hint_idx: usize,
22 pref_idx: usize,
23 non_pref_idx: usize,
24 offset_pref: usize,
25 offset_non_pref: usize,
26 is_fixed: bool,
27 fixed: Option<PReg>,
28}
29
30impl<'a> RegTraversalIter<'a> {
31 pub fn new(
32 env: &'a MachineEnv,
33 class: RegClass,
34 hint_reg: PReg,
35 hint2_reg: PReg,
36 offset: usize,
37 fixed: Option<PReg>,
38 ) -> Self {
39 let mut hint_reg = if hint_reg != PReg::invalid() {
40 Some(hint_reg)
41 } else {
42 None
43 };
44 let mut hint2_reg = if hint2_reg != PReg::invalid() {
45 Some(hint2_reg)
46 } else {
47 None
48 };
49
50 if hint_reg.is_none() {
51 hint_reg = hint2_reg;
52 hint2_reg = None;
53 }
54 let hints = [hint_reg, hint2_reg];
55 let class = class as u8 as usize;
56 let offset_pref = if env.preferred_regs_by_class[class].len() > 0 {
57 offset % env.preferred_regs_by_class[class].len()
58 } else {
59 0
60 };
61 let offset_non_pref = if env.non_preferred_regs_by_class[class].len() > 0 {
62 offset % env.non_preferred_regs_by_class[class].len()
63 } else {
64 0
65 };
66 Self {
67 env,
68 class,
69 hints,
70 hint_idx: 0,
71 pref_idx: 0,
72 non_pref_idx: 0,
73 offset_pref,
74 offset_non_pref,
75 is_fixed: fixed.is_some(),
76 fixed,
77 }
78 }
79}
80
81impl<'a> std::iter::Iterator for RegTraversalIter<'a> {
82 type Item = PReg;
83
84 fn next(&mut self) -> Option<PReg> {
85 if self.is_fixed {
86 let ret = self.fixed;
87 self.fixed = None;
88 return ret;
89 }
90
91 fn wrap(idx: usize, limit: usize) -> usize {
92 if idx >= limit {
93 idx - limit
94 } else {
95 idx
96 }
97 }
98 if self.hint_idx < 2 && self.hints[self.hint_idx].is_some() {
99 let h = self.hints[self.hint_idx];
100 self.hint_idx += 1;
101 return h;
102 }
103 while self.pref_idx < self.env.preferred_regs_by_class[self.class].len() {
104 let arr = &self.env.preferred_regs_by_class[self.class][..];
105 let r = arr[wrap(self.pref_idx + self.offset_pref, arr.len())];
106 self.pref_idx += 1;
107 if Some(r) == self.hints[0] || Some(r) == self.hints[1] {
108 continue;
109 }
110 return Some(r);
111 }
112 while self.non_pref_idx < self.env.non_preferred_regs_by_class[self.class].len() {
113 let arr = &self.env.non_preferred_regs_by_class[self.class][..];
114 let r = arr[wrap(self.non_pref_idx + self.offset_non_pref, arr.len())];
115 self.non_pref_idx += 1;
116 if Some(r) == self.hints[0] || Some(r) == self.hints[1] {
117 continue;
118 }
119 return Some(r);
120 }
121 None
122 }
123}