20
20
#include " llvm/ADT/StringExtras.h"
21
21
#include " llvm/ADT/TypeSwitch.h"
22
22
#include " llvm/Support/Casting.h"
23
+ #include " llvm/Support/FormatVariadic.h"
23
24
24
25
using namespace mlir ;
25
26
using namespace mlir ::emitc;
@@ -154,6 +155,64 @@ static LogicalResult verifyInitializationAttribute(Operation *op,
154
155
return success ();
155
156
}
156
157
158
+ // / Parse a format string and return a list of its parts.
159
+ // / A part is either a StringRef that has to be printed as-is, or
160
+ // / a Placeholder which requires printing the next operand of the VerbatimOp.
161
+ // / In the format string, all `{}` are replaced by Placeholders, except if the
162
+ // / `{` is escaped by `{{` - then it doesn't start a placeholder.
163
+ template <class ArgType >
164
+ FailureOr<SmallVector<ReplacementItem>>
165
+ parseFormatString (StringRef toParse, ArgType fmtArgs,
166
+ std::optional<llvm::function_ref<mlir::InFlightDiagnostic()>>
167
+ emitError = {}) {
168
+ SmallVector<ReplacementItem> items;
169
+
170
+ // If there are not operands, the format string is not interpreted.
171
+ if (fmtArgs.empty ()) {
172
+ items.push_back (toParse);
173
+ return items;
174
+ }
175
+
176
+ while (!toParse.empty ()) {
177
+ size_t idx = toParse.find (' {' );
178
+ if (idx == StringRef::npos) {
179
+ // No '{'
180
+ items.push_back (toParse);
181
+ break ;
182
+ }
183
+ if (idx > 0 ) {
184
+ // Take all chars excluding the '{'.
185
+ items.push_back (toParse.take_front (idx));
186
+ toParse = toParse.drop_front (idx);
187
+ continue ;
188
+ }
189
+ if (toParse.size () < 2 ) {
190
+ // '{' is last character
191
+ items.push_back (toParse);
192
+ break ;
193
+ }
194
+ // toParse contains at least two characters and starts with `{`.
195
+ char nextChar = toParse[1 ];
196
+ if (nextChar == ' {' ) {
197
+ // Double '{{' -> '{' (escaping).
198
+ items.push_back (toParse.take_front (1 ));
199
+ toParse = toParse.drop_front (2 );
200
+ continue ;
201
+ }
202
+ if (nextChar == ' }' ) {
203
+ items.push_back (Placeholder{});
204
+ toParse = toParse.drop_front (2 );
205
+ continue ;
206
+ }
207
+
208
+ if (emitError.has_value ()) {
209
+ return (*emitError)() << " expected '}' after unescaped '{'" ;
210
+ }
211
+ return failure ();
212
+ }
213
+ return items;
214
+ }
215
+
157
216
// ===----------------------------------------------------------------------===//
158
217
// AddOp
159
218
// ===----------------------------------------------------------------------===//
@@ -914,7 +973,11 @@ LogicalResult emitc::SubscriptOp::verify() {
914
973
// ===----------------------------------------------------------------------===//
915
974
916
975
LogicalResult emitc::VerbatimOp::verify () {
917
- FailureOr<SmallVector<ReplacementItem>> fmt = parseFormatString ();
976
+ auto errorCallback = [&]() -> InFlightDiagnostic {
977
+ return this ->emitOpError ();
978
+ };
979
+ FailureOr<SmallVector<ReplacementItem>> fmt =
980
+ ::parseFormatString (getValue(), getFmtArgs(), errorCallback);
918
981
if (failed (fmt))
919
982
return failure ();
920
983
@@ -929,56 +992,29 @@ LogicalResult emitc::VerbatimOp::verify() {
929
992
return success ();
930
993
}
931
994
932
- // / Parse a format string and return a list of its parts.
933
- // / A part is either a StringRef that has to be printed as-is, or
934
- // / a Placeholder which requires printing the next operand of the VerbatimOp.
935
- // / In the format string, all `{}` are replaced by Placeholders, except if the
936
- // / `{` is escaped by `{{` - then it doesn't start a placeholder.
937
- FailureOr<SmallVector<emitc::VerbatimOp::ReplacementItem>>
938
- emitc::VerbatimOp::parseFormatString () {
939
- SmallVector<ReplacementItem> items;
995
+ static ParseResult parseVariadicTypeFmtArgs (AsmParser &p,
996
+ SmallVector<Type> ¶ms) {
997
+ Type type;
998
+ if (p.parseType (type))
999
+ return failure ();
940
1000
941
- // If there are not operands, the format string is not interpreted.
942
- if (getFmtArgs ().empty ()) {
943
- items.push_back (getValue ());
944
- return items;
1001
+ params.push_back (type);
1002
+ while (succeeded (p.parseOptionalComma ())) {
1003
+ if (p.parseType (type))
1004
+ return failure ();
1005
+ params.push_back (type);
945
1006
}
946
1007
947
- StringRef toParse = getValue ();
948
- while (!toParse.empty ()) {
949
- size_t idx = toParse.find (' {' );
950
- if (idx == StringRef::npos) {
951
- // No '{'
952
- items.push_back (toParse);
953
- break ;
954
- }
955
- if (idx > 0 ) {
956
- // Take all chars excluding the '{'.
957
- items.push_back (toParse.take_front (idx));
958
- toParse = toParse.drop_front (idx);
959
- continue ;
960
- }
961
- if (toParse.size () < 2 ) {
962
- // '{' is last character
963
- items.push_back (toParse);
964
- break ;
965
- }
966
- // toParse contains at least two characters and starts with `{`.
967
- char nextChar = toParse[1 ];
968
- if (nextChar == ' {' ) {
969
- // Double '{{' -> '{' (escaping).
970
- items.push_back (toParse.take_front (1 ));
971
- toParse = toParse.drop_front (2 );
972
- continue ;
973
- }
974
- if (nextChar == ' }' ) {
975
- items.push_back (Placeholder{});
976
- toParse = toParse.drop_front (2 );
977
- continue ;
978
- }
979
- return emitOpError () << " expected '}' after unescaped '{'" ;
980
- }
981
- return items;
1008
+ return success ();
1009
+ }
1010
+
1011
+ static void printVariadicTypeFmtArgs (AsmPrinter &p, ArrayRef<Type> params) {
1012
+ llvm::interleaveComma (params, p, [&](Type type) { p.printType (type); });
1013
+ }
1014
+
1015
+ FailureOr<SmallVector<ReplacementItem>> emitc::VerbatimOp::parseFormatString () {
1016
+ // Error checking is done in verify.
1017
+ return ::parseFormatString (getValue (), getFmtArgs ());
982
1018
}
983
1019
984
1020
// ===----------------------------------------------------------------------===//
@@ -1072,17 +1108,37 @@ emitc::ArrayType::cloneWith(std::optional<ArrayRef<int64_t>> shape,
1072
1108
1073
1109
LogicalResult mlir::emitc::OpaqueType::verify (
1074
1110
llvm::function_ref<mlir::InFlightDiagnostic()> emitError,
1075
- llvm::StringRef value) {
1111
+ llvm::StringRef value, ArrayRef<Type> fmtArgs ) {
1076
1112
if (value.empty ()) {
1077
1113
return emitError () << " expected non empty string in !emitc.opaque type" ;
1078
1114
}
1079
1115
if (value.back () == ' *' ) {
1080
1116
return emitError () << " pointer not allowed as outer type with "
1081
1117
" !emitc.opaque, use !emitc.ptr instead" ;
1082
1118
}
1119
+
1120
+ FailureOr<SmallVector<ReplacementItem>> fmt =
1121
+ ::parseFormatString (value, fmtArgs, emitError);
1122
+ if (failed (fmt))
1123
+ return failure ();
1124
+
1125
+ size_t numPlaceholders = llvm::count_if (*fmt, [](ReplacementItem &item) {
1126
+ return std::holds_alternative<Placeholder>(item);
1127
+ });
1128
+
1129
+ if (numPlaceholders != fmtArgs.size ()) {
1130
+ return emitError ()
1131
+ << " requires operands for each placeholder in the format string" ;
1132
+ }
1133
+
1083
1134
return success ();
1084
1135
}
1085
1136
1137
+ FailureOr<SmallVector<ReplacementItem>> emitc::OpaqueType::parseFormatString () {
1138
+ // Error checking is done in verify.
1139
+ return ::parseFormatString (getValue (), getFmtArgs ());
1140
+ }
1141
+
1086
1142
// ===----------------------------------------------------------------------===//
1087
1143
// GlobalOp
1088
1144
// ===----------------------------------------------------------------------===//
0 commit comments