@@ -379,8 +379,11 @@ struct OperationFormat {
379
379
std::vector<TypeResolution> operandTypes, resultTypes;
380
380
381
381
// / The set of attributes explicitly used within the format.
382
- SmallVector <const NamedAttribute *, 8 > usedAttributes;
382
+ llvm::SmallSetVector <const NamedAttribute *, 8 > usedAttributes;
383
383
llvm::StringSet<> inferredAttributes;
384
+
385
+ // / The set of properties explicitly used within the format.
386
+ llvm::SmallSetVector<const NamedProperty *, 8 > usedProperties;
384
387
};
385
388
} // namespace
386
389
@@ -1183,6 +1186,105 @@ static void genAttrParser(AttributeVariable *attr, MethodBody &body,
1183
1186
}
1184
1187
}
1185
1188
1189
+ // Generates the 'setPropertiesFromParsedAttr' used to set properties from a
1190
+ // 'prop-dict' dictionary attr.
1191
+ static void genParsedAttrPropertiesSetter (OperationFormat &fmt, Operator &op,
1192
+ OpClass &opClass) {
1193
+ // Not required unless 'prop-dict' is present.
1194
+ if (!fmt.hasPropDict )
1195
+ return ;
1196
+
1197
+ SmallVector<MethodParameter> paramList;
1198
+ paramList.emplace_back (" Properties &" , " prop" );
1199
+ paramList.emplace_back (" ::mlir::Attribute" , " attr" );
1200
+ paramList.emplace_back (" ::llvm::function_ref<::mlir::InFlightDiagnostic()>" ,
1201
+ " emitError" );
1202
+
1203
+ Method *method = opClass.addStaticMethod (" ::mlir::LogicalResult" ,
1204
+ " setPropertiesFromParsedAttr" ,
1205
+ std::move (paramList));
1206
+ MethodBody &body = method->body ().indent ();
1207
+
1208
+ body << R"decl(
1209
+ ::mlir::DictionaryAttr dict = ::llvm::dyn_cast<::mlir::DictionaryAttr>(attr);
1210
+ if (!dict) {
1211
+ emitError() << "expected DictionaryAttr to set properties";
1212
+ return ::mlir::failure();
1213
+ }
1214
+ )decl" ;
1215
+
1216
+ // TODO: properties might be optional as well.
1217
+ const char *propFromAttrFmt = R"decl(
1218
+ auto setFromAttr = [] (auto &propStorage, ::mlir::Attribute propAttr,
1219
+ ::llvm::function_ref<::mlir::InFlightDiagnostic()> emitError) {{
1220
+ {0};
1221
+ };
1222
+ auto attr = dict.get("{1}");
1223
+ if (!attr) {{
1224
+ emitError() << "expected key entry for {1} in DictionaryAttr to set "
1225
+ "Properties.";
1226
+ return ::mlir::failure();
1227
+ }
1228
+ if (::mlir::failed(setFromAttr(prop.{1}, attr, emitError)))
1229
+ return ::mlir::failure();
1230
+ )decl" ;
1231
+
1232
+ // Generate the setter for any property not parsed elsewhere.
1233
+ for (const NamedProperty &namedProperty : op.getProperties ()) {
1234
+ if (fmt.usedProperties .contains (&namedProperty))
1235
+ continue ;
1236
+
1237
+ auto scope = body.scope (" {\n " , " }\n " , /* indent=*/ true );
1238
+
1239
+ StringRef name = namedProperty.name ;
1240
+ const Property &prop = namedProperty.prop ;
1241
+ FmtContext fctx;
1242
+ body << formatv (propFromAttrFmt,
1243
+ tgfmt (prop.getConvertFromAttributeCall (),
1244
+ &fctx.addSubst (" _attr" , " propAttr" )
1245
+ .addSubst (" _storage" , " propStorage" )
1246
+ .addSubst (" _diag" , " emitError" )),
1247
+ name);
1248
+ }
1249
+
1250
+ // Generate the setter for any attribute not parsed elsewhere.
1251
+ for (const NamedAttribute &namedAttr : op.getAttributes ()) {
1252
+ if (fmt.usedAttributes .contains (&namedAttr))
1253
+ continue ;
1254
+
1255
+ const Attribute &attr = namedAttr.attr ;
1256
+ // Derived attributes do not need to be parsed.
1257
+ if (attr.isDerivedAttr ())
1258
+ continue ;
1259
+
1260
+ auto scope = body.scope (" {\n " , " }\n " , /* indent=*/ true );
1261
+
1262
+ // If the attribute has a default value or is optional, it does not need to
1263
+ // be present in the parsed dictionary attribute.
1264
+ bool isRequired = !attr.isOptional () && !attr.hasDefaultValue ();
1265
+ body << formatv (R"decl(
1266
+ auto &propStorage = prop.{0};
1267
+ auto attr = dict.get("{0}");
1268
+ if (attr || /*isRequired=*/{1}) {{
1269
+ if (!attr) {{
1270
+ emitError() << "expected key entry for {0} in DictionaryAttr to set "
1271
+ "Properties.";
1272
+ return ::mlir::failure();
1273
+ }
1274
+ auto convertedAttr = ::llvm::dyn_cast<std::remove_reference_t<decltype(propStorage)>>(attr);
1275
+ if (convertedAttr) {{
1276
+ propStorage = convertedAttr;
1277
+ } else {{
1278
+ emitError() << "Invalid attribute `{0}` in property conversion: " << attr;
1279
+ return ::mlir::failure();
1280
+ }
1281
+ }
1282
+ )decl" ,
1283
+ namedAttr.name , isRequired);
1284
+ }
1285
+ body << " return ::mlir::success();\n " ;
1286
+ }
1287
+
1186
1288
void OperationFormat::genParser (Operator &op, OpClass &opClass) {
1187
1289
SmallVector<MethodParameter> paramList;
1188
1290
paramList.emplace_back (" ::mlir::OpAsmParser &" , " parser" );
@@ -1214,6 +1316,8 @@ void OperationFormat::genParser(Operator &op, OpClass &opClass) {
1214
1316
genParserTypeResolution (op, body);
1215
1317
1216
1318
body << " return ::mlir::success();\n " ;
1319
+
1320
+ genParsedAttrPropertiesSetter (*this , op, opClass);
1217
1321
}
1218
1322
1219
1323
void OperationFormat::genElementParser (FormatElement *element, MethodBody &body,
@@ -1776,6 +1880,11 @@ const char *enumAttrBeginPrinterCode = R"(
1776
1880
static void genPropDictPrinter (OperationFormat &fmt, Operator &op,
1777
1881
MethodBody &body) {
1778
1882
body << " ::llvm::SmallVector<::llvm::StringRef, 2> elidedProps;\n " ;
1883
+ for (const NamedProperty *namedProperty : fmt.usedProperties )
1884
+ body << " elidedProps.push_back(\" " << namedProperty->name << " \" );\n " ;
1885
+ for (const NamedAttribute *namedAttr : fmt.usedAttributes )
1886
+ body << " elidedProps.push_back(\" " << namedAttr->name << " \" );\n " ;
1887
+
1779
1888
// Add code to check attributes for equality with the default value
1780
1889
// for attributes with the elidePrintingDefaultValue bit set.
1781
1890
for (const NamedAttribute &namedAttr : op.getAttributes ()) {
@@ -2543,7 +2652,7 @@ class OpFormatParser : public FormatParser {
2543
2652
llvm::DenseSet<const NamedTypeConstraint *> seenOperands;
2544
2653
llvm::DenseSet<const NamedRegion *> seenRegions;
2545
2654
llvm::DenseSet<const NamedSuccessor *> seenSuccessors;
2546
- llvm::DenseSet <const NamedProperty *> seenProperties;
2655
+ llvm::SmallSetVector <const NamedProperty *, 8 > seenProperties;
2547
2656
};
2548
2657
} // namespace
2549
2658
@@ -2589,7 +2698,8 @@ LogicalResult OpFormatParser::verify(SMLoc loc,
2589
2698
return failure ();
2590
2699
2591
2700
// Collect the set of used attributes in the format.
2592
- fmt.usedAttributes = seenAttrs.takeVector ();
2701
+ fmt.usedAttributes = std::move (seenAttrs);
2702
+ fmt.usedProperties = std::move (seenProperties);
2593
2703
2594
2704
// Set whether prop-dict is used in the format
2595
2705
fmt.hasPropDict = hasPropDict;
@@ -3042,7 +3152,7 @@ OpFormatParser::parseVariableImpl(SMLoc loc, StringRef name, Context ctx) {
3042
3152
return emitError (loc, " property '" + name +
3043
3153
" ' must be bound before it is referenced" );
3044
3154
} else {
3045
- if (!seenProperties.insert (property). second )
3155
+ if (!seenProperties.insert (property))
3046
3156
return emitError (loc, " property '" + name + " ' is already bound" );
3047
3157
}
3048
3158
0 commit comments