Skip to main content

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    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/// Struct that holds all records from a TableGen file.
44#[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    /// Returns an iterator over all classes.
59    ///
60    /// The iterator yields tuples of type `(String, Record)`.
61    pub fn classes(&self) -> NamedRecordIter<'_, IsClass> {
62        unsafe { NamedRecordIter::from_raw(tableGenRecordKeeperGetFirstClass(self.raw)) }
63    }
64
65    /// Returns an iterator over all definitions.
66    ///
67    /// The iterator yields tuples of type `(String, Record)`.
68    pub fn defs(&self) -> NamedRecordIter<'_, IsDef> {
69        unsafe { NamedRecordIter::from_raw(tableGenRecordKeeperGetFirstDef(self.raw)) }
70    }
71
72    /// Returns the class with the given name.
73    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    /// Returns the definition with the given name.
85    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    /// Returns an iterator over all definitions that derive from the class with
97    /// the given name.
98    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    /// Returns an iterator over all definitions that derive from the class with
108    /// the given name. Returns an empty iterator if the class is not defined.
109    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    /// Returns the input filename.
123    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    /// Returns the global variable with the given name, if it exists.
131    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/// Iterator over named records (classes or definitions) in a [`RecordKeeper`].
176#[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
230/// Iterator over records derived from a given class in a [`RecordKeeper`].
231pub 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            // Restore back so the element is not silently skipped on the next call.
287            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        // Must not segfault when cloning an exhausted iterator.
382        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        // B exists but nothing derives from it
438        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        // Clone mid-iteration; both should continue independently
452        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        // Existing class
475        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        // Non-existing class returns empty
481        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        // Collect from both ends alternately.
493        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}