1#[cfg(feature = "llvm22-0")]
19use crate::raw::tableGenBitsInitConvertKnownBitsToInt;
20use crate::{
21 raw::{
22 TableGenRecTyKind, TableGenTypedInitRef, tableGenBitInitGetValue, tableGenBitInitIsVarBit,
23 tableGenBitsInitGetBitInit, tableGenBitsInitGetNumBits, tableGenDagRecordArgName,
24 tableGenDagRecordGet, tableGenDagRecordGetArgNo, tableGenDagRecordNumArgs,
25 tableGenDagRecordOperator, tableGenDefInitGetValue, tableGenInitDump, tableGenInitPrint,
26 tableGenInitRecType, tableGenIntInitGetValue, tableGenListInitGetElementType,
27 tableGenListRecordGet, tableGenListRecordNumElements, tableGenStringInitGetValue,
28 tableGenVarBitInitGetBitNum, tableGenVarBitInitGetVarName,
29 },
30 string_ref::StringRef,
31 util::print_callback,
32};
33use paste::paste;
34
35use crate::{
36 error::{Error, TableGenError},
37 record::Record,
38};
39use std::{
40 ffi::c_void,
41 fmt::{self, Debug, Display, Formatter},
42 marker::PhantomData,
43 str::Utf8Error,
44 string::FromUtf8Error,
45};
46
47#[derive(Clone, Copy, PartialEq, Eq)]
49pub enum TypedInit<'a> {
50 Bit(BitInit<'a>),
51 Bits(BitsInit<'a>),
52 Code(StringInit<'a>),
53 Int(IntInit<'a>),
54 String(StringInit<'a>),
55 List(ListInit<'a>),
56 Dag(DagInit<'a>),
57 Def(DefInit<'a>),
58 Invalid,
59}
60
61impl TypedInit<'_> {
62 fn variant_name(&self) -> &'static str {
63 match self {
64 TypedInit::Bit(_) => "Bit",
65 TypedInit::Bits(_) => "Bits",
66 TypedInit::Code(_) => "Code",
67 TypedInit::Int(_) => "Int",
68 TypedInit::String(_) => "String",
69 TypedInit::List(_) => "List",
70 TypedInit::Dag(_) => "Dag",
71 TypedInit::Def(_) => "Def",
72 TypedInit::Invalid => "Invalid",
73 }
74 }
75}
76
77impl Display for TypedInit<'_> {
78 fn fmt(&self, f: &mut Formatter) -> fmt::Result {
79 match self {
80 Self::Bit(init) => write!(f, "{}", &init),
81 Self::Bits(init) => write!(f, "{}", &init),
82 Self::Code(init) => write!(f, "{}", &init),
83 Self::Int(init) => write!(f, "{}", &init),
84 Self::String(init) => write!(f, "{}", &init),
85 Self::List(init) => write!(f, "{}", &init),
86 Self::Dag(init) => write!(f, "{}", &init),
87 Self::Def(init) => write!(f, "{}", &init),
88 Self::Invalid => write!(f, "Invalid"),
89 }
90 }
91}
92
93impl Debug for TypedInit<'_> {
94 fn fmt(&self, f: &mut Formatter) -> fmt::Result {
95 write!(f, "TypedInit(")?;
96 let name = self.variant_name();
97 write!(f, "{name}(")?;
98 match self {
99 Self::Bit(init) => write!(f, "{:#?}", &init),
100 Self::Bits(init) => write!(f, "{:#?}", &init),
101 Self::Code(init) => write!(f, "{:#?}", &init),
102 Self::Int(init) => write!(f, "{:#?}", &init),
103 Self::String(init) => write!(f, "{:#?}", &init),
104 Self::List(init) => write!(f, "{:#?}", &init),
105 Self::Dag(init) => write!(f, "{:#?}", &init),
106 Self::Def(init) => write!(f, "{:#?}", &init),
107 Self::Invalid => write!(f, ""),
108 }?;
109 write!(f, "))")
110 }
111}
112
113impl std::hash::Hash for TypedInit<'_> {
114 fn hash<H: std::hash::Hasher>(&self, state: &mut H) {
115 std::mem::discriminant(self).hash(state);
116 match self {
117 Self::Bit(v) => v.hash(state),
118 Self::Bits(v) => v.hash(state),
119 Self::Code(v) => v.hash(state),
120 Self::Int(v) => v.hash(state),
121 Self::String(v) => v.hash(state),
122 Self::List(v) => v.hash(state),
123 Self::Dag(v) => v.hash(state),
124 Self::Def(v) => v.hash(state),
125 Self::Invalid => {}
126 }
127 }
128}
129
130macro_rules! as_inner {
131 ($name:ident, $variant:ident, $type:ty) => {
132 paste! {
133 pub fn [<as_ $name>](self) -> Result<$type<'a>, Error> {
134 match self {
135 Self::$variant(v) => Ok(v),
136 _ => Err(TableGenError::InitConversion {
137 from: self.variant_name(),
138 to: std::any::type_name::<$type>()
139 }.into())
140 }
141 }
142 }
143 };
144}
145
146macro_rules! try_into {
147 ($variant:ident, $init:ty, $type:ty) => {
148 impl<'a> TryFrom<TypedInit<'a>> for $type {
149 type Error = Error;
150
151 fn try_from(value: TypedInit<'a>) -> Result<Self, Self::Error> {
152 match value {
153 TypedInit::$variant(v) => Ok(Self::try_from(v).map_err(TableGenError::from)?),
154 _ => Err(TableGenError::InitConversion {
155 from: value.variant_name(),
156 to: std::any::type_name::<$type>(),
157 }
158 .into()),
159 }
160 }
161 }
162 };
163}
164
165try_into!(Bit, BitInit<'a>, bool);
166try_into!(Bits, BitsInit<'a>, Vec<BitInit<'a>>);
167try_into!(Bits, BitsInit<'a>, Vec<bool>);
168try_into!(Int, IntInit<'a>, i64);
169try_into!(Def, DefInit<'a>, Record<'a>);
170try_into!(List, ListInit<'a>, ListInit<'a>);
171try_into!(Dag, DagInit<'a>, DagInit<'a>);
172
173impl<'a> TryFrom<TypedInit<'a>> for String {
174 type Error = Error;
175
176 fn try_from(value: TypedInit<'a>) -> Result<Self, Self::Error> {
177 match value {
178 TypedInit::String(v) | TypedInit::Code(v) => {
179 Ok(Self::try_from(v).map_err(TableGenError::from)?)
180 }
181 _ => Err(TableGenError::InitConversion {
182 from: value.variant_name(),
183 to: std::any::type_name::<String>(),
184 }
185 .into()),
186 }
187 }
188}
189
190impl<'a> TryFrom<TypedInit<'a>> for &'a str {
191 type Error = Error;
192
193 fn try_from(value: TypedInit<'a>) -> Result<Self, Self::Error> {
194 match value {
195 TypedInit::String(v) | TypedInit::Code(v) => {
196 Ok(v.to_str().map_err(TableGenError::from)?)
197 }
198 _ => Err(TableGenError::InitConversion {
199 from: value.variant_name(),
200 to: std::any::type_name::<&'a str>(),
201 }
202 .into()),
203 }
204 }
205}
206
207impl<'a> TypedInit<'a> {
208 as_inner!(bit, Bit, BitInit);
209 as_inner!(bits, Bits, BitsInit);
210 as_inner!(code, Code, StringInit);
211 as_inner!(int, Int, IntInit);
212 as_inner!(string, String, StringInit);
213 as_inner!(list, List, ListInit);
214 as_inner!(dag, Dag, DagInit);
215 as_inner!(def, Def, DefInit);
216
217 #[allow(non_upper_case_globals)]
223 pub unsafe fn from_raw(init: TableGenTypedInitRef) -> Self {
224 use TableGenRecTyKind::*;
225
226 match unsafe { tableGenInitRecType(init) } {
227 TableGenBitRecTyKind => Self::Bit(unsafe { BitInit::from_raw(init) }),
228 TableGenBitsRecTyKind => Self::Bits(unsafe { BitsInit::from_raw(init) }),
229 TableGenCodeRecTyKind => Self::Code(unsafe { StringInit::from_raw(init) }),
230 TableGenIntRecTyKind => TypedInit::Int(unsafe { IntInit::from_raw(init) }),
231 TableGenStringRecTyKind => Self::String(unsafe { StringInit::from_raw(init) }),
232 TableGenListRecTyKind => TypedInit::List(unsafe { ListInit::from_raw(init) }),
233 TableGenDagRecTyKind => TypedInit::Dag(unsafe { DagInit::from_raw(init) }),
234 TableGenRecordRecTyKind => Self::Def(unsafe { DefInit::from_raw(init) }),
235 _ => Self::Invalid,
236 }
237 }
238}
239
240macro_rules! init {
241 ($name:ident) => {
242 #[derive(Clone, Copy, PartialEq, Eq)]
243 pub struct $name<'a> {
244 raw: TableGenTypedInitRef,
245 _reference: PhantomData<&'a TableGenTypedInitRef>,
246 }
247
248 impl<'a> $name<'a> {
249 pub unsafe fn from_raw(raw: TableGenTypedInitRef) -> Self {
255 Self {
256 raw,
257 _reference: PhantomData,
258 }
259 }
260
261 pub fn dump(self) {
263 unsafe { tableGenInitDump(self.raw) }
264 }
265 }
266
267 impl std::hash::Hash for $name<'_> {
268 fn hash<H: std::hash::Hasher>(&self, state: &mut H) {
269 self.raw.hash(state);
270 }
271 }
272
273 impl<'a> Display for $name<'a> {
274 fn fmt(&self, formatter: &mut Formatter) -> fmt::Result {
275 let mut data = (formatter, Ok(()));
276
277 unsafe {
278 tableGenInitPrint(
279 self.raw,
280 Some(print_callback),
281 &mut data as *mut _ as *mut c_void,
282 );
283 }
284
285 data.1
286 }
287 }
288
289 impl<'a> Debug for $name<'a> {
290 fn fmt(&self, formatter: &mut Formatter) -> fmt::Result {
291 write!(formatter, "{}(", stringify!($name))?;
292 Display::fmt(self, formatter)?;
293 write!(formatter, ")")
294 }
295 }
296 };
297}
298
299init!(BitInit);
300
301impl<'a> BitInit<'a> {
302 pub fn is_var_bit(self) -> bool {
305 unsafe { tableGenBitInitIsVarBit(self.raw) != 0 }
306 }
307
308 pub fn as_var_bit(self) -> Option<(&'a str, usize)> {
311 if !self.is_var_bit() {
312 return None;
313 }
314 let name_ref = unsafe { tableGenVarBitInitGetVarName(self.raw) };
315 if name_ref.data.is_null() {
316 return None;
317 }
318 let name = unsafe {
319 std::str::from_utf8(std::slice::from_raw_parts(
320 name_ref.data as *const u8,
321 name_ref.len,
322 ))
323 .ok()?
324 };
325 let bit_num = unsafe { tableGenVarBitInitGetBitNum(self.raw) };
326 Some((name, bit_num))
327 }
328
329 pub fn as_literal(self) -> Option<bool> {
332 if self.is_var_bit() {
333 return None;
334 }
335 let mut bit = -1i8;
336 let ok = unsafe { tableGenBitInitGetValue(self.raw, &mut bit) };
337 if ok > 0 && (bit == 0 || bit == 1) {
338 Some(bit != 0)
339 } else {
340 None
341 }
342 }
343}
344
345impl<'a> TryFrom<BitInit<'a>> for bool {
346 type Error = TableGenError;
347
348 fn try_from(value: BitInit<'a>) -> Result<Self, Self::Error> {
349 value.as_literal().ok_or(TableGenError::InitConversion {
350 from: "VarBitInit",
351 to: "bool",
352 })
353 }
354}
355
356init!(BitsInit);
357
358impl<'a> From<BitsInit<'a>> for Vec<BitInit<'a>> {
359 fn from(value: BitsInit<'a>) -> Self {
360 (0..value.num_bits())
361 .map(|i| value.bit(i).expect("index within range"))
362 .collect()
363 }
364}
365
366impl<'a> TryFrom<BitsInit<'a>> for Vec<bool> {
367 type Error = TableGenError;
368
369 fn try_from(value: BitsInit<'a>) -> Result<Self, Self::Error> {
370 (0..value.num_bits())
371 .map(|i| {
372 value
373 .bit(i)
374 .ok_or(TableGenError::InitConversion {
375 from: "BitsInit",
376 to: "bool",
377 })
378 .and_then(bool::try_from)
379 })
380 .collect()
381 }
382}
383
384impl<'a> From<BitsInit<'a>> for Vec<Option<bool>> {
385 fn from(value: BitsInit<'a>) -> Self {
386 (0..value.num_bits())
387 .map(|i| value.bit(i).expect("index within range").as_literal())
388 .collect()
389 }
390}
391
392impl<'a> BitsInit<'a> {
393 pub fn bit(self, index: usize) -> Option<BitInit<'a>> {
395 let bit = unsafe { tableGenBitsInitGetBitInit(self.raw, index) };
396 if !bit.is_null() {
397 Some(unsafe { BitInit::from_raw(bit) })
398 } else {
399 None
400 }
401 }
402
403 pub fn num_bits(self) -> usize {
405 let mut len = 0;
406 unsafe { tableGenBitsInitGetNumBits(self.raw, &mut len) };
407 len
408 }
409
410 #[cfg(feature = "llvm22-0")]
414 pub fn known_bits_to_int(self) -> u64 {
415 unsafe { tableGenBitsInitConvertKnownBitsToInt(self.raw) }
416 }
417}
418
419init!(IntInit);
420
421impl<'a> TryFrom<IntInit<'a>> for i64 {
422 type Error = TableGenError;
423
424 fn try_from(value: IntInit<'a>) -> Result<Self, Self::Error> {
425 let mut int: i64 = 0;
426 let res = unsafe { tableGenIntInitGetValue(value.raw, &mut int) };
427 if res > 0 {
428 Ok(int)
429 } else {
430 Err(TableGenError::InitConversion {
431 from: "Int",
432 to: "i64",
433 })
434 }
435 }
436}
437
438init!(StringInit);
439
440impl<'a> TryFrom<StringInit<'a>> for String {
441 type Error = FromUtf8Error;
442
443 fn try_from(value: StringInit<'a>) -> Result<Self, Self::Error> {
444 String::from_utf8(value.as_bytes().to_vec())
445 }
446}
447
448impl<'a> TryFrom<StringInit<'a>> for &'a str {
449 type Error = Utf8Error;
450
451 fn try_from(value: StringInit<'a>) -> Result<Self, Utf8Error> {
452 value.to_str()
453 }
454}
455
456impl<'a> StringInit<'a> {
457 pub fn to_str(self) -> Result<&'a str, Utf8Error> {
463 unsafe { StringRef::from_raw(tableGenStringInitGetValue(self.raw)) }.try_into()
464 }
465
466 pub fn as_bytes(self) -> &'a [u8] {
468 unsafe { StringRef::from_raw(tableGenStringInitGetValue(self.raw)) }.into()
469 }
470}
471
472init!(DefInit);
473
474impl<'a> From<DefInit<'a>> for Record<'a> {
475 fn from(value: DefInit<'a>) -> Self {
476 unsafe { Record::from_raw(tableGenDefInitGetValue(value.raw)) }
477 }
478}
479
480init!(DagInit);
481
482impl<'a> DagInit<'a> {
483 pub fn args(self) -> DagIter<'a> {
491 let back = self.num_args();
492 DagIter {
493 dag: self,
494 index: 0,
495 back,
496 }
497 }
498
499 pub fn operator(self) -> Record<'a> {
501 unsafe { Record::from_raw(tableGenDagRecordOperator(self.raw)) }
502 }
503
504 pub fn num_args(self) -> usize {
506 unsafe { tableGenDagRecordNumArgs(self.raw) }
507 }
508
509 pub fn name(self, index: usize) -> Option<&'a str> {
511 unsafe { StringRef::from_option_raw(tableGenDagRecordArgName(self.raw, index)) }
512 .and_then(|s| s.try_into().ok())
513 }
514
515 pub fn arg_no(self, name: &str) -> Option<usize> {
517 let result = unsafe { tableGenDagRecordGetArgNo(self.raw, StringRef::from(name).to_raw()) };
518 if result == usize::MAX {
519 None
520 } else {
521 Some(result)
522 }
523 }
524
525 pub fn get(self, index: usize) -> Option<TypedInit<'a>> {
527 let value = unsafe { tableGenDagRecordGet(self.raw, index) };
528 if !value.is_null() {
529 Some(unsafe { TypedInit::from_raw(value) })
530 } else {
531 None
532 }
533 }
534}
535
536#[derive(Debug, Clone)]
538pub struct DagIter<'a> {
539 dag: DagInit<'a>,
540 index: usize,
541 back: usize,
542}
543
544impl<'a> Iterator for DagIter<'a> {
545 type Item = (Option<&'a str>, TypedInit<'a>);
546
547 fn next(&mut self) -> Option<Self::Item> {
548 if self.index >= self.back {
549 return None;
550 }
551 let next = self.dag.get(self.index)?;
552 let name = self.dag.name(self.index);
553 self.index += 1;
554 Some((name, next))
555 }
556
557 fn size_hint(&self) -> (usize, Option<usize>) {
558 let remaining = self.back.saturating_sub(self.index);
559 (remaining, Some(remaining))
560 }
561}
562
563impl<'a> DoubleEndedIterator for DagIter<'a> {
564 fn next_back(&mut self) -> Option<Self::Item> {
565 if self.index >= self.back {
566 return None;
567 }
568 self.back -= 1;
569 match self.dag.get(self.back) {
570 Some(next) => {
571 let name = self.dag.name(self.back);
572 Some((name, next))
573 }
574 None => {
575 self.back += 1;
576 None
577 }
578 }
579 }
580}
581
582impl ExactSizeIterator for DagIter<'_> {}
583
584impl std::iter::FusedIterator for DagIter<'_> {}
585
586init!(ListInit);
587
588impl<'a> ListInit<'a> {
589 pub fn iter(self) -> ListIter<'a> {
593 let back = self.len();
594 ListIter {
595 list: self,
596 index: 0,
597 back,
598 }
599 }
600
601 pub fn is_empty(self) -> bool {
603 self.len() == 0
604 }
605
606 pub fn len(self) -> usize {
608 unsafe { tableGenListRecordNumElements(self.raw) }
609 }
610
611 pub fn get(self, index: usize) -> Option<TypedInit<'a>> {
613 let value = unsafe { tableGenListRecordGet(self.raw, index) };
614 if !value.is_null() {
615 Some(unsafe { TypedInit::from_raw(value) })
616 } else {
617 None
618 }
619 }
620
621 pub fn element_type(self) -> Option<crate::raw::TableGenRecTyKind::Type> {
623 use crate::raw::TableGenRecTyKind::TableGenInvalidRecTyKind;
624 let kind = unsafe { tableGenListInitGetElementType(self.raw) };
625 if kind == TableGenInvalidRecTyKind {
626 None
627 } else {
628 Some(kind)
629 }
630 }
631}
632
633#[derive(Debug, Clone)]
635pub struct ListIter<'a> {
636 list: ListInit<'a>,
637 index: usize,
638 back: usize,
639}
640
641impl<'a> Iterator for ListIter<'a> {
642 type Item = TypedInit<'a>;
643
644 fn next(&mut self) -> Option<TypedInit<'a>> {
645 if self.index >= self.back {
646 return None;
647 }
648 let next = unsafe { tableGenListRecordGet(self.list.raw, self.index) };
649 self.index += 1;
650 if !next.is_null() {
651 Some(unsafe { TypedInit::from_raw(next) })
652 } else {
653 None
654 }
655 }
656
657 fn size_hint(&self) -> (usize, Option<usize>) {
658 let remaining = self.back.saturating_sub(self.index);
659 (remaining, Some(remaining))
660 }
661}
662
663impl<'a> DoubleEndedIterator for ListIter<'a> {
664 fn next_back(&mut self) -> Option<TypedInit<'a>> {
665 if self.index >= self.back {
666 return None;
667 }
668 self.back -= 1;
669 let next = unsafe { tableGenListRecordGet(self.list.raw, self.back) };
670 if !next.is_null() {
671 Some(unsafe { TypedInit::from_raw(next) })
672 } else {
673 self.back += 1;
675 None
676 }
677 }
678}
679
680impl ExactSizeIterator for ListIter<'_> {}
681
682impl std::iter::FusedIterator for ListIter<'_> {}
683
684#[cfg(test)]
685mod tests {
686 use super::*;
687 use crate::TableGenParser;
688
689 macro_rules! test_init {
690 ($name:ident, $td_field:expr, $expected:expr) => {
691 #[test]
692 fn $name() {
693 let rk = TableGenParser::new()
694 .add_source(&format!(
695 "
696 def A {{
697 {}
698 }}
699 ",
700 $td_field
701 ))
702 .unwrap()
703 .parse()
704 .expect("valid tablegen");
705 let a = rk
706 .def("A")
707 .expect("def A exists")
708 .value("a")
709 .expect("field a exists");
710 assert_eq!(a.init.try_into(), Ok($expected));
711 }
712 };
713 }
714
715 test_init!(bit, "bit a = 0;", false);
716 test_init!(
717 bits,
718 "bits<4> a = { 0, 0, 1, 0 };",
719 vec![false, true, false, false]
720 );
721 test_init!(int, "int a = 42;", 42);
722 test_init!(string, "string a = \"hi\";", "hi");
723 test_init!(code, "code a = \"hi\";", "hi");
724
725 #[test]
726 fn dag() {
727 let rk = TableGenParser::new()
728 .add_source(
729 "
730 def ins;
731 def X {
732 int i = 4;
733 }
734 def Y {
735 string s = \"test\";
736 }
737 def A {
738 dag args = (ins X:$src1, Y:$src2);
739 }
740 ",
741 )
742 .unwrap()
743 .parse()
744 .expect("valid tablegen");
745 let a: DagInit = rk
746 .def("A")
747 .expect("def A exists")
748 .value("args")
749 .expect("field args exists")
750 .try_into()
751 .expect("is dag init");
752 assert_eq!(a.num_args(), 2);
753 assert_eq!(a.operator().name(), Ok("ins"));
754 let mut args = a.args();
755 assert_eq!(
756 args.clone().next().map(|(name, init)| (
757 name,
758 Record::try_from(init).expect("is record").int_value("i")
759 )),
760 Some((Some("src1"), Ok(4)))
761 );
762 assert_eq!(
763 args.nth(1).map(|(name, init)| (
764 name,
765 Record::try_from(init).expect("is record").string_value("s")
766 )),
767 Some((Some("src2"), Ok("test".into())))
768 );
769 }
770
771 #[test]
772 fn dag_unnamed_args() {
773 let rk = TableGenParser::new()
774 .add_source(
775 "
776 def add;
777 def X { int i = 1; }
778 def Y { int i = 2; }
779 def A {
780 dag args = (add X, Y);
781 }
782 ",
783 )
784 .unwrap()
785 .parse()
786 .expect("valid tablegen");
787 let a: DagInit = rk
788 .def("A")
789 .expect("def A exists")
790 .value("args")
791 .expect("field args exists")
792 .try_into()
793 .expect("is dag init");
794 assert_eq!(a.num_args(), 2);
795 let collected: Vec<_> = a
796 .args()
797 .map(|(name, init)| {
798 (
799 name,
800 Record::try_from(init).expect("is record").int_value("i"),
801 )
802 })
803 .collect();
804 assert_eq!(collected, vec![(None, Ok(1)), (None, Ok(2))]);
805 }
806
807 #[test]
808 fn dag_mixed_named_unnamed_args() {
809 let rk = TableGenParser::new()
810 .add_source(
811 "
812 def op;
813 def X { int i = 10; }
814 def Y { int i = 20; }
815 def A {
816 dag args = (op X:$named, Y);
817 }
818 ",
819 )
820 .unwrap()
821 .parse()
822 .expect("valid tablegen");
823 let a: DagInit = rk
824 .def("A")
825 .expect("def A exists")
826 .value("args")
827 .expect("field args exists")
828 .try_into()
829 .expect("is dag init");
830 assert_eq!(a.num_args(), 2);
831 let collected: Vec<_> = a
832 .args()
833 .map(|(name, init)| {
834 (
835 name,
836 Record::try_from(init).expect("is record").int_value("i"),
837 )
838 })
839 .collect();
840 assert_eq!(collected, vec![(Some("named"), Ok(10)), (None, Ok(20))]);
841 }
842
843 #[test]
844 fn list() {
845 let rk = TableGenParser::new()
846 .add_source(
847 "
848 def A {
849 list<int> l = [0, 1, 2, 3];
850 }
851 ",
852 )
853 .unwrap()
854 .parse()
855 .expect("valid tablegen");
856 let l: ListInit = rk
857 .def("A")
858 .expect("def A exists")
859 .value("l")
860 .expect("field args exists")
861 .try_into()
862 .expect("is list init");
863 assert_eq!(l.len(), 4);
864 let iter = l.iter();
865 assert_eq!(iter.clone().count(), 4);
866 assert_eq!(iter.clone().next().unwrap().try_into(), Ok(0));
867 assert_eq!(iter.clone().nth(1).unwrap().try_into(), Ok(1));
868 assert_eq!(iter.clone().nth(2).unwrap().try_into(), Ok(2));
869 assert_eq!(iter.clone().nth(3).unwrap().try_into(), Ok(3));
870 }
871
872 #[test]
873 fn list_double_ended() {
874 let rk = TableGenParser::new()
875 .add_source("def A { list<int> l = [10, 20, 30, 40]; }")
876 .unwrap()
877 .parse()
878 .expect("valid tablegen");
879 let l: ListInit = rk.def("A").unwrap().value("l").unwrap().try_into().unwrap();
880 let mut iter = l.iter();
881 assert_eq!(iter.len(), 4);
882 assert_eq!(iter.next().unwrap().try_into(), Ok(10i64));
883 assert_eq!(iter.len(), 3);
884 assert_eq!(iter.next_back().unwrap().try_into(), Ok(40i64));
885 assert_eq!(iter.len(), 2);
886 assert_eq!(iter.next().unwrap().try_into(), Ok(20i64));
887 assert_eq!(iter.next_back().unwrap().try_into(), Ok(30i64));
888 assert_eq!(iter.len(), 0);
889 assert!(iter.next().is_none());
890 assert!(iter.next_back().is_none());
891 }
892
893 #[test]
894 fn dag_double_ended() {
895 let rk = TableGenParser::new()
896 .add_source(
897 "def op; def A { int i = 1; } def B { int i = 2; } def C { int i = 3; }
898 def R { dag d = (op A, B, C); }",
899 )
900 .unwrap()
901 .parse()
902 .expect("valid tablegen");
903 let dag: DagInit = rk.def("R").unwrap().value("d").unwrap().try_into().unwrap();
904 let mut iter = dag.args();
905 assert_eq!(iter.len(), 3);
906 let (_, first) = iter.next().unwrap();
907 assert_eq!(Record::try_from(first).unwrap().int_value("i"), Ok(1));
908 assert_eq!(iter.len(), 2);
909 let (_, last) = iter.next_back().unwrap();
910 assert_eq!(Record::try_from(last).unwrap().int_value("i"), Ok(3));
911 assert_eq!(iter.len(), 1);
912 let (_, mid) = iter.next().unwrap();
913 assert_eq!(Record::try_from(mid).unwrap().int_value("i"), Ok(2));
914 assert_eq!(iter.len(), 0);
915 assert!(iter.next().is_none());
916 assert!(iter.next_back().is_none());
917 }
918
919 #[test]
920 fn varbit() {
921 let rk = TableGenParser::new()
924 .add_source("class Foo<bits<4> src> { bits<4> val = src; }")
925 .unwrap()
926 .parse()
927 .expect("valid tablegen");
928 let bits: BitsInit = rk
929 .class("Foo")
930 .expect("class Foo exists")
931 .value("val")
932 .expect("field val exists")
933 .init
934 .as_bits()
935 .expect("is BitsInit");
936 assert_eq!(bits.num_bits(), 4);
937 for i in 0..4 {
938 let bit = bits.bit(i).expect("bit in range");
939 assert!(bit.is_var_bit());
940 assert_eq!(bit.as_var_bit(), Some(("Foo:src", i)));
941 assert_eq!(bit.as_literal(), None);
942 }
943 let optional: Vec<Option<bool>> = bits.into();
944 assert_eq!(optional, vec![None, None, None, None]);
945 }
946
947 #[test]
948 fn vec_bool_from_varbit_bits_returns_err() {
949 let rk = TableGenParser::new()
952 .add_source("class Foo<bits<4> src> { bits<4> val = src; }")
953 .unwrap()
954 .parse()
955 .expect("valid tablegen");
956 let bits: BitsInit = rk
957 .class("Foo")
958 .expect("class Foo exists")
959 .value("val")
960 .expect("field val exists")
961 .init
962 .as_bits()
963 .expect("is BitsInit");
964 let result = Vec::<bool>::try_from(bits);
965 assert!(result.is_err());
966 }
967
968 #[test]
969 fn empty_list() {
970 let rk = TableGenParser::new()
971 .add_source("def A { list<int> l = []; }")
972 .unwrap()
973 .parse()
974 .expect("valid tablegen");
975 let l: ListInit = rk
976 .def("A")
977 .expect("def A exists")
978 .value("l")
979 .expect("field l exists")
980 .try_into()
981 .expect("is list init");
982 assert_eq!(l.len(), 0);
983 assert!(l.is_empty());
984 assert!(l.iter().next().is_none());
985 let mut iter = l.iter();
987 assert!(iter.next().is_none());
988 assert!(iter.next().is_none());
989 }
990
991 #[test]
992 fn literal_bit_methods() {
993 let rk = TableGenParser::new()
994 .add_source("def A { bits<4> a = { 0, 1, 0, 1 }; }")
995 .unwrap()
996 .parse()
997 .expect("valid tablegen");
998 let bits: BitsInit = rk
999 .def("A")
1000 .expect("def A exists")
1001 .value("a")
1002 .expect("field a exists")
1003 .init
1004 .as_bits()
1005 .expect("is BitsInit");
1006 for i in 0..4 {
1007 let bit = bits.bit(i).expect("bit in range");
1008 assert!(!bit.is_var_bit());
1009 assert!(bit.as_var_bit().is_none());
1010 assert!(bit.as_literal().is_some());
1011 }
1012 }
1013
1014 #[test]
1015 fn list_element_type() {
1016 use crate::raw::TableGenRecTyKind::{
1017 TableGenDagRecTyKind, TableGenIntRecTyKind, TableGenStringRecTyKind,
1018 };
1019 let rk = TableGenParser::new()
1020 .add_source(
1021 r#"
1022 def op;
1023 def A {
1024 list<int> li = [1, 2, 3];
1025 list<string> ls = ["a", "b"];
1026 list<dag> ld = [(op)];
1027 }
1028 "#,
1029 )
1030 .unwrap()
1031 .parse()
1032 .expect("valid tablegen");
1033 let a = rk.def("A").expect("def A exists");
1034 let li: ListInit = a.value("li").unwrap().try_into().unwrap();
1035 assert_eq!(li.element_type(), Some(TableGenIntRecTyKind));
1036 let ls: ListInit = a.value("ls").unwrap().try_into().unwrap();
1037 assert_eq!(ls.element_type(), Some(TableGenStringRecTyKind));
1038 let ld: ListInit = a.value("ld").unwrap().try_into().unwrap();
1039 assert_eq!(ld.element_type(), Some(TableGenDagRecTyKind));
1040 }
1041}