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