1use std::{fmt, marker::PhantomData};
12
13#[cfg(any(
14 feature = "llvm18-0",
15 feature = "llvm19-0",
16 feature = "llvm20-0",
17 feature = "llvm21-0",
18 feature = "llvm22-0"
19))]
20use crate::error::TableGenError;
21#[cfg(any(feature = "llvm16-0", feature = "llvm17-0"))]
22use crate::error::{SourceLocation, TableGenError, WithLocation};
23use crate::{
24 Error, SourceInfo, TableGenParser,
25 init::TypedInit,
26 raw::{
27 TableGenRecordKeeperIteratorRef, TableGenRecordKeeperRef, TableGenRecordVectorRef,
28 tableGenRecordKeeperFree, tableGenRecordKeeperGetAllDerivedDefinitions,
29 tableGenRecordKeeperGetAllDerivedDefinitionsIfDefined, tableGenRecordKeeperGetClass,
30 tableGenRecordKeeperGetDef, tableGenRecordKeeperGetFirstClass,
31 tableGenRecordKeeperGetFirstDef, tableGenRecordKeeperGetGlobal,
32 tableGenRecordKeeperGetInputFilename, tableGenRecordKeeperGetNextClass,
33 tableGenRecordKeeperGetNextDef, tableGenRecordKeeperItemGetName,
34 tableGenRecordKeeperItemGetRecord, tableGenRecordKeeperIteratorClone,
35 tableGenRecordKeeperIteratorFree, tableGenRecordVectorFree, tableGenRecordVectorGet,
36 tableGenRecordVectorSize,
37 },
38 record::Record,
39 string_ref::StringRef,
40};
41
42#[derive(Debug, PartialEq, Eq)]
44pub struct RecordKeeper<'s> {
45 raw: TableGenRecordKeeperRef,
46 pub(crate) parser: TableGenParser<'s>,
47}
48
49impl<'s> RecordKeeper<'s> {
50 pub(crate) unsafe fn from_raw(
51 raw: TableGenRecordKeeperRef,
52 parser: TableGenParser<'s>,
53 ) -> RecordKeeper<'s> {
54 RecordKeeper { raw, parser }
55 }
56
57 pub fn classes(&self) -> NamedRecordIter<'_, IsClass> {
61 unsafe { NamedRecordIter::from_raw(tableGenRecordKeeperGetFirstClass(self.raw)) }
62 }
63
64 pub fn defs(&self) -> NamedRecordIter<'_, IsDef> {
68 unsafe { NamedRecordIter::from_raw(tableGenRecordKeeperGetFirstDef(self.raw)) }
69 }
70
71 pub fn class(&self, name: &str) -> Result<Record<'_>, Error> {
73 unsafe {
74 let class = tableGenRecordKeeperGetClass(self.raw, StringRef::from(name).to_raw());
75 if class.is_null() {
76 Err(TableGenError::MissingClass(name.into()).into())
77 } else {
78 Ok(Record::from_raw(class))
79 }
80 }
81 }
82
83 pub fn def(&self, name: &str) -> Result<Record<'_>, Error> {
85 unsafe {
86 let def = tableGenRecordKeeperGetDef(self.raw, StringRef::from(name).to_raw());
87 if def.is_null() {
88 Err(TableGenError::MissingDef(name.into()).into())
89 } else {
90 Ok(Record::from_raw(def))
91 }
92 }
93 }
94
95 pub fn all_derived_definitions(&self, name: &str) -> RecordIter<'_> {
98 unsafe {
99 RecordIter::from_raw_vector(tableGenRecordKeeperGetAllDerivedDefinitions(
100 self.raw,
101 StringRef::from(name).to_raw(),
102 ))
103 }
104 }
105
106 pub fn all_derived_definitions_if_defined(&self, name: &str) -> RecordIter<'_> {
109 unsafe {
110 RecordIter::from_raw_vector(tableGenRecordKeeperGetAllDerivedDefinitionsIfDefined(
111 self.raw,
112 StringRef::from(name).to_raw(),
113 ))
114 }
115 }
116
117 pub fn source_info(&self) -> SourceInfo<'_> {
118 SourceInfo(&self.parser)
119 }
120
121 pub fn input_filename(&self) -> Result<&str, Error> {
123 let raw = unsafe { tableGenRecordKeeperGetInputFilename(self.raw) };
124 unsafe { StringRef::from_raw(raw) }
125 .try_into()
126 .map_err(|e: std::str::Utf8Error| TableGenError::from(e).into())
127 }
128
129 pub fn global(&self, name: &str) -> Option<TypedInit<'_>> {
131 let ptr =
132 unsafe { tableGenRecordKeeperGetGlobal(self.raw, StringRef::from(name).to_raw()) };
133 if ptr.is_null() {
134 None
135 } else {
136 Some(unsafe { TypedInit::from_raw(ptr) })
137 }
138 }
139}
140
141impl Drop for RecordKeeper<'_> {
142 fn drop(&mut self) {
143 unsafe {
144 tableGenRecordKeeperFree(self.raw);
145 }
146 }
147}
148
149#[doc(hidden)]
150pub struct IsClass;
151#[doc(hidden)]
152pub struct IsDef;
153
154trait NextRecord {
155 unsafe fn next(raw: &mut TableGenRecordKeeperIteratorRef);
156}
157
158impl NextRecord for IsClass {
159 unsafe fn next(raw: &mut TableGenRecordKeeperIteratorRef) {
160 unsafe {
161 tableGenRecordKeeperGetNextClass(raw);
162 }
163 }
164}
165
166impl NextRecord for IsDef {
167 unsafe fn next(raw: &mut TableGenRecordKeeperIteratorRef) {
168 unsafe {
169 tableGenRecordKeeperGetNextDef(raw);
170 }
171 }
172}
173
174#[derive(Debug)]
176pub struct NamedRecordIter<'a, T> {
177 raw: TableGenRecordKeeperIteratorRef,
178 _kind: PhantomData<&'a T>,
179}
180
181impl<T> NamedRecordIter<'_, T> {
182 unsafe fn from_raw(raw: TableGenRecordKeeperIteratorRef) -> Self {
183 NamedRecordIter {
184 raw,
185 _kind: PhantomData,
186 }
187 }
188}
189
190impl<'a, T: NextRecord> Iterator for NamedRecordIter<'a, T> {
191 type Item = (Result<&'a str, std::str::Utf8Error>, Record<'a>);
192
193 fn next(&mut self) -> Option<Self::Item> {
194 let current = if self.raw.is_null() {
195 return None;
196 } else {
197 unsafe {
198 Some((
199 StringRef::from_raw(tableGenRecordKeeperItemGetName(self.raw)).try_into(),
200 Record::from_raw(tableGenRecordKeeperItemGetRecord(self.raw)),
201 ))
202 }
203 };
204 unsafe { T::next(&mut self.raw) };
205 current
206 }
207}
208
209impl<T> Clone for NamedRecordIter<'_, T> {
210 fn clone(&self) -> Self {
211 if self.raw.is_null() {
212 return Self {
213 raw: std::ptr::null_mut(),
214 _kind: PhantomData,
215 };
216 }
217 unsafe { Self::from_raw(tableGenRecordKeeperIteratorClone(self.raw)) }
218 }
219}
220
221impl<T> Drop for NamedRecordIter<'_, T> {
222 fn drop(&mut self) {
223 unsafe { tableGenRecordKeeperIteratorFree(self.raw) }
224 }
225}
226
227impl<T: NextRecord> std::iter::FusedIterator for NamedRecordIter<'_, T> {}
228
229pub struct RecordIter<'a> {
231 raw: TableGenRecordVectorRef,
232 index: usize,
233 back: usize,
234 _reference: PhantomData<&'a ()>,
235}
236
237impl fmt::Debug for RecordIter<'_> {
238 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
239 write!(f, "RecordIter {{ remaining: {} }}", self.back - self.index)
240 }
241}
242
243impl<'a> RecordIter<'a> {
244 unsafe fn from_raw_vector(ptr: TableGenRecordVectorRef) -> RecordIter<'a> {
245 let len = unsafe { tableGenRecordVectorSize(ptr) };
246 RecordIter {
247 raw: ptr,
248 index: 0,
249 back: len,
250 _reference: PhantomData,
251 }
252 }
253}
254
255impl<'a> Iterator for RecordIter<'a> {
256 type Item = Record<'a>;
257
258 fn next(&mut self) -> Option<Record<'a>> {
259 if self.index >= self.back {
260 return None;
261 }
262 let next = unsafe { tableGenRecordVectorGet(self.raw, self.index) };
263 self.index += 1;
264 if next.is_null() {
265 None
266 } else {
267 unsafe { Some(Record::from_raw(next)) }
268 }
269 }
270
271 fn size_hint(&self) -> (usize, Option<usize>) {
272 let remaining = self.back.saturating_sub(self.index);
273 (remaining, Some(remaining))
274 }
275}
276
277impl<'a> DoubleEndedIterator for RecordIter<'a> {
278 fn next_back(&mut self) -> Option<Record<'a>> {
279 if self.index >= self.back {
280 return None;
281 }
282 self.back -= 1;
283 let next = unsafe { tableGenRecordVectorGet(self.raw, self.back) };
284 if next.is_null() {
285 self.back += 1;
287 None
288 } else {
289 unsafe { Some(Record::from_raw(next)) }
290 }
291 }
292}
293
294impl ExactSizeIterator for RecordIter<'_> {}
295
296impl std::iter::FusedIterator for RecordIter<'_> {}
297
298impl Drop for RecordIter<'_> {
299 fn drop(&mut self) {
300 unsafe { tableGenRecordVectorFree(self.raw) }
301 }
302}
303
304#[cfg(test)]
305mod test {
306 use crate::TableGenParser;
307
308 #[test]
309 fn classes_and_defs() {
310 let rk = TableGenParser::new()
311 .add_source(
312 r#"
313 class A;
314 class B;
315 class C;
316 def D1: A;
317 def D2: B;
318 def D3: C;
319 "#,
320 )
321 .unwrap()
322 .parse()
323 .expect("valid tablegen");
324 rk.classes()
325 .for_each(|i| assert!(i.1.name().unwrap() == i.0.unwrap()));
326 rk.defs()
327 .for_each(|i| assert!(i.1.name().unwrap() == i.0.unwrap()));
328 assert!(rk.classes().map(|i| i.0.unwrap()).eq(["A", "B", "C"]));
329 assert!(rk.defs().map(|i| i.0.unwrap()).eq(["D1", "D2", "D3"]));
330 }
331
332 #[test]
333 fn derived_defs() {
334 let rk = TableGenParser::new()
335 .add_source(
336 r#"
337 class A;
338 class B;
339 class C;
340
341 def D1: A;
342 def D2: A, B;
343 def D3: B, C;
344 "#,
345 )
346 .unwrap()
347 .parse()
348 .expect("valid tablegen");
349 let a = rk.all_derived_definitions("A");
350 assert!(a.map(|i| i.name().unwrap().to_string()).eq(["D1", "D2"]));
351 let b = rk.all_derived_definitions("B");
352 assert!(b.map(|i| i.name().unwrap().to_string()).eq(["D2", "D3"]));
353 }
354
355 #[test]
356 fn single() {
357 let rk = TableGenParser::new()
358 .add_source(
359 r#"
360 class A;
361 def D1;
362 "#,
363 )
364 .unwrap()
365 .parse()
366 .expect("valid tablegen");
367 assert_eq!(rk.class("A").expect("class exists").name().unwrap(), "A");
368 assert_eq!(rk.def("D1").expect("def exists").name().unwrap(), "D1");
369 }
370
371 #[test]
372 fn clone_exhausted_named_iter() {
373 let rk = TableGenParser::new()
374 .add_source("class A; class B;")
375 .unwrap()
376 .parse()
377 .expect("valid tablegen");
378 let mut it = rk.classes();
379 while it.next().is_some() {}
380 let mut cloned = it.clone();
382 assert!(cloned.next().is_none());
383 }
384
385 #[test]
386 fn empty_classes_and_defs() {
387 let rk = TableGenParser::new()
388 .add_source("// empty")
389 .unwrap()
390 .parse()
391 .expect("valid tablegen");
392 assert_eq!(rk.classes().count(), 0);
393 assert_eq!(rk.defs().count(), 0);
394 }
395
396 #[test]
397 fn record_iter_size_hint() {
398 let rk = TableGenParser::new()
399 .add_source(
400 r#"
401 class A;
402 def D1: A;
403 def D2: A;
404 def D3: A;
405 "#,
406 )
407 .unwrap()
408 .parse()
409 .expect("valid tablegen");
410 let mut iter = rk.all_derived_definitions("A");
411 assert_eq!(iter.size_hint(), (3, Some(3)));
412 assert_eq!(iter.len(), 3);
413 iter.next();
414 assert_eq!(iter.size_hint(), (2, Some(2)));
415 iter.next();
416 assert_eq!(iter.size_hint(), (1, Some(1)));
417 iter.next();
418 assert_eq!(iter.size_hint(), (0, Some(0)));
419 assert!(iter.next().is_none());
420 assert_eq!(iter.size_hint(), (0, Some(0)));
421 }
422
423 #[test]
424 fn add_source_interior_null() {
425 let result = TableGenParser::new().add_source("def A;\0invalid");
426 assert!(result.is_err());
427 }
428
429 #[test]
430 fn derived_defs_if_defined_empty_results() {
431 let rk = TableGenParser::new()
432 .add_source("class A; class B; def D1: A;")
433 .unwrap()
434 .parse()
435 .expect("valid tablegen");
436 let b = rk.all_derived_definitions_if_defined("B");
438 assert_eq!(b.count(), 0);
439 }
440
441 #[test]
442 fn named_iter_clone_mid_iteration() {
443 let rk = TableGenParser::new()
444 .add_source("class A; class B; class C;")
445 .unwrap()
446 .parse()
447 .expect("valid tablegen");
448 let mut iter = rk.classes();
449 assert_eq!(iter.next().unwrap().0, Ok("A"));
450 let mut cloned = iter.clone();
452 assert_eq!(iter.next().unwrap().0, Ok("B"));
453 assert_eq!(cloned.next().unwrap().0, Ok("B"));
454 assert_eq!(iter.next().unwrap().0, Ok("C"));
455 assert_eq!(cloned.next().unwrap().0, Ok("C"));
456 assert!(iter.next().is_none());
457 assert!(cloned.next().is_none());
458 }
459
460 #[test]
461 fn derived_defs_if_defined() {
462 let rk = TableGenParser::new()
463 .add_source(
464 r#"
465 class A;
466 def D1: A;
467 def D2: A;
468 "#,
469 )
470 .unwrap()
471 .parse()
472 .expect("valid tablegen");
473 let a = rk.all_derived_definitions_if_defined("A");
475 assert_eq!(
476 a.map(|r| r.name().unwrap().to_string()).collect::<Vec<_>>(),
477 vec!["D1", "D2"]
478 );
479 let b = rk.all_derived_definitions_if_defined("NonExistent");
481 assert_eq!(b.count(), 0);
482 }
483
484 #[test]
485 fn record_iter_double_ended() {
486 let rk = TableGenParser::new()
487 .add_source("class A; def D1: A; def D2: A; def D3: A; def D4: A;")
488 .unwrap()
489 .parse()
490 .expect("valid tablegen");
491 let mut iter = rk.all_derived_definitions("A");
493 assert_eq!(iter.next().unwrap().name().unwrap(), "D1");
494 assert_eq!(iter.next_back().unwrap().name().unwrap(), "D4");
495 assert_eq!(iter.next().unwrap().name().unwrap(), "D2");
496 assert_eq!(iter.next_back().unwrap().name().unwrap(), "D3");
497 assert!(iter.next().is_none());
498 assert!(iter.next_back().is_none());
499 }
500
501 #[test]
502 fn record_iter_size_hint_double_ended() {
503 let rk = TableGenParser::new()
504 .add_source("class A; def D1: A; def D2: A; def D3: A;")
505 .unwrap()
506 .parse()
507 .expect("valid tablegen");
508 let mut iter = rk.all_derived_definitions("A");
509 assert_eq!(iter.len(), 3);
510 iter.next();
511 assert_eq!(iter.len(), 2);
512 iter.next_back();
513 assert_eq!(iter.len(), 1);
514 iter.next();
515 assert_eq!(iter.len(), 0);
516 assert!(iter.next().is_none());
517 assert!(iter.next_back().is_none());
518 }
519}