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