1use crate::ir::entities::{BasicBlockData, FunctionData, Program, ValueData};
9use std::borrow::Borrow;
10use std::collections::{HashMap, HashSet};
11use std::fs::File;
12use std::io::{Result, Write};
13use std::num::NonZeroUsize;
14use std::path::Path;
15use std::rc::Rc;
16
17#[derive(Default)]
20pub struct NameManager {
21 next_id: usize,
22 cur_scope: ScopeKind,
23 prefix: Prefix,
24 global_names: HashSet<StringRc>,
25 bb_names: HashSet<StringRc>,
26 global_vars: HashMap<*const ValueData, Rc<String>>,
27 funcs: HashMap<*const FunctionData, Rc<String>>,
28 bbs: HashMap<*const BasicBlockData, Rc<String>>,
29 values: HashMap<*const ValueData, Rc<String>>,
30}
31
32impl NameManager {
33 pub fn new() -> Self {
35 Self::default()
36 }
37
38 pub fn enter_func_scope(&mut self) {
45 assert!(
46 matches!(self.cur_scope, ScopeKind::Global),
47 "already in function scope"
48 );
49 self.cur_scope = ScopeKind::Function;
50 self.values.clear();
51 }
52
53 pub fn exit_func_scope(&mut self) {
60 assert!(
61 matches!(self.cur_scope, ScopeKind::Function),
62 "not in function scope"
63 );
64 self.cur_scope = ScopeKind::Global;
65 self.bb_names.clear();
66 self.bbs.clear();
67 for name in self.values.values() {
68 self.global_names.remove(name);
69 }
70 }
71
72 pub fn set_prefix(&mut self, prefix: Prefix) {
74 self.prefix = prefix;
75 }
76
77 pub fn func_name(&mut self, func: &FunctionData) -> Rc<String> {
79 let ptr: *const FunctionData = func;
80 if let Some(name) = self.funcs.get(&ptr) {
81 name.clone()
82 } else {
83 let name = self.next_name_str(func.name(), |s| &mut s.global_names);
84 self.funcs.insert(ptr, name);
85 self.funcs[&ptr].clone()
86 }
87 }
88
89 pub fn bb_name(&mut self, bb: &BasicBlockData) -> Rc<String> {
91 let ptr: *const BasicBlockData = bb;
92 if let Some(name) = self.bbs.get(&ptr) {
93 name.clone()
94 } else {
95 let name = self.next_name(bb.name(), |s| &mut s.bb_names);
96 self.bbs.insert(ptr, name);
97 self.bbs[&ptr].clone()
98 }
99 }
100
101 pub fn value_name(&mut self, value: &ValueData) -> Rc<String> {
107 assert!(!value.kind().is_const(), "can not name constants");
108 if value.kind().is_global_alloc() {
109 self.value_name_impl(value, |s| &mut s.global_vars)
110 } else {
111 self.value_name_impl(value, |s| &mut s.values)
112 }
113 }
114
115 fn value_name_impl<F>(&mut self, value: &ValueData, value_set: F) -> Rc<String>
116 where
117 F: for<'a> Fn(&'a mut Self) -> &'a mut HashMap<*const ValueData, Rc<String>>,
118 {
119 let ptr: *const ValueData = value;
120 if let Some(name) = value_set(self).get(&ptr) {
121 name.clone()
122 } else {
123 let name = self.next_name(value.name(), |s| &mut s.global_names);
124 let values = value_set(self);
125 values.insert(ptr, name);
126 values[&ptr].clone()
127 }
128 }
129
130 pub fn temp_value_name(&mut self) -> Rc<String> {
132 self.next_name(&None, |s| &mut s.global_names)
133 }
134
135 fn next_name<F>(&mut self, name: &Option<String>, name_set: F) -> Rc<String>
138 where
139 F: for<'a> FnOnce(&'a mut Self) -> &'a mut HashSet<StringRc>,
140 {
141 if let Some(name) = name {
143 self.next_name_str(name, name_set)
144 } else {
145 let name = self.prefix.temp_name(self.next_id);
147 self.next_id += 1;
148 let names = name_set(self);
149 names.insert(name.clone().into());
150 names.get(&name).unwrap().to_rc()
151 }
152 }
153
154 fn next_name_str<F>(&mut self, name: &str, name_set: F) -> Rc<String>
157 where
158 F: for<'a> FnOnce(&'a mut Self) -> &'a mut HashSet<StringRc>,
159 {
160 let name = self.prefix.name(name);
161 let names = name_set(self);
162 if !names.contains(&name) {
164 names.insert(name.clone().into());
165 names.get(&name).unwrap().to_rc()
166 } else {
167 for id in 0.. {
169 let new_name = format!("{}_{}", name, id);
170 if !names.contains(&new_name) {
171 names.insert(new_name.clone().into());
172 return names.get(&new_name).unwrap().to_rc();
173 }
174 }
175 unreachable!()
176 }
177 }
178}
179
180#[derive(Clone, Copy, Default)]
182enum ScopeKind {
183 #[default]
184 Global,
185 Function,
186}
187
188#[derive(Default)]
190pub enum Prefix {
191 #[default]
195 Default,
196 Custom {
200 named: String,
202 temp: String,
204 max_len: Option<NonZeroUsize>,
208 },
209}
210
211impl Prefix {
212 fn name(&self, name: &str) -> String {
214 match self {
215 Prefix::Default => name.into(),
216 Prefix::Custom {
217 named,
218 temp,
219 max_len,
220 } => {
221 let mut name = if let Some(name) = name.strip_prefix('@') {
222 format!("{}{}", named, name)
223 } else {
224 format!("{}{}", temp, &name[1..])
225 };
226 if let Some(max_len) = max_len {
227 name.truncate(max_len.get());
228 }
229 name
230 }
231 }
232 }
233
234 fn temp_name(&self, id: usize) -> String {
236 match self {
237 Prefix::Default => format!("%{}", id),
238 Prefix::Custom { temp, .. } => format!("{}{}", temp, id),
239 }
240 }
241}
242
243#[derive(Clone, PartialEq, Eq, Hash)]
245struct StringRc(Rc<String>);
246
247impl StringRc {
248 fn to_rc(&self) -> Rc<String> {
249 self.0.clone()
250 }
251}
252
253impl From<String> for StringRc {
254 fn from(s: String) -> Self {
255 Self(Rc::new(s))
256 }
257}
258
259impl From<&str> for StringRc {
260 fn from(s: &str) -> Self {
261 Self(Rc::new(s.into()))
262 }
263}
264
265impl Borrow<Rc<String>> for StringRc {
266 fn borrow(&self) -> &Rc<String> {
267 &self.0
268 }
269}
270
271impl Borrow<String> for StringRc {
272 fn borrow(&self) -> &String {
273 self.0.as_ref()
274 }
275}
276
277impl Borrow<str> for StringRc {
278 fn borrow(&self) -> &str {
279 self.0.as_ref()
280 }
281}
282
283pub struct Generator<W: Write, V: Visitor<W>> {
285 writer: W,
286 visitor: V,
287 name_man: NameManager,
288}
289
290impl<W: Write, V: Visitor<W>> Generator<W, V> {
291 pub fn new(writer: W) -> Self
293 where
294 V: Default,
295 {
296 Self {
297 writer,
298 visitor: V::default(),
299 name_man: NameManager::new(),
300 }
301 }
302
303 pub fn with_visitor(writer: W, visitor: V) -> Self {
305 Self {
306 writer,
307 visitor,
308 name_man: NameManager::new(),
309 }
310 }
311
312 pub fn writer(self) -> W {
314 self.writer
315 }
316
317 pub fn generate_on(&mut self, program: &Program) -> Result<V::Output> {
319 self
320 .visitor
321 .visit(&mut self.writer, &mut self.name_man, program)
322 }
323}
324
325impl<V: Visitor<File>> Generator<File, V> {
326 pub fn from_path<P>(path: P) -> Result<Self>
328 where
329 V: Default,
330 P: AsRef<Path>,
331 {
332 File::create(path).map(Generator::new)
333 }
334}
335
336pub trait Visitor<W: Write> {
338 type Output;
340
341 fn visit(&mut self, w: &mut W, nm: &mut NameManager, program: &Program) -> Result<Self::Output>;
343}