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