1 //===- OpDefinitionsGen.cpp - MLIR op definitions generator ---------------===//
2 //
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6 //
7 //===----------------------------------------------------------------------===//
8 //
9 // OpDefinitionsGen uses the description of operations to generate C++
10 // definitions for ops.
11 //
12 //===----------------------------------------------------------------------===//
13 
14 #include "OpFormatGen.h"
15 #include "OpGenHelpers.h"
16 #include "mlir/TableGen/CodeGenHelpers.h"
17 #include "mlir/TableGen/Format.h"
18 #include "mlir/TableGen/GenInfo.h"
19 #include "mlir/TableGen/Interfaces.h"
20 #include "mlir/TableGen/OpClass.h"
21 #include "mlir/TableGen/Operator.h"
22 #include "mlir/TableGen/SideEffects.h"
23 #include "mlir/TableGen/Trait.h"
24 #include "llvm/ADT/MapVector.h"
25 #include "llvm/ADT/Sequence.h"
26 #include "llvm/ADT/StringExtras.h"
27 #include "llvm/ADT/StringSet.h"
28 #include "llvm/Support/Signals.h"
29 #include "llvm/TableGen/Error.h"
30 #include "llvm/TableGen/Record.h"
31 #include "llvm/TableGen/TableGenBackend.h"
32 
33 #define DEBUG_TYPE "mlir-tblgen-opdefgen"
34 
35 using namespace llvm;
36 using namespace mlir;
37 using namespace mlir::tblgen;
38 
39 static const char *const tblgenNamePrefix = "tblgen_";
40 static const char *const generatedArgName = "odsArg";
41 static const char *const odsBuilder = "odsBuilder";
42 static const char *const builderOpState = "odsState";
43 
44 // The logic to calculate the actual value range for a declared operand/result
45 // of an op with variadic operands/results. Note that this logic is not for
46 // general use; it assumes all variadic operands/results must have the same
47 // number of values.
48 //
49 // {0}: The list of whether each declared operand/result is variadic.
50 // {1}: The total number of non-variadic operands/results.
51 // {2}: The total number of variadic operands/results.
52 // {3}: The total number of actual values.
53 // {4}: "operand" or "result".
54 const char *sameVariadicSizeValueRangeCalcCode = R"(
55   bool isVariadic[] = {{{0}};
56   int prevVariadicCount = 0;
57   for (unsigned i = 0; i < index; ++i)
58     if (isVariadic[i]) ++prevVariadicCount;
59 
60   // Calculate how many dynamic values a static variadic {4} corresponds to.
61   // This assumes all static variadic {4}s have the same dynamic value count.
62   int variadicSize = ({3} - {1}) / {2};
63   // `index` passed in as the parameter is the static index which counts each
64   // {4} (variadic or not) as size 1. So here for each previous static variadic
65   // {4}, we need to offset by (variadicSize - 1) to get where the dynamic
66   // value pack for this static {4} starts.
67   int start = index + (variadicSize - 1) * prevVariadicCount;
68   int size = isVariadic[index] ? variadicSize : 1;
69   return {{start, size};
70 )";
71 
72 // The logic to calculate the actual value range for a declared operand/result
73 // of an op with variadic operands/results. Note that this logic is assumes
74 // the op has an attribute specifying the size of each operand/result segment
75 // (variadic or not).
76 //
77 // {0}: The name of the attribute specifying the segment sizes.
78 const char *adapterSegmentSizeAttrInitCode = R"(
79   assert(odsAttrs && "missing segment size attribute for op");
80   auto sizeAttr = odsAttrs.get("{0}").cast<::mlir::DenseIntElementsAttr>();
81 )";
82 const char *opSegmentSizeAttrInitCode = R"(
83   auto sizeAttr = (*this)->getAttr({0}).cast<::mlir::DenseIntElementsAttr>();
84 )";
85 const char *attrSizedSegmentValueRangeCalcCode = R"(
86   auto sizeAttrValues = sizeAttr.getValues<uint32_t>();
87   unsigned start = 0;
88   for (unsigned i = 0; i < index; ++i)
89     start += *(sizeAttrValues.begin() + i);
90   unsigned size = *(sizeAttrValues.begin() + index);
91   return {start, size};
92 )";
93 // The logic to calculate the actual value range for a declared operand
94 // of an op with variadic of variadic operands within the OpAdaptor.
95 //
96 // {0}: The name of the segment attribute.
97 // {1}: The index of the main operand.
98 const char *variadicOfVariadicAdaptorCalcCode = R"(
99   auto tblgenTmpOperands = getODSOperands({1});
100   auto sizeAttrValues = {0}().getValues<uint32_t>();
101   auto sizeAttrIt = sizeAttrValues.begin();
102 
103   ::llvm::SmallVector<::mlir::ValueRange> tblgenTmpOperandGroups;
104   for (int i = 0, e = ::llvm::size(sizeAttrValues); i < e; ++i, ++sizeAttrIt) {{
105     tblgenTmpOperandGroups.push_back(tblgenTmpOperands.take_front(*sizeAttrIt));
106     tblgenTmpOperands = tblgenTmpOperands.drop_front(*sizeAttrIt);
107   }
108   return tblgenTmpOperandGroups;
109 )";
110 
111 // The logic to build a range of either operand or result values.
112 //
113 // {0}: The begin iterator of the actual values.
114 // {1}: The call to generate the start and length of the value range.
115 const char *valueRangeReturnCode = R"(
116   auto valueRange = {1};
117   return {{std::next({0}, valueRange.first),
118            std::next({0}, valueRange.first + valueRange.second)};
119 )";
120 
121 const char *typeVerifierSignature =
122     "static ::mlir::LogicalResult {0}(::mlir::Operation *op, ::mlir::Type "
123     "type, ::llvm::StringRef valueKind, unsigned valueGroupStartIndex)";
124 
125 const char *typeVerifierErrorHandler =
126     " op->emitOpError(valueKind) << \" #\" << valueGroupStartIndex << \" must "
127     "be {0}, but got \" << type";
128 
129 static const char *const opCommentHeader = R"(
130 //===----------------------------------------------------------------------===//
131 // {0} {1}
132 //===----------------------------------------------------------------------===//
133 
134 )";
135 
136 //===----------------------------------------------------------------------===//
137 // Utility structs and functions
138 //===----------------------------------------------------------------------===//
139 
140 // Replaces all occurrences of `match` in `str` with `substitute`.
141 static std::string replaceAllSubstrs(std::string str, const std::string &match,
142                                      const std::string &substitute) {
143   std::string::size_type scanLoc = 0, matchLoc = std::string::npos;
144   while ((matchLoc = str.find(match, scanLoc)) != std::string::npos) {
145     str = str.replace(matchLoc, match.size(), substitute);
146     scanLoc = matchLoc + substitute.size();
147   }
148   return str;
149 }
150 
151 // Returns whether the record has a value of the given name that can be returned
152 // via getValueAsString.
153 static inline bool hasStringAttribute(const Record &record,
154                                       StringRef fieldName) {
155   auto valueInit = record.getValueInit(fieldName);
156   return isa<StringInit>(valueInit);
157 }
158 
159 static std::string getArgumentName(const Operator &op, int index) {
160   const auto &operand = op.getOperand(index);
161   if (!operand.name.empty())
162     return std::string(operand.name);
163   else
164     return std::string(formatv("{0}_{1}", generatedArgName, index));
165 }
166 
167 // Returns true if we can use unwrapped value for the given `attr` in builders.
168 static bool canUseUnwrappedRawValue(const tblgen::Attribute &attr) {
169   return attr.getReturnType() != attr.getStorageType() &&
170          // We need to wrap the raw value into an attribute in the builder impl
171          // so we need to make sure that the attribute specifies how to do that.
172          !attr.getConstBuilderTemplate().empty();
173 }
174 
175 //===----------------------------------------------------------------------===//
176 // Op emitter
177 //===----------------------------------------------------------------------===//
178 
179 namespace {
180 // Helper class to emit a record into the given output stream.
181 class OpEmitter {
182 public:
183   static void
184   emitDecl(const Operator &op, raw_ostream &os,
185            const StaticVerifierFunctionEmitter &staticVerifierEmitter);
186   static void
187   emitDef(const Operator &op, raw_ostream &os,
188           const StaticVerifierFunctionEmitter &staticVerifierEmitter);
189 
190 private:
191   OpEmitter(const Operator &op,
192             const StaticVerifierFunctionEmitter &staticVerifierEmitter);
193 
194   void emitDecl(raw_ostream &os);
195   void emitDef(raw_ostream &os);
196 
197   // Generate methods for accessing the attribute names of this operation.
198   void genAttrNameGetters();
199 
200   // Generates the OpAsmOpInterface for this operation if possible.
201   void genOpAsmInterface();
202 
203   // Generates the `getOperationName` method for this op.
204   void genOpNameGetter();
205 
206   // Generates getters for the attributes.
207   void genAttrGetters();
208 
209   // Generates setter for the attributes.
210   void genAttrSetters();
211 
212   // Generates removers for optional attributes.
213   void genOptionalAttrRemovers();
214 
215   // Generates getters for named operands.
216   void genNamedOperandGetters();
217 
218   // Generates setters for named operands.
219   void genNamedOperandSetters();
220 
221   // Generates getters for named results.
222   void genNamedResultGetters();
223 
224   // Generates getters for named regions.
225   void genNamedRegionGetters();
226 
227   // Generates getters for named successors.
228   void genNamedSuccessorGetters();
229 
230   // Generates builder methods for the operation.
231   void genBuilder();
232 
233   // Generates the build() method that takes each operand/attribute
234   // as a stand-alone parameter.
235   void genSeparateArgParamBuilder();
236 
237   // Generates the build() method that takes each operand/attribute as a
238   // stand-alone parameter. The generated build() method uses first operand's
239   // type as all results' types.
240   void genUseOperandAsResultTypeSeparateParamBuilder();
241 
242   // Generates the build() method that takes all operands/attributes
243   // collectively as one parameter. The generated build() method uses first
244   // operand's type as all results' types.
245   void genUseOperandAsResultTypeCollectiveParamBuilder();
246 
247   // Generates the build() method that takes aggregate operands/attributes
248   // parameters. This build() method uses inferred types as result types.
249   // Requires: The type needs to be inferable via InferTypeOpInterface.
250   void genInferredTypeCollectiveParamBuilder();
251 
252   // Generates the build() method that takes each operand/attribute as a
253   // stand-alone parameter. The generated build() method uses first attribute's
254   // type as all result's types.
255   void genUseAttrAsResultTypeBuilder();
256 
257   // Generates the build() method that takes all result types collectively as
258   // one parameter. Similarly for operands and attributes.
259   void genCollectiveParamBuilder();
260 
261   // The kind of parameter to generate for result types in builders.
262   enum class TypeParamKind {
263     None,       // No result type in parameter list.
264     Separate,   // A separate parameter for each result type.
265     Collective, // An ArrayRef<Type> for all result types.
266   };
267 
268   // The kind of parameter to generate for attributes in builders.
269   enum class AttrParamKind {
270     WrappedAttr,    // A wrapped MLIR Attribute instance.
271     UnwrappedValue, // A raw value without MLIR Attribute wrapper.
272   };
273 
274   // Builds the parameter list for build() method of this op. This method writes
275   // to `paramList` the comma-separated parameter list and updates
276   // `resultTypeNames` with the names for parameters for specifying result
277   // types. `inferredAttributes` is populated with any attributes that are
278   // elided from the build list. The given `typeParamKind` and `attrParamKind`
279   // controls how result types and attributes are placed in the parameter list.
280   void buildParamList(llvm::SmallVectorImpl<OpMethodParameter> &paramList,
281                       llvm::StringSet<> &inferredAttributes,
282                       SmallVectorImpl<std::string> &resultTypeNames,
283                       TypeParamKind typeParamKind,
284                       AttrParamKind attrParamKind = AttrParamKind::WrappedAttr);
285 
286   // Adds op arguments and regions into operation state for build() methods.
287   void
288   genCodeForAddingArgAndRegionForBuilder(OpMethodBody &body,
289                                          llvm::StringSet<> &inferredAttributes,
290                                          bool isRawValueAttr = false);
291 
292   // Generates canonicalizer declaration for the operation.
293   void genCanonicalizerDecls();
294 
295   // Generates the folder declaration for the operation.
296   void genFolderDecls();
297 
298   // Generates the parser for the operation.
299   void genParser();
300 
301   // Generates the printer for the operation.
302   void genPrinter();
303 
304   // Generates verify method for the operation.
305   void genVerifier();
306 
307   // Generates verify statements for operands and results in the operation.
308   // The generated code will be attached to `body`.
309   void genOperandResultVerifier(OpMethodBody &body,
310                                 Operator::value_range values,
311                                 StringRef valueKind);
312 
313   // Generates verify statements for regions in the operation.
314   // The generated code will be attached to `body`.
315   void genRegionVerifier(OpMethodBody &body);
316 
317   // Generates verify statements for successors in the operation.
318   // The generated code will be attached to `body`.
319   void genSuccessorVerifier(OpMethodBody &body);
320 
321   // Generates the traits used by the object.
322   void genTraits();
323 
324   // Generate the OpInterface methods for all interfaces.
325   void genOpInterfaceMethods();
326 
327   // Generate op interface methods for the given interface.
328   void genOpInterfaceMethods(const tblgen::InterfaceTrait *trait);
329 
330   // Generate op interface method for the given interface method. If
331   // 'declaration' is true, generates a declaration, else a definition.
332   OpMethod *genOpInterfaceMethod(const tblgen::InterfaceMethod &method,
333                                  bool declaration = true);
334 
335   // Generate the side effect interface methods.
336   void genSideEffectInterfaceMethods();
337 
338   // Generate the type inference interface methods.
339   void genTypeInterfaceMethods();
340 
341 private:
342   // The TableGen record for this op.
343   // TODO: OpEmitter should not have a Record directly,
344   // it should rather go through the Operator for better abstraction.
345   const Record &def;
346 
347   // The wrapper operator class for querying information from this op.
348   Operator op;
349 
350   // The C++ code builder for this op
351   OpClass opClass;
352 
353   // The format context for verification code generation.
354   FmtContext verifyCtx;
355 
356   // The emitter containing all of the locally emitted verification functions.
357   const StaticVerifierFunctionEmitter &staticVerifierEmitter;
358 
359   // A map of attribute names (including implicit attributes) registered to the
360   // current operation, to the relative order in which they were registered.
361   llvm::MapVector<StringRef, unsigned> attributeNames;
362 };
363 } // end anonymous namespace
364 
365 // Populate the format context `ctx` with substitutions of attributes, operands
366 // and results.
367 // - attrGet corresponds to the name of the function to call to get value of
368 //   attribute (the generated function call returns an Attribute);
369 // - operandGet corresponds to the name of the function with which to retrieve
370 //   an operand (the generated function call returns an OperandRange);
371 // - resultGet corresponds to the name of the function to get an result (the
372 //   generated function call returns a ValueRange);
373 static void populateSubstitutions(const Operator &op, const char *attrGet,
374                                   const char *operandGet, const char *resultGet,
375                                   FmtContext &ctx) {
376   // Populate substitutions for attributes and named operands.
377   for (const auto &namedAttr : op.getAttributes())
378     ctx.addSubst(namedAttr.name,
379                  formatv("{0}(\"{1}\")", attrGet, namedAttr.name));
380   for (int i = 0, e = op.getNumOperands(); i < e; ++i) {
381     auto &value = op.getOperand(i);
382     if (value.name.empty())
383       continue;
384 
385     if (value.isVariadic())
386       ctx.addSubst(value.name, formatv("{0}({1})", operandGet, i));
387     else
388       ctx.addSubst(value.name, formatv("(*{0}({1}).begin())", operandGet, i));
389   }
390 
391   // Populate substitutions for results.
392   for (int i = 0, e = op.getNumResults(); i < e; ++i) {
393     auto &value = op.getResult(i);
394     if (value.name.empty())
395       continue;
396 
397     if (value.isVariadic())
398       ctx.addSubst(value.name, formatv("{0}({1})", resultGet, i));
399     else
400       ctx.addSubst(value.name, formatv("(*{0}({1}).begin())", resultGet, i));
401   }
402 }
403 
404 // Generate attribute verification. If emitVerificationRequiringOp is set then
405 // only verification for attributes whose value depend on op being known are
406 // emitted, else only verification that doesn't depend on the op being known are
407 // generated.
408 // - emitErrorPrefix is the prefix for the error emitting call which consists
409 //   of the entire function call up to start of error message fragment;
410 // - emitVerificationRequiringOp specifies whether verification should be
411 //   emitted for verification that require the op to exist;
412 static void genAttributeVerifier(const Operator &op, const char *attrGet,
413                                  const Twine &emitErrorPrefix,
414                                  bool emitVerificationRequiringOp,
415                                  FmtContext &ctx, OpMethodBody &body) {
416   for (const auto &namedAttr : op.getAttributes()) {
417     const auto &attr = namedAttr.attr;
418     if (attr.isDerivedAttr())
419       continue;
420 
421     auto attrName = namedAttr.name;
422     bool allowMissingAttr = attr.hasDefaultValue() || attr.isOptional();
423     auto attrPred = attr.getPredicate();
424     auto condition = attrPred.isNull() ? "" : attrPred.getCondition();
425     // There is a condition to emit only if the use of $_op and whether to
426     // emit verifications for op matches.
427     bool hasConditionToEmit = (!(condition.find("$_op") != StringRef::npos) ^
428                                emitVerificationRequiringOp);
429 
430     // Prefix with `tblgen_` to avoid hiding the attribute accessor.
431     auto varName = tblgenNamePrefix + attrName;
432 
433     // If the attribute is
434     //  1. Required (not allowed missing) and not in op verification, or
435     //  2. Has a condition that will get verified
436     // then the variable will be used.
437     //
438     // Therefore, for optional attributes whose verification requires that an
439     // op already exists for verification/emitVerificationRequiringOp is set
440     // has nothing that can be verified here.
441     if ((allowMissingAttr || emitVerificationRequiringOp) &&
442         !hasConditionToEmit)
443       continue;
444 
445     body << formatv("  {\n  auto {0} = {1}(\"{2}\");\n", varName, attrGet,
446                     attrName);
447 
448     if (!emitVerificationRequiringOp && !allowMissingAttr) {
449       body << "  if (!" << varName << ") return " << emitErrorPrefix
450            << "\"requires attribute '" << attrName << "'\");\n";
451     }
452 
453     if (!hasConditionToEmit) {
454       body << "  }\n";
455       continue;
456     }
457 
458     if (allowMissingAttr) {
459       // If the attribute has a default value, then only verify the predicate if
460       // set. This does effectively assume that the default value is valid.
461       // TODO: verify the debug value is valid (perhaps in debug mode only).
462       body << "  if (" << varName << ") {\n";
463     }
464 
465     body << tgfmt("    if (!($0)) return $1\"attribute '$2' "
466                   "failed to satisfy constraint: $3\");\n",
467                   /*ctx=*/nullptr, tgfmt(condition, &ctx.withSelf(varName)),
468                   emitErrorPrefix, attrName, attr.getSummary());
469     if (allowMissingAttr)
470       body << "  }\n";
471     body << "  }\n";
472   }
473 }
474 
475 OpEmitter::OpEmitter(const Operator &op,
476                      const StaticVerifierFunctionEmitter &staticVerifierEmitter)
477     : def(op.getDef()), op(op),
478       opClass(op.getCppClassName(), op.getExtraClassDeclaration()),
479       staticVerifierEmitter(staticVerifierEmitter) {
480   verifyCtx.withOp("(*this->getOperation())");
481   verifyCtx.addSubst("_ctxt", "this->getOperation()->getContext()");
482 
483   genTraits();
484 
485   // Generate C++ code for various op methods. The order here determines the
486   // methods in the generated file.
487   genAttrNameGetters();
488   genOpAsmInterface();
489   genOpNameGetter();
490   genNamedOperandGetters();
491   genNamedOperandSetters();
492   genNamedResultGetters();
493   genNamedRegionGetters();
494   genNamedSuccessorGetters();
495   genAttrGetters();
496   genAttrSetters();
497   genOptionalAttrRemovers();
498   genBuilder();
499   genParser();
500   genPrinter();
501   genVerifier();
502   genCanonicalizerDecls();
503   genFolderDecls();
504   genTypeInterfaceMethods();
505   genOpInterfaceMethods();
506   generateOpFormat(op, opClass);
507   genSideEffectInterfaceMethods();
508 }
509 void OpEmitter::emitDecl(
510     const Operator &op, raw_ostream &os,
511     const StaticVerifierFunctionEmitter &staticVerifierEmitter) {
512   OpEmitter(op, staticVerifierEmitter).emitDecl(os);
513 }
514 
515 void OpEmitter::emitDef(
516     const Operator &op, raw_ostream &os,
517     const StaticVerifierFunctionEmitter &staticVerifierEmitter) {
518   OpEmitter(op, staticVerifierEmitter).emitDef(os);
519 }
520 
521 void OpEmitter::emitDecl(raw_ostream &os) { opClass.writeDeclTo(os); }
522 
523 void OpEmitter::emitDef(raw_ostream &os) { opClass.writeDefTo(os); }
524 
525 void OpEmitter::genAttrNameGetters() {
526   // Enumerate the attribute names of this op, assigning each a relative
527   // ordering.
528   auto addAttrName = [&](StringRef name) {
529     unsigned index = attributeNames.size();
530     attributeNames.insert({name, index});
531   };
532   for (const NamedAttribute &namedAttr : op.getAttributes())
533     addAttrName(namedAttr.name);
534   // Include key attributes from several traits as implicitly registered.
535   if (op.getTrait("::mlir::OpTrait::AttrSizedOperandSegments"))
536     addAttrName("operand_segment_sizes");
537   if (op.getTrait("::mlir::OpTrait::AttrSizedResultSegments"))
538     addAttrName("result_segment_sizes");
539 
540   // Emit the getAttributeNames method.
541   {
542     auto *method = opClass.addMethodAndPrune(
543         "::llvm::ArrayRef<::llvm::StringRef>", "getAttributeNames",
544         OpMethod::Property(OpMethod::MP_Static | OpMethod::MP_Inline));
545     auto &body = method->body();
546     if (attributeNames.empty()) {
547       body << "  return {};";
548     } else {
549       body << "  static ::llvm::StringRef attrNames[] = {";
550       llvm::interleaveComma(llvm::make_first_range(attributeNames), body,
551                             [&](StringRef attrName) {
552                               body << "::llvm::StringRef(\"" << attrName
553                                    << "\")";
554                             });
555       body << "};\n  return ::llvm::makeArrayRef(attrNames);";
556     }
557   }
558   if (attributeNames.empty())
559     return;
560 
561   // Emit the getAttributeNameForIndex methods.
562   {
563     auto *method = opClass.addMethodAndPrune(
564         "::mlir::Identifier", "getAttributeNameForIndex",
565         OpMethod::Property(OpMethod::MP_Private | OpMethod::MP_Inline),
566         "unsigned", "index");
567     method->body()
568         << "  return getAttributeNameForIndex((*this)->getName(), index);";
569   }
570   {
571     auto *method = opClass.addMethodAndPrune(
572         "::mlir::Identifier", "getAttributeNameForIndex",
573         OpMethod::Property(OpMethod::MP_Private | OpMethod::MP_Inline |
574                            OpMethod::MP_Static),
575         "::mlir::OperationName name, unsigned index");
576     method->body() << "assert(index < " << attributeNames.size()
577                    << " && \"invalid attribute index\");\n"
578                       "  return name.getAbstractOperation()"
579                       "->getAttributeNames()[index];";
580   }
581 
582   // Generate the <attr>AttrName methods, that expose the attribute names to
583   // users.
584   const char *attrNameMethodBody = "  return getAttributeNameForIndex({0});";
585   for (const std::pair<StringRef, unsigned> &attrIt : attributeNames) {
586     std::string methodName = (attrIt.first + "AttrName").str();
587 
588     // Generate the non-static variant.
589     {
590       auto *method =
591           opClass.addMethodAndPrune("::mlir::Identifier", methodName,
592                                     OpMethod::Property(OpMethod::MP_Inline));
593       method->body() << llvm::formatv(attrNameMethodBody, attrIt.second).str();
594     }
595 
596     // Generate the static variant.
597     {
598       auto *method = opClass.addMethodAndPrune(
599           "::mlir::Identifier", methodName,
600           OpMethod::Property(OpMethod::MP_Inline | OpMethod::MP_Static),
601           "::mlir::OperationName", "name");
602       method->body() << llvm::formatv(attrNameMethodBody,
603                                       "name, " + Twine(attrIt.second))
604                             .str();
605     }
606   }
607 }
608 
609 void OpEmitter::genAttrGetters() {
610   FmtContext fctx;
611   fctx.withBuilder("::mlir::Builder((*this)->getContext())");
612 
613   // Emit the derived attribute body.
614   auto emitDerivedAttr = [&](StringRef name, Attribute attr) {
615     if (auto *method = opClass.addMethodAndPrune(attr.getReturnType(), name))
616       method->body() << "  " << attr.getDerivedCodeBody() << "\n";
617   };
618 
619   // Emit with return type specified.
620   auto emitAttrWithReturnType = [&](StringRef name, Attribute attr) {
621     auto *method = opClass.addMethodAndPrune(attr.getReturnType(), name);
622     auto &body = method->body();
623     body << "  auto attr = " << name << "Attr();\n";
624     if (attr.hasDefaultValue()) {
625       // Returns the default value if not set.
626       // TODO: this is inefficient, we are recreating the attribute for every
627       // call. This should be set instead.
628       std::string defaultValue = std::string(
629           tgfmt(attr.getConstBuilderTemplate(), &fctx, attr.getDefaultValue()));
630       body << "    if (!attr)\n      return "
631            << tgfmt(attr.getConvertFromStorageCall(),
632                     &fctx.withSelf(defaultValue))
633            << ";\n";
634     }
635     body << "  return "
636          << tgfmt(attr.getConvertFromStorageCall(), &fctx.withSelf("attr"))
637          << ";\n";
638   };
639 
640   // Generate raw named accessor type. This is a wrapper class that allows
641   // referring to the attributes via accessors instead of having to use
642   // the string interface for better compile time verification.
643   auto emitAttrWithStorageType = [&](StringRef name, Attribute attr) {
644     auto *method =
645         opClass.addMethodAndPrune(attr.getStorageType(), (name + "Attr").str());
646     if (!method)
647       return;
648     auto &body = method->body();
649     body << "  return (*this)->getAttr(" << name << "AttrName()).template ";
650     if (attr.isOptional() || attr.hasDefaultValue())
651       body << "dyn_cast_or_null<";
652     else
653       body << "cast<";
654     body << attr.getStorageType() << ">();";
655   };
656 
657   for (const NamedAttribute &namedAttr : op.getAttributes()) {
658     if (namedAttr.attr.isDerivedAttr()) {
659       emitDerivedAttr(namedAttr.name, namedAttr.attr);
660     } else {
661       emitAttrWithStorageType(namedAttr.name, namedAttr.attr);
662       emitAttrWithReturnType(namedAttr.name, namedAttr.attr);
663     }
664   }
665 
666   auto derivedAttrs = make_filter_range(op.getAttributes(),
667                                         [](const NamedAttribute &namedAttr) {
668                                           return namedAttr.attr.isDerivedAttr();
669                                         });
670   if (!derivedAttrs.empty()) {
671     opClass.addTrait("::mlir::DerivedAttributeOpInterface::Trait");
672     // Generate helper method to query whether a named attribute is a derived
673     // attribute. This enables, for example, avoiding adding an attribute that
674     // overlaps with a derived attribute.
675     {
676       auto *method = opClass.addMethodAndPrune("bool", "isDerivedAttribute",
677                                                OpMethod::MP_Static,
678                                                "::llvm::StringRef", "name");
679       auto &body = method->body();
680       for (auto namedAttr : derivedAttrs)
681         body << "  if (name == \"" << namedAttr.name << "\") return true;\n";
682       body << " return false;";
683     }
684     // Generate method to materialize derived attributes as a DictionaryAttr.
685     {
686       auto *method = opClass.addMethodAndPrune("::mlir::DictionaryAttr",
687                                                "materializeDerivedAttributes");
688       auto &body = method->body();
689 
690       auto nonMaterializable =
691           make_filter_range(derivedAttrs, [](const NamedAttribute &namedAttr) {
692             return namedAttr.attr.getConvertFromStorageCall().empty();
693           });
694       if (!nonMaterializable.empty()) {
695         std::string attrs;
696         llvm::raw_string_ostream os(attrs);
697         interleaveComma(nonMaterializable, os,
698                         [&](const NamedAttribute &attr) { os << attr.name; });
699         PrintWarning(
700             op.getLoc(),
701             formatv(
702                 "op has non-materializable derived attributes '{0}', skipping",
703                 os.str()));
704         body << formatv("  emitOpError(\"op has non-materializable derived "
705                         "attributes '{0}'\");\n",
706                         attrs);
707         body << "  return nullptr;";
708         return;
709       }
710 
711       body << "  ::mlir::MLIRContext* ctx = getContext();\n";
712       body << "  ::mlir::Builder odsBuilder(ctx); (void)odsBuilder;\n";
713       body << "  return ::mlir::DictionaryAttr::get(";
714       body << "  ctx, {\n";
715       interleave(
716           derivedAttrs, body,
717           [&](const NamedAttribute &namedAttr) {
718             auto tmpl = namedAttr.attr.getConvertFromStorageCall();
719             body << "    {" << namedAttr.name << "AttrName(),\n"
720                  << tgfmt(tmpl, &fctx.withSelf(namedAttr.name + "()")
721                                      .withBuilder("odsBuilder")
722                                      .addSubst("_ctx", "ctx"))
723                  << "}";
724           },
725           ",\n");
726       body << "});";
727     }
728   }
729 }
730 
731 void OpEmitter::genAttrSetters() {
732   // Generate raw named setter type. This is a wrapper class that allows setting
733   // to the attributes via setters instead of having to use the string interface
734   // for better compile time verification.
735   auto emitAttrWithStorageType = [&](StringRef name, Attribute attr) {
736     auto *method = opClass.addMethodAndPrune("void", (name + "Attr").str(),
737                                              attr.getStorageType(), "attr");
738     if (method)
739       method->body() << "  (*this)->setAttr(" << name << "AttrName(), attr);";
740   };
741 
742   for (const NamedAttribute &namedAttr : op.getAttributes())
743     if (!namedAttr.attr.isDerivedAttr())
744       emitAttrWithStorageType(namedAttr.name, namedAttr.attr);
745 }
746 
747 void OpEmitter::genOptionalAttrRemovers() {
748   // Generate methods for removing optional attributes, instead of having to
749   // use the string interface. Enables better compile time verification.
750   auto emitRemoveAttr = [&](StringRef name) {
751     auto upperInitial = name.take_front().upper();
752     auto suffix = name.drop_front();
753     auto *method = opClass.addMethodAndPrune(
754         "::mlir::Attribute", ("remove" + upperInitial + suffix + "Attr").str());
755     if (!method)
756       return;
757     method->body() << "  return (*this)->removeAttr(" << name << "AttrName());";
758   };
759 
760   for (const NamedAttribute &namedAttr : op.getAttributes())
761     if (namedAttr.attr.isOptional())
762       emitRemoveAttr(namedAttr.name);
763 }
764 
765 // Generates the code to compute the start and end index of an operand or result
766 // range.
767 template <typename RangeT>
768 static void
769 generateValueRangeStartAndEnd(Class &opClass, StringRef methodName,
770                               int numVariadic, int numNonVariadic,
771                               StringRef rangeSizeCall, bool hasAttrSegmentSize,
772                               StringRef sizeAttrInit, RangeT &&odsValues) {
773   auto *method = opClass.addMethodAndPrune("std::pair<unsigned, unsigned>",
774                                            methodName, "unsigned", "index");
775   if (!method)
776     return;
777   auto &body = method->body();
778   if (numVariadic == 0) {
779     body << "  return {index, 1};\n";
780   } else if (hasAttrSegmentSize) {
781     body << sizeAttrInit << attrSizedSegmentValueRangeCalcCode;
782   } else {
783     // Because the op can have arbitrarily interleaved variadic and non-variadic
784     // operands, we need to embed a list in the "sink" getter method for
785     // calculation at run-time.
786     llvm::SmallVector<StringRef, 4> isVariadic;
787     isVariadic.reserve(llvm::size(odsValues));
788     for (auto &it : odsValues)
789       isVariadic.push_back(it.isVariableLength() ? "true" : "false");
790     std::string isVariadicList = llvm::join(isVariadic, ", ");
791     body << formatv(sameVariadicSizeValueRangeCalcCode, isVariadicList,
792                     numNonVariadic, numVariadic, rangeSizeCall, "operand");
793   }
794 }
795 
796 // Generates the named operand getter methods for the given Operator `op` and
797 // puts them in `opClass`.  Uses `rangeType` as the return type of getters that
798 // return a range of operands (individual operands are `Value ` and each
799 // element in the range must also be `Value `); use `rangeBeginCall` to get
800 // an iterator to the beginning of the operand range; use `rangeSizeCall` to
801 // obtain the number of operands. `getOperandCallPattern` contains the code
802 // necessary to obtain a single operand whose position will be substituted
803 // instead of
804 // "{0}" marker in the pattern.  Note that the pattern should work for any kind
805 // of ops, in particular for one-operand ops that may not have the
806 // `getOperand(unsigned)` method.
807 static void generateNamedOperandGetters(const Operator &op, Class &opClass,
808                                         bool isAdaptor, StringRef sizeAttrInit,
809                                         StringRef rangeType,
810                                         StringRef rangeBeginCall,
811                                         StringRef rangeSizeCall,
812                                         StringRef getOperandCallPattern) {
813   const int numOperands = op.getNumOperands();
814   const int numVariadicOperands = op.getNumVariableLengthOperands();
815   const int numNormalOperands = numOperands - numVariadicOperands;
816 
817   const auto *sameVariadicSize =
818       op.getTrait("::mlir::OpTrait::SameVariadicOperandSize");
819   const auto *attrSizedOperands =
820       op.getTrait("::mlir::OpTrait::AttrSizedOperandSegments");
821 
822   if (numVariadicOperands > 1 && !sameVariadicSize && !attrSizedOperands) {
823     PrintFatalError(op.getLoc(), "op has multiple variadic operands but no "
824                                  "specification over their sizes");
825   }
826 
827   if (numVariadicOperands < 2 && attrSizedOperands) {
828     PrintFatalError(op.getLoc(), "op must have at least two variadic operands "
829                                  "to use 'AttrSizedOperandSegments' trait");
830   }
831 
832   if (attrSizedOperands && sameVariadicSize) {
833     PrintFatalError(op.getLoc(),
834                     "op cannot have both 'AttrSizedOperandSegments' and "
835                     "'SameVariadicOperandSize' traits");
836   }
837 
838   // First emit a few "sink" getter methods upon which we layer all nicer named
839   // getter methods.
840   generateValueRangeStartAndEnd(opClass, "getODSOperandIndexAndLength",
841                                 numVariadicOperands, numNormalOperands,
842                                 rangeSizeCall, attrSizedOperands, sizeAttrInit,
843                                 const_cast<Operator &>(op).getOperands());
844 
845   auto *m = opClass.addMethodAndPrune(rangeType, "getODSOperands", "unsigned",
846                                       "index");
847   auto &body = m->body();
848   body << formatv(valueRangeReturnCode, rangeBeginCall,
849                   "getODSOperandIndexAndLength(index)");
850 
851   // Then we emit nicer named getter methods by redirecting to the "sink" getter
852   // method.
853   // Keep track of the operand names to find duplicates.
854   SmallDenseSet<StringRef> operandNames;
855   for (int i = 0; i != numOperands; ++i) {
856     const auto &operand = op.getOperand(i);
857     if (operand.name.empty())
858       continue;
859     if (!operandNames.insert(operand.name).second)
860       PrintFatalError(op.getLoc(), "op has two operands with the same name: '" +
861                                        operand.name + "'");
862 
863     if (operand.isOptional()) {
864       m = opClass.addMethodAndPrune("::mlir::Value", operand.name);
865       m->body()
866           << "  auto operands = getODSOperands(" << i << ");\n"
867           << "  return operands.empty() ? ::mlir::Value() : *operands.begin();";
868     } else if (operand.isVariadicOfVariadic()) {
869       StringRef segmentAttr =
870           operand.constraint.getVariadicOfVariadicSegmentSizeAttr();
871       if (isAdaptor) {
872         m = opClass.addMethodAndPrune("::llvm::SmallVector<::mlir::ValueRange>",
873                                       operand.name);
874         m->body() << llvm::formatv(variadicOfVariadicAdaptorCalcCode,
875                                    segmentAttr, i);
876         continue;
877       }
878 
879       m = opClass.addMethodAndPrune("::mlir::OperandRangeRange", operand.name);
880       m->body() << "  return getODSOperands(" << i << ").split(" << segmentAttr
881                 << "Attr());";
882     } else if (operand.isVariadic()) {
883       m = opClass.addMethodAndPrune(rangeType, operand.name);
884       m->body() << "  return getODSOperands(" << i << ");";
885     } else {
886       m = opClass.addMethodAndPrune("::mlir::Value", operand.name);
887       m->body() << "  return *getODSOperands(" << i << ").begin();";
888     }
889   }
890 }
891 
892 void OpEmitter::genNamedOperandGetters() {
893   // Build the code snippet used for initializing the operand_segment_sizes
894   // array.
895   std::string attrSizeInitCode;
896   if (op.getTrait("::mlir::OpTrait::AttrSizedOperandSegments")) {
897     attrSizeInitCode =
898         formatv(opSegmentSizeAttrInitCode, "operand_segment_sizesAttrName()")
899             .str();
900   }
901 
902   generateNamedOperandGetters(
903       op, opClass,
904       /*isAdaptor=*/false,
905       /*sizeAttrInit=*/attrSizeInitCode,
906       /*rangeType=*/"::mlir::Operation::operand_range",
907       /*rangeBeginCall=*/"getOperation()->operand_begin()",
908       /*rangeSizeCall=*/"getOperation()->getNumOperands()",
909       /*getOperandCallPattern=*/"getOperation()->getOperand({0})");
910 }
911 
912 void OpEmitter::genNamedOperandSetters() {
913   auto *attrSizedOperands =
914       op.getTrait("::mlir::OpTrait::AttrSizedOperandSegments");
915   for (int i = 0, e = op.getNumOperands(); i != e; ++i) {
916     const auto &operand = op.getOperand(i);
917     if (operand.name.empty())
918       continue;
919     auto *m = opClass.addMethodAndPrune(operand.isVariadicOfVariadic()
920                                             ? "::mlir::MutableOperandRangeRange"
921                                             : "::mlir::MutableOperandRange",
922                                         (operand.name + "Mutable").str());
923     auto &body = m->body();
924     body << "  auto range = getODSOperandIndexAndLength(" << i << ");\n"
925          << "  auto mutableRange = ::mlir::MutableOperandRange(getOperation(), "
926             "range.first, range.second";
927     if (attrSizedOperands)
928       body << ", ::mlir::MutableOperandRange::OperandSegment(" << i
929            << "u, *getOperation()->getAttrDictionary().getNamed("
930               "operand_segment_sizesAttrName()))";
931     body << ");\n";
932 
933     // If this operand is a nested variadic, we split the range into a
934     // MutableOperandRangeRange that provides a range over all of the
935     // sub-ranges.
936     if (operand.isVariadicOfVariadic()) {
937       body << "  return "
938               "mutableRange.split(*(*this)->getAttrDictionary().getNamed("
939            << operand.constraint.getVariadicOfVariadicSegmentSizeAttr()
940            << "AttrName()));\n";
941     } else {
942       // Otherwise, we use the full range directly.
943       body << "  return mutableRange;\n";
944     }
945   }
946 }
947 
948 void OpEmitter::genNamedResultGetters() {
949   const int numResults = op.getNumResults();
950   const int numVariadicResults = op.getNumVariableLengthResults();
951   const int numNormalResults = numResults - numVariadicResults;
952 
953   // If we have more than one variadic results, we need more complicated logic
954   // to calculate the value range for each result.
955 
956   const auto *sameVariadicSize =
957       op.getTrait("::mlir::OpTrait::SameVariadicResultSize");
958   const auto *attrSizedResults =
959       op.getTrait("::mlir::OpTrait::AttrSizedResultSegments");
960 
961   if (numVariadicResults > 1 && !sameVariadicSize && !attrSizedResults) {
962     PrintFatalError(op.getLoc(), "op has multiple variadic results but no "
963                                  "specification over their sizes");
964   }
965 
966   if (numVariadicResults < 2 && attrSizedResults) {
967     PrintFatalError(op.getLoc(), "op must have at least two variadic results "
968                                  "to use 'AttrSizedResultSegments' trait");
969   }
970 
971   if (attrSizedResults && sameVariadicSize) {
972     PrintFatalError(op.getLoc(),
973                     "op cannot have both 'AttrSizedResultSegments' and "
974                     "'SameVariadicResultSize' traits");
975   }
976 
977   // Build the initializer string for the result segment size attribute.
978   std::string attrSizeInitCode;
979   if (attrSizedResults) {
980     attrSizeInitCode =
981         formatv(opSegmentSizeAttrInitCode, "result_segment_sizesAttrName()")
982             .str();
983   }
984 
985   generateValueRangeStartAndEnd(
986       opClass, "getODSResultIndexAndLength", numVariadicResults,
987       numNormalResults, "getOperation()->getNumResults()", attrSizedResults,
988       attrSizeInitCode, op.getResults());
989 
990   auto *m = opClass.addMethodAndPrune("::mlir::Operation::result_range",
991                                       "getODSResults", "unsigned", "index");
992   m->body() << formatv(valueRangeReturnCode, "getOperation()->result_begin()",
993                        "getODSResultIndexAndLength(index)");
994 
995   SmallDenseSet<StringRef> resultNames;
996   for (int i = 0; i != numResults; ++i) {
997     const auto &result = op.getResult(i);
998     if (result.name.empty())
999       continue;
1000     if (!resultNames.insert(result.name).second)
1001       PrintFatalError(op.getLoc(), "op has two results with the same name: '" +
1002                                        result.name + "'");
1003 
1004     if (result.isOptional()) {
1005       m = opClass.addMethodAndPrune("::mlir::Value", result.name);
1006       m->body()
1007           << "  auto results = getODSResults(" << i << ");\n"
1008           << "  return results.empty() ? ::mlir::Value() : *results.begin();";
1009     } else if (result.isVariadic()) {
1010       m = opClass.addMethodAndPrune("::mlir::Operation::result_range",
1011                                     result.name);
1012       m->body() << "  return getODSResults(" << i << ");";
1013     } else {
1014       m = opClass.addMethodAndPrune("::mlir::Value", result.name);
1015       m->body() << "  return *getODSResults(" << i << ").begin();";
1016     }
1017   }
1018 }
1019 
1020 void OpEmitter::genNamedRegionGetters() {
1021   unsigned numRegions = op.getNumRegions();
1022   for (unsigned i = 0; i < numRegions; ++i) {
1023     const auto &region = op.getRegion(i);
1024     if (region.name.empty())
1025       continue;
1026 
1027     // Generate the accessors for a variadic region.
1028     if (region.isVariadic()) {
1029       auto *m = opClass.addMethodAndPrune(
1030           "::mlir::MutableArrayRef<::mlir::Region>", region.name);
1031       m->body() << formatv("  return (*this)->getRegions().drop_front({0});",
1032                            i);
1033       continue;
1034     }
1035 
1036     auto *m = opClass.addMethodAndPrune("::mlir::Region &", region.name);
1037     m->body() << formatv("  return (*this)->getRegion({0});", i);
1038   }
1039 }
1040 
1041 void OpEmitter::genNamedSuccessorGetters() {
1042   unsigned numSuccessors = op.getNumSuccessors();
1043   for (unsigned i = 0; i < numSuccessors; ++i) {
1044     const NamedSuccessor &successor = op.getSuccessor(i);
1045     if (successor.name.empty())
1046       continue;
1047 
1048     // Generate the accessors for a variadic successor list.
1049     if (successor.isVariadic()) {
1050       auto *m =
1051           opClass.addMethodAndPrune("::mlir::SuccessorRange", successor.name);
1052       m->body() << formatv(
1053           "  return {std::next((*this)->successor_begin(), {0}), "
1054           "(*this)->successor_end()};",
1055           i);
1056       continue;
1057     }
1058 
1059     auto *m = opClass.addMethodAndPrune("::mlir::Block *", successor.name);
1060     m->body() << formatv("  return (*this)->getSuccessor({0});", i);
1061   }
1062 }
1063 
1064 static bool canGenerateUnwrappedBuilder(Operator &op) {
1065   // If this op does not have native attributes at all, return directly to avoid
1066   // redefining builders.
1067   if (op.getNumNativeAttributes() == 0)
1068     return false;
1069 
1070   bool canGenerate = false;
1071   // We are generating builders that take raw values for attributes. We need to
1072   // make sure the native attributes have a meaningful "unwrapped" value type
1073   // different from the wrapped mlir::Attribute type to avoid redefining
1074   // builders. This checks for the op has at least one such native attribute.
1075   for (int i = 0, e = op.getNumNativeAttributes(); i < e; ++i) {
1076     NamedAttribute &namedAttr = op.getAttribute(i);
1077     if (canUseUnwrappedRawValue(namedAttr.attr)) {
1078       canGenerate = true;
1079       break;
1080     }
1081   }
1082   return canGenerate;
1083 }
1084 
1085 static bool canInferType(Operator &op) {
1086   return op.getTrait("::mlir::InferTypeOpInterface::Trait") &&
1087          op.getNumRegions() == 0;
1088 }
1089 
1090 void OpEmitter::genSeparateArgParamBuilder() {
1091   SmallVector<AttrParamKind, 2> attrBuilderType;
1092   attrBuilderType.push_back(AttrParamKind::WrappedAttr);
1093   if (canGenerateUnwrappedBuilder(op))
1094     attrBuilderType.push_back(AttrParamKind::UnwrappedValue);
1095 
1096   // Emit with separate builders with or without unwrapped attributes and/or
1097   // inferring result type.
1098   auto emit = [&](AttrParamKind attrType, TypeParamKind paramKind,
1099                   bool inferType) {
1100     llvm::SmallVector<OpMethodParameter, 4> paramList;
1101     llvm::SmallVector<std::string, 4> resultNames;
1102     llvm::StringSet<> inferredAttributes;
1103     buildParamList(paramList, inferredAttributes, resultNames, paramKind,
1104                    attrType);
1105 
1106     auto *m = opClass.addMethodAndPrune("void", "build", OpMethod::MP_Static,
1107                                         std::move(paramList));
1108     // If the builder is redundant, skip generating the method.
1109     if (!m)
1110       return;
1111     auto &body = m->body();
1112     genCodeForAddingArgAndRegionForBuilder(body, inferredAttributes,
1113                                            /*isRawValueAttr=*/attrType ==
1114                                                AttrParamKind::UnwrappedValue);
1115 
1116     // Push all result types to the operation state
1117 
1118     if (inferType) {
1119       // Generate builder that infers type too.
1120       // TODO: Subsume this with general checking if type can be
1121       // inferred automatically.
1122       // TODO: Expand to handle regions.
1123       body << formatv(R"(
1124         ::llvm::SmallVector<::mlir::Type, 2> inferredReturnTypes;
1125         if (::mlir::succeeded({0}::inferReturnTypes(odsBuilder.getContext(),
1126                       {1}.location, {1}.operands,
1127                       {1}.attributes.getDictionary({1}.getContext()),
1128                       /*regions=*/{{}, inferredReturnTypes)))
1129           {1}.addTypes(inferredReturnTypes);
1130         else
1131           ::llvm::report_fatal_error("Failed to infer result type(s).");)",
1132                       opClass.getClassName(), builderOpState);
1133       return;
1134     }
1135 
1136     switch (paramKind) {
1137     case TypeParamKind::None:
1138       return;
1139     case TypeParamKind::Separate:
1140       for (int i = 0, e = op.getNumResults(); i < e; ++i) {
1141         if (op.getResult(i).isOptional())
1142           body << "  if (" << resultNames[i] << ")\n  ";
1143         body << "  " << builderOpState << ".addTypes(" << resultNames[i]
1144              << ");\n";
1145       }
1146       return;
1147     case TypeParamKind::Collective: {
1148       int numResults = op.getNumResults();
1149       int numVariadicResults = op.getNumVariableLengthResults();
1150       int numNonVariadicResults = numResults - numVariadicResults;
1151       bool hasVariadicResult = numVariadicResults != 0;
1152 
1153       // Avoid emitting "resultTypes.size() >= 0u" which is always true.
1154       if (!(hasVariadicResult && numNonVariadicResults == 0))
1155         body << "  "
1156              << "assert(resultTypes.size() "
1157              << (hasVariadicResult ? ">=" : "==") << " "
1158              << numNonVariadicResults
1159              << "u && \"mismatched number of results\");\n";
1160       body << "  " << builderOpState << ".addTypes(resultTypes);\n";
1161     }
1162       return;
1163     }
1164     llvm_unreachable("unhandled TypeParamKind");
1165   };
1166 
1167   // Some of the build methods generated here may be ambiguous, but TableGen's
1168   // ambiguous function detection will elide those ones.
1169   for (auto attrType : attrBuilderType) {
1170     emit(attrType, TypeParamKind::Separate, /*inferType=*/false);
1171     if (canInferType(op))
1172       emit(attrType, TypeParamKind::None, /*inferType=*/true);
1173     emit(attrType, TypeParamKind::Collective, /*inferType=*/false);
1174   }
1175 }
1176 
1177 void OpEmitter::genUseOperandAsResultTypeCollectiveParamBuilder() {
1178   int numResults = op.getNumResults();
1179 
1180   // Signature
1181   llvm::SmallVector<OpMethodParameter, 4> paramList;
1182   paramList.emplace_back("::mlir::OpBuilder &", "odsBuilder");
1183   paramList.emplace_back("::mlir::OperationState &", builderOpState);
1184   paramList.emplace_back("::mlir::ValueRange", "operands");
1185   // Provide default value for `attributes` when its the last parameter
1186   StringRef attributesDefaultValue = op.getNumVariadicRegions() ? "" : "{}";
1187   paramList.emplace_back("::llvm::ArrayRef<::mlir::NamedAttribute>",
1188                          "attributes", attributesDefaultValue);
1189   if (op.getNumVariadicRegions())
1190     paramList.emplace_back("unsigned", "numRegions");
1191 
1192   auto *m = opClass.addMethodAndPrune("void", "build", OpMethod::MP_Static,
1193                                       std::move(paramList));
1194   // If the builder is redundant, skip generating the method
1195   if (!m)
1196     return;
1197   auto &body = m->body();
1198 
1199   // Operands
1200   body << "  " << builderOpState << ".addOperands(operands);\n";
1201 
1202   // Attributes
1203   body << "  " << builderOpState << ".addAttributes(attributes);\n";
1204 
1205   // Create the correct number of regions
1206   if (int numRegions = op.getNumRegions()) {
1207     body << llvm::formatv(
1208         "  for (unsigned i = 0; i != {0}; ++i)\n",
1209         (op.getNumVariadicRegions() ? "numRegions" : Twine(numRegions)));
1210     body << "    (void)" << builderOpState << ".addRegion();\n";
1211   }
1212 
1213   // Result types
1214   SmallVector<std::string, 2> resultTypes(numResults, "operands[0].getType()");
1215   body << "  " << builderOpState << ".addTypes({"
1216        << llvm::join(resultTypes, ", ") << "});\n\n";
1217 }
1218 
1219 void OpEmitter::genInferredTypeCollectiveParamBuilder() {
1220   // TODO: Expand to support regions.
1221   SmallVector<OpMethodParameter, 4> paramList;
1222   paramList.emplace_back("::mlir::OpBuilder &", "odsBuilder");
1223   paramList.emplace_back("::mlir::OperationState &", builderOpState);
1224   paramList.emplace_back("::mlir::ValueRange", "operands");
1225   paramList.emplace_back("::llvm::ArrayRef<::mlir::NamedAttribute>",
1226                          "attributes", "{}");
1227   auto *m = opClass.addMethodAndPrune("void", "build", OpMethod::MP_Static,
1228                                       std::move(paramList));
1229   // If the builder is redundant, skip generating the method
1230   if (!m)
1231     return;
1232   auto &body = m->body();
1233 
1234   int numResults = op.getNumResults();
1235   int numVariadicResults = op.getNumVariableLengthResults();
1236   int numNonVariadicResults = numResults - numVariadicResults;
1237 
1238   int numOperands = op.getNumOperands();
1239   int numVariadicOperands = op.getNumVariableLengthOperands();
1240   int numNonVariadicOperands = numOperands - numVariadicOperands;
1241 
1242   // Operands
1243   if (numVariadicOperands == 0 || numNonVariadicOperands != 0)
1244     body << "  assert(operands.size()"
1245          << (numVariadicOperands != 0 ? " >= " : " == ")
1246          << numNonVariadicOperands
1247          << "u && \"mismatched number of parameters\");\n";
1248   body << "  " << builderOpState << ".addOperands(operands);\n";
1249   body << "  " << builderOpState << ".addAttributes(attributes);\n";
1250 
1251   // Create the correct number of regions
1252   if (int numRegions = op.getNumRegions()) {
1253     body << llvm::formatv(
1254         "  for (unsigned i = 0; i != {0}; ++i)\n",
1255         (op.getNumVariadicRegions() ? "numRegions" : Twine(numRegions)));
1256     body << "    (void)" << builderOpState << ".addRegion();\n";
1257   }
1258 
1259   // Result types
1260   body << formatv(R"(
1261     ::mlir::SmallVector<::mlir::Type, 2> inferredReturnTypes;
1262     if (::mlir::succeeded({0}::inferReturnTypes(odsBuilder.getContext(),
1263                   {1}.location, operands,
1264                   {1}.attributes.getDictionary({1}.getContext()),
1265                   /*regions=*/{{}, inferredReturnTypes))) {{)",
1266                   opClass.getClassName(), builderOpState);
1267   if (numVariadicResults == 0 || numNonVariadicResults != 0)
1268     body << "  assert(inferredReturnTypes.size()"
1269          << (numVariadicResults != 0 ? " >= " : " == ") << numNonVariadicResults
1270          << "u && \"mismatched number of return types\");\n";
1271   body << "      " << builderOpState << ".addTypes(inferredReturnTypes);";
1272 
1273   body << formatv(R"(
1274     } else
1275       ::llvm::report_fatal_error("Failed to infer result type(s).");)",
1276                   opClass.getClassName(), builderOpState);
1277 }
1278 
1279 void OpEmitter::genUseOperandAsResultTypeSeparateParamBuilder() {
1280   llvm::SmallVector<OpMethodParameter, 4> paramList;
1281   llvm::SmallVector<std::string, 4> resultNames;
1282   llvm::StringSet<> inferredAttributes;
1283   buildParamList(paramList, inferredAttributes, resultNames,
1284                  TypeParamKind::None);
1285 
1286   auto *m = opClass.addMethodAndPrune("void", "build", OpMethod::MP_Static,
1287                                       std::move(paramList));
1288   // If the builder is redundant, skip generating the method
1289   if (!m)
1290     return;
1291   auto &body = m->body();
1292   genCodeForAddingArgAndRegionForBuilder(body, inferredAttributes);
1293 
1294   auto numResults = op.getNumResults();
1295   if (numResults == 0)
1296     return;
1297 
1298   // Push all result types to the operation state
1299   const char *index = op.getOperand(0).isVariadic() ? ".front()" : "";
1300   std::string resultType =
1301       formatv("{0}{1}.getType()", getArgumentName(op, 0), index).str();
1302   body << "  " << builderOpState << ".addTypes({" << resultType;
1303   for (int i = 1; i != numResults; ++i)
1304     body << ", " << resultType;
1305   body << "});\n\n";
1306 }
1307 
1308 void OpEmitter::genUseAttrAsResultTypeBuilder() {
1309   SmallVector<OpMethodParameter, 4> paramList;
1310   paramList.emplace_back("::mlir::OpBuilder &", "odsBuilder");
1311   paramList.emplace_back("::mlir::OperationState &", builderOpState);
1312   paramList.emplace_back("::mlir::ValueRange", "operands");
1313   paramList.emplace_back("::llvm::ArrayRef<::mlir::NamedAttribute>",
1314                          "attributes", "{}");
1315   auto *m = opClass.addMethodAndPrune("void", "build", OpMethod::MP_Static,
1316                                       std::move(paramList));
1317   // If the builder is redundant, skip generating the method
1318   if (!m)
1319     return;
1320 
1321   auto &body = m->body();
1322 
1323   // Push all result types to the operation state
1324   std::string resultType;
1325   const auto &namedAttr = op.getAttribute(0);
1326 
1327   body << "  auto attrName = " << namedAttr.name << "AttrName("
1328        << builderOpState
1329        << ".name);\n"
1330           "  for (auto attr : attributes) {\n"
1331           "    if (attr.first != attrName) continue;\n";
1332   if (namedAttr.attr.isTypeAttr()) {
1333     resultType = "attr.second.cast<::mlir::TypeAttr>().getValue()";
1334   } else {
1335     resultType = "attr.second.getType()";
1336   }
1337 
1338   // Operands
1339   body << "  " << builderOpState << ".addOperands(operands);\n";
1340 
1341   // Attributes
1342   body << "  " << builderOpState << ".addAttributes(attributes);\n";
1343 
1344   // Result types
1345   SmallVector<std::string, 2> resultTypes(op.getNumResults(), resultType);
1346   body << "    " << builderOpState << ".addTypes({"
1347        << llvm::join(resultTypes, ", ") << "});\n";
1348   body << "  }\n";
1349 }
1350 
1351 /// Returns a signature of the builder. Updates the context `fctx` to enable
1352 /// replacement of $_builder and $_state in the body.
1353 static std::string getBuilderSignature(const Builder &builder) {
1354   ArrayRef<Builder::Parameter> params(builder.getParameters());
1355 
1356   // Inject builder and state arguments.
1357   llvm::SmallVector<std::string, 8> arguments;
1358   arguments.reserve(params.size() + 2);
1359   arguments.push_back(
1360       llvm::formatv("::mlir::OpBuilder &{0}", odsBuilder).str());
1361   arguments.push_back(
1362       llvm::formatv("::mlir::OperationState &{0}", builderOpState).str());
1363 
1364   for (unsigned i = 0, e = params.size(); i < e; ++i) {
1365     // If no name is provided, generate one.
1366     Optional<StringRef> paramName = params[i].getName();
1367     std::string name =
1368         paramName ? paramName->str() : "odsArg" + std::to_string(i);
1369 
1370     std::string defaultValue;
1371     if (Optional<StringRef> defaultParamValue = params[i].getDefaultValue())
1372       defaultValue = llvm::formatv(" = {0}", *defaultParamValue).str();
1373     arguments.push_back(
1374         llvm::formatv("{0} {1}{2}", params[i].getCppType(), name, defaultValue)
1375             .str());
1376   }
1377 
1378   return llvm::join(arguments, ", ");
1379 }
1380 
1381 void OpEmitter::genBuilder() {
1382   // Handle custom builders if provided.
1383   for (const Builder &builder : op.getBuilders()) {
1384     std::string paramStr = getBuilderSignature(builder);
1385 
1386     Optional<StringRef> body = builder.getBody();
1387     OpMethod::Property properties =
1388         body ? OpMethod::MP_Static : OpMethod::MP_StaticDeclaration;
1389     auto *method =
1390         opClass.addMethodAndPrune("void", "build", properties, paramStr);
1391 
1392     FmtContext fctx;
1393     fctx.withBuilder(odsBuilder);
1394     fctx.addSubst("_state", builderOpState);
1395     if (body)
1396       method->body() << tgfmt(*body, &fctx);
1397   }
1398 
1399   // Generate default builders that requires all result type, operands, and
1400   // attributes as parameters.
1401   if (op.skipDefaultBuilders())
1402     return;
1403 
1404   // We generate three classes of builders here:
1405   // 1. one having a stand-alone parameter for each operand / attribute, and
1406   genSeparateArgParamBuilder();
1407   // 2. one having an aggregated parameter for all result types / operands /
1408   //    attributes, and
1409   genCollectiveParamBuilder();
1410   // 3. one having a stand-alone parameter for each operand and attribute,
1411   //    use the first operand or attribute's type as all result types
1412   //    to facilitate different call patterns.
1413   if (op.getNumVariableLengthResults() == 0) {
1414     if (op.getTrait("::mlir::OpTrait::SameOperandsAndResultType")) {
1415       genUseOperandAsResultTypeSeparateParamBuilder();
1416       genUseOperandAsResultTypeCollectiveParamBuilder();
1417     }
1418     if (op.getTrait("::mlir::OpTrait::FirstAttrDerivedResultType"))
1419       genUseAttrAsResultTypeBuilder();
1420   }
1421 }
1422 
1423 void OpEmitter::genCollectiveParamBuilder() {
1424   int numResults = op.getNumResults();
1425   int numVariadicResults = op.getNumVariableLengthResults();
1426   int numNonVariadicResults = numResults - numVariadicResults;
1427 
1428   int numOperands = op.getNumOperands();
1429   int numVariadicOperands = op.getNumVariableLengthOperands();
1430   int numNonVariadicOperands = numOperands - numVariadicOperands;
1431 
1432   SmallVector<OpMethodParameter, 4> paramList;
1433   paramList.emplace_back("::mlir::OpBuilder &", "");
1434   paramList.emplace_back("::mlir::OperationState &", builderOpState);
1435   paramList.emplace_back("::mlir::TypeRange", "resultTypes");
1436   paramList.emplace_back("::mlir::ValueRange", "operands");
1437   // Provide default value for `attributes` when its the last parameter
1438   StringRef attributesDefaultValue = op.getNumVariadicRegions() ? "" : "{}";
1439   paramList.emplace_back("::llvm::ArrayRef<::mlir::NamedAttribute>",
1440                          "attributes", attributesDefaultValue);
1441   if (op.getNumVariadicRegions())
1442     paramList.emplace_back("unsigned", "numRegions");
1443 
1444   auto *m = opClass.addMethodAndPrune("void", "build", OpMethod::MP_Static,
1445                                       std::move(paramList));
1446   // If the builder is redundant, skip generating the method
1447   if (!m)
1448     return;
1449   auto &body = m->body();
1450 
1451   // Operands
1452   if (numVariadicOperands == 0 || numNonVariadicOperands != 0)
1453     body << "  assert(operands.size()"
1454          << (numVariadicOperands != 0 ? " >= " : " == ")
1455          << numNonVariadicOperands
1456          << "u && \"mismatched number of parameters\");\n";
1457   body << "  " << builderOpState << ".addOperands(operands);\n";
1458 
1459   // Attributes
1460   body << "  " << builderOpState << ".addAttributes(attributes);\n";
1461 
1462   // Create the correct number of regions
1463   if (int numRegions = op.getNumRegions()) {
1464     body << llvm::formatv(
1465         "  for (unsigned i = 0; i != {0}; ++i)\n",
1466         (op.getNumVariadicRegions() ? "numRegions" : Twine(numRegions)));
1467     body << "    (void)" << builderOpState << ".addRegion();\n";
1468   }
1469 
1470   // Result types
1471   if (numVariadicResults == 0 || numNonVariadicResults != 0)
1472     body << "  assert(resultTypes.size()"
1473          << (numVariadicResults != 0 ? " >= " : " == ") << numNonVariadicResults
1474          << "u && \"mismatched number of return types\");\n";
1475   body << "  " << builderOpState << ".addTypes(resultTypes);\n";
1476 
1477   // Generate builder that infers type too.
1478   // TODO: Expand to handle regions and successors.
1479   if (canInferType(op) && op.getNumSuccessors() == 0)
1480     genInferredTypeCollectiveParamBuilder();
1481 }
1482 
1483 void OpEmitter::buildParamList(SmallVectorImpl<OpMethodParameter> &paramList,
1484                                llvm::StringSet<> &inferredAttributes,
1485                                SmallVectorImpl<std::string> &resultTypeNames,
1486                                TypeParamKind typeParamKind,
1487                                AttrParamKind attrParamKind) {
1488   resultTypeNames.clear();
1489   auto numResults = op.getNumResults();
1490   resultTypeNames.reserve(numResults);
1491 
1492   paramList.emplace_back("::mlir::OpBuilder &", "odsBuilder");
1493   paramList.emplace_back("::mlir::OperationState &", builderOpState);
1494 
1495   switch (typeParamKind) {
1496   case TypeParamKind::None:
1497     break;
1498   case TypeParamKind::Separate: {
1499     // Add parameters for all return types
1500     for (int i = 0; i < numResults; ++i) {
1501       const auto &result = op.getResult(i);
1502       std::string resultName = std::string(result.name);
1503       if (resultName.empty())
1504         resultName = std::string(formatv("resultType{0}", i));
1505 
1506       StringRef type =
1507           result.isVariadic() ? "::mlir::TypeRange" : "::mlir::Type";
1508       OpMethodParameter::Property properties = OpMethodParameter::PP_None;
1509       if (result.isOptional())
1510         properties = OpMethodParameter::PP_Optional;
1511 
1512       paramList.emplace_back(type, resultName, properties);
1513       resultTypeNames.emplace_back(std::move(resultName));
1514     }
1515   } break;
1516   case TypeParamKind::Collective: {
1517     paramList.emplace_back("::mlir::TypeRange", "resultTypes");
1518     resultTypeNames.push_back("resultTypes");
1519   } break;
1520   }
1521 
1522   // Add parameters for all arguments (operands and attributes).
1523   int defaultValuedAttrStartIndex = op.getNumArgs();
1524   if (attrParamKind == AttrParamKind::UnwrappedValue) {
1525     // Calculate the start index from which we can attach default values in the
1526     // builder declaration.
1527     for (int i = op.getNumArgs() - 1; i >= 0; --i) {
1528       auto *namedAttr = op.getArg(i).dyn_cast<tblgen::NamedAttribute *>();
1529       if (!namedAttr || !namedAttr->attr.hasDefaultValue())
1530         break;
1531 
1532       if (!canUseUnwrappedRawValue(namedAttr->attr))
1533         break;
1534 
1535       // Creating an APInt requires us to provide bitwidth, value, and
1536       // signedness, which is complicated compared to others. Similarly
1537       // for APFloat.
1538       // TODO: Adjust the 'returnType' field of such attributes
1539       // to support them.
1540       StringRef retType = namedAttr->attr.getReturnType();
1541       if (retType == "::llvm::APInt" || retType == "::llvm::APFloat")
1542         break;
1543 
1544       defaultValuedAttrStartIndex = i;
1545     }
1546   }
1547 
1548   /// Collect any inferred attributes.
1549   for (const NamedTypeConstraint &operand : op.getOperands()) {
1550     if (operand.isVariadicOfVariadic()) {
1551       inferredAttributes.insert(
1552           operand.constraint.getVariadicOfVariadicSegmentSizeAttr());
1553     }
1554   }
1555 
1556   for (int i = 0, e = op.getNumArgs(), numOperands = 0; i < e; ++i) {
1557     Argument arg = op.getArg(i);
1558     if (const auto *operand = arg.dyn_cast<NamedTypeConstraint *>()) {
1559       StringRef type;
1560       if (operand->isVariadicOfVariadic())
1561         type = "::llvm::ArrayRef<::mlir::ValueRange>";
1562       else if (operand->isVariadic())
1563         type = "::mlir::ValueRange";
1564       else
1565         type = "::mlir::Value";
1566 
1567       OpMethodParameter::Property properties = OpMethodParameter::PP_None;
1568       if (operand->isOptional())
1569         properties = OpMethodParameter::PP_Optional;
1570       paramList.emplace_back(type, getArgumentName(op, numOperands++),
1571                              properties);
1572       continue;
1573     }
1574     const NamedAttribute &namedAttr = *arg.get<NamedAttribute *>();
1575     const Attribute &attr = namedAttr.attr;
1576 
1577     // inferred attributes don't need to be added to the param list.
1578     if (inferredAttributes.contains(namedAttr.name))
1579       continue;
1580 
1581     OpMethodParameter::Property properties = OpMethodParameter::PP_None;
1582     if (attr.isOptional())
1583       properties = OpMethodParameter::PP_Optional;
1584 
1585     StringRef type;
1586     switch (attrParamKind) {
1587     case AttrParamKind::WrappedAttr:
1588       type = attr.getStorageType();
1589       break;
1590     case AttrParamKind::UnwrappedValue:
1591       if (canUseUnwrappedRawValue(attr))
1592         type = attr.getReturnType();
1593       else
1594         type = attr.getStorageType();
1595       break;
1596     }
1597 
1598     // Attach default value if requested and possible.
1599     std::string defaultValue;
1600     if (attrParamKind == AttrParamKind::UnwrappedValue &&
1601         i >= defaultValuedAttrStartIndex) {
1602       bool isString = attr.getReturnType() == "::llvm::StringRef";
1603       if (isString)
1604         defaultValue.append("\"");
1605       defaultValue += attr.getDefaultValue();
1606       if (isString)
1607         defaultValue.append("\"");
1608     }
1609     paramList.emplace_back(type, namedAttr.name, defaultValue, properties);
1610   }
1611 
1612   /// Insert parameters for each successor.
1613   for (const NamedSuccessor &succ : op.getSuccessors()) {
1614     StringRef type =
1615         succ.isVariadic() ? "::mlir::BlockRange" : "::mlir::Block *";
1616     paramList.emplace_back(type, succ.name);
1617   }
1618 
1619   /// Insert parameters for variadic regions.
1620   for (const NamedRegion &region : op.getRegions())
1621     if (region.isVariadic())
1622       paramList.emplace_back("unsigned",
1623                              llvm::formatv("{0}Count", region.name).str());
1624 }
1625 
1626 void OpEmitter::genCodeForAddingArgAndRegionForBuilder(
1627     OpMethodBody &body, llvm::StringSet<> &inferredAttributes,
1628     bool isRawValueAttr) {
1629   // Push all operands to the result.
1630   for (int i = 0, e = op.getNumOperands(); i < e; ++i) {
1631     std::string argName = getArgumentName(op, i);
1632     NamedTypeConstraint &operand = op.getOperand(i);
1633     if (operand.constraint.isVariadicOfVariadic()) {
1634       body << "  for (::mlir::ValueRange range : " << argName << ")\n   "
1635            << builderOpState << ".addOperands(range);\n";
1636 
1637       // Add the segment attribute.
1638       body << "  {\n"
1639            << "    SmallVector<int32_t> rangeSegments;\n"
1640            << "    for (::mlir::ValueRange range : " << argName << ")\n"
1641            << "      rangeSegments.push_back(range.size());\n"
1642            << "    " << builderOpState << ".addAttribute("
1643            << operand.constraint.getVariadicOfVariadicSegmentSizeAttr()
1644            << "AttrName(" << builderOpState << ".name), " << odsBuilder
1645            << ".getI32TensorAttr(rangeSegments));"
1646            << "  }\n";
1647       continue;
1648     }
1649 
1650     if (operand.isOptional())
1651       body << "  if (" << argName << ")\n  ";
1652     body << "  " << builderOpState << ".addOperands(" << argName << ");\n";
1653   }
1654 
1655   // If the operation has the operand segment size attribute, add it here.
1656   if (op.getTrait("::mlir::OpTrait::AttrSizedOperandSegments")) {
1657     body << "  " << builderOpState
1658          << ".addAttribute(operand_segment_sizesAttrName(" << builderOpState
1659          << ".name), "
1660          << "odsBuilder.getI32VectorAttr({";
1661     interleaveComma(llvm::seq<int>(0, op.getNumOperands()), body, [&](int i) {
1662       const NamedTypeConstraint &operand = op.getOperand(i);
1663       if (!operand.isVariableLength()) {
1664         body << "1";
1665         return;
1666       }
1667 
1668       std::string operandName = getArgumentName(op, i);
1669       if (operand.isOptional()) {
1670         body << "(" << operandName << " ? 1 : 0)";
1671       } else if (operand.isVariadicOfVariadic()) {
1672         body << llvm::formatv(
1673             "static_cast<int32_t>(std::accumulate({0}.begin(), {0}.end(), 0, "
1674             "[](int32_t curSum, ::mlir::ValueRange range) {{ return curSum + "
1675             "range.size(); }))",
1676             operandName);
1677       } else {
1678         body << "static_cast<int32_t>(" << getArgumentName(op, i) << ".size())";
1679       }
1680     });
1681     body << "}));\n";
1682   }
1683 
1684   // Push all attributes to the result.
1685   for (const auto &namedAttr : op.getAttributes()) {
1686     auto &attr = namedAttr.attr;
1687     if (attr.isDerivedAttr() || inferredAttributes.contains(namedAttr.name))
1688       continue;
1689 
1690     bool emitNotNullCheck = attr.isOptional();
1691     if (emitNotNullCheck)
1692       body << formatv("  if ({0}) ", namedAttr.name) << "{\n";
1693 
1694     if (isRawValueAttr && canUseUnwrappedRawValue(attr)) {
1695       // If this is a raw value, then we need to wrap it in an Attribute
1696       // instance.
1697       FmtContext fctx;
1698       fctx.withBuilder("odsBuilder");
1699 
1700       std::string builderTemplate = std::string(attr.getConstBuilderTemplate());
1701 
1702       // For StringAttr, its constant builder call will wrap the input in
1703       // quotes, which is correct for normal string literals, but incorrect
1704       // here given we use function arguments. So we need to strip the
1705       // wrapping quotes.
1706       if (StringRef(builderTemplate).contains("\"$0\""))
1707         builderTemplate = replaceAllSubstrs(builderTemplate, "\"$0\"", "$0");
1708 
1709       std::string value =
1710           std::string(tgfmt(builderTemplate, &fctx, namedAttr.name));
1711       body << formatv("  {0}.addAttribute({1}AttrName({0}.name), {2});\n",
1712                       builderOpState, namedAttr.name, value);
1713     } else {
1714       body << formatv("  {0}.addAttribute({1}AttrName({0}.name), {1});\n",
1715                       builderOpState, namedAttr.name);
1716     }
1717     if (emitNotNullCheck)
1718       body << "  }\n";
1719   }
1720 
1721   // Create the correct number of regions.
1722   for (const NamedRegion &region : op.getRegions()) {
1723     if (region.isVariadic())
1724       body << formatv("  for (unsigned i = 0; i < {0}Count; ++i)\n  ",
1725                       region.name);
1726 
1727     body << "  (void)" << builderOpState << ".addRegion();\n";
1728   }
1729 
1730   // Push all successors to the result.
1731   for (const NamedSuccessor &namedSuccessor : op.getSuccessors()) {
1732     body << formatv("  {0}.addSuccessors({1});\n", builderOpState,
1733                     namedSuccessor.name);
1734   }
1735 }
1736 
1737 void OpEmitter::genCanonicalizerDecls() {
1738   bool hasCanonicalizeMethod = def.getValueAsBit("hasCanonicalizeMethod");
1739   if (hasCanonicalizeMethod) {
1740     // static LogicResult FooOp::
1741     // canonicalize(FooOp op, PatternRewriter &rewriter);
1742     SmallVector<OpMethodParameter, 2> paramList;
1743     paramList.emplace_back(op.getCppClassName(), "op");
1744     paramList.emplace_back("::mlir::PatternRewriter &", "rewriter");
1745     opClass.addMethodAndPrune("::mlir::LogicalResult", "canonicalize",
1746                               OpMethod::MP_StaticDeclaration,
1747                               std::move(paramList));
1748   }
1749 
1750   // We get a prototype for 'getCanonicalizationPatterns' if requested directly
1751   // or if using a 'canonicalize' method.
1752   bool hasCanonicalizer = def.getValueAsBit("hasCanonicalizer");
1753   if (!hasCanonicalizeMethod && !hasCanonicalizer)
1754     return;
1755 
1756   // We get a body for 'getCanonicalizationPatterns' when using a 'canonicalize'
1757   // method, but not implementing 'getCanonicalizationPatterns' manually.
1758   bool hasBody = hasCanonicalizeMethod && !hasCanonicalizer;
1759 
1760   // Add a signature for getCanonicalizationPatterns if implemented by the
1761   // dialect or if synthesized to call 'canonicalize'.
1762   SmallVector<OpMethodParameter, 2> paramList;
1763   paramList.emplace_back("::mlir::RewritePatternSet &", "results");
1764   paramList.emplace_back("::mlir::MLIRContext *", "context");
1765   auto kind = hasBody ? OpMethod::MP_Static : OpMethod::MP_StaticDeclaration;
1766   auto *method = opClass.addMethodAndPrune(
1767       "void", "getCanonicalizationPatterns", kind, std::move(paramList));
1768 
1769   // If synthesizing the method, fill it it.
1770   if (hasBody)
1771     method->body() << "  results.add(canonicalize);\n";
1772 }
1773 
1774 void OpEmitter::genFolderDecls() {
1775   bool hasSingleResult =
1776       op.getNumResults() == 1 && op.getNumVariableLengthResults() == 0;
1777 
1778   if (def.getValueAsBit("hasFolder")) {
1779     if (hasSingleResult) {
1780       opClass.addMethodAndPrune(
1781           "::mlir::OpFoldResult", "fold", OpMethod::MP_Declaration,
1782           "::llvm::ArrayRef<::mlir::Attribute>", "operands");
1783     } else {
1784       SmallVector<OpMethodParameter, 2> paramList;
1785       paramList.emplace_back("::llvm::ArrayRef<::mlir::Attribute>", "operands");
1786       paramList.emplace_back("::llvm::SmallVectorImpl<::mlir::OpFoldResult> &",
1787                              "results");
1788       opClass.addMethodAndPrune("::mlir::LogicalResult", "fold",
1789                                 OpMethod::MP_Declaration, std::move(paramList));
1790     }
1791   }
1792 }
1793 
1794 void OpEmitter::genOpInterfaceMethods(const tblgen::InterfaceTrait *opTrait) {
1795   Interface interface = opTrait->getInterface();
1796 
1797   // Get the set of methods that should always be declared.
1798   auto alwaysDeclaredMethodsVec = opTrait->getAlwaysDeclaredMethods();
1799   llvm::StringSet<> alwaysDeclaredMethods;
1800   alwaysDeclaredMethods.insert(alwaysDeclaredMethodsVec.begin(),
1801                                alwaysDeclaredMethodsVec.end());
1802 
1803   for (const InterfaceMethod &method : interface.getMethods()) {
1804     // Don't declare if the method has a body.
1805     if (method.getBody())
1806       continue;
1807     // Don't declare if the method has a default implementation and the op
1808     // didn't request that it always be declared.
1809     if (method.getDefaultImplementation() &&
1810         !alwaysDeclaredMethods.count(method.getName()))
1811       continue;
1812     genOpInterfaceMethod(method);
1813   }
1814 }
1815 
1816 OpMethod *OpEmitter::genOpInterfaceMethod(const InterfaceMethod &method,
1817                                           bool declaration) {
1818   SmallVector<OpMethodParameter, 4> paramList;
1819   for (const InterfaceMethod::Argument &arg : method.getArguments())
1820     paramList.emplace_back(arg.type, arg.name);
1821 
1822   auto properties = method.isStatic() ? OpMethod::MP_Static : OpMethod::MP_None;
1823   if (declaration)
1824     properties =
1825         static_cast<OpMethod::Property>(properties | OpMethod::MP_Declaration);
1826   return opClass.addMethodAndPrune(method.getReturnType(), method.getName(),
1827                                    properties, std::move(paramList));
1828 }
1829 
1830 void OpEmitter::genOpInterfaceMethods() {
1831   for (const auto &trait : op.getTraits()) {
1832     if (const auto *opTrait = dyn_cast<tblgen::InterfaceTrait>(&trait))
1833       if (opTrait->shouldDeclareMethods())
1834         genOpInterfaceMethods(opTrait);
1835   }
1836 }
1837 
1838 void OpEmitter::genSideEffectInterfaceMethods() {
1839   enum EffectKind { Operand, Result, Symbol, Static };
1840   struct EffectLocation {
1841     /// The effect applied.
1842     SideEffect effect;
1843 
1844     /// The index if the kind is not static.
1845     unsigned index : 30;
1846 
1847     /// The kind of the location.
1848     unsigned kind : 2;
1849   };
1850 
1851   StringMap<SmallVector<EffectLocation, 1>> interfaceEffects;
1852   auto resolveDecorators = [&](Operator::var_decorator_range decorators,
1853                                unsigned index, unsigned kind) {
1854     for (auto decorator : decorators)
1855       if (SideEffect *effect = dyn_cast<SideEffect>(&decorator)) {
1856         opClass.addTrait(effect->getInterfaceTrait());
1857         interfaceEffects[effect->getBaseEffectName()].push_back(
1858             EffectLocation{*effect, index, kind});
1859       }
1860   };
1861 
1862   // Collect effects that were specified via:
1863   /// Traits.
1864   for (const auto &trait : op.getTraits()) {
1865     const auto *opTrait = dyn_cast<tblgen::SideEffectTrait>(&trait);
1866     if (!opTrait)
1867       continue;
1868     auto &effects = interfaceEffects[opTrait->getBaseEffectName()];
1869     for (auto decorator : opTrait->getEffects())
1870       effects.push_back(EffectLocation{cast<SideEffect>(decorator),
1871                                        /*index=*/0, EffectKind::Static});
1872   }
1873   /// Attributes and Operands.
1874   for (unsigned i = 0, operandIt = 0, e = op.getNumArgs(); i != e; ++i) {
1875     Argument arg = op.getArg(i);
1876     if (arg.is<NamedTypeConstraint *>()) {
1877       resolveDecorators(op.getArgDecorators(i), operandIt, EffectKind::Operand);
1878       ++operandIt;
1879       continue;
1880     }
1881     const NamedAttribute *attr = arg.get<NamedAttribute *>();
1882     if (attr->attr.getBaseAttr().isSymbolRefAttr())
1883       resolveDecorators(op.getArgDecorators(i), i, EffectKind::Symbol);
1884   }
1885   /// Results.
1886   for (unsigned i = 0, e = op.getNumResults(); i != e; ++i)
1887     resolveDecorators(op.getResultDecorators(i), i, EffectKind::Result);
1888 
1889   // The code used to add an effect instance.
1890   // {0}: The effect class.
1891   // {1}: Optional value or symbol reference.
1892   // {1}: The resource class.
1893   const char *addEffectCode =
1894       "  effects.emplace_back({0}::get(), {1}{2}::get());\n";
1895 
1896   for (auto &it : interfaceEffects) {
1897     // Generate the 'getEffects' method.
1898     std::string type = llvm::formatv("::mlir::SmallVectorImpl<::mlir::"
1899                                      "SideEffects::EffectInstance<{0}>> &",
1900                                      it.first())
1901                            .str();
1902     auto *getEffects =
1903         opClass.addMethodAndPrune("void", "getEffects", type, "effects");
1904     auto &body = getEffects->body();
1905 
1906     // Add effect instances for each of the locations marked on the operation.
1907     for (auto &location : it.second) {
1908       StringRef effect = location.effect.getName();
1909       StringRef resource = location.effect.getResource();
1910       if (location.kind == EffectKind::Static) {
1911         // A static instance has no attached value.
1912         body << llvm::formatv(addEffectCode, effect, "", resource).str();
1913       } else if (location.kind == EffectKind::Symbol) {
1914         // A symbol reference requires adding the proper attribute.
1915         const auto *attr = op.getArg(location.index).get<NamedAttribute *>();
1916         if (attr->attr.isOptional()) {
1917           body << "  if (auto symbolRef = " << attr->name << "Attr())\n  "
1918                << llvm::formatv(addEffectCode, effect, "symbolRef, ", resource)
1919                       .str();
1920         } else {
1921           body << llvm::formatv(addEffectCode, effect, attr->name + "(), ",
1922                                 resource)
1923                       .str();
1924         }
1925       } else {
1926         // Otherwise this is an operand/result, so we need to attach the Value.
1927         body << "  for (::mlir::Value value : getODS"
1928              << (location.kind == EffectKind::Operand ? "Operands" : "Results")
1929              << "(" << location.index << "))\n  "
1930              << llvm::formatv(addEffectCode, effect, "value, ", resource).str();
1931       }
1932     }
1933   }
1934 }
1935 
1936 void OpEmitter::genTypeInterfaceMethods() {
1937   if (!op.allResultTypesKnown())
1938     return;
1939   // Generate 'inferReturnTypes' method declaration using the interface method
1940   // declared in 'InferTypeOpInterface' op interface.
1941   const auto *trait = dyn_cast<InterfaceTrait>(
1942       op.getTrait("::mlir::InferTypeOpInterface::Trait"));
1943   Interface interface = trait->getInterface();
1944   OpMethod *method = [&]() -> OpMethod * {
1945     for (const InterfaceMethod &interfaceMethod : interface.getMethods()) {
1946       if (interfaceMethod.getName() == "inferReturnTypes") {
1947         return genOpInterfaceMethod(interfaceMethod, /*declaration=*/false);
1948       }
1949     }
1950     assert(0 && "unable to find inferReturnTypes interface method");
1951     return nullptr;
1952   }();
1953   auto &body = method->body();
1954   body << "  inferredReturnTypes.resize(" << op.getNumResults() << ");\n";
1955 
1956   FmtContext fctx;
1957   fctx.withBuilder("odsBuilder");
1958   body << "  ::mlir::Builder odsBuilder(context);\n";
1959 
1960   auto emitType =
1961       [&](const tblgen::Operator::ArgOrType &type) -> OpMethodBody & {
1962     if (type.isArg()) {
1963       auto argIndex = type.getArg();
1964       assert(!op.getArg(argIndex).is<NamedAttribute *>());
1965       auto arg = op.getArgToOperandOrAttribute(argIndex);
1966       if (arg.kind() == Operator::OperandOrAttribute::Kind::Operand)
1967         return body << "operands[" << arg.operandOrAttributeIndex()
1968                     << "].getType()";
1969       return body << "attributes[" << arg.operandOrAttributeIndex()
1970                   << "].getType()";
1971     } else {
1972       return body << tgfmt(*type.getType().getBuilderCall(), &fctx);
1973     }
1974   };
1975 
1976   for (int i = 0, e = op.getNumResults(); i != e; ++i) {
1977     body << "  inferredReturnTypes[" << i << "] = ";
1978     auto types = op.getSameTypeAsResult(i);
1979     emitType(types[0]) << ";\n";
1980     if (types.size() == 1)
1981       continue;
1982     // TODO: We could verify equality here, but skipping that for verification.
1983   }
1984   body << "  return ::mlir::success();";
1985 }
1986 
1987 void OpEmitter::genParser() {
1988   if (!hasStringAttribute(def, "parser") ||
1989       hasStringAttribute(def, "assemblyFormat"))
1990     return;
1991 
1992   SmallVector<OpMethodParameter, 2> paramList;
1993   paramList.emplace_back("::mlir::OpAsmParser &", "parser");
1994   paramList.emplace_back("::mlir::OperationState &", "result");
1995   auto *method =
1996       opClass.addMethodAndPrune("::mlir::ParseResult", "parse",
1997                                 OpMethod::MP_Static, std::move(paramList));
1998 
1999   FmtContext fctx;
2000   fctx.addSubst("cppClass", opClass.getClassName());
2001   auto parser = def.getValueAsString("parser").ltrim().rtrim(" \t\v\f\r");
2002   method->body() << "  " << tgfmt(parser, &fctx);
2003 }
2004 
2005 void OpEmitter::genPrinter() {
2006   if (hasStringAttribute(def, "assemblyFormat"))
2007     return;
2008 
2009   auto valueInit = def.getValueInit("printer");
2010   StringInit *stringInit = dyn_cast<StringInit>(valueInit);
2011   if (!stringInit)
2012     return;
2013 
2014   auto *method =
2015       opClass.addMethodAndPrune("void", "print", "::mlir::OpAsmPrinter &", "p");
2016   FmtContext fctx;
2017   fctx.addSubst("cppClass", opClass.getClassName());
2018   auto printer = stringInit->getValue().ltrim().rtrim(" \t\v\f\r");
2019   method->body() << "  " << tgfmt(printer, &fctx);
2020 }
2021 
2022 void OpEmitter::genVerifier() {
2023   auto *method = opClass.addMethodAndPrune("::mlir::LogicalResult", "verify");
2024   auto &body = method->body();
2025   body << "  if (::mlir::failed(" << op.getAdaptorName()
2026        << "(*this).verify((*this)->getLoc()))) "
2027        << "return ::mlir::failure();\n";
2028 
2029   auto *valueInit = def.getValueInit("verifier");
2030   StringInit *stringInit = dyn_cast<StringInit>(valueInit);
2031   bool hasCustomVerify = stringInit && !stringInit->getValue().empty();
2032   populateSubstitutions(op, "(*this)->getAttr", "this->getODSOperands",
2033                         "this->getODSResults", verifyCtx);
2034 
2035   genAttributeVerifier(op, "(*this)->getAttr", "emitOpError(",
2036                        /*emitVerificationRequiringOp=*/true, verifyCtx, body);
2037   genOperandResultVerifier(body, op.getOperands(), "operand");
2038   genOperandResultVerifier(body, op.getResults(), "result");
2039 
2040   for (auto &trait : op.getTraits()) {
2041     if (auto *t = dyn_cast<tblgen::PredTrait>(&trait)) {
2042       body << tgfmt("  if (!($0))\n    "
2043                     "return emitOpError(\"failed to verify that $1\");\n",
2044                     &verifyCtx, tgfmt(t->getPredTemplate(), &verifyCtx),
2045                     t->getSummary());
2046     }
2047   }
2048 
2049   genRegionVerifier(body);
2050   genSuccessorVerifier(body);
2051 
2052   if (hasCustomVerify) {
2053     FmtContext fctx;
2054     fctx.addSubst("cppClass", opClass.getClassName());
2055     auto printer = stringInit->getValue().ltrim().rtrim(" \t\v\f\r");
2056     body << "  " << tgfmt(printer, &fctx);
2057   } else {
2058     body << "  return ::mlir::success();\n";
2059   }
2060 }
2061 
2062 void OpEmitter::genOperandResultVerifier(OpMethodBody &body,
2063                                          Operator::value_range values,
2064                                          StringRef valueKind) {
2065   FmtContext fctx;
2066 
2067   body << "  {\n";
2068   body << "    unsigned index = 0; (void)index;\n";
2069 
2070   for (auto staticValue : llvm::enumerate(values)) {
2071     const NamedTypeConstraint &value = staticValue.value();
2072 
2073     bool hasPredicate = value.hasPredicate();
2074     bool isOptional = value.isOptional();
2075     bool isVariadicOfVariadic = value.isVariadicOfVariadic();
2076     if (!hasPredicate && !isOptional && !isVariadicOfVariadic)
2077       continue;
2078     body << formatv("    auto valueGroup{2} = getODS{0}{1}s({2});\n",
2079                     // Capitalize the first letter to match the function name
2080                     valueKind.substr(0, 1).upper(), valueKind.substr(1),
2081                     staticValue.index());
2082 
2083     // If the constraint is optional check that the value group has at most 1
2084     // value.
2085     if (isOptional) {
2086       body << formatv("    if (valueGroup{0}.size() > 1)\n"
2087                       "      return emitOpError(\"{1} group starting at #\") "
2088                       "<< index << \" requires 0 or 1 element, but found \" << "
2089                       "valueGroup{0}.size();\n",
2090                       staticValue.index(), valueKind);
2091     } else if (isVariadicOfVariadic) {
2092       body << formatv(
2093           "    if (::mlir::failed(::mlir::OpTrait::impl::verifyValueSizeAttr("
2094           "*this, \"{0}\", \"{1}\", valueGroup{2}.size())))\n"
2095           "      return ::mlir::failure();\n",
2096           value.constraint.getVariadicOfVariadicSegmentSizeAttr(), value.name,
2097           staticValue.index());
2098     }
2099 
2100     // Otherwise, if there is no predicate there is nothing left to do.
2101     if (!hasPredicate)
2102       continue;
2103     // Emit a loop to check all the dynamic values in the pack.
2104     StringRef constraintFn =
2105         staticVerifierEmitter.getTypeConstraintFn(value.constraint);
2106     body << "    for (::mlir::Value v : valueGroup" << staticValue.index()
2107          << ") {\n"
2108          << "      if (::mlir::failed(" << constraintFn
2109          << "(getOperation(), v.getType(), \"" << valueKind << "\", index)))\n"
2110          << "        return ::mlir::failure();\n"
2111          << "      ++index;\n"
2112          << "    }\n";
2113   }
2114 
2115   body << "  }\n";
2116 }
2117 
2118 void OpEmitter::genRegionVerifier(OpMethodBody &body) {
2119   // If we have no regions, there is nothing more to do.
2120   unsigned numRegions = op.getNumRegions();
2121   if (numRegions == 0)
2122     return;
2123 
2124   body << "{\n";
2125   body << "    unsigned index = 0; (void)index;\n";
2126 
2127   for (unsigned i = 0; i < numRegions; ++i) {
2128     const auto &region = op.getRegion(i);
2129     if (region.constraint.getPredicate().isNull())
2130       continue;
2131 
2132     body << "    for (::mlir::Region &region : ";
2133     body << formatv(region.isVariadic()
2134                         ? "{0}()"
2135                         : "::mlir::MutableArrayRef<::mlir::Region>((*this)"
2136                           "->getRegion({1}))",
2137                     region.name, i);
2138     body << ") {\n";
2139     auto constraint = tgfmt(region.constraint.getConditionTemplate(),
2140                             &verifyCtx.withSelf("region"))
2141                           .str();
2142 
2143     body << formatv("      (void)region;\n"
2144                     "      if (!({0})) {\n        "
2145                     "return emitOpError(\"region #\") << index << \" {1}"
2146                     "failed to "
2147                     "verify constraint: {2}\";\n      }\n",
2148                     constraint,
2149                     region.name.empty() ? "" : "('" + region.name + "') ",
2150                     region.constraint.getSummary())
2151          << "      ++index;\n"
2152          << "    }\n";
2153   }
2154   body << "  }\n";
2155 }
2156 
2157 void OpEmitter::genSuccessorVerifier(OpMethodBody &body) {
2158   // If we have no successors, there is nothing more to do.
2159   unsigned numSuccessors = op.getNumSuccessors();
2160   if (numSuccessors == 0)
2161     return;
2162 
2163   body << "{\n";
2164   body << "    unsigned index = 0; (void)index;\n";
2165 
2166   for (unsigned i = 0; i < numSuccessors; ++i) {
2167     const auto &successor = op.getSuccessor(i);
2168     if (successor.constraint.getPredicate().isNull())
2169       continue;
2170 
2171     if (successor.isVariadic()) {
2172       body << formatv("    for (::mlir::Block *successor : {0}()) {\n",
2173                       successor.name);
2174     } else {
2175       body << "    {\n";
2176       body << formatv("      ::mlir::Block *successor = {0}();\n",
2177                       successor.name);
2178     }
2179     auto constraint = tgfmt(successor.constraint.getConditionTemplate(),
2180                             &verifyCtx.withSelf("successor"))
2181                           .str();
2182 
2183     body << formatv("      (void)successor;\n"
2184                     "      if (!({0})) {\n        "
2185                     "return emitOpError(\"successor #\") << index << \"('{1}') "
2186                     "failed to "
2187                     "verify constraint: {2}\";\n      }\n",
2188                     constraint, successor.name,
2189                     successor.constraint.getSummary())
2190          << "      ++index;\n"
2191          << "    }\n";
2192   }
2193   body << "  }\n";
2194 }
2195 
2196 /// Add a size count trait to the given operation class.
2197 static void addSizeCountTrait(OpClass &opClass, StringRef traitKind,
2198                               int numTotal, int numVariadic) {
2199   if (numVariadic != 0) {
2200     if (numTotal == numVariadic)
2201       opClass.addTrait("::mlir::OpTrait::Variadic" + traitKind + "s");
2202     else
2203       opClass.addTrait("::mlir::OpTrait::AtLeastN" + traitKind + "s<" +
2204                        Twine(numTotal - numVariadic) + ">::Impl");
2205     return;
2206   }
2207   switch (numTotal) {
2208   case 0:
2209     opClass.addTrait("::mlir::OpTrait::Zero" + traitKind);
2210     break;
2211   case 1:
2212     opClass.addTrait("::mlir::OpTrait::One" + traitKind);
2213     break;
2214   default:
2215     opClass.addTrait("::mlir::OpTrait::N" + traitKind + "s<" + Twine(numTotal) +
2216                      ">::Impl");
2217     break;
2218   }
2219 }
2220 
2221 void OpEmitter::genTraits() {
2222   // Add region size trait.
2223   unsigned numRegions = op.getNumRegions();
2224   unsigned numVariadicRegions = op.getNumVariadicRegions();
2225   addSizeCountTrait(opClass, "Region", numRegions, numVariadicRegions);
2226 
2227   // Add result size traits.
2228   int numResults = op.getNumResults();
2229   int numVariadicResults = op.getNumVariableLengthResults();
2230   addSizeCountTrait(opClass, "Result", numResults, numVariadicResults);
2231 
2232   // For single result ops with a known specific type, generate a OneTypedResult
2233   // trait.
2234   if (numResults == 1 && numVariadicResults == 0) {
2235     auto cppName = op.getResults().begin()->constraint.getCPPClassName();
2236     opClass.addTrait("::mlir::OpTrait::OneTypedResult<" + cppName + ">::Impl");
2237   }
2238 
2239   // Add successor size trait.
2240   unsigned numSuccessors = op.getNumSuccessors();
2241   unsigned numVariadicSuccessors = op.getNumVariadicSuccessors();
2242   addSizeCountTrait(opClass, "Successor", numSuccessors, numVariadicSuccessors);
2243 
2244   // Add variadic size trait and normal op traits.
2245   int numOperands = op.getNumOperands();
2246   int numVariadicOperands = op.getNumVariableLengthOperands();
2247 
2248   // Add operand size trait.
2249   if (numVariadicOperands != 0) {
2250     if (numOperands == numVariadicOperands)
2251       opClass.addTrait("::mlir::OpTrait::VariadicOperands");
2252     else
2253       opClass.addTrait("::mlir::OpTrait::AtLeastNOperands<" +
2254                        Twine(numOperands - numVariadicOperands) + ">::Impl");
2255   } else {
2256     switch (numOperands) {
2257     case 0:
2258       opClass.addTrait("::mlir::OpTrait::ZeroOperands");
2259       break;
2260     case 1:
2261       opClass.addTrait("::mlir::OpTrait::OneOperand");
2262       break;
2263     default:
2264       opClass.addTrait("::mlir::OpTrait::NOperands<" + Twine(numOperands) +
2265                        ">::Impl");
2266       break;
2267     }
2268   }
2269 
2270   // Add the native and interface traits.
2271   for (const auto &trait : op.getTraits()) {
2272     if (auto opTrait = dyn_cast<tblgen::NativeTrait>(&trait))
2273       opClass.addTrait(opTrait->getFullyQualifiedTraitName());
2274     else if (auto opTrait = dyn_cast<tblgen::InterfaceTrait>(&trait))
2275       opClass.addTrait(opTrait->getFullyQualifiedTraitName());
2276   }
2277 }
2278 
2279 void OpEmitter::genOpNameGetter() {
2280   auto *method = opClass.addMethodAndPrune(
2281       "::llvm::StringLiteral", "getOperationName",
2282       OpMethod::Property(OpMethod::MP_Static | OpMethod::MP_Constexpr));
2283   method->body() << "  return ::llvm::StringLiteral(\"" << op.getOperationName()
2284                  << "\");";
2285 }
2286 
2287 void OpEmitter::genOpAsmInterface() {
2288   // If the user only has one results or specifically added the Asm trait,
2289   // then don't generate it for them. We specifically only handle multi result
2290   // operations, because the name of a single result in the common case is not
2291   // interesting(generally 'result'/'output'/etc.).
2292   // TODO: We could also add a flag to allow operations to opt in to this
2293   // generation, even if they only have a single operation.
2294   int numResults = op.getNumResults();
2295   if (numResults <= 1 || op.getTrait("::mlir::OpAsmOpInterface::Trait"))
2296     return;
2297 
2298   SmallVector<StringRef, 4> resultNames(numResults);
2299   for (int i = 0; i != numResults; ++i)
2300     resultNames[i] = op.getResultName(i);
2301 
2302   // Don't add the trait if none of the results have a valid name.
2303   if (llvm::all_of(resultNames, [](StringRef name) { return name.empty(); }))
2304     return;
2305   opClass.addTrait("::mlir::OpAsmOpInterface::Trait");
2306 
2307   // Generate the right accessor for the number of results.
2308   auto *method = opClass.addMethodAndPrune(
2309       "void", "getAsmResultNames", "::mlir::OpAsmSetValueNameFn", "setNameFn");
2310   auto &body = method->body();
2311   for (int i = 0; i != numResults; ++i) {
2312     body << "  auto resultGroup" << i << " = getODSResults(" << i << ");\n"
2313          << "  if (!llvm::empty(resultGroup" << i << "))\n"
2314          << "    setNameFn(*resultGroup" << i << ".begin(), \""
2315          << resultNames[i] << "\");\n";
2316   }
2317 }
2318 
2319 //===----------------------------------------------------------------------===//
2320 // OpOperandAdaptor emitter
2321 //===----------------------------------------------------------------------===//
2322 
2323 namespace {
2324 // Helper class to emit Op operand adaptors to an output stream.  Operand
2325 // adaptors are wrappers around ArrayRef<Value> that provide named operand
2326 // getters identical to those defined in the Op.
2327 class OpOperandAdaptorEmitter {
2328 public:
2329   static void emitDecl(const Operator &op, raw_ostream &os);
2330   static void emitDef(const Operator &op, raw_ostream &os);
2331 
2332 private:
2333   explicit OpOperandAdaptorEmitter(const Operator &op);
2334 
2335   // Add verification function. This generates a verify method for the adaptor
2336   // which verifies all the op-independent attribute constraints.
2337   void addVerification();
2338 
2339   const Operator &op;
2340   Class adaptor;
2341 };
2342 } // end namespace
2343 
2344 OpOperandAdaptorEmitter::OpOperandAdaptorEmitter(const Operator &op)
2345     : op(op), adaptor(op.getAdaptorName()) {
2346   adaptor.newField("::mlir::ValueRange", "odsOperands");
2347   adaptor.newField("::mlir::DictionaryAttr", "odsAttrs");
2348   adaptor.newField("::mlir::RegionRange", "odsRegions");
2349   const auto *attrSizedOperands =
2350       op.getTrait("::mlir::OpTrait::AttrSizedOperandSegments");
2351   {
2352     SmallVector<OpMethodParameter, 2> paramList;
2353     paramList.emplace_back("::mlir::ValueRange", "values");
2354     paramList.emplace_back("::mlir::DictionaryAttr", "attrs",
2355                            attrSizedOperands ? "" : "nullptr");
2356     paramList.emplace_back("::mlir::RegionRange", "regions", "{}");
2357     auto *constructor = adaptor.addConstructorAndPrune(std::move(paramList));
2358 
2359     constructor->addMemberInitializer("odsOperands", "values");
2360     constructor->addMemberInitializer("odsAttrs", "attrs");
2361     constructor->addMemberInitializer("odsRegions", "regions");
2362   }
2363 
2364   {
2365     auto *constructor = adaptor.addConstructorAndPrune(
2366         llvm::formatv("{0}&", op.getCppClassName()).str(), "op");
2367     constructor->addMemberInitializer("odsOperands", "op->getOperands()");
2368     constructor->addMemberInitializer("odsAttrs", "op->getAttrDictionary()");
2369     constructor->addMemberInitializer("odsRegions", "op->getRegions()");
2370   }
2371 
2372   {
2373     auto *m = adaptor.addMethodAndPrune("::mlir::ValueRange", "getOperands");
2374     m->body() << "  return odsOperands;";
2375   }
2376   std::string sizeAttrInit =
2377       formatv(adapterSegmentSizeAttrInitCode, "operand_segment_sizes");
2378   generateNamedOperandGetters(op, adaptor,
2379                               /*isAdaptor=*/true, sizeAttrInit,
2380                               /*rangeType=*/"::mlir::ValueRange",
2381                               /*rangeBeginCall=*/"odsOperands.begin()",
2382                               /*rangeSizeCall=*/"odsOperands.size()",
2383                               /*getOperandCallPattern=*/"odsOperands[{0}]");
2384 
2385   FmtContext fctx;
2386   fctx.withBuilder("::mlir::Builder(odsAttrs.getContext())");
2387 
2388   auto emitAttr = [&](StringRef name, Attribute attr) {
2389     auto &body = adaptor.addMethodAndPrune(attr.getStorageType(), name)->body();
2390     body << "  assert(odsAttrs && \"no attributes when constructing adapter\");"
2391          << "\n  " << attr.getStorageType() << " attr = "
2392          << "odsAttrs.get(\"" << name << "\").";
2393     if (attr.hasDefaultValue() || attr.isOptional())
2394       body << "dyn_cast_or_null<";
2395     else
2396       body << "cast<";
2397     body << attr.getStorageType() << ">();\n";
2398 
2399     if (attr.hasDefaultValue()) {
2400       // Use the default value if attribute is not set.
2401       // TODO: this is inefficient, we are recreating the attribute for every
2402       // call. This should be set instead.
2403       std::string defaultValue = std::string(
2404           tgfmt(attr.getConstBuilderTemplate(), &fctx, attr.getDefaultValue()));
2405       body << "  if (!attr)\n    attr = " << defaultValue << ";\n";
2406     }
2407     body << "  return attr;\n";
2408   };
2409 
2410   {
2411     auto *m =
2412         adaptor.addMethodAndPrune("::mlir::DictionaryAttr", "getAttributes");
2413     m->body() << "  return odsAttrs;";
2414   }
2415   for (auto &namedAttr : op.getAttributes()) {
2416     const auto &name = namedAttr.name;
2417     const auto &attr = namedAttr.attr;
2418     if (!attr.isDerivedAttr())
2419       emitAttr(name, attr);
2420   }
2421 
2422   unsigned numRegions = op.getNumRegions();
2423   if (numRegions > 0) {
2424     auto *m = adaptor.addMethodAndPrune("::mlir::RegionRange", "getRegions");
2425     m->body() << "  return odsRegions;";
2426   }
2427   for (unsigned i = 0; i < numRegions; ++i) {
2428     const auto &region = op.getRegion(i);
2429     if (region.name.empty())
2430       continue;
2431 
2432     // Generate the accessors for a variadic region.
2433     if (region.isVariadic()) {
2434       auto *m = adaptor.addMethodAndPrune("::mlir::RegionRange", region.name);
2435       m->body() << formatv("  return odsRegions.drop_front({0});", i);
2436       continue;
2437     }
2438 
2439     auto *m = adaptor.addMethodAndPrune("::mlir::Region &", region.name);
2440     m->body() << formatv("  return *odsRegions[{0}];", i);
2441   }
2442 
2443   // Add verification function.
2444   addVerification();
2445 }
2446 
2447 void OpOperandAdaptorEmitter::addVerification() {
2448   auto *method = adaptor.addMethodAndPrune("::mlir::LogicalResult", "verify",
2449                                            "::mlir::Location", "loc");
2450   auto &body = method->body();
2451 
2452   const char *checkAttrSizedValueSegmentsCode = R"(
2453   {
2454     auto sizeAttr = odsAttrs.get("{0}").cast<::mlir::DenseIntElementsAttr>();
2455     auto numElements = sizeAttr.getType().cast<::mlir::ShapedType>().getNumElements();
2456     if (numElements != {1})
2457       return emitError(loc, "'{0}' attribute for specifying {2} segments "
2458                        "must have {1} elements, but got ") << numElements;
2459   }
2460   )";
2461 
2462   // Verify a few traits first so that we can use
2463   // getODSOperands()/getODSResults() in the rest of the verifier.
2464   for (auto &trait : op.getTraits()) {
2465     if (auto *t = dyn_cast<tblgen::NativeTrait>(&trait)) {
2466       if (t->getFullyQualifiedTraitName() ==
2467           "::mlir::OpTrait::AttrSizedOperandSegments") {
2468         body << formatv(checkAttrSizedValueSegmentsCode,
2469                         "operand_segment_sizes", op.getNumOperands(),
2470                         "operand");
2471       } else if (t->getFullyQualifiedTraitName() ==
2472                  "::mlir::OpTrait::AttrSizedResultSegments") {
2473         body << formatv(checkAttrSizedValueSegmentsCode, "result_segment_sizes",
2474                         op.getNumResults(), "result");
2475       }
2476     }
2477   }
2478 
2479   FmtContext verifyCtx;
2480   populateSubstitutions(op, "odsAttrs.get", "getODSOperands",
2481                         "<no results should be generated>", verifyCtx);
2482   genAttributeVerifier(op, "odsAttrs.get",
2483                        Twine("emitError(loc, \"'") + op.getOperationName() +
2484                            "' op \"",
2485                        /*emitVerificationRequiringOp*/ false, verifyCtx, body);
2486 
2487   body << "  return ::mlir::success();";
2488 }
2489 
2490 void OpOperandAdaptorEmitter::emitDecl(const Operator &op, raw_ostream &os) {
2491   OpOperandAdaptorEmitter(op).adaptor.writeDeclTo(os);
2492 }
2493 
2494 void OpOperandAdaptorEmitter::emitDef(const Operator &op, raw_ostream &os) {
2495   OpOperandAdaptorEmitter(op).adaptor.writeDefTo(os);
2496 }
2497 
2498 // Emits the opcode enum and op classes.
2499 static void emitOpClasses(const RecordKeeper &recordKeeper,
2500                           const std::vector<Record *> &defs, raw_ostream &os,
2501                           bool emitDecl) {
2502   // First emit forward declaration for each class, this allows them to refer
2503   // to each others in traits for example.
2504   if (emitDecl) {
2505     os << "#if defined(GET_OP_CLASSES) || defined(GET_OP_FWD_DEFINES)\n";
2506     os << "#undef GET_OP_FWD_DEFINES\n";
2507     for (auto *def : defs) {
2508       Operator op(*def);
2509       NamespaceEmitter emitter(os, op.getCppNamespace());
2510       os << "class " << op.getCppClassName() << ";\n";
2511     }
2512     os << "#endif\n\n";
2513   }
2514 
2515   IfDefScope scope("GET_OP_CLASSES", os);
2516   if (defs.empty())
2517     return;
2518 
2519   // Generate all of the locally instantiated methods first.
2520   StaticVerifierFunctionEmitter staticVerifierEmitter(recordKeeper, os);
2521   os << formatv(opCommentHeader, "Local Utility Method", "Definitions");
2522   staticVerifierEmitter.emitFunctionsFor(
2523       typeVerifierSignature, typeVerifierErrorHandler, /*typeArgName=*/"type",
2524       defs, emitDecl);
2525 
2526   for (auto *def : defs) {
2527     Operator op(*def);
2528     if (emitDecl) {
2529       {
2530         NamespaceEmitter emitter(os, op.getCppNamespace());
2531         os << formatv(opCommentHeader, op.getQualCppClassName(),
2532                       "declarations");
2533         OpOperandAdaptorEmitter::emitDecl(op, os);
2534         OpEmitter::emitDecl(op, os, staticVerifierEmitter);
2535       }
2536       // Emit the TypeID explicit specialization to have a single definition.
2537       if (!op.getCppNamespace().empty())
2538         os << "DECLARE_EXPLICIT_TYPE_ID(" << op.getCppNamespace()
2539            << "::" << op.getCppClassName() << ")\n\n";
2540     } else {
2541       {
2542         NamespaceEmitter emitter(os, op.getCppNamespace());
2543         os << formatv(opCommentHeader, op.getQualCppClassName(), "definitions");
2544         OpOperandAdaptorEmitter::emitDef(op, os);
2545         OpEmitter::emitDef(op, os, staticVerifierEmitter);
2546       }
2547       // Emit the TypeID explicit specialization to have a single definition.
2548       if (!op.getCppNamespace().empty())
2549         os << "DEFINE_EXPLICIT_TYPE_ID(" << op.getCppNamespace()
2550            << "::" << op.getCppClassName() << ")\n\n";
2551     }
2552   }
2553 }
2554 
2555 // Emits a comma-separated list of the ops.
2556 static void emitOpList(const std::vector<Record *> &defs, raw_ostream &os) {
2557   IfDefScope scope("GET_OP_LIST", os);
2558 
2559   interleave(
2560       // TODO: We are constructing the Operator wrapper instance just for
2561       // getting it's qualified class name here. Reduce the overhead by having a
2562       // lightweight version of Operator class just for that purpose.
2563       defs, [&os](Record *def) { os << Operator(def).getQualCppClassName(); },
2564       [&os]() { os << ",\n"; });
2565 }
2566 
2567 static bool emitOpDecls(const RecordKeeper &recordKeeper, raw_ostream &os) {
2568   emitSourceFileHeader("Op Declarations", os);
2569 
2570   std::vector<Record *> defs = getRequestedOpDefinitions(recordKeeper);
2571   emitOpClasses(recordKeeper, defs, os, /*emitDecl=*/true);
2572 
2573   return false;
2574 }
2575 
2576 static bool emitOpDefs(const RecordKeeper &recordKeeper, raw_ostream &os) {
2577   emitSourceFileHeader("Op Definitions", os);
2578 
2579   std::vector<Record *> defs = getRequestedOpDefinitions(recordKeeper);
2580   emitOpList(defs, os);
2581   emitOpClasses(recordKeeper, defs, os, /*emitDecl=*/false);
2582 
2583   return false;
2584 }
2585 
2586 static mlir::GenRegistration
2587     genOpDecls("gen-op-decls", "Generate op declarations",
2588                [](const RecordKeeper &records, raw_ostream &os) {
2589                  return emitOpDecls(records, os);
2590                });
2591 
2592 static mlir::GenRegistration genOpDefs("gen-op-defs", "Generate op definitions",
2593                                        [](const RecordKeeper &records,
2594                                           raw_ostream &os) {
2595                                          return emitOpDefs(records, os);
2596                                        });
2597