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