@@ -50,6 +50,36 @@ class AsmPrinter {
50
50
virtual void printType (Type type);
51
51
virtual void printAttribute (Attribute attr);
52
52
53
+ // / Trait to check if `AttrType` provides a `print` method.
54
+ template <typename AttrOrType>
55
+ using has_print_method =
56
+ decltype (std::declval<AttrOrType>().print(std::declval<AsmPrinter &>()));
57
+ template <typename AttrOrType>
58
+ using detect_has_print_method =
59
+ llvm::is_detected<has_print_method, AttrOrType>;
60
+
61
+ // / Print the provided attribute in the context of an operation custom
62
+ // / printer/parser: this will invoke directly the print method on the
63
+ // / attribute class and skip the `#dialect.mnemonic` prefix in most cases.
64
+ template <typename AttrOrType,
65
+ std::enable_if_t <detect_has_print_method<AttrOrType>::value>
66
+ *sfinae = nullptr >
67
+ void printStrippedAttrOrType (AttrOrType attrOrType) {
68
+ if (succeeded (printAlias (attrOrType)))
69
+ return ;
70
+ attrOrType.print (*this );
71
+ }
72
+
73
+ // / SFINAE for printing the provided attribute in the context of an operation
74
+ // / custom printer in the case where the attribute does not define a print
75
+ // / method.
76
+ template <typename AttrOrType,
77
+ std::enable_if_t <!detect_has_print_method<AttrOrType>::value>
78
+ *sfinae = nullptr >
79
+ void printStrippedAttrOrType (AttrOrType attrOrType) {
80
+ *this << attrOrType;
81
+ }
82
+
53
83
// / Print the given attribute without its type. The corresponding parser must
54
84
// / provide a valid type for the attribute.
55
85
virtual void printAttributeWithoutType (Attribute attr);
@@ -102,6 +132,14 @@ class AsmPrinter {
102
132
AsmPrinter (const AsmPrinter &) = delete ;
103
133
void operator =(const AsmPrinter &) = delete ;
104
134
135
+ // / Print the alias for the given attribute, return failure if no alias could
136
+ // / be printed.
137
+ virtual LogicalResult printAlias (Attribute attr);
138
+
139
+ // / Print the alias for the given type, return failure if no alias could
140
+ // / be printed.
141
+ virtual LogicalResult printAlias (Type type);
142
+
105
143
// / The internal implementation of the printer.
106
144
Impl *impl;
107
145
};
@@ -608,6 +646,13 @@ class AsmParser {
608
646
// / Parse an arbitrary attribute of a given type and return it in result.
609
647
virtual ParseResult parseAttribute (Attribute &result, Type type = {}) = 0;
610
648
649
+ // / Parse a custom attribute with the provided callback, unless the next
650
+ // / token is `#`, in which case the generic parser is invoked.
651
+ virtual ParseResult parseCustomAttributeWithFallback (
652
+ Attribute &result, Type type,
653
+ function_ref<ParseResult(Attribute &result, Type type)>
654
+ parseAttribute) = 0;
655
+
611
656
// / Parse an attribute of a specific kind and type.
612
657
template <typename AttrType>
613
658
ParseResult parseAttribute (AttrType &result, Type type = {}) {
@@ -639,9 +684,9 @@ class AsmParser {
639
684
return parseAttribute (result, Type (), attrName, attrs);
640
685
}
641
686
642
- // / Parse an arbitrary attribute of a given type and return it in result. This
643
- // / also adds the attribute to the specified attribute list with the specified
644
- // / name.
687
+ // / Parse an arbitrary attribute of a given type and populate it in ` result`.
688
+ // / This also adds the attribute to the specified attribute list with the
689
+ // / specified name.
645
690
template <typename AttrType>
646
691
ParseResult parseAttribute (AttrType &result, Type type, StringRef attrName,
647
692
NamedAttrList &attrs) {
@@ -661,6 +706,82 @@ class AsmParser {
661
706
return success ();
662
707
}
663
708
709
+ // / Trait to check if `AttrType` provides a `parse` method.
710
+ template <typename AttrType>
711
+ using has_parse_method = decltype (AttrType::parse(std::declval<AsmParser &>(),
712
+ std::declval<Type>()));
713
+ template <typename AttrType>
714
+ using detect_has_parse_method = llvm::is_detected<has_parse_method, AttrType>;
715
+
716
+ // / Parse a custom attribute of a given type unless the next token is `#`, in
717
+ // / which case the generic parser is invoked. The parsed attribute is
718
+ // / populated in `result` and also added to the specified attribute list with
719
+ // / the specified name.
720
+ template <typename AttrType>
721
+ std::enable_if_t <detect_has_parse_method<AttrType>::value, ParseResult>
722
+ parseCustomAttributeWithFallback (AttrType &result, Type type,
723
+ StringRef attrName, NamedAttrList &attrs) {
724
+ llvm::SMLoc loc = getCurrentLocation ();
725
+
726
+ // Parse any kind of attribute.
727
+ Attribute attr;
728
+ if (parseCustomAttributeWithFallback (
729
+ attr, type, [&](Attribute &result, Type type) -> ParseResult {
730
+ result = AttrType::parse (*this , type);
731
+ if (!result)
732
+ return failure ();
733
+ return success ();
734
+ }))
735
+ return failure ();
736
+
737
+ // Check for the right kind of attribute.
738
+ result = attr.dyn_cast <AttrType>();
739
+ if (!result)
740
+ return emitError (loc, " invalid kind of attribute specified" );
741
+
742
+ attrs.append (attrName, result);
743
+ return success ();
744
+ }
745
+
746
+ // / SFINAE parsing method for Attribute that don't implement a parse method.
747
+ template <typename AttrType>
748
+ std::enable_if_t <!detect_has_parse_method<AttrType>::value, ParseResult>
749
+ parseCustomAttributeWithFallback (AttrType &result, Type type,
750
+ StringRef attrName, NamedAttrList &attrs) {
751
+ return parseAttribute (result, type, attrName, attrs);
752
+ }
753
+
754
+ // / Parse a custom attribute of a given type unless the next token is `#`, in
755
+ // / which case the generic parser is invoked. The parsed attribute is
756
+ // / populated in `result`.
757
+ template <typename AttrType>
758
+ std::enable_if_t <detect_has_parse_method<AttrType>::value, ParseResult>
759
+ parseCustomAttributeWithFallback (AttrType &result) {
760
+ llvm::SMLoc loc = getCurrentLocation ();
761
+
762
+ // Parse any kind of attribute.
763
+ Attribute attr;
764
+ if (parseCustomAttributeWithFallback (
765
+ attr, {}, [&](Attribute &result, Type type) -> ParseResult {
766
+ result = AttrType::parse (*this , type);
767
+ return success (!!result);
768
+ }))
769
+ return failure ();
770
+
771
+ // Check for the right kind of attribute.
772
+ result = attr.dyn_cast <AttrType>();
773
+ if (!result)
774
+ return emitError (loc, " invalid kind of attribute specified" );
775
+ return success ();
776
+ }
777
+
778
+ // / SFINAE parsing method for Attribute that don't implement a parse method.
779
+ template <typename AttrType>
780
+ std::enable_if_t <!detect_has_parse_method<AttrType>::value, ParseResult>
781
+ parseCustomAttributeWithFallback (AttrType &result) {
782
+ return parseAttribute (result);
783
+ }
784
+
664
785
// / Parse an arbitrary optional attribute of a given type and return it in
665
786
// / result.
666
787
virtual OptionalParseResult parseOptionalAttribute (Attribute &result,
@@ -740,6 +861,11 @@ class AsmParser {
740
861
// / Parse a type.
741
862
virtual ParseResult parseType (Type &result) = 0;
742
863
864
+ // / Parse a custom type with the provided callback, unless the next
865
+ // / token is `#`, in which case the generic parser is invoked.
866
+ virtual ParseResult parseCustomTypeWithFallback (
867
+ Type &result, function_ref<ParseResult(Type &result)> parseType) = 0;
868
+
743
869
// / Parse an optional type.
744
870
virtual OptionalParseResult parseOptionalType (Type &result) = 0;
745
871
@@ -753,14 +879,52 @@ class AsmParser {
753
879
if (parseType (type))
754
880
return failure ();
755
881
756
- // Check for the right kind of attribute .
882
+ // Check for the right kind of type .
757
883
result = type.dyn_cast <TypeT>();
758
884
if (!result)
759
885
return emitError (loc, " invalid kind of type specified" );
760
886
761
887
return success ();
762
888
}
763
889
890
+ // / Trait to check if `TypeT` provides a `parse` method.
891
+ template <typename TypeT>
892
+ using type_has_parse_method =
893
+ decltype (TypeT::parse(std::declval<AsmParser &>()));
894
+ template <typename TypeT>
895
+ using detect_type_has_parse_method =
896
+ llvm::is_detected<type_has_parse_method, TypeT>;
897
+
898
+ // / Parse a custom Type of a given type unless the next token is `#`, in
899
+ // / which case the generic parser is invoked. The parsed Type is
900
+ // / populated in `result`.
901
+ template <typename TypeT>
902
+ std::enable_if_t <detect_type_has_parse_method<TypeT>::value, ParseResult>
903
+ parseCustomTypeWithFallback (TypeT &result) {
904
+ llvm::SMLoc loc = getCurrentLocation ();
905
+
906
+ // Parse any kind of Type.
907
+ Type type;
908
+ if (parseCustomTypeWithFallback (type, [&](Type &result) -> ParseResult {
909
+ result = TypeT::parse (*this );
910
+ return success (!!result);
911
+ }))
912
+ return failure ();
913
+
914
+ // Check for the right kind of Type.
915
+ result = type.dyn_cast <TypeT>();
916
+ if (!result)
917
+ return emitError (loc, " invalid kind of Type specified" );
918
+ return success ();
919
+ }
920
+
921
+ // / SFINAE parsing method for Type that don't implement a parse method.
922
+ template <typename TypeT>
923
+ std::enable_if_t <!detect_type_has_parse_method<TypeT>::value, ParseResult>
924
+ parseCustomTypeWithFallback (TypeT &result) {
925
+ return parseType (result);
926
+ }
927
+
764
928
// / Parse a type list.
765
929
ParseResult parseTypeList (SmallVectorImpl<Type> &result) {
766
930
do {
@@ -792,7 +956,7 @@ class AsmParser {
792
956
if (parseColonType (type))
793
957
return failure ();
794
958
795
- // Check for the right kind of attribute .
959
+ // Check for the right kind of type .
796
960
result = type.dyn_cast <TypeType>();
797
961
if (!result)
798
962
return emitError (loc, " invalid kind of type specified" );
0 commit comments