1use std::marker::PhantomData;
12
13#[cfg(any(feature = "llvm18-0", feature = "llvm19-0", feature = "llvm20-0"))]
14use crate::error::TableGenError;
15#[cfg(any(feature = "llvm16-0", feature = "llvm17-0"))]
16use crate::error::{SourceLocation, TableGenError, WithLocation};
17use crate::{
18 Error, SourceInfo, TableGenParser,
19 raw::{
20 TableGenRecordKeeperIteratorRef, TableGenRecordKeeperRef, TableGenRecordVectorRef,
21 tableGenRecordKeeperFree, tableGenRecordKeeperGetAllDerivedDefinitions,
22 tableGenRecordKeeperGetClass, tableGenRecordKeeperGetDef,
23 tableGenRecordKeeperGetFirstClass, tableGenRecordKeeperGetFirstDef,
24 tableGenRecordKeeperGetNextClass, tableGenRecordKeeperGetNextDef,
25 tableGenRecordKeeperItemGetName, tableGenRecordKeeperItemGetRecord,
26 tableGenRecordKeeperIteratorClone, tableGenRecordKeeperIteratorFree,
27 tableGenRecordVectorFree, tableGenRecordVectorGet,
28 },
29 record::Record,
30 string_ref::StringRef,
31};
32
33#[derive(Debug, PartialEq, Eq)]
35pub struct RecordKeeper<'s> {
36 raw: TableGenRecordKeeperRef,
37 pub(crate) parser: TableGenParser<'s>,
38}
39
40impl<'s> RecordKeeper<'s> {
41 pub(crate) unsafe fn from_raw(
42 raw: TableGenRecordKeeperRef,
43 parser: TableGenParser<'s>,
44 ) -> RecordKeeper<'s> {
45 RecordKeeper { raw, parser }
46 }
47
48 pub fn classes(&self) -> NamedRecordIter<'_, IsClass> {
52 unsafe { NamedRecordIter::from_raw(tableGenRecordKeeperGetFirstClass(self.raw)) }
53 }
54
55 pub fn defs(&self) -> NamedRecordIter<'_, IsDef> {
59 unsafe { NamedRecordIter::from_raw(tableGenRecordKeeperGetFirstDef(self.raw)) }
60 }
61
62 pub fn class(&self, name: &str) -> Result<Record<'_>, Error> {
64 unsafe {
65 let class = tableGenRecordKeeperGetClass(self.raw, StringRef::from(name).to_raw());
66 if class.is_null() {
67 Err(TableGenError::MissingClass(name.into()).into())
68 } else {
69 Ok(Record::from_raw(class))
70 }
71 }
72 }
73
74 pub fn def(&self, name: &str) -> Result<Record<'_>, Error> {
76 unsafe {
77 let def = tableGenRecordKeeperGetDef(self.raw, StringRef::from(name).to_raw());
78 if def.is_null() {
79 Err(TableGenError::MissingDef(name.into()).into())
80 } else {
81 Ok(Record::from_raw(def))
82 }
83 }
84 }
85
86 pub fn all_derived_definitions(&self, name: &str) -> RecordIter<'_> {
89 unsafe {
90 RecordIter::from_raw_vector(tableGenRecordKeeperGetAllDerivedDefinitions(
91 self.raw,
92 StringRef::from(name).to_raw(),
93 ))
94 }
95 }
96
97 pub fn source_info(&self) -> SourceInfo<'_> {
98 SourceInfo(&self.parser)
99 }
100}
101
102impl Drop for RecordKeeper<'_> {
103 fn drop(&mut self) {
104 unsafe {
105 tableGenRecordKeeperFree(self.raw);
106 }
107 }
108}
109
110#[doc(hidden)]
111pub struct IsClass;
112#[doc(hidden)]
113pub struct IsDef;
114
115trait NextRecord {
116 unsafe fn next(raw: &mut TableGenRecordKeeperIteratorRef);
117}
118
119impl NextRecord for IsClass {
120 unsafe fn next(raw: &mut TableGenRecordKeeperIteratorRef) {
121 unsafe {
122 tableGenRecordKeeperGetNextClass(raw);
123 }
124 }
125}
126
127impl NextRecord for IsDef {
128 unsafe fn next(raw: &mut TableGenRecordKeeperIteratorRef) {
129 unsafe {
130 tableGenRecordKeeperGetNextDef(raw);
131 }
132 }
133}
134
135#[derive(Debug)]
136pub struct NamedRecordIter<'a, T> {
137 raw: TableGenRecordKeeperIteratorRef,
138 _kind: PhantomData<&'a T>,
139}
140
141impl<T> NamedRecordIter<'_, T> {
142 unsafe fn from_raw(raw: TableGenRecordKeeperIteratorRef) -> Self {
143 NamedRecordIter {
144 raw,
145 _kind: PhantomData,
146 }
147 }
148}
149
150impl<'a, T: NextRecord> Iterator for NamedRecordIter<'a, T> {
151 type Item = (Result<&'a str, std::str::Utf8Error>, Record<'a>);
152
153 fn next(&mut self) -> Option<Self::Item> {
154 let current = if self.raw.is_null() {
155 return None;
156 } else {
157 unsafe {
158 Some((
159 StringRef::from_raw(tableGenRecordKeeperItemGetName(self.raw)).try_into(),
160 Record::from_raw(tableGenRecordKeeperItemGetRecord(self.raw)),
161 ))
162 }
163 };
164 unsafe { T::next(&mut self.raw) };
165 current
166 }
167}
168
169impl<T> Clone for NamedRecordIter<'_, T> {
170 fn clone(&self) -> Self {
171 unsafe { Self::from_raw(tableGenRecordKeeperIteratorClone(self.raw)) }
172 }
173}
174
175impl<T> Drop for NamedRecordIter<'_, T> {
176 fn drop(&mut self) {
177 unsafe { tableGenRecordKeeperIteratorFree(self.raw) }
178 }
179}
180
181pub struct RecordIter<'a> {
182 raw: TableGenRecordVectorRef,
183 index: usize,
184 _reference: PhantomData<&'a ()>,
185}
186
187impl<'a> RecordIter<'a> {
188 unsafe fn from_raw_vector(ptr: TableGenRecordVectorRef) -> RecordIter<'a> {
189 RecordIter {
190 raw: ptr,
191 index: 0,
192 _reference: PhantomData,
193 }
194 }
195}
196
197impl<'a> Iterator for RecordIter<'a> {
198 type Item = Record<'a>;
199
200 fn next(&mut self) -> Option<Record<'a>> {
201 let next = unsafe { tableGenRecordVectorGet(self.raw, self.index) };
202 self.index += 1;
203 if next.is_null() {
204 None
205 } else {
206 unsafe { Some(Record::from_raw(next)) }
207 }
208 }
209}
210
211impl Drop for RecordIter<'_> {
212 fn drop(&mut self) {
213 unsafe { tableGenRecordVectorFree(self.raw) }
214 }
215}
216
217#[cfg(test)]
218mod test {
219 use crate::TableGenParser;
220
221 #[test]
222 fn classes_and_defs() {
223 let rk = TableGenParser::new()
224 .add_source(
225 r#"
226 class A;
227 class B;
228 class C;
229 def D1: A;
230 def D2: B;
231 def D3: C;
232 "#,
233 )
234 .unwrap()
235 .parse()
236 .expect("valid tablegen");
237 rk.classes()
238 .for_each(|i| assert!(i.1.name().unwrap() == i.0.unwrap()));
239 rk.defs()
240 .for_each(|i| assert!(i.1.name().unwrap() == i.0.unwrap()));
241 assert!(rk.classes().map(|i| i.0.unwrap()).eq(["A", "B", "C"]));
242 assert!(rk.defs().map(|i| i.0.unwrap()).eq(["D1", "D2", "D3"]));
243 }
244
245 #[test]
246 fn derived_defs() {
247 let rk = TableGenParser::new()
248 .add_source(
249 r#"
250 class A;
251 class B;
252 class C;
253
254 def D1: A;
255 def D2: A, B;
256 def D3: B, C;
257 "#,
258 )
259 .unwrap()
260 .parse()
261 .expect("valid tablegen");
262 let a = rk.all_derived_definitions("A");
263 assert!(a.map(|i| i.name().unwrap().to_string()).eq(["D1", "D2"]));
264 let b = rk.all_derived_definitions("B");
265 assert!(b.map(|i| i.name().unwrap().to_string()).eq(["D2", "D3"]));
266 }
267
268 #[test]
269 fn single() {
270 let rk = TableGenParser::new()
271 .add_source(
272 r#"
273 class A;
274 def D1;
275 "#,
276 )
277 .unwrap()
278 .parse()
279 .expect("valid tablegen");
280 assert_eq!(rk.class("A").expect("class exists").name().unwrap(), "A");
281 assert_eq!(rk.def("D1").expect("def exists").name().unwrap(), "D1");
282 }
283}