yz_basic_block/arena/
check.rs1use super::*;
2
3fn check_finish(mut offending: Vec<(BbId, BbId)>) -> Result<(), OffendingIds> {
4 if offending.is_empty() {
5 Ok(())
6 } else {
7 offending.sort();
8 offending.dedup();
9 offending.shrink_to_fit();
10 Err(OffendingIds(offending))
11 }
12}
13
14impl<S, C> Arena<S, C>
15where
16 ABB<S, C>: ForeachTarget<JumpTarget = BbId>,
17{
18 fn check_intern(&self, bbid: BbId, bb: &ABB<S, C>, offending: &mut Vec<(BbId, BbId)>) {
19 bb.foreach_target(|&t| {
20 if t != bbid && self.bbs.get(&t).is_none() {
21 offending.push((bbid, t));
22 }
23 });
24 }
25
26 fn check_bbs(&self) -> Vec<(BbId, BbId)> {
27 let mut errs = Vec::new();
28 for (&n, i) in self.bbs.iter() {
29 self.check_intern(n, i, &mut errs);
30 }
31 errs
32 }
33
34 pub fn check(&self) -> Result<(), OffendingIds> {
37 let mut errs = self.check_bbs();
38 errs.extend(self.labels.values().filter_map(|&i| {
40 if self.bbs.get(&i).is_none() {
41 Some((i, i))
42 } else {
43 None
44 }
45 }));
46 for (&n, i) in self.bbs.iter() {
48 if i.inner.is_placeholder() && self.labels_of_bb(n).next().is_none() {
49 errs.push((n, n));
50 }
51 }
52 check_finish(errs)
53 }
54
55 fn find_first_free(&self) -> Option<usize> {
56 for i in self.cache_ins_start..usize::MAX {
57 if self.bbs.get(&i).is_none() {
58 return Some(i);
59 }
60 }
61 None
62 }
63
64 pub fn push(&mut self, bb: ABB<S, C>) -> Result<usize, (ABB<S, C>, OffendingIds)> {
67 let ret = match self.find_first_free() {
68 Some(n) => n,
69 None => return Err((bb, OffendingIds(Vec::new()))),
70 };
71 let mut errs = Vec::new();
72 self.check_intern(ret, &bb, &mut errs);
73 match check_finish(errs) {
74 Ok(()) => {
75 self.bbs.insert(ret, bb);
76 self.cache_ins_start = ret.saturating_add(1);
77 Ok(ret)
78 }
79 Err(errs) => Err((bb, errs)),
80 }
81 }
82
83 pub fn remove(&mut self, bbid: BbId) -> Option<Result<(ABB<S, C>, Vec<String>), OffendingIds>> {
87 let x = self.bbs.remove(&bbid)?;
88 let offending = self.check_bbs();
89 Some(if offending.is_empty() {
90 let (labelrt, rlabels) = take(&mut self.labels)
91 .into_iter()
92 .partition(|&(_, v)| v == bbid);
93 self.labels = rlabels;
94 if bbid < self.cache_ins_start {
95 self.cache_ins_start = bbid;
96 }
97 Ok((x, labelrt.into_iter().map(|x| x.0).collect()))
98 } else {
99 self.bbs.insert(bbid, x);
100 Err(OffendingIds(offending))
101 })
102 }
103}