1use crate::{
11 impl_table_key,
12 ir::{ExtUnit, Signature, Unit, UnitBuilder, UnitData, UnitName},
13 table::{PrimaryTable, TableKey},
14 verifier::Verifier,
15};
16use rayon::prelude::*;
17use std::collections::{BTreeSet, HashMap};
18
19#[derive(Serialize, Deserialize)]
24pub struct Module {
25 pub(crate) units: PrimaryTable<UnitId, UnitData>,
27 unit_order: BTreeSet<UnitId>,
29 pub(crate) decls: PrimaryTable<DeclId, DeclData>,
31 decl_order: BTreeSet<DeclId>,
33 link_table: Option<HashMap<(UnitId, ExtUnit), LinkedUnit>>,
36 location_hints: HashMap<UnitId, usize>,
40}
41
42impl Module {
43 pub fn new() -> Self {
45 Self {
46 units: PrimaryTable::new(),
47 unit_order: BTreeSet::new(),
48 decls: PrimaryTable::new(),
49 decl_order: BTreeSet::new(),
50 link_table: None,
51 location_hints: Default::default(),
52 }
53 }
54
55 pub fn dump(&self) -> ModuleDumper {
57 ModuleDumper(self)
58 }
59
60 pub fn add_unit(&mut self, data: UnitData) -> UnitId {
62 let unit = self.units.add(data);
63 self.unit_order.insert(unit);
64 self.link_table = None;
65 unit
66 }
67
68 pub fn remove_unit(&mut self, unit: UnitId) {
70 self.units.remove(unit);
71 self.unit_order.remove(&unit);
72 }
73
74 pub fn declare(&mut self, name: UnitName, sig: Signature) -> DeclId {
76 self.add_decl(DeclData {
77 name,
78 sig,
79 loc: None,
80 })
81 }
82
83 pub fn add_decl(&mut self, data: DeclData) -> DeclId {
85 let decl = self.decls.add(data);
86 self.decl_order.insert(decl);
87 self.link_table = None;
88 decl
89 }
90
91 pub fn remove_decl(&mut self, decl: DeclId) {
93 self.decls.remove(decl);
94 self.decl_order.remove(&decl);
95 }
96
97 pub fn units<'a>(&'a self) -> impl Iterator<Item = Unit<'a>> + 'a {
99 self.unit_order.iter().map(move |&id| self.unit(id))
100 }
101
102 pub fn units_mut<'a>(&'a mut self) -> impl Iterator<Item = UnitBuilder<'a>> + 'a {
104 self.units
105 .storage
106 .iter_mut()
107 .map(|(&id, data)| UnitBuilder::new(UnitId::new(id), data))
108 }
109
110 pub fn par_units<'a>(&'a self) -> impl ParallelIterator<Item = Unit<'a>> + 'a {
112 self.unit_order.par_iter().map(move |&id| self.unit(id))
113 }
114
115 pub fn par_units_mut<'a>(&'a mut self) -> impl ParallelIterator<Item = UnitBuilder<'a>> + 'a {
117 self.units
118 .storage
119 .par_iter_mut()
120 .map(|(&id, data)| UnitBuilder::new(UnitId::new(id), data))
121 }
122
123 pub fn functions<'a>(&'a self) -> impl Iterator<Item = Unit<'a>> + 'a {
125 self.units().filter(|unit| unit.is_function())
126 }
127
128 pub fn processes<'a>(&'a self) -> impl Iterator<Item = Unit<'a>> + 'a {
130 self.units().filter(|unit| unit.is_process())
131 }
132
133 pub fn entities<'a>(&'a self) -> impl Iterator<Item = Unit<'a>> + 'a {
135 self.units().filter(|unit| unit.is_entity())
136 }
137
138 pub fn decls<'a>(&'a self) -> impl Iterator<Item = DeclId> + 'a {
140 self.decl_order.iter().cloned()
141 }
142
143 pub fn unit(&self, unit: UnitId) -> Unit {
145 Unit::new(unit, &self[unit])
146 }
147
148 pub fn unit_mut(&mut self, unit: UnitId) -> UnitBuilder {
150 self.link_table = None;
151 UnitBuilder::new(unit, &mut self[unit])
152 }
153
154 pub fn symbols<'a>(&'a self) -> impl Iterator<Item = (&UnitName, LinkedUnit, &Signature)> + 'a {
156 self.units()
157 .map(|unit| (unit.name(), LinkedUnit::Def(unit.id()), unit.sig()))
158 .chain(
159 self.decls()
160 .map(move |decl| (&self[decl].name, LinkedUnit::Decl(decl), &self[decl].sig)),
161 )
162 }
163
164 pub fn local_symbols<'a>(
166 &'a self,
167 ) -> impl Iterator<Item = (&UnitName, LinkedUnit, &Signature)> + 'a {
168 self.symbols().filter(|&(name, ..)| name.is_local())
169 }
170
171 pub fn global_symbols<'a>(
173 &'a self,
174 ) -> impl Iterator<Item = (&UnitName, LinkedUnit, &Signature)> + 'a {
175 self.symbols().filter(|&(name, ..)| name.is_global())
176 }
177
178 pub fn is_linked(&self) -> bool {
182 self.link_table.is_some()
183 }
184
185 pub fn link(&mut self) {
187 let mut failed = false;
188
189 let mut symbols = HashMap::new();
191 for (name, unit, sig) in self.symbols() {
192 if let Some((existing, _)) = symbols.insert(name, (unit, sig)) {
193 if !existing.is_decl() {
194 eprintln!("unit {} declared multiple times", name);
195 failed = true;
196 }
197 }
198 }
199 if failed {
200 panic!("linking failed; multiple uses of the same name");
201 }
202
203 let mut linked = HashMap::new();
205 for unit in self.units() {
206 for (ext_unit, data) in unit.extern_units() {
207 let (to, to_sig) = match symbols.get(&data.name).cloned() {
208 Some(to) => to,
209 None => {
210 eprintln!(
211 "unit {} not found; referenced in {}",
212 data.name,
213 unit.name()
214 );
215 failed = true;
216 continue;
217 }
218 };
219 if to_sig != &data.sig {
220 eprintln!(
221 "signature mismatch: {} has {}, but reference in {} expects {}",
222 data.name,
223 to_sig,
224 unit.name(),
225 data.sig
226 );
227 failed = true;
228 continue;
229 }
230 linked.insert((unit.id(), ext_unit), to);
231 }
232 }
233 if failed {
234 panic!("linking failed; unresolved references");
235 }
236 self.link_table = Some(linked);
237 }
238
239 pub fn verify(&self) {
241 let mut verifier = Verifier::new();
242 verifier.verify_module(self);
243 match verifier.finish() {
244 Ok(()) => (),
245 Err(errs) => {
246 eprintln!("");
247 eprintln!("Verified module:");
248 eprintln!("{}", self.dump());
249 eprintln!("");
250 eprintln!("Verification errors:");
251 eprintln!("{}", errs);
252 panic!("verification failed");
253 }
254 }
255 }
256
257 pub fn lookup_ext_unit(&self, ext_unit: ExtUnit, within: UnitId) -> Option<LinkedUnit> {
261 self.link_table
262 .as_ref()
263 .and_then(|lt| lt.get(&(within, ext_unit)))
264 .cloned()
265 }
266
267 pub fn set_location_hint(&mut self, mod_unit: UnitId, loc: usize) {
271 self.location_hints.insert(mod_unit, loc);
272 }
273
274 pub fn location_hint(&self, mod_unit: UnitId) -> Option<usize> {
279 self.location_hints.get(&mod_unit).cloned()
280 }
281}
282
283impl std::ops::Index<UnitId> for Module {
284 type Output = UnitData;
285 fn index(&self, idx: UnitId) -> &UnitData {
286 &self.units[idx]
287 }
288}
289
290impl std::ops::IndexMut<UnitId> for Module {
291 fn index_mut(&mut self, idx: UnitId) -> &mut UnitData {
292 self.link_table = None;
293 &mut self.units[idx]
294 }
295}
296
297impl std::ops::Index<DeclId> for Module {
298 type Output = DeclData;
299 fn index(&self, idx: DeclId) -> &DeclData {
300 &self.decls[idx]
301 }
302}
303
304impl std::ops::IndexMut<DeclId> for Module {
305 fn index_mut(&mut self, idx: DeclId) -> &mut DeclData {
306 self.link_table = None;
307 &mut self.decls[idx]
308 }
309}
310
311pub struct ModuleDumper<'a>(&'a Module);
313
314impl std::fmt::Display for ModuleDumper<'_> {
315 fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
316 let mut newline = false;
317 for unit in self.0.units() {
318 if newline {
319 writeln!(f, "")?;
320 writeln!(f, "")?;
321 }
322 newline = true;
323 write!(f, "{}: ", unit.id())?;
324 write!(f, "{}", unit)?;
325 }
326 if newline && !self.0.decls().count() > 0 {
327 writeln!(f, "")?;
328 }
329 for decl in self.0.decls() {
330 if newline {
331 writeln!(f, "")?;
332 }
333 newline = true;
334 let data = &self.0[decl];
335 write!(f, "declare {} {}", data.name, data.sig)?;
336 }
337 Ok(())
338 }
339}
340
341impl_table_key! {
342 struct UnitId(u32) as "u";
344 struct DeclId(u32) as "decl";
346}
347
348#[derive(Serialize, Deserialize)]
350pub struct DeclData {
351 pub sig: Signature,
353 pub name: UnitName,
355 pub loc: Option<usize>,
357}
358
359#[derive(Copy, Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash, Serialize, Deserialize)]
361pub enum LinkedUnit {
362 Def(UnitId),
364 Decl(DeclId),
366}
367
368impl LinkedUnit {
369 pub fn is_def(&self) -> bool {
371 match self {
372 LinkedUnit::Def(..) => true,
373 _ => false,
374 }
375 }
376
377 pub fn is_decl(&self) -> bool {
379 match self {
380 LinkedUnit::Decl(..) => true,
381 _ => false,
382 }
383 }
384}