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   bool hasCanonicalizeMethod = def.getValueAsBit("hasCanonicalizeMethod");
1678   if (hasCanonicalizeMethod) {
1679     // static LogicResult FooOp::
1680     // canonicalize(FooOp op, PatternRewriter &rewriter);
1681     SmallVector<OpMethodParameter, 2> paramList;
1682     paramList.emplace_back(op.getCppClassName(), "op");
1683     paramList.emplace_back("::mlir::PatternRewriter &", "rewriter");
1684     opClass.addMethodAndPrune("::mlir::LogicalResult", "canonicalize",
1685                               OpMethod::MP_StaticDeclaration,
1686                               std::move(paramList));
1687   }
1688 
1689   // We get a prototype for 'getCanonicalizationPatterns' if requested directly
1690   // or if using a 'canonicalize' method.
1691   bool hasCanonicalizer = def.getValueAsBit("hasCanonicalizer");
1692   if (!hasCanonicalizeMethod && !hasCanonicalizer)
1693     return;
1694 
1695   // We get a body for 'getCanonicalizationPatterns' when using a 'canonicalize'
1696   // method, but not implementing 'getCanonicalizationPatterns' manually.
1697   bool hasBody = hasCanonicalizeMethod && !hasCanonicalizer;
1698 
1699   // Add a signature for getCanonicalizationPatterns if implemented by the
1700   // dialect or if synthesized to call 'canonicalize'.
1701   SmallVector<OpMethodParameter, 2> paramList;
1702   paramList.emplace_back("::mlir::RewritePatternSet &", "results");
1703   paramList.emplace_back("::mlir::MLIRContext *", "context");
1704   auto kind = hasBody ? OpMethod::MP_Static : OpMethod::MP_StaticDeclaration;
1705   auto *method = opClass.addMethodAndPrune(
1706       "void", "getCanonicalizationPatterns", kind, std::move(paramList));
1707 
1708   // If synthesizing the method, fill it it.
1709   if (hasBody)
1710     method->body() << "  results.add(canonicalize);\n";
1711 }
1712 
1713 void OpEmitter::genFolderDecls() {
1714   bool hasSingleResult =
1715       op.getNumResults() == 1 && op.getNumVariableLengthResults() == 0;
1716 
1717   if (def.getValueAsBit("hasFolder")) {
1718     if (hasSingleResult) {
1719       opClass.addMethodAndPrune(
1720           "::mlir::OpFoldResult", "fold", OpMethod::MP_Declaration,
1721           "::llvm::ArrayRef<::mlir::Attribute>", "operands");
1722     } else {
1723       SmallVector<OpMethodParameter, 2> paramList;
1724       paramList.emplace_back("::llvm::ArrayRef<::mlir::Attribute>", "operands");
1725       paramList.emplace_back("::llvm::SmallVectorImpl<::mlir::OpFoldResult> &",
1726                              "results");
1727       opClass.addMethodAndPrune("::mlir::LogicalResult", "fold",
1728                                 OpMethod::MP_Declaration, std::move(paramList));
1729     }
1730   }
1731 }
1732 
1733 void OpEmitter::genOpInterfaceMethods(const tblgen::InterfaceOpTrait *opTrait) {
1734   auto interface = opTrait->getOpInterface();
1735 
1736   // Get the set of methods that should always be declared.
1737   auto alwaysDeclaredMethodsVec = opTrait->getAlwaysDeclaredMethods();
1738   llvm::StringSet<> alwaysDeclaredMethods;
1739   alwaysDeclaredMethods.insert(alwaysDeclaredMethodsVec.begin(),
1740                                alwaysDeclaredMethodsVec.end());
1741 
1742   for (const InterfaceMethod &method : interface.getMethods()) {
1743     // Don't declare if the method has a body.
1744     if (method.getBody())
1745       continue;
1746     // Don't declare if the method has a default implementation and the op
1747     // didn't request that it always be declared.
1748     if (method.getDefaultImplementation() &&
1749         !alwaysDeclaredMethods.count(method.getName()))
1750       continue;
1751     genOpInterfaceMethod(method);
1752   }
1753 }
1754 
1755 OpMethod *OpEmitter::genOpInterfaceMethod(const InterfaceMethod &method,
1756                                           bool declaration) {
1757   SmallVector<OpMethodParameter, 4> paramList;
1758   for (const InterfaceMethod::Argument &arg : method.getArguments())
1759     paramList.emplace_back(arg.type, arg.name);
1760 
1761   auto properties = method.isStatic() ? OpMethod::MP_Static : OpMethod::MP_None;
1762   if (declaration)
1763     properties =
1764         static_cast<OpMethod::Property>(properties | OpMethod::MP_Declaration);
1765   return opClass.addMethodAndPrune(method.getReturnType(), method.getName(),
1766                                    properties, std::move(paramList));
1767 }
1768 
1769 void OpEmitter::genOpInterfaceMethods() {
1770   for (const auto &trait : op.getTraits()) {
1771     if (const auto *opTrait = dyn_cast<tblgen::InterfaceOpTrait>(&trait))
1772       if (opTrait->shouldDeclareMethods())
1773         genOpInterfaceMethods(opTrait);
1774   }
1775 }
1776 
1777 void OpEmitter::genSideEffectInterfaceMethods() {
1778   enum EffectKind { Operand, Result, Symbol, Static };
1779   struct EffectLocation {
1780     /// The effect applied.
1781     SideEffect effect;
1782 
1783     /// The index if the kind is not static.
1784     unsigned index : 30;
1785 
1786     /// The kind of the location.
1787     unsigned kind : 2;
1788   };
1789 
1790   StringMap<SmallVector<EffectLocation, 1>> interfaceEffects;
1791   auto resolveDecorators = [&](Operator::var_decorator_range decorators,
1792                                unsigned index, unsigned kind) {
1793     for (auto decorator : decorators)
1794       if (SideEffect *effect = dyn_cast<SideEffect>(&decorator)) {
1795         opClass.addTrait(effect->getInterfaceTrait());
1796         interfaceEffects[effect->getBaseEffectName()].push_back(
1797             EffectLocation{*effect, index, kind});
1798       }
1799   };
1800 
1801   // Collect effects that were specified via:
1802   /// Traits.
1803   for (const auto &trait : op.getTraits()) {
1804     const auto *opTrait = dyn_cast<tblgen::SideEffectTrait>(&trait);
1805     if (!opTrait)
1806       continue;
1807     auto &effects = interfaceEffects[opTrait->getBaseEffectName()];
1808     for (auto decorator : opTrait->getEffects())
1809       effects.push_back(EffectLocation{cast<SideEffect>(decorator),
1810                                        /*index=*/0, EffectKind::Static});
1811   }
1812   /// Attributes and Operands.
1813   for (unsigned i = 0, operandIt = 0, e = op.getNumArgs(); i != e; ++i) {
1814     Argument arg = op.getArg(i);
1815     if (arg.is<NamedTypeConstraint *>()) {
1816       resolveDecorators(op.getArgDecorators(i), operandIt, EffectKind::Operand);
1817       ++operandIt;
1818       continue;
1819     }
1820     const NamedAttribute *attr = arg.get<NamedAttribute *>();
1821     if (attr->attr.getBaseAttr().isSymbolRefAttr())
1822       resolveDecorators(op.getArgDecorators(i), i, EffectKind::Symbol);
1823   }
1824   /// Results.
1825   for (unsigned i = 0, e = op.getNumResults(); i != e; ++i)
1826     resolveDecorators(op.getResultDecorators(i), i, EffectKind::Result);
1827 
1828   // The code used to add an effect instance.
1829   // {0}: The effect class.
1830   // {1}: Optional value or symbol reference.
1831   // {1}: The resource class.
1832   const char *addEffectCode =
1833       "  effects.emplace_back({0}::get(), {1}{2}::get());\n";
1834 
1835   for (auto &it : interfaceEffects) {
1836     // Generate the 'getEffects' method.
1837     std::string type = llvm::formatv("::mlir::SmallVectorImpl<::mlir::"
1838                                      "SideEffects::EffectInstance<{0}>> &",
1839                                      it.first())
1840                            .str();
1841     auto *getEffects =
1842         opClass.addMethodAndPrune("void", "getEffects", type, "effects");
1843     auto &body = getEffects->body();
1844 
1845     // Add effect instances for each of the locations marked on the operation.
1846     for (auto &location : it.second) {
1847       StringRef effect = location.effect.getName();
1848       StringRef resource = location.effect.getResource();
1849       if (location.kind == EffectKind::Static) {
1850         // A static instance has no attached value.
1851         body << llvm::formatv(addEffectCode, effect, "", resource).str();
1852       } else if (location.kind == EffectKind::Symbol) {
1853         // A symbol reference requires adding the proper attribute.
1854         const auto *attr = op.getArg(location.index).get<NamedAttribute *>();
1855         if (attr->attr.isOptional()) {
1856           body << "  if (auto symbolRef = " << attr->name << "Attr())\n  "
1857                << llvm::formatv(addEffectCode, effect, "symbolRef, ", resource)
1858                       .str();
1859         } else {
1860           body << llvm::formatv(addEffectCode, effect, attr->name + "(), ",
1861                                 resource)
1862                       .str();
1863         }
1864       } else {
1865         // Otherwise this is an operand/result, so we need to attach the Value.
1866         body << "  for (::mlir::Value value : getODS"
1867              << (location.kind == EffectKind::Operand ? "Operands" : "Results")
1868              << "(" << location.index << "))\n  "
1869              << llvm::formatv(addEffectCode, effect, "value, ", resource).str();
1870       }
1871     }
1872   }
1873 }
1874 
1875 void OpEmitter::genTypeInterfaceMethods() {
1876   if (!op.allResultTypesKnown())
1877     return;
1878   // Generate 'inferReturnTypes' method declaration using the interface method
1879   // declared in 'InferTypeOpInterface' op interface.
1880   const auto *trait = dyn_cast<InterfaceOpTrait>(
1881       op.getTrait("::mlir::InferTypeOpInterface::Trait"));
1882   auto interface = trait->getOpInterface();
1883   OpMethod *method = [&]() -> OpMethod * {
1884     for (const InterfaceMethod &interfaceMethod : interface.getMethods()) {
1885       if (interfaceMethod.getName() == "inferReturnTypes") {
1886         return genOpInterfaceMethod(interfaceMethod, /*declaration=*/false);
1887       }
1888     }
1889     assert(0 && "unable to find inferReturnTypes interface method");
1890     return nullptr;
1891   }();
1892   auto &body = method->body();
1893   body << "  inferredReturnTypes.resize(" << op.getNumResults() << ");\n";
1894 
1895   FmtContext fctx;
1896   fctx.withBuilder("odsBuilder");
1897   body << "  ::mlir::Builder odsBuilder(context);\n";
1898 
1899   auto emitType =
1900       [&](const tblgen::Operator::ArgOrType &type) -> OpMethodBody & {
1901     if (type.isArg()) {
1902       auto argIndex = type.getArg();
1903       assert(!op.getArg(argIndex).is<NamedAttribute *>());
1904       auto arg = op.getArgToOperandOrAttribute(argIndex);
1905       if (arg.kind() == Operator::OperandOrAttribute::Kind::Operand)
1906         return body << "operands[" << arg.operandOrAttributeIndex()
1907                     << "].getType()";
1908       return body << "attributes[" << arg.operandOrAttributeIndex()
1909                   << "].getType()";
1910     } else {
1911       return body << tgfmt(*type.getType().getBuilderCall(), &fctx);
1912     }
1913   };
1914 
1915   for (int i = 0, e = op.getNumResults(); i != e; ++i) {
1916     body << "  inferredReturnTypes[" << i << "] = ";
1917     auto types = op.getSameTypeAsResult(i);
1918     emitType(types[0]) << ";\n";
1919     if (types.size() == 1)
1920       continue;
1921     // TODO: We could verify equality here, but skipping that for verification.
1922   }
1923   body << "  return ::mlir::success();";
1924 }
1925 
1926 void OpEmitter::genParser() {
1927   if (!hasStringAttribute(def, "parser") ||
1928       hasStringAttribute(def, "assemblyFormat"))
1929     return;
1930 
1931   SmallVector<OpMethodParameter, 2> paramList;
1932   paramList.emplace_back("::mlir::OpAsmParser &", "parser");
1933   paramList.emplace_back("::mlir::OperationState &", "result");
1934   auto *method =
1935       opClass.addMethodAndPrune("::mlir::ParseResult", "parse",
1936                                 OpMethod::MP_Static, std::move(paramList));
1937 
1938   FmtContext fctx;
1939   fctx.addSubst("cppClass", opClass.getClassName());
1940   auto parser = def.getValueAsString("parser").ltrim().rtrim(" \t\v\f\r");
1941   method->body() << "  " << tgfmt(parser, &fctx);
1942 }
1943 
1944 void OpEmitter::genPrinter() {
1945   if (hasStringAttribute(def, "assemblyFormat"))
1946     return;
1947 
1948   auto valueInit = def.getValueInit("printer");
1949   StringInit *stringInit = dyn_cast<StringInit>(valueInit);
1950   if (!stringInit)
1951     return;
1952 
1953   auto *method =
1954       opClass.addMethodAndPrune("void", "print", "::mlir::OpAsmPrinter &", "p");
1955   FmtContext fctx;
1956   fctx.addSubst("cppClass", opClass.getClassName());
1957   auto printer = stringInit->getValue().ltrim().rtrim(" \t\v\f\r");
1958   method->body() << "  " << tgfmt(printer, &fctx);
1959 }
1960 
1961 void OpEmitter::genVerifier() {
1962   auto *method = opClass.addMethodAndPrune("::mlir::LogicalResult", "verify");
1963   auto &body = method->body();
1964   body << "  if (failed(" << op.getAdaptorName()
1965        << "(*this).verify((*this)->getLoc()))) "
1966        << "return ::mlir::failure();\n";
1967 
1968   auto *valueInit = def.getValueInit("verifier");
1969   StringInit *stringInit = dyn_cast<StringInit>(valueInit);
1970   bool hasCustomVerify = stringInit && !stringInit->getValue().empty();
1971   populateSubstitutions(op, "(*this)->getAttr", "this->getODSOperands",
1972                         "this->getODSResults", verifyCtx);
1973 
1974   genAttributeVerifier(op, "(*this)->getAttr", "emitOpError(",
1975                        /*emitVerificationRequiringOp=*/true, verifyCtx, body);
1976   genOperandResultVerifier(body, op.getOperands(), "operand");
1977   genOperandResultVerifier(body, op.getResults(), "result");
1978 
1979   for (auto &trait : op.getTraits()) {
1980     if (auto *t = dyn_cast<tblgen::PredOpTrait>(&trait)) {
1981       body << tgfmt("  if (!($0))\n    "
1982                     "return emitOpError(\"failed to verify that $1\");\n",
1983                     &verifyCtx, tgfmt(t->getPredTemplate(), &verifyCtx),
1984                     t->getSummary());
1985     }
1986   }
1987 
1988   genRegionVerifier(body);
1989   genSuccessorVerifier(body);
1990 
1991   if (hasCustomVerify) {
1992     FmtContext fctx;
1993     fctx.addSubst("cppClass", opClass.getClassName());
1994     auto printer = stringInit->getValue().ltrim().rtrim(" \t\v\f\r");
1995     body << "  " << tgfmt(printer, &fctx);
1996   } else {
1997     body << "  return ::mlir::success();\n";
1998   }
1999 }
2000 
2001 void OpEmitter::genOperandResultVerifier(OpMethodBody &body,
2002                                          Operator::value_range values,
2003                                          StringRef valueKind) {
2004   FmtContext fctx;
2005 
2006   body << "  {\n";
2007   body << "    unsigned index = 0; (void)index;\n";
2008 
2009   for (auto staticValue : llvm::enumerate(values)) {
2010     bool hasPredicate = staticValue.value().hasPredicate();
2011     bool isOptional = staticValue.value().isOptional();
2012     if (!hasPredicate && !isOptional)
2013       continue;
2014     body << formatv("    auto valueGroup{2} = getODS{0}{1}s({2});\n",
2015                     // Capitalize the first letter to match the function name
2016                     valueKind.substr(0, 1).upper(), valueKind.substr(1),
2017                     staticValue.index());
2018 
2019     // If the constraint is optional check that the value group has at most 1
2020     // value.
2021     if (isOptional) {
2022       body << formatv("    if (valueGroup{0}.size() > 1)\n"
2023                       "      return emitOpError(\"{1} group starting at #\") "
2024                       "<< index << \" requires 0 or 1 element, but found \" << "
2025                       "valueGroup{0}.size();\n",
2026                       staticValue.index(), valueKind);
2027     }
2028 
2029     // Otherwise, if there is no predicate there is nothing left to do.
2030     if (!hasPredicate)
2031       continue;
2032     // Emit a loop to check all the dynamic values in the pack.
2033     StringRef constraintFn = staticVerifierEmitter.getTypeConstraintFn(
2034         staticValue.value().constraint);
2035     body << "    for (::mlir::Value v : valueGroup" << staticValue.index()
2036          << ") {\n"
2037          << "      if (::mlir::failed(" << constraintFn
2038          << "(getOperation(), v.getType(), \"" << valueKind << "\", index)))\n"
2039          << "        return ::mlir::failure();\n"
2040          << "      ++index;\n"
2041          << "    }\n";
2042   }
2043 
2044   body << "  }\n";
2045 }
2046 
2047 void OpEmitter::genRegionVerifier(OpMethodBody &body) {
2048   // If we have no regions, there is nothing more to do.
2049   unsigned numRegions = op.getNumRegions();
2050   if (numRegions == 0)
2051     return;
2052 
2053   body << "{\n";
2054   body << "    unsigned index = 0; (void)index;\n";
2055 
2056   for (unsigned i = 0; i < numRegions; ++i) {
2057     const auto &region = op.getRegion(i);
2058     if (region.constraint.getPredicate().isNull())
2059       continue;
2060 
2061     body << "    for (::mlir::Region &region : ";
2062     body << formatv(region.isVariadic()
2063                         ? "{0}()"
2064                         : "::mlir::MutableArrayRef<::mlir::Region>((*this)"
2065                           "->getRegion({1}))",
2066                     region.name, i);
2067     body << ") {\n";
2068     auto constraint = tgfmt(region.constraint.getConditionTemplate(),
2069                             &verifyCtx.withSelf("region"))
2070                           .str();
2071 
2072     body << formatv("      (void)region;\n"
2073                     "      if (!({0})) {\n        "
2074                     "return emitOpError(\"region #\") << index << \" {1}"
2075                     "failed to "
2076                     "verify constraint: {2}\";\n      }\n",
2077                     constraint,
2078                     region.name.empty() ? "" : "('" + region.name + "') ",
2079                     region.constraint.getSummary())
2080          << "      ++index;\n"
2081          << "    }\n";
2082   }
2083   body << "  }\n";
2084 }
2085 
2086 void OpEmitter::genSuccessorVerifier(OpMethodBody &body) {
2087   // If we have no successors, there is nothing more to do.
2088   unsigned numSuccessors = op.getNumSuccessors();
2089   if (numSuccessors == 0)
2090     return;
2091 
2092   body << "{\n";
2093   body << "    unsigned index = 0; (void)index;\n";
2094 
2095   for (unsigned i = 0; i < numSuccessors; ++i) {
2096     const auto &successor = op.getSuccessor(i);
2097     if (successor.constraint.getPredicate().isNull())
2098       continue;
2099 
2100     if (successor.isVariadic()) {
2101       body << formatv("    for (::mlir::Block *successor : {0}()) {\n",
2102                       successor.name);
2103     } else {
2104       body << "    {\n";
2105       body << formatv("      ::mlir::Block *successor = {0}();\n",
2106                       successor.name);
2107     }
2108     auto constraint = tgfmt(successor.constraint.getConditionTemplate(),
2109                             &verifyCtx.withSelf("successor"))
2110                           .str();
2111 
2112     body << formatv("      (void)successor;\n"
2113                     "      if (!({0})) {\n        "
2114                     "return emitOpError(\"successor #\") << index << \"('{1}') "
2115                     "failed to "
2116                     "verify constraint: {2}\";\n      }\n",
2117                     constraint, successor.name,
2118                     successor.constraint.getSummary())
2119          << "      ++index;\n"
2120          << "    }\n";
2121   }
2122   body << "  }\n";
2123 }
2124 
2125 /// Add a size count trait to the given operation class.
2126 static void addSizeCountTrait(OpClass &opClass, StringRef traitKind,
2127                               int numTotal, int numVariadic) {
2128   if (numVariadic != 0) {
2129     if (numTotal == numVariadic)
2130       opClass.addTrait("::mlir::OpTrait::Variadic" + traitKind + "s");
2131     else
2132       opClass.addTrait("::mlir::OpTrait::AtLeastN" + traitKind + "s<" +
2133                        Twine(numTotal - numVariadic) + ">::Impl");
2134     return;
2135   }
2136   switch (numTotal) {
2137   case 0:
2138     opClass.addTrait("::mlir::OpTrait::Zero" + traitKind);
2139     break;
2140   case 1:
2141     opClass.addTrait("::mlir::OpTrait::One" + traitKind);
2142     break;
2143   default:
2144     opClass.addTrait("::mlir::OpTrait::N" + traitKind + "s<" + Twine(numTotal) +
2145                      ">::Impl");
2146     break;
2147   }
2148 }
2149 
2150 void OpEmitter::genTraits() {
2151   // Add region size trait.
2152   unsigned numRegions = op.getNumRegions();
2153   unsigned numVariadicRegions = op.getNumVariadicRegions();
2154   addSizeCountTrait(opClass, "Region", numRegions, numVariadicRegions);
2155 
2156   // Add result size traits.
2157   int numResults = op.getNumResults();
2158   int numVariadicResults = op.getNumVariableLengthResults();
2159   addSizeCountTrait(opClass, "Result", numResults, numVariadicResults);
2160 
2161   // For single result ops with a known specific type, generate a OneTypedResult
2162   // trait.
2163   if (numResults == 1 && numVariadicResults == 0) {
2164     auto cppName = op.getResults().begin()->constraint.getCPPClassName();
2165     opClass.addTrait("::mlir::OpTrait::OneTypedResult<" + cppName + ">::Impl");
2166   }
2167 
2168   // Add successor size trait.
2169   unsigned numSuccessors = op.getNumSuccessors();
2170   unsigned numVariadicSuccessors = op.getNumVariadicSuccessors();
2171   addSizeCountTrait(opClass, "Successor", numSuccessors, numVariadicSuccessors);
2172 
2173   // Add variadic size trait and normal op traits.
2174   int numOperands = op.getNumOperands();
2175   int numVariadicOperands = op.getNumVariableLengthOperands();
2176 
2177   // Add operand size trait.
2178   if (numVariadicOperands != 0) {
2179     if (numOperands == numVariadicOperands)
2180       opClass.addTrait("::mlir::OpTrait::VariadicOperands");
2181     else
2182       opClass.addTrait("::mlir::OpTrait::AtLeastNOperands<" +
2183                        Twine(numOperands - numVariadicOperands) + ">::Impl");
2184   } else {
2185     switch (numOperands) {
2186     case 0:
2187       opClass.addTrait("::mlir::OpTrait::ZeroOperands");
2188       break;
2189     case 1:
2190       opClass.addTrait("::mlir::OpTrait::OneOperand");
2191       break;
2192     default:
2193       opClass.addTrait("::mlir::OpTrait::NOperands<" + Twine(numOperands) +
2194                        ">::Impl");
2195       break;
2196     }
2197   }
2198 
2199   // Add the native and interface traits.
2200   for (const auto &trait : op.getTraits()) {
2201     if (auto opTrait = dyn_cast<tblgen::NativeOpTrait>(&trait))
2202       opClass.addTrait(opTrait->getTrait());
2203     else if (auto opTrait = dyn_cast<tblgen::InterfaceOpTrait>(&trait))
2204       opClass.addTrait(opTrait->getTrait());
2205   }
2206 }
2207 
2208 void OpEmitter::genOpNameGetter() {
2209   auto *method = opClass.addMethodAndPrune(
2210       "::llvm::StringLiteral", "getOperationName",
2211       OpMethod::Property(OpMethod::MP_Static | OpMethod::MP_Constexpr));
2212   method->body() << "  return ::llvm::StringLiteral(\"" << op.getOperationName()
2213                  << "\");";
2214 }
2215 
2216 void OpEmitter::genOpAsmInterface() {
2217   // If the user only has one results or specifically added the Asm trait,
2218   // then don't generate it for them. We specifically only handle multi result
2219   // operations, because the name of a single result in the common case is not
2220   // interesting(generally 'result'/'output'/etc.).
2221   // TODO: We could also add a flag to allow operations to opt in to this
2222   // generation, even if they only have a single operation.
2223   int numResults = op.getNumResults();
2224   if (numResults <= 1 || op.getTrait("::mlir::OpAsmOpInterface::Trait"))
2225     return;
2226 
2227   SmallVector<StringRef, 4> resultNames(numResults);
2228   for (int i = 0; i != numResults; ++i)
2229     resultNames[i] = op.getResultName(i);
2230 
2231   // Don't add the trait if none of the results have a valid name.
2232   if (llvm::all_of(resultNames, [](StringRef name) { return name.empty(); }))
2233     return;
2234   opClass.addTrait("::mlir::OpAsmOpInterface::Trait");
2235 
2236   // Generate the right accessor for the number of results.
2237   auto *method = opClass.addMethodAndPrune(
2238       "void", "getAsmResultNames", "::mlir::OpAsmSetValueNameFn", "setNameFn");
2239   auto &body = method->body();
2240   for (int i = 0; i != numResults; ++i) {
2241     body << "  auto resultGroup" << i << " = getODSResults(" << i << ");\n"
2242          << "  if (!llvm::empty(resultGroup" << i << "))\n"
2243          << "    setNameFn(*resultGroup" << i << ".begin(), \""
2244          << resultNames[i] << "\");\n";
2245   }
2246 }
2247 
2248 //===----------------------------------------------------------------------===//
2249 // OpOperandAdaptor emitter
2250 //===----------------------------------------------------------------------===//
2251 
2252 namespace {
2253 // Helper class to emit Op operand adaptors to an output stream.  Operand
2254 // adaptors are wrappers around ArrayRef<Value> that provide named operand
2255 // getters identical to those defined in the Op.
2256 class OpOperandAdaptorEmitter {
2257 public:
2258   static void emitDecl(const Operator &op, raw_ostream &os);
2259   static void emitDef(const Operator &op, raw_ostream &os);
2260 
2261 private:
2262   explicit OpOperandAdaptorEmitter(const Operator &op);
2263 
2264   // Add verification function. This generates a verify method for the adaptor
2265   // which verifies all the op-independent attribute constraints.
2266   void addVerification();
2267 
2268   const Operator &op;
2269   Class adaptor;
2270 };
2271 } // end namespace
2272 
2273 OpOperandAdaptorEmitter::OpOperandAdaptorEmitter(const Operator &op)
2274     : op(op), adaptor(op.getAdaptorName()) {
2275   adaptor.newField("::mlir::ValueRange", "odsOperands");
2276   adaptor.newField("::mlir::DictionaryAttr", "odsAttrs");
2277   adaptor.newField("::mlir::RegionRange", "odsRegions");
2278   const auto *attrSizedOperands =
2279       op.getTrait("::mlir::OpTrait::AttrSizedOperandSegments");
2280   {
2281     SmallVector<OpMethodParameter, 2> paramList;
2282     paramList.emplace_back("::mlir::ValueRange", "values");
2283     paramList.emplace_back("::mlir::DictionaryAttr", "attrs",
2284                            attrSizedOperands ? "" : "nullptr");
2285     paramList.emplace_back("::mlir::RegionRange", "regions", "{}");
2286     auto *constructor = adaptor.addConstructorAndPrune(std::move(paramList));
2287 
2288     constructor->addMemberInitializer("odsOperands", "values");
2289     constructor->addMemberInitializer("odsAttrs", "attrs");
2290     constructor->addMemberInitializer("odsRegions", "regions");
2291   }
2292 
2293   {
2294     auto *constructor = adaptor.addConstructorAndPrune(
2295         llvm::formatv("{0}&", op.getCppClassName()).str(), "op");
2296     constructor->addMemberInitializer("odsOperands", "op->getOperands()");
2297     constructor->addMemberInitializer("odsAttrs", "op->getAttrDictionary()");
2298     constructor->addMemberInitializer("odsRegions", "op->getRegions()");
2299   }
2300 
2301   {
2302     auto *m = adaptor.addMethodAndPrune("::mlir::ValueRange", "getOperands");
2303     m->body() << "  return odsOperands;";
2304   }
2305   std::string sizeAttrInit =
2306       formatv(adapterSegmentSizeAttrInitCode, "operand_segment_sizes");
2307   generateNamedOperandGetters(op, adaptor, sizeAttrInit,
2308                               /*rangeType=*/"::mlir::ValueRange",
2309                               /*rangeBeginCall=*/"odsOperands.begin()",
2310                               /*rangeSizeCall=*/"odsOperands.size()",
2311                               /*getOperandCallPattern=*/"odsOperands[{0}]");
2312 
2313   FmtContext fctx;
2314   fctx.withBuilder("::mlir::Builder(odsAttrs.getContext())");
2315 
2316   auto emitAttr = [&](StringRef name, Attribute attr) {
2317     auto &body = adaptor.addMethodAndPrune(attr.getStorageType(), name)->body();
2318     body << "  assert(odsAttrs && \"no attributes when constructing adapter\");"
2319          << "\n  " << attr.getStorageType() << " attr = "
2320          << "odsAttrs.get(\"" << name << "\").";
2321     if (attr.hasDefaultValue() || attr.isOptional())
2322       body << "dyn_cast_or_null<";
2323     else
2324       body << "cast<";
2325     body << attr.getStorageType() << ">();\n";
2326 
2327     if (attr.hasDefaultValue()) {
2328       // Use the default value if attribute is not set.
2329       // TODO: this is inefficient, we are recreating the attribute for every
2330       // call. This should be set instead.
2331       std::string defaultValue = std::string(
2332           tgfmt(attr.getConstBuilderTemplate(), &fctx, attr.getDefaultValue()));
2333       body << "  if (!attr)\n    attr = " << defaultValue << ";\n";
2334     }
2335     body << "  return attr;\n";
2336   };
2337 
2338   {
2339     auto *m =
2340         adaptor.addMethodAndPrune("::mlir::DictionaryAttr", "getAttributes");
2341     m->body() << "  return odsAttrs;";
2342   }
2343   for (auto &namedAttr : op.getAttributes()) {
2344     const auto &name = namedAttr.name;
2345     const auto &attr = namedAttr.attr;
2346     if (!attr.isDerivedAttr())
2347       emitAttr(name, attr);
2348   }
2349 
2350   unsigned numRegions = op.getNumRegions();
2351   if (numRegions > 0) {
2352     auto *m = adaptor.addMethodAndPrune("::mlir::RegionRange", "getRegions");
2353     m->body() << "  return odsRegions;";
2354   }
2355   for (unsigned i = 0; i < numRegions; ++i) {
2356     const auto &region = op.getRegion(i);
2357     if (region.name.empty())
2358       continue;
2359 
2360     // Generate the accessors for a variadic region.
2361     if (region.isVariadic()) {
2362       auto *m = adaptor.addMethodAndPrune("::mlir::RegionRange", region.name);
2363       m->body() << formatv("  return odsRegions.drop_front({0});", i);
2364       continue;
2365     }
2366 
2367     auto *m = adaptor.addMethodAndPrune("::mlir::Region &", region.name);
2368     m->body() << formatv("  return *odsRegions[{0}];", i);
2369   }
2370 
2371   // Add verification function.
2372   addVerification();
2373 }
2374 
2375 void OpOperandAdaptorEmitter::addVerification() {
2376   auto *method = adaptor.addMethodAndPrune("::mlir::LogicalResult", "verify",
2377                                            "::mlir::Location", "loc");
2378   auto &body = method->body();
2379 
2380   const char *checkAttrSizedValueSegmentsCode = R"(
2381   {
2382     auto sizeAttr = odsAttrs.get("{0}").cast<::mlir::DenseIntElementsAttr>();
2383     auto numElements = sizeAttr.getType().cast<::mlir::ShapedType>().getNumElements();
2384     if (numElements != {1})
2385       return emitError(loc, "'{0}' attribute for specifying {2} segments "
2386                        "must have {1} elements, but got ") << numElements;
2387   }
2388   )";
2389 
2390   // Verify a few traits first so that we can use
2391   // getODSOperands()/getODSResults() in the rest of the verifier.
2392   for (auto &trait : op.getTraits()) {
2393     if (auto *t = dyn_cast<tblgen::NativeOpTrait>(&trait)) {
2394       if (t->getTrait() == "::mlir::OpTrait::AttrSizedOperandSegments") {
2395         body << formatv(checkAttrSizedValueSegmentsCode,
2396                         "operand_segment_sizes", op.getNumOperands(),
2397                         "operand");
2398       } else if (t->getTrait() == "::mlir::OpTrait::AttrSizedResultSegments") {
2399         body << formatv(checkAttrSizedValueSegmentsCode, "result_segment_sizes",
2400                         op.getNumResults(), "result");
2401       }
2402     }
2403   }
2404 
2405   FmtContext verifyCtx;
2406   populateSubstitutions(op, "odsAttrs.get", "getODSOperands",
2407                         "<no results should be generated>", verifyCtx);
2408   genAttributeVerifier(op, "odsAttrs.get",
2409                        Twine("emitError(loc, \"'") + op.getOperationName() +
2410                            "' op \"",
2411                        /*emitVerificationRequiringOp*/ false, verifyCtx, body);
2412 
2413   body << "  return ::mlir::success();";
2414 }
2415 
2416 void OpOperandAdaptorEmitter::emitDecl(const Operator &op, raw_ostream &os) {
2417   OpOperandAdaptorEmitter(op).adaptor.writeDeclTo(os);
2418 }
2419 
2420 void OpOperandAdaptorEmitter::emitDef(const Operator &op, raw_ostream &os) {
2421   OpOperandAdaptorEmitter(op).adaptor.writeDefTo(os);
2422 }
2423 
2424 // Emits the opcode enum and op classes.
2425 static void emitOpClasses(const RecordKeeper &recordKeeper,
2426                           const std::vector<Record *> &defs, raw_ostream &os,
2427                           bool emitDecl) {
2428   // First emit forward declaration for each class, this allows them to refer
2429   // to each others in traits for example.
2430   if (emitDecl) {
2431     os << "#if defined(GET_OP_CLASSES) || defined(GET_OP_FWD_DEFINES)\n";
2432     os << "#undef GET_OP_FWD_DEFINES\n";
2433     for (auto *def : defs) {
2434       Operator op(*def);
2435       NamespaceEmitter emitter(os, op.getDialect());
2436       os << "class " << op.getCppClassName() << ";\n";
2437     }
2438     os << "#endif\n\n";
2439   }
2440 
2441   IfDefScope scope("GET_OP_CLASSES", os);
2442   if (defs.empty())
2443     return;
2444 
2445   // Generate all of the locally instantiated methods first.
2446   StaticVerifierFunctionEmitter staticVerifierEmitter(recordKeeper, defs, os,
2447                                                       emitDecl);
2448   for (auto *def : defs) {
2449     Operator op(*def);
2450     NamespaceEmitter emitter(os, op.getDialect());
2451     if (emitDecl) {
2452       os << formatv(opCommentHeader, op.getQualCppClassName(), "declarations");
2453       OpOperandAdaptorEmitter::emitDecl(op, os);
2454       OpEmitter::emitDecl(op, os, staticVerifierEmitter);
2455     } else {
2456       os << formatv(opCommentHeader, op.getQualCppClassName(), "definitions");
2457       OpOperandAdaptorEmitter::emitDef(op, os);
2458       OpEmitter::emitDef(op, os, staticVerifierEmitter);
2459     }
2460   }
2461 }
2462 
2463 // Emits a comma-separated list of the ops.
2464 static void emitOpList(const std::vector<Record *> &defs, raw_ostream &os) {
2465   IfDefScope scope("GET_OP_LIST", os);
2466 
2467   interleave(
2468       // TODO: We are constructing the Operator wrapper instance just for
2469       // getting it's qualified class name here. Reduce the overhead by having a
2470       // lightweight version of Operator class just for that purpose.
2471       defs, [&os](Record *def) { os << Operator(def).getQualCppClassName(); },
2472       [&os]() { os << ",\n"; });
2473 }
2474 
2475 static std::string getOperationName(const Record &def) {
2476   auto prefix = def.getValueAsDef("opDialect")->getValueAsString("name");
2477   auto opName = def.getValueAsString("opName");
2478   if (prefix.empty())
2479     return std::string(opName);
2480   return std::string(llvm::formatv("{0}.{1}", prefix, opName));
2481 }
2482 
2483 static std::vector<Record *>
2484 getAllDerivedDefinitions(const RecordKeeper &recordKeeper,
2485                          StringRef className) {
2486   Record *classDef = recordKeeper.getClass(className);
2487   if (!classDef)
2488     PrintFatalError("ERROR: Couldn't find the `" + className + "' class!\n");
2489 
2490   llvm::Regex includeRegex(opIncFilter), excludeRegex(opExcFilter);
2491   std::vector<Record *> defs;
2492   for (const auto &def : recordKeeper.getDefs()) {
2493     if (!def.second->isSubClassOf(classDef))
2494       continue;
2495     // Include if no include filter or include filter matches.
2496     if (!opIncFilter.empty() &&
2497         !includeRegex.match(getOperationName(*def.second)))
2498       continue;
2499     // Unless there is an exclude filter and it matches.
2500     if (!opExcFilter.empty() &&
2501         excludeRegex.match(getOperationName(*def.second)))
2502       continue;
2503     defs.push_back(def.second.get());
2504   }
2505 
2506   return defs;
2507 }
2508 
2509 static bool emitOpDecls(const RecordKeeper &recordKeeper, raw_ostream &os) {
2510   emitSourceFileHeader("Op Declarations", os);
2511 
2512   const auto &defs = getAllDerivedDefinitions(recordKeeper, "Op");
2513   emitOpClasses(recordKeeper, defs, os, /*emitDecl=*/true);
2514 
2515   return false;
2516 }
2517 
2518 static bool emitOpDefs(const RecordKeeper &recordKeeper, raw_ostream &os) {
2519   emitSourceFileHeader("Op Definitions", os);
2520 
2521   const auto &defs = getAllDerivedDefinitions(recordKeeper, "Op");
2522   emitOpList(defs, os);
2523   emitOpClasses(recordKeeper, defs, os, /*emitDecl=*/false);
2524 
2525   return false;
2526 }
2527 
2528 static mlir::GenRegistration
2529     genOpDecls("gen-op-decls", "Generate op declarations",
2530                [](const RecordKeeper &records, raw_ostream &os) {
2531                  return emitOpDecls(records, os);
2532                });
2533 
2534 static mlir::GenRegistration genOpDefs("gen-op-defs", "Generate op definitions",
2535                                        [](const RecordKeeper &records,
2536                                           raw_ostream &os) {
2537                                          return emitOpDefs(records, os);
2538                                        });
2539