yz_basic_block/arena/
mod.rs1use crate::bb::{BasicBlock, BasicBlockInner};
2use crate::jump::ForeachTarget;
3use crate::{BbId, Label};
4use alloc::collections::{btree_map::Entry as MapEntry, BTreeMap as Map};
5use alloc::{string::String, vec::Vec};
6use core::mem::{replace, take};
7
8#[cfg(feature = "serde")]
9use serde::{Deserialize, Serialize};
10
11mod check;
12mod optimize;
13
14type ABB<S, C> = BasicBlock<S, C, BbId>;
15type LabelMap = Map<String, BbId>;
16
17#[derive(Debug)]
18#[cfg_attr(feature = "serde", derive(Deserialize, Serialize))]
19pub struct Arena<S, C> {
20 bbs: Map<BbId, ABB<S, C>>,
22 labels: LabelMap,
23
24 #[cfg_attr(feature = "serde", serde(skip))]
26 cache_ins_start: usize,
27}
28
29#[derive(Clone, Debug)]
30#[cfg_attr(feature = "std", derive(thiserror::Error))]
31#[cfg_attr(feature = "serde", derive(Deserialize, Serialize))]
32pub enum SetBbLabelError {
33 #[cfg_attr(feature = "std", error("got invalid basic block id {0}"))]
34 InvalidId(BbId),
35
36 #[cfg_attr(
37 feature = "std",
38 error("label already exists with target = {orig_target}")
39 )]
40 LabelAlreadyExists { orig_target: BbId },
41}
42
43#[derive(Clone, Debug)]
44#[cfg_attr(feature = "std", derive(thiserror::Error))]
45#[cfg_attr(
46 feature = "std",
47 error("got offending basic block ids (from -> to) {0:?}")
48)]
49#[cfg_attr(feature = "serde", derive(Deserialize, Serialize))]
50pub struct OffendingIds(pub Vec<(BbId, BbId)>);
51
52impl<S, C> Default for Arena<S, C> {
53 #[inline]
54 fn default() -> Self {
55 Self {
56 bbs: Map::new(),
57 labels: Map::new(),
58 cache_ins_start: 0,
59 }
60 }
61}
62
63fn labels_of_bb(labels: &LabelMap, bbid: BbId) -> impl Iterator<Item = &str> {
64 labels.iter().filter_map(move |(label, &curid)| {
65 if curid == bbid {
66 Some(label.as_str())
67 } else {
68 None
69 }
70 })
71}
72
73fn set_label(
74 labels: &mut LabelMap,
75 label: String,
76 target: BbId,
77 overwrite: bool,
78) -> Result<Option<BbId>, SetBbLabelError> {
79 match labels.entry(label) {
80 MapEntry::Occupied(mut e) if overwrite => Ok(Some(replace(e.get_mut(), target))),
81 MapEntry::Occupied(e) => Err(SetBbLabelError::LabelAlreadyExists {
82 orig_target: *e.get(),
83 }),
84 MapEntry::Vacant(e) => {
85 e.insert(target);
86 Ok(None)
87 }
88 }
89}
90
91impl<S, C> Arena<S, C> {
92 #[inline(always)]
93 pub fn new() -> Self {
94 Default::default()
95 }
96
97 #[inline(always)]
98 pub fn len(&self) -> usize {
99 self.bbs.len()
100 }
101
102 #[inline(always)]
103 pub fn is_empty(&self) -> bool {
104 self.bbs.is_empty()
105 }
106
107 #[inline(always)]
108 pub fn bbs(&self) -> &Map<BbId, ABB<S, C>> {
109 &self.bbs
110 }
111
112 #[inline(always)]
113 pub fn bbs_mut(&mut self) -> &mut Map<BbId, ABB<S, C>> {
114 &mut self.bbs
115 }
116
117 #[inline(always)]
118 pub fn labels(&self) -> &LabelMap {
119 &self.labels
120 }
121
122 #[inline(always)]
123 pub fn labels_of_bb(&self, bbid: BbId) -> impl Iterator<Item = &str> {
124 labels_of_bb(&self.labels, bbid)
125 }
126
127 pub fn label2bb(&self, label: &str) -> Option<(BbId, &ABB<S, C>)> {
128 if let Some(bbid) = self.labels.get(label) {
129 if let Some(bb) = self.bbs.get(bbid) {
130 return Some((*bbid, bb));
131 }
132 }
133 None
134 }
135
136 pub fn set_label(
139 &mut self,
140 label: Label,
141 target: BbId,
142 overwrite: bool,
143 ) -> Result<Option<BbId>, SetBbLabelError> {
144 if self.bbs.get(&target).is_none() {
145 return Err(SetBbLabelError::InvalidId(target));
146 }
147 set_label(&mut self.labels, label.into_owned(), target, overwrite)
148 }
149
150 pub fn shrink_to_fit(&mut self) {
151 for i in self.bbs.values_mut() {
152 if let BasicBlockInner::Concrete { statements, .. } = &mut i.inner {
153 statements.shrink_to_fit();
154 }
155 }
156 }
157}
158
159impl<S, C> ForeachTarget for Arena<S, C>
160where
161 ABB<S, C>: ForeachTarget<JumpTarget = BbId>,
162{
163 type JumpTarget = BbId;
164
165 fn foreach_target<F>(&self, mut f: F)
166 where
167 F: FnMut(&Self::JumpTarget),
168 {
169 for i in self.bbs.values() {
170 i.foreach_target(&mut f);
171 }
172 for i in self.labels.values() {
173 f(i);
174 }
175 }
176
177 fn foreach_target_mut<F>(&mut self, mut f: F)
178 where
179 F: FnMut(&mut Self::JumpTarget),
180 {
181 for i in self.bbs.values_mut() {
182 i.foreach_target_mut(&mut f);
183 }
184 for i in self.labels.values_mut() {
185 f(i);
186 }
187 }
188}