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