1use paste::paste;
12use std::{ffi::c_void, marker::PhantomData};
13
14use crate::raw::{
15 TableGenRecTyKind::TableGenInvalidRecTyKind as RawInvalidRecTyKind, TableGenRecordRef,
16 TableGenRecordValRef, tableGenIntArrayFree, tableGenRecordDump, tableGenRecordGetDefInit,
17 tableGenRecordGetFieldType, tableGenRecordGetFirstValue, tableGenRecordGetID,
18 tableGenRecordGetLoc, tableGenRecordGetName, tableGenRecordGetNameInit,
19 tableGenRecordGetNumSuperClasses, tableGenRecordGetNumTemplateArgs,
20 tableGenRecordGetSuperClass, tableGenRecordGetTemplateArgName, tableGenRecordGetValue,
21 tableGenRecordGetValueAsBit, tableGenRecordGetValueAsBitsInit, tableGenRecordGetValueAsDag,
22 tableGenRecordGetValueAsDef, tableGenRecordGetValueAsInt, tableGenRecordGetValueAsListInit,
23 tableGenRecordGetValueAsListOfDefs, tableGenRecordGetValueAsListOfInts,
24 tableGenRecordGetValueAsListOfStrings, tableGenRecordGetValueAsOptionalDef,
25 tableGenRecordGetValueAsOptionalString, tableGenRecordGetValueAsString,
26 tableGenRecordHasDirectSuperClass, tableGenRecordIsAnonymous, tableGenRecordIsClass,
27 tableGenRecordIsSubclassOf, tableGenRecordIsValueUnset, tableGenRecordPrint,
28 tableGenRecordRecTyGetClass, tableGenRecordRecTyGetNumClasses, tableGenRecordRecTyIsSubClassOf,
29 tableGenRecordValDump, tableGenRecordValGetBitsWidth, tableGenRecordValGetListElementType,
30 tableGenRecordValGetLoc, tableGenRecordValGetNameInit, tableGenRecordValGetValue,
31 tableGenRecordValIsNonconcreteOK, tableGenRecordValIsTemplateArg, tableGenRecordValNext,
32 tableGenRecordValPrint, tableGenStringRefArrayFree,
33};
34
35use crate::{
36 error::{Error, SourceLoc, SourceLocation, TableGenError, WithLocation},
37 init::{BitInit, BitsInit, DagInit, DefInit, ListInit, StringInit, TypedInit},
38 string_ref::StringRef,
39 util::print_callback,
40};
41use std::fmt::{self, Debug, Display, Formatter};
42
43#[derive(Clone, Copy, PartialEq, Eq)]
49pub struct Record<'a> {
50 raw: TableGenRecordRef,
51 _reference: PhantomData<&'a TableGenRecordRef>,
52}
53
54impl Display for Record<'_> {
55 fn fmt(&self, formatter: &mut Formatter) -> fmt::Result {
56 let mut data = (formatter, Ok(()));
57
58 unsafe {
59 tableGenRecordPrint(
60 self.raw,
61 Some(print_callback),
62 &mut data as *mut _ as *mut c_void,
63 );
64 }
65
66 data.1
67 }
68}
69
70impl Debug for Record<'_> {
71 fn fmt(&self, formatter: &mut Formatter) -> fmt::Result {
72 writeln!(formatter, "Record(")?;
73 Display::fmt(self, formatter)?;
74 write!(formatter, ")")
75 }
76}
77
78impl std::hash::Hash for Record<'_> {
79 fn hash<H: std::hash::Hasher>(&self, state: &mut H) {
80 self.raw.hash(state);
81 }
82}
83
84macro_rules! record_value {
85 ($(#[$attr:meta])* $name:ident, $type:ty) => {
86 paste! {
87 $(#[$attr])*
88 pub fn [<$name _value>](self, name: &str) -> Result<$type, Error> {
89 self.value(name)?.try_into()
90 }
91 }
92 };
93}
94
95impl<'a> Record<'a> {
96 pub unsafe fn from_raw(ptr: TableGenRecordRef) -> Record<'a> {
102 Record {
103 raw: ptr,
104 _reference: PhantomData,
105 }
106 }
107
108 pub fn name(self) -> Result<&'a str, Error> {
114 unsafe { StringRef::from_raw(tableGenRecordGetName(self.raw)) }
115 .try_into()
116 .map_err(TableGenError::from)
117 .map_err(|e| e.with_location(self))
118 }
119
120 record_value!(
121 bits,
124 Vec<bool>
125 );
126 record_value!(
127 code,
132 String
133 );
134 record_value!(
135 code_str,
138 &'a str
139 );
140 record_value!(
141 string,
146 String
147 );
148
149 pub fn value<'n>(self, name: &'n str) -> Result<RecordValue<'a>, Error> {
151 let value = unsafe { tableGenRecordGetValue(self.raw, StringRef::from(name).to_raw()) };
152 if !value.is_null() {
153 Ok(unsafe { RecordValue::from_raw(value) })
154 } else {
155 Err(TableGenError::MissingValue(String::from(name)).with_location(self))
156 }
157 }
158
159 pub fn anonymous(self) -> bool {
161 unsafe { tableGenRecordIsAnonymous(self.raw) > 0 }
162 }
163
164 pub fn subclass_of(self, class: &str) -> bool {
167 unsafe { tableGenRecordIsSubclassOf(self.raw, StringRef::from(class).to_raw()) > 0 }
168 }
169
170 pub fn values(self) -> RecordValueIter<'a> {
174 RecordValueIter::new(self)
175 }
176
177 pub fn has_field(self, name: &str) -> bool {
179 let v = unsafe { tableGenRecordGetValue(self.raw, StringRef::from(name).to_raw()) };
180 !v.is_null()
181 }
182
183 pub fn field_type(self, name: &str) -> Option<crate::raw::TableGenRecTyKind::Type> {
186 use crate::raw::TableGenRecTyKind::TableGenInvalidRecTyKind;
187 let kind = unsafe { tableGenRecordGetFieldType(self.raw, StringRef::from(name).to_raw()) };
188 if kind == TableGenInvalidRecTyKind {
189 None
190 } else {
191 Some(kind)
192 }
193 }
194
195 pub fn dump(self) {
197 unsafe { tableGenRecordDump(self.raw) }
198 }
199
200 pub fn num_template_args(self) -> usize {
202 unsafe { tableGenRecordGetNumTemplateArgs(self.raw) }
203 }
204
205 pub fn template_arg_name(self, index: usize) -> Option<&'a str> {
207 unsafe { StringRef::from_option_raw(tableGenRecordGetTemplateArgName(self.raw, index)) }
208 .and_then(|s| s.try_into().ok())
209 }
210
211 pub fn template_args(self) -> TemplateArgIter<'a> {
213 let back = self.num_template_args();
214 TemplateArgIter {
215 record: self,
216 index: 0,
217 back,
218 }
219 }
220
221 pub fn num_super_classes(self) -> usize {
223 unsafe { tableGenRecordGetNumSuperClasses(self.raw) }
224 }
225
226 pub fn super_class(self, index: usize) -> Option<Record<'a>> {
228 let ptr = unsafe { tableGenRecordGetSuperClass(self.raw, index) };
229 if ptr.is_null() {
230 None
231 } else {
232 Some(unsafe { Record::from_raw(ptr) })
233 }
234 }
235
236 pub fn direct_super_classes(self) -> SuperClassIter<'a> {
238 let back = self.num_super_classes();
239 SuperClassIter {
240 record: self,
241 index: 0,
242 back,
243 }
244 }
245
246 pub fn int_value(self, name: &str) -> Result<i64, Error> {
248 let mut out: i64 = 0;
249 let ok = unsafe {
250 tableGenRecordGetValueAsInt(self.raw, StringRef::from(name).to_raw(), &mut out)
251 };
252 if ok > 0 {
253 Ok(out)
254 } else {
255 Err(TableGenError::MissingValue(name.into()).with_location(self))
256 }
257 }
258
259 pub fn str_value(self, name: &str) -> Result<&'a str, Error> {
261 let raw =
262 unsafe { tableGenRecordGetValueAsString(self.raw, StringRef::from(name).to_raw()) };
263 if raw.data.is_null() {
264 Err(TableGenError::MissingValue(name.into()).with_location(self))
265 } else {
266 unsafe { StringRef::from_raw(raw) }
267 .try_into()
268 .map_err(TableGenError::from)
269 .map_err(|e| e.with_location(self))
270 }
271 }
272
273 pub fn bit_value(self, name: &str) -> Result<bool, Error> {
275 let mut out: i8 = 0;
276 let ok = unsafe {
277 tableGenRecordGetValueAsBit(self.raw, StringRef::from(name).to_raw(), &mut out)
278 };
279 if ok > 0 {
280 Ok(out != 0)
281 } else {
282 Err(TableGenError::MissingValue(name.into()).with_location(self))
283 }
284 }
285
286 pub fn def_value(self, name: &str) -> Result<Record<'a>, Error> {
288 let ptr = unsafe { tableGenRecordGetValueAsDef(self.raw, StringRef::from(name).to_raw()) };
289 if ptr.is_null() {
290 Err(TableGenError::MissingValue(name.into()).with_location(self))
291 } else {
292 Ok(unsafe { Record::from_raw(ptr) })
293 }
294 }
295
296 pub fn dag_value(self, name: &str) -> Result<DagInit<'a>, Error> {
298 let ptr = unsafe { tableGenRecordGetValueAsDag(self.raw, StringRef::from(name).to_raw()) };
299 if ptr.is_null() {
300 Err(TableGenError::MissingValue(name.into()).with_location(self))
301 } else {
302 Ok(unsafe { DagInit::from_raw(ptr) })
303 }
304 }
305
306 pub fn bits_init_value(self, name: &str) -> Result<BitsInit<'a>, Error> {
308 let ptr =
309 unsafe { tableGenRecordGetValueAsBitsInit(self.raw, StringRef::from(name).to_raw()) };
310 if ptr.is_null() {
311 Err(TableGenError::MissingValue(name.into()).with_location(self))
312 } else {
313 Ok(unsafe { BitsInit::from_raw(ptr) })
314 }
315 }
316
317 pub fn list_init_value(self, name: &str) -> Result<ListInit<'a>, Error> {
319 let ptr =
320 unsafe { tableGenRecordGetValueAsListInit(self.raw, StringRef::from(name).to_raw()) };
321 if ptr.is_null() {
322 Err(TableGenError::MissingValue(name.into()).with_location(self))
323 } else {
324 Ok(unsafe { ListInit::from_raw(ptr) })
325 }
326 }
327
328 pub fn list_of_defs_value(self, name: &str) -> Result<Vec<Record<'a>>, Error> {
330 let ptr =
331 unsafe { tableGenRecordGetValueAsListOfDefs(self.raw, StringRef::from(name).to_raw()) };
332 if ptr.is_null() {
333 return Err(TableGenError::MissingValue(name.into()).with_location(self));
334 }
335 let len = unsafe { crate::raw::tableGenRecordVectorSize(ptr) };
336 let mut result = Vec::with_capacity(len);
337 for i in 0..len {
338 let rec = unsafe { crate::raw::tableGenRecordVectorGet(ptr, i) };
339 result.push(unsafe { Record::from_raw(rec) });
340 }
341 unsafe { crate::raw::tableGenRecordVectorFree(ptr) };
342 Ok(result)
343 }
344
345 pub fn list_of_ints_value(self, name: &str) -> Result<Vec<i64>, Error> {
347 let mut arr = std::ptr::null_mut();
348 let mut len: usize = 0;
349 let ok = unsafe {
350 tableGenRecordGetValueAsListOfInts(
351 self.raw,
352 StringRef::from(name).to_raw(),
353 &mut arr,
354 &mut len,
355 )
356 };
357 if ok == 0 {
358 return Err(TableGenError::MissingValue(name.into()).with_location(self));
359 }
360 let result = unsafe { std::slice::from_raw_parts(arr, len) }.to_vec();
361 unsafe { tableGenIntArrayFree(arr) };
362 Ok(result)
363 }
364
365 pub fn list_of_strings_value(self, name: &str) -> Result<Vec<&'a str>, Error> {
367 let mut arr = std::ptr::null_mut();
368 let mut len: usize = 0;
369 let ok = unsafe {
370 tableGenRecordGetValueAsListOfStrings(
371 self.raw,
372 StringRef::from(name).to_raw(),
373 &mut arr,
374 &mut len,
375 )
376 };
377 if ok == 0 {
378 return Err(TableGenError::MissingValue(name.into()).with_location(self));
379 }
380 let raw_refs = unsafe { std::slice::from_raw_parts(arr, len) };
381 let mut result = Vec::with_capacity(len);
382 for raw_ref in raw_refs {
383 let s: &'a str = unsafe { StringRef::from_raw(*raw_ref) }
384 .try_into()
385 .map_err(TableGenError::from)
386 .map_err(|e| e.with_location(self))?;
387 result.push(s);
388 }
389 unsafe { tableGenStringRefArrayFree(arr) };
390 Ok(result)
391 }
392
393 pub fn optional_str_value(self, name: &str) -> Result<Option<&'a str>, Error> {
397 let mut out = crate::raw::TableGenStringRef {
398 data: std::ptr::null(),
399 len: 0,
400 };
401 let ok = unsafe {
402 tableGenRecordGetValueAsOptionalString(
403 self.raw,
404 StringRef::from(name).to_raw(),
405 &mut out,
406 )
407 };
408 if ok == 0 {
409 return Err(TableGenError::MissingValue(name.into()).with_location(self));
410 }
411 if out.data.is_null() {
412 Ok(None)
413 } else {
414 let s: &'a str = unsafe { StringRef::from_raw(out) }
415 .try_into()
416 .map_err(TableGenError::from)
417 .map_err(|e| e.with_location(self))?;
418 Ok(Some(s))
419 }
420 }
421
422 pub fn optional_def_value(self, name: &str) -> Option<Record<'a>> {
424 let ptr = unsafe {
425 tableGenRecordGetValueAsOptionalDef(self.raw, StringRef::from(name).to_raw())
426 };
427 if ptr.is_null() {
428 None
429 } else {
430 Some(unsafe { Record::from_raw(ptr) })
431 }
432 }
433
434 pub fn is_value_unset(self, name: &str) -> bool {
436 unsafe { tableGenRecordIsValueUnset(self.raw, StringRef::from(name).to_raw()) > 0 }
437 }
438
439 pub fn is_class(self) -> bool {
441 unsafe { tableGenRecordIsClass(self.raw) > 0 }
442 }
443
444 pub fn def_init(self) -> DefInit<'a> {
446 unsafe { DefInit::from_raw(tableGenRecordGetDefInit(self.raw)) }
447 }
448
449 pub fn id(self) -> u32 {
451 unsafe { tableGenRecordGetID(self.raw) }
452 }
453
454 pub fn name_init(self) -> TypedInit<'a> {
456 unsafe { TypedInit::from_raw(tableGenRecordGetNameInit(self.raw)) }
457 }
458
459 pub fn has_direct_super_class(self, super_class: Record<'a>) -> bool {
461 unsafe { tableGenRecordHasDirectSuperClass(self.raw, super_class.raw) > 0 }
462 }
463
464 pub fn num_type_classes(self) -> usize {
466 unsafe { tableGenRecordRecTyGetNumClasses(self.raw) }
467 }
468
469 pub fn type_class(self, index: usize) -> Option<Record<'a>> {
471 let ptr = unsafe { tableGenRecordRecTyGetClass(self.raw, index) };
472 if ptr.is_null() {
473 None
474 } else {
475 Some(unsafe { Record::from_raw(ptr) })
476 }
477 }
478
479 pub fn type_is_subclass_of(self, class: Record<'a>) -> bool {
481 unsafe { tableGenRecordRecTyIsSubClassOf(self.raw, class.raw) > 0 }
482 }
483}
484
485impl SourceLoc for Record<'_> {
486 fn source_location(self) -> SourceLocation {
487 unsafe { SourceLocation::from_raw(tableGenRecordGetLoc(self.raw)) }
488 }
489}
490
491macro_rules! try_into {
492 ($type:ty) => {
493 impl<'a> TryFrom<RecordValue<'a>> for $type {
494 type Error = Error;
495
496 fn try_from(record_value: RecordValue<'a>) -> Result<Self, Self::Error> {
497 Self::try_from(record_value.init).map_err(|e| e.set_location(record_value))
498 }
499 }
500 };
501}
502
503try_into!(bool);
504try_into!(Vec<bool>);
505try_into!(Vec<BitInit<'a>>);
506try_into!(i64);
507try_into!(ListInit<'a>);
508try_into!(DagInit<'a>);
509try_into!(Record<'a>);
510try_into!(String);
511try_into!(&'a str);
512
513impl<'a> From<RecordValue<'a>> for TypedInit<'a> {
514 fn from(value: RecordValue<'a>) -> Self {
515 value.init
516 }
517}
518
519#[derive(Debug, Clone, Copy, PartialEq, Eq)]
523pub struct RecordValue<'a> {
524 raw: TableGenRecordValRef,
525 pub name: StringInit<'a>,
526 pub init: TypedInit<'a>,
527 _reference: PhantomData<&'a TableGenRecordRef>,
528}
529
530impl Display for RecordValue<'_> {
531 fn fmt(&self, formatter: &mut Formatter) -> fmt::Result {
532 let mut data = (formatter, Ok(()));
533
534 unsafe {
535 tableGenRecordValPrint(
536 self.raw,
537 Some(print_callback),
538 &mut data as *mut _ as *mut c_void,
539 );
540 }
541
542 data.1
543 }
544}
545
546impl std::hash::Hash for RecordValue<'_> {
547 fn hash<H: std::hash::Hasher>(&self, state: &mut H) {
548 self.raw.hash(state);
549 }
550}
551
552impl RecordValue<'_> {
553 pub unsafe fn from_raw(ptr: TableGenRecordValRef) -> Self {
559 let name = unsafe { StringInit::from_raw(tableGenRecordValGetNameInit(ptr)) };
560 let value = unsafe { TypedInit::from_raw(tableGenRecordValGetValue(ptr)) };
561 Self {
562 name,
563 init: value,
564 raw: ptr,
565 _reference: PhantomData,
566 }
567 }
568
569 pub fn dump(self) {
571 unsafe { tableGenRecordValDump(self.raw) }
572 }
573
574 pub fn is_template_arg(self) -> bool {
576 unsafe { tableGenRecordValIsTemplateArg(self.raw) > 0 }
577 }
578
579 pub fn is_nonconcrete_ok(self) -> bool {
581 unsafe { tableGenRecordValIsNonconcreteOK(self.raw) > 0 }
582 }
583
584 pub fn bits_width(self) -> Option<usize> {
586 let w = unsafe { tableGenRecordValGetBitsWidth(self.raw) };
587 if w == 0 { None } else { Some(w) }
588 }
589
590 pub fn list_element_type(self) -> Option<crate::raw::TableGenRecTyKind::Type> {
592 let k = unsafe { tableGenRecordValGetListElementType(self.raw) };
593 if k == RawInvalidRecTyKind {
594 None
595 } else {
596 Some(k)
597 }
598 }
599}
600
601impl SourceLoc for RecordValue<'_> {
602 fn source_location(self) -> SourceLocation {
603 unsafe { SourceLocation::from_raw(tableGenRecordValGetLoc(self.raw)) }
604 }
605}
606
607#[derive(Debug, Clone)]
609pub struct RecordValueIter<'a> {
610 record: TableGenRecordRef,
611 current: TableGenRecordValRef,
612 _reference: PhantomData<&'a TableGenRecordRef>,
613}
614
615impl<'a> RecordValueIter<'a> {
616 fn new(record: Record<'a>) -> RecordValueIter<'a> {
617 unsafe {
618 RecordValueIter {
619 record: record.raw,
620 current: tableGenRecordGetFirstValue(record.raw),
621 _reference: PhantomData,
622 }
623 }
624 }
625}
626
627impl<'a> Iterator for RecordValueIter<'a> {
628 type Item = RecordValue<'a>;
629
630 fn next(&mut self) -> Option<RecordValue<'a>> {
631 if self.current.is_null() {
632 return None;
633 }
634 let res = unsafe { RecordValue::from_raw(self.current) };
635 self.current = unsafe { tableGenRecordValNext(self.record, self.current) };
636 Some(res)
637 }
638}
639
640impl std::iter::FusedIterator for RecordValueIter<'_> {}
641
642#[derive(Debug, Clone)]
644pub struct TemplateArgIter<'a> {
645 record: Record<'a>,
646 index: usize,
647 back: usize,
648}
649
650impl<'a> Iterator for TemplateArgIter<'a> {
651 type Item = &'a str;
652
653 fn next(&mut self) -> Option<Self::Item> {
654 if self.index >= self.back {
655 return None;
656 }
657 let name = self.record.template_arg_name(self.index);
658 self.index += 1;
659 name
660 }
661
662 fn size_hint(&self) -> (usize, Option<usize>) {
663 let remaining = self.back.saturating_sub(self.index);
664 (remaining, Some(remaining))
665 }
666}
667
668impl<'a> DoubleEndedIterator for TemplateArgIter<'a> {
669 fn next_back(&mut self) -> Option<Self::Item> {
670 if self.index >= self.back {
671 return None;
672 }
673 self.back -= 1;
674 match self.record.template_arg_name(self.back) {
675 Some(name) => Some(name),
676 None => {
677 self.back += 1;
678 None
679 }
680 }
681 }
682}
683
684impl ExactSizeIterator for TemplateArgIter<'_> {}
685
686impl std::iter::FusedIterator for TemplateArgIter<'_> {}
687
688#[derive(Debug, Clone)]
690pub struct SuperClassIter<'a> {
691 record: Record<'a>,
692 index: usize,
693 back: usize,
694}
695
696impl<'a> Iterator for SuperClassIter<'a> {
697 type Item = Record<'a>;
698
699 fn next(&mut self) -> Option<Self::Item> {
700 if self.index >= self.back {
701 return None;
702 }
703 let class = self.record.super_class(self.index);
704 self.index += 1;
705 class
706 }
707
708 fn size_hint(&self) -> (usize, Option<usize>) {
709 let remaining = self.back.saturating_sub(self.index);
710 (remaining, Some(remaining))
711 }
712}
713
714impl<'a> DoubleEndedIterator for SuperClassIter<'a> {
715 fn next_back(&mut self) -> Option<Self::Item> {
716 if self.index >= self.back {
717 return None;
718 }
719 self.back -= 1;
720 match self.record.super_class(self.back) {
721 Some(class) => Some(class),
722 None => {
723 self.back += 1;
724 None
725 }
726 }
727 }
728}
729
730impl ExactSizeIterator for SuperClassIter<'_> {}
731
732impl std::iter::FusedIterator for SuperClassIter<'_> {}
733
734#[cfg(test)]
735mod tests {
736 use super::*;
737 use crate::TableGenParser;
738
739 #[test]
740 fn record() {
741 let rk = TableGenParser::new()
742 .add_source(
743 r#"
744 class A;
745 class B;
746 class C;
747
748 def D1: A;
749 def D2: A, B;
750 def : B, C;
751 "#,
752 )
753 .unwrap()
754 .parse()
755 .expect("valid tablegen");
756 let d2 = rk.def("D2").expect("D2 exists");
757 assert!(d2.subclass_of("A"));
758 assert!(d2.subclass_of("B"));
759 assert!(!d2.subclass_of("C"));
760 assert!(!d2.subclass_of("D"));
761 let anon = rk
762 .defs()
763 .map(|(_name, def)| def)
764 .find(|d| d.anonymous())
765 .expect("anonymous class exists");
766 assert!(!anon.subclass_of("A"));
767 assert!(anon.subclass_of("B"));
768 assert!(anon.subclass_of("C"));
769 }
770
771 #[test]
772 fn single_value() {
773 let rk = TableGenParser::new()
774 .add_source(
775 r#"
776 def A {
777 int size = 42;
778 }
779 "#,
780 )
781 .unwrap()
782 .parse()
783 .expect("valid tablegen");
784 let a = rk.def("A").expect("def A exists");
785 assert_eq!(a.name(), Ok("A"));
786 assert_eq!(a.int_value("size"), Ok(42));
787 assert_eq!(
788 a.value("size")
789 .and_then(|v| {
790 assert!(v.name.to_str() == Ok("size"));
791 v.init.as_int().map_err(|e| e.set_location(v))
792 })
793 .and_then(|i| {
794 i64::try_from(i)
795 .map_err(|e| e.with_location(crate::error::SourceLocation::none()))
796 }),
797 Ok(42)
798 );
799 }
800
801 #[test]
802 fn values() {
803 let rk = TableGenParser::new()
804 .add_source(
805 r#"
806 def A {
807 int a = 5;
808 string n = "hello";
809 }
810 "#,
811 )
812 .unwrap()
813 .parse()
814 .expect("valid tablegen");
815 let a = rk.def("A").expect("def A exists");
816 let values = a.values();
817 assert_eq!(values.clone().count(), 2);
818 for v in values {
819 match v.init {
820 TypedInit::Int(i) => {
821 assert_eq!(v.name.to_str(), Ok("a"));
822 assert_eq!(i64::try_from(i).unwrap(), 5);
823 }
824 TypedInit::String(i) => {
825 assert_eq!(v.name.to_str(), Ok("n"));
826 assert_eq!(i.to_str(), Ok("hello"));
827 }
828 _ => panic!("unexpected type"),
829 }
830 }
831 }
832
833 #[test]
834 fn empty_record_values() {
835 let rk = TableGenParser::new()
836 .add_source("def Empty;")
837 .unwrap()
838 .parse()
839 .expect("valid tablegen");
840 let r = rk.def("Empty").expect("def Empty exists");
841 assert_eq!(r.values().count(), 0);
842 let mut iter = r.values();
844 assert!(iter.next().is_none());
845 assert!(iter.next().is_none());
846 }
847
848 #[test]
849 fn print_error() {
850 let rk = TableGenParser::new()
851 .add_source(
852 r#"
853 class C<int test> {
854 int a = test;
855 }
856 def A : C<4>;
857 "#,
858 )
859 .unwrap()
860 .parse()
861 .expect("valid tablegen");
862 let a = rk.def("A").expect("def A exists");
863 if let Err(e) = a.string_value("a") {
864 let msg = format!("{}", e.clone().add_source_info(rk.source_info()));
866 let msg = msg.trim();
867 #[cfg(any(
869 feature = "llvm16-0",
870 feature = "llvm17-0",
871 feature = "llvm18-0",
872 feature = "llvm19-0",
873 feature = "llvm20-0",
874 feature = "llvm21-0"
875 ))]
876 assert_eq!(
877 msg,
878 r#"
879 error: invalid conversion from Int to alloc::string::String
880 int a = test;
881 ^
882 "#
883 .trim()
884 );
885 #[cfg(feature = "llvm22-0")]
886 assert!(
887 msg.contains("error: invalid conversion from Int to alloc::string::String"),
888 "unexpected error message: {msg}"
889 );
890
891 drop(rk);
893 assert_eq!(
894 format!("{}", e).trim(),
895 r#"
896 invalid conversion from Int to alloc::string::String
897 "#
898 .trim()
899 );
900
901 let rk = TableGenParser::new()
903 .add_source("def A;")
904 .unwrap()
905 .parse()
906 .expect("valid tablegen");
907 assert_eq!(
908 format!("{}", e.add_source_info(rk.source_info())).trim(),
909 "invalid conversion from Int to alloc::string::String\nfailed to print source information: invalid source location"
910 .trim()
911 );
912 } else {
913 panic!("expected error")
914 }
915 }
916
917 #[test]
918 fn has_field() {
919 let rk = TableGenParser::new()
920 .add_source("def A { int x = 1; }")
921 .unwrap()
922 .parse()
923 .expect("valid tablegen");
924 let a = rk.def("A").expect("def A exists");
925 assert!(a.has_field("x"));
926 assert!(!a.has_field("y"));
927 }
928
929 #[test]
930 fn field_type() {
931 use crate::raw::TableGenRecTyKind::{
932 TableGenBitRecTyKind, TableGenIntRecTyKind, TableGenStringRecTyKind,
933 };
934 let rk = TableGenParser::new()
935 .add_source("def A { int i = 1; string s = \"hi\"; bit b = 1; }")
936 .unwrap()
937 .parse()
938 .expect("valid tablegen");
939 let a = rk.def("A").expect("def A exists");
940 assert_eq!(a.field_type("i"), Some(TableGenIntRecTyKind));
941 assert_eq!(a.field_type("s"), Some(TableGenStringRecTyKind));
942 assert_eq!(a.field_type("b"), Some(TableGenBitRecTyKind));
943 assert_eq!(a.field_type("nonexistent"), None);
944 }
945
946 #[test]
947 fn template_args() {
948 let rk = TableGenParser::new()
949 .add_source("class Foo<int x, string y>;")
950 .unwrap()
951 .parse()
952 .expect("valid tablegen");
953 let foo = rk.class("Foo").expect("class Foo exists");
954 assert_eq!(foo.num_template_args(), 2);
955 assert_eq!(foo.template_arg_name(0), Some("Foo:x"));
956 assert_eq!(foo.template_arg_name(1), Some("Foo:y"));
957 assert_eq!(foo.template_arg_name(2), None);
958 let names: Vec<_> = foo.template_args().collect();
959 assert_eq!(names, vec!["Foo:x", "Foo:y"]);
960 let mut iter = foo.template_args();
962 assert_eq!(iter.next_back(), Some("Foo:y"));
963 assert_eq!(iter.next(), Some("Foo:x"));
964 assert!(iter.next().is_none());
965 }
966
967 #[test]
968 fn template_args_on_def() {
969 let rk = TableGenParser::new()
970 .add_source("class A; def D: A;")
971 .unwrap()
972 .parse()
973 .expect("valid tablegen");
974 let d = rk.def("D").expect("def D exists");
975 assert_eq!(d.num_template_args(), 0);
976 assert_eq!(d.template_arg_name(0), None);
977 assert_eq!(d.template_args().count(), 0);
978 }
979
980 #[test]
981 fn template_args_no_params() {
982 let rk = TableGenParser::new()
983 .add_source("class Foo;")
984 .unwrap()
985 .parse()
986 .expect("valid tablegen");
987 let foo = rk.class("Foo").expect("class Foo exists");
988 assert_eq!(foo.num_template_args(), 0);
989 assert_eq!(foo.template_args().count(), 0);
990 let mut iter = foo.template_args();
991 assert!(iter.next().is_none());
992 assert!(iter.next_back().is_none());
993 }
994
995 #[test]
996 fn template_args_len_tracks() {
997 let rk = TableGenParser::new()
998 .add_source("class Foo<int a, int b, int c>;")
999 .unwrap()
1000 .parse()
1001 .expect("valid tablegen");
1002 let foo = rk.class("Foo").expect("class Foo exists");
1003 let mut iter = foo.template_args();
1004 assert_eq!(iter.len(), 3);
1005 iter.next();
1006 assert_eq!(iter.len(), 2);
1007 iter.next_back();
1008 assert_eq!(iter.len(), 1);
1009 iter.next();
1010 assert_eq!(iter.len(), 0);
1011 assert!(iter.next().is_none());
1012 assert!(iter.next_back().is_none());
1013 }
1014
1015 #[test]
1016 fn super_classes() {
1017 let rk = TableGenParser::new()
1018 .add_source(
1019 r#"
1020 class A;
1021 class B;
1022 class C;
1023 def D: A, B, C;
1024 "#,
1025 )
1026 .unwrap()
1027 .parse()
1028 .expect("valid tablegen");
1029 let d = rk.def("D").expect("def D exists");
1030 assert_eq!(d.num_super_classes(), 3);
1031 assert_eq!(d.super_class(0).unwrap().name().unwrap(), "A");
1032 assert_eq!(d.super_class(1).unwrap().name().unwrap(), "B");
1033 assert_eq!(d.super_class(2).unwrap().name().unwrap(), "C");
1034 assert!(d.super_class(3).is_none());
1035 let names: Vec<_> = d
1036 .direct_super_classes()
1037 .map(|r| r.name().unwrap().to_string())
1038 .collect();
1039 assert_eq!(names, vec!["A", "B", "C"]);
1040 let mut iter = d.direct_super_classes();
1042 assert_eq!(iter.next_back().unwrap().name().unwrap(), "C");
1043 assert_eq!(iter.next().unwrap().name().unwrap(), "A");
1044 assert_eq!(iter.next().unwrap().name().unwrap(), "B");
1045 assert!(iter.next().is_none());
1046 }
1047
1048 #[test]
1049 fn super_classes_on_class() {
1050 let rk = TableGenParser::new()
1051 .add_source("class A; class B: A; class C: A, B;")
1052 .unwrap()
1053 .parse()
1054 .expect("valid tablegen");
1055 let b = rk.class("B").expect("class B exists");
1056 assert_eq!(b.num_super_classes(), 1);
1057 assert_eq!(b.super_class(0).unwrap().name().unwrap(), "A");
1058 let c = rk.class("C").expect("class C exists");
1059 assert_eq!(c.num_super_classes(), 2);
1060 let names: Vec<_> = c
1061 .direct_super_classes()
1062 .map(|r| r.name().unwrap().to_string())
1063 .collect();
1064 assert_eq!(names, vec!["A", "B"]);
1065 }
1066
1067 #[test]
1068 fn super_classes_empty() {
1069 let rk = TableGenParser::new()
1070 .add_source("def D;")
1071 .unwrap()
1072 .parse()
1073 .expect("valid tablegen");
1074 let d = rk.def("D").expect("def D exists");
1075 assert_eq!(d.num_super_classes(), 0);
1076 assert!(d.super_class(0).is_none());
1077 assert_eq!(d.direct_super_classes().count(), 0);
1078 let mut iter = d.direct_super_classes();
1079 assert!(iter.next().is_none());
1080 assert!(iter.next_back().is_none());
1081 }
1082
1083 #[test]
1084 fn super_classes_len_tracks() {
1085 let rk = TableGenParser::new()
1086 .add_source("class A; class B; class C; def D: A, B, C;")
1087 .unwrap()
1088 .parse()
1089 .expect("valid tablegen");
1090 let d = rk.def("D").expect("def D exists");
1091 let mut iter = d.direct_super_classes();
1092 assert_eq!(iter.len(), 3);
1093 iter.next();
1094 assert_eq!(iter.len(), 2);
1095 iter.next_back();
1096 assert_eq!(iter.len(), 1);
1097 iter.next();
1098 assert_eq!(iter.len(), 0);
1099 assert!(iter.next().is_none());
1100 assert!(iter.next_back().is_none());
1101 }
1102}