tblgen/
record_keeper.rs

1// Original work Copyright 2016 Alexander Stocko <as@coder.gg>.
2// Modified work Copyright 2023 Daan Vanoverloop
3// See the COPYRIGHT file at the top-level directory of this distribution.
4//
5// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
6// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
7// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
8// option. This file may not be copied, modified, or distributed
9// except according to those terms.
10
11use 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/// Struct that holds all records from a TableGen file.
43#[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    /// Returns an iterator over all classes.
58    ///
59    /// The iterator yields tuples of type `(String, Record)`.
60    pub fn classes(&self) -> NamedRecordIter<'_, IsClass> {
61        unsafe { NamedRecordIter::from_raw(tableGenRecordKeeperGetFirstClass(self.raw)) }
62    }
63
64    /// Returns an iterator over all definitions.
65    ///
66    /// The iterator yields tuples of type `(String, Record)`.
67    pub fn defs(&self) -> NamedRecordIter<'_, IsDef> {
68        unsafe { NamedRecordIter::from_raw(tableGenRecordKeeperGetFirstDef(self.raw)) }
69    }
70
71    /// Returns the class with the given name.
72    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    /// Returns the definition with the given name.
84    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    /// Returns an iterator over all definitions that derive from the class with
96    /// the given name.
97    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    /// Returns an iterator over all definitions that derive from the class with
107    /// the given name. Returns an empty iterator if the class is not defined.
108    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    /// Returns the input filename.
122    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    /// Returns the global variable with the given name, if it exists.
130    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/// Iterator over named records (classes or definitions) in a [`RecordKeeper`].
175#[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
229/// Iterator over records derived from a given class in a [`RecordKeeper`].
230pub 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            // Restore back so the element is not silently skipped on the next call.
286            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        // Must not segfault when cloning an exhausted iterator.
381        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        // B exists but nothing derives from it
437        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        // Clone mid-iteration; both should continue independently
451        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        // Existing class
474        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        // Non-existing class returns empty
480        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        // Collect from both ends alternately.
492        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}