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   verifyCtx.addSubst("_ctxt", "this->getOperation()->getContext()");
583 
584   genTraits();
585 
586   // Generate C++ code for various op methods. The order here determines the
587   // methods in the generated file.
588   genOpAsmInterface();
589   genOpNameGetter();
590   genNamedOperandGetters();
591   genNamedOperandSetters();
592   genNamedResultGetters();
593   genNamedRegionGetters();
594   genNamedSuccessorGetters();
595   genAttrGetters();
596   genAttrSetters();
597   genOptionalAttrRemovers();
598   genBuilder();
599   genParser();
600   genPrinter();
601   genVerifier();
602   genCanonicalizerDecls();
603   genFolderDecls();
604   genTypeInterfaceMethods();
605   genOpInterfaceMethods();
606   generateOpFormat(op, opClass);
607   genSideEffectInterfaceMethods();
608 }
609 
610 void OpEmitter::emitDecl(
611     const Operator &op, raw_ostream &os,
612     const StaticVerifierFunctionEmitter &staticVerifierEmitter) {
613   OpEmitter(op, staticVerifierEmitter).emitDecl(os);
614 }
615 
616 void OpEmitter::emitDef(
617     const Operator &op, raw_ostream &os,
618     const StaticVerifierFunctionEmitter &staticVerifierEmitter) {
619   OpEmitter(op, staticVerifierEmitter).emitDef(os);
620 }
621 
622 void OpEmitter::emitDecl(raw_ostream &os) { opClass.writeDeclTo(os); }
623 
624 void OpEmitter::emitDef(raw_ostream &os) { opClass.writeDefTo(os); }
625 
626 void OpEmitter::genAttrGetters() {
627   FmtContext fctx;
628   fctx.withBuilder("::mlir::Builder((*this)->getContext())");
629 
630   Dialect opDialect = op.getDialect();
631   // Emit the derived attribute body.
632   auto emitDerivedAttr = [&](StringRef name, Attribute attr) {
633     auto *method = opClass.addMethodAndPrune(attr.getReturnType(), name);
634     if (!method)
635       return;
636     auto &body = method->body();
637     body << "  " << attr.getDerivedCodeBody() << "\n";
638   };
639 
640   // Emit with return type specified.
641   auto emitAttrWithReturnType = [&](StringRef name, Attribute attr) {
642     auto *method = opClass.addMethodAndPrune(attr.getReturnType(), name);
643     auto &body = method->body();
644     body << "  auto attr = " << name << "Attr();\n";
645     if (attr.hasDefaultValue()) {
646       // Returns the default value if not set.
647       // TODO: this is inefficient, we are recreating the attribute for every
648       // call. This should be set instead.
649       std::string defaultValue = std::string(
650           tgfmt(attr.getConstBuilderTemplate(), &fctx, attr.getDefaultValue()));
651       body << "    if (!attr)\n      return "
652            << tgfmt(attr.getConvertFromStorageCall(),
653                     &fctx.withSelf(defaultValue))
654            << ";\n";
655     }
656     body << "  return "
657          << tgfmt(attr.getConvertFromStorageCall(), &fctx.withSelf("attr"))
658          << ";\n";
659   };
660 
661   // Generate raw named accessor type. This is a wrapper class that allows
662   // referring to the attributes via accessors instead of having to use
663   // the string interface for better compile time verification.
664   auto emitAttrWithStorageType = [&](StringRef name, Attribute attr) {
665     auto *method =
666         opClass.addMethodAndPrune(attr.getStorageType(), (name + "Attr").str());
667     if (!method)
668       return;
669     auto &body = method->body();
670     body << "  return (*this)->getAttr(\"" << name << "\").template ";
671     if (attr.isOptional() || attr.hasDefaultValue())
672       body << "dyn_cast_or_null<";
673     else
674       body << "cast<";
675     body << attr.getStorageType() << ">();";
676   };
677 
678   for (auto &namedAttr : op.getAttributes()) {
679     const auto &name = namedAttr.name;
680     const auto &attr = namedAttr.attr;
681     if (attr.isDerivedAttr()) {
682       emitDerivedAttr(name, attr);
683     } else {
684       emitAttrWithStorageType(name, attr);
685       emitAttrWithReturnType(name, attr);
686     }
687   }
688 
689   auto derivedAttrs = make_filter_range(op.getAttributes(),
690                                         [](const NamedAttribute &namedAttr) {
691                                           return namedAttr.attr.isDerivedAttr();
692                                         });
693   if (!derivedAttrs.empty()) {
694     opClass.addTrait("::mlir::DerivedAttributeOpInterface::Trait");
695     // Generate helper method to query whether a named attribute is a derived
696     // attribute. This enables, for example, avoiding adding an attribute that
697     // overlaps with a derived attribute.
698     {
699       auto *method = opClass.addMethodAndPrune("bool", "isDerivedAttribute",
700                                                OpMethod::MP_Static,
701                                                "::llvm::StringRef", "name");
702       auto &body = method->body();
703       for (auto namedAttr : derivedAttrs)
704         body << "  if (name == \"" << namedAttr.name << "\") return true;\n";
705       body << " return false;";
706     }
707     // Generate method to materialize derived attributes as a DictionaryAttr.
708     {
709       auto *method = opClass.addMethodAndPrune("::mlir::DictionaryAttr",
710                                                "materializeDerivedAttributes");
711       auto &body = method->body();
712 
713       auto nonMaterializable =
714           make_filter_range(derivedAttrs, [](const NamedAttribute &namedAttr) {
715             return namedAttr.attr.getConvertFromStorageCall().empty();
716           });
717       if (!nonMaterializable.empty()) {
718         std::string attrs;
719         llvm::raw_string_ostream os(attrs);
720         interleaveComma(nonMaterializable, os,
721                         [&](const NamedAttribute &attr) { os << attr.name; });
722         PrintWarning(
723             op.getLoc(),
724             formatv(
725                 "op has non-materializable derived attributes '{0}', skipping",
726                 os.str()));
727         body << formatv("  emitOpError(\"op has non-materializable derived "
728                         "attributes '{0}'\");\n",
729                         attrs);
730         body << "  return nullptr;";
731         return;
732       }
733 
734       body << "  ::mlir::MLIRContext* ctx = getContext();\n";
735       body << "  ::mlir::Builder odsBuilder(ctx); (void)odsBuilder;\n";
736       body << "  return ::mlir::DictionaryAttr::get(";
737       body << "  ctx, {\n";
738       interleave(
739           derivedAttrs, body,
740           [&](const NamedAttribute &namedAttr) {
741             auto tmpl = namedAttr.attr.getConvertFromStorageCall();
742             body << "    {::mlir::Identifier::get(\"" << namedAttr.name
743                  << "\", ctx),\n"
744                  << tgfmt(tmpl, &fctx.withSelf(namedAttr.name + "()")
745                                      .withBuilder("odsBuilder")
746                                      .addSubst("_ctx", "ctx"))
747                  << "}";
748           },
749           ",\n");
750       body << "});";
751     }
752   }
753 }
754 
755 void OpEmitter::genAttrSetters() {
756   // Generate raw named setter type. This is a wrapper class that allows setting
757   // to the attributes via setters instead of having to use the string interface
758   // for better compile time verification.
759   auto emitAttrWithStorageType = [&](StringRef name, Attribute attr) {
760     auto *method = opClass.addMethodAndPrune("void", (name + "Attr").str(),
761                                              attr.getStorageType(), "attr");
762     if (!method)
763       return;
764     auto &body = method->body();
765     body << "  (*this)->setAttr(\"" << name << "\", attr);";
766   };
767 
768   for (auto &namedAttr : op.getAttributes()) {
769     const auto &name = namedAttr.name;
770     const auto &attr = namedAttr.attr;
771     if (!attr.isDerivedAttr())
772       emitAttrWithStorageType(name, attr);
773   }
774 }
775 
776 void OpEmitter::genOptionalAttrRemovers() {
777   // Generate methods for removing optional attributes, instead of having to
778   // use the string interface. Enables better compile time verification.
779   auto emitRemoveAttr = [&](StringRef name) {
780     auto upperInitial = name.take_front().upper();
781     auto suffix = name.drop_front();
782     auto *method = opClass.addMethodAndPrune(
783         "::mlir::Attribute", ("remove" + upperInitial + suffix + "Attr").str());
784     if (!method)
785       return;
786     auto &body = method->body();
787     body << "  return (*this)->removeAttr(\"" << name << "\");";
788   };
789 
790   for (const auto &namedAttr : op.getAttributes()) {
791     const auto &name = namedAttr.name;
792     const auto &attr = namedAttr.attr;
793     if (attr.isOptional())
794       emitRemoveAttr(name);
795   }
796 }
797 
798 // Generates the code to compute the start and end index of an operand or result
799 // range.
800 template <typename RangeT>
801 static void
802 generateValueRangeStartAndEnd(Class &opClass, StringRef methodName,
803                               int numVariadic, int numNonVariadic,
804                               StringRef rangeSizeCall, bool hasAttrSegmentSize,
805                               StringRef sizeAttrInit, RangeT &&odsValues) {
806   auto *method = opClass.addMethodAndPrune("std::pair<unsigned, unsigned>",
807                                            methodName, "unsigned", "index");
808   if (!method)
809     return;
810   auto &body = method->body();
811   if (numVariadic == 0) {
812     body << "  return {index, 1};\n";
813   } else if (hasAttrSegmentSize) {
814     body << sizeAttrInit << attrSizedSegmentValueRangeCalcCode;
815   } else {
816     // Because the op can have arbitrarily interleaved variadic and non-variadic
817     // operands, we need to embed a list in the "sink" getter method for
818     // calculation at run-time.
819     llvm::SmallVector<StringRef, 4> isVariadic;
820     isVariadic.reserve(llvm::size(odsValues));
821     for (auto &it : odsValues)
822       isVariadic.push_back(it.isVariableLength() ? "true" : "false");
823     std::string isVariadicList = llvm::join(isVariadic, ", ");
824     body << formatv(sameVariadicSizeValueRangeCalcCode, isVariadicList,
825                     numNonVariadic, numVariadic, rangeSizeCall, "operand");
826   }
827 }
828 
829 // Generates the named operand getter methods for the given Operator `op` and
830 // puts them in `opClass`.  Uses `rangeType` as the return type of getters that
831 // return a range of operands (individual operands are `Value ` and each
832 // element in the range must also be `Value `); use `rangeBeginCall` to get
833 // an iterator to the beginning of the operand range; use `rangeSizeCall` to
834 // obtain the number of operands. `getOperandCallPattern` contains the code
835 // necessary to obtain a single operand whose position will be substituted
836 // instead of
837 // "{0}" marker in the pattern.  Note that the pattern should work for any kind
838 // of ops, in particular for one-operand ops that may not have the
839 // `getOperand(unsigned)` method.
840 static void generateNamedOperandGetters(const Operator &op, Class &opClass,
841                                         StringRef sizeAttrInit,
842                                         StringRef rangeType,
843                                         StringRef rangeBeginCall,
844                                         StringRef rangeSizeCall,
845                                         StringRef getOperandCallPattern) {
846   const int numOperands = op.getNumOperands();
847   const int numVariadicOperands = op.getNumVariableLengthOperands();
848   const int numNormalOperands = numOperands - numVariadicOperands;
849 
850   const auto *sameVariadicSize =
851       op.getTrait("::mlir::OpTrait::SameVariadicOperandSize");
852   const auto *attrSizedOperands =
853       op.getTrait("::mlir::OpTrait::AttrSizedOperandSegments");
854 
855   if (numVariadicOperands > 1 && !sameVariadicSize && !attrSizedOperands) {
856     PrintFatalError(op.getLoc(), "op has multiple variadic operands but no "
857                                  "specification over their sizes");
858   }
859 
860   if (numVariadicOperands < 2 && attrSizedOperands) {
861     PrintFatalError(op.getLoc(), "op must have at least two variadic operands "
862                                  "to use 'AttrSizedOperandSegments' trait");
863   }
864 
865   if (attrSizedOperands && sameVariadicSize) {
866     PrintFatalError(op.getLoc(),
867                     "op cannot have both 'AttrSizedOperandSegments' and "
868                     "'SameVariadicOperandSize' traits");
869   }
870 
871   // First emit a few "sink" getter methods upon which we layer all nicer named
872   // getter methods.
873   generateValueRangeStartAndEnd(opClass, "getODSOperandIndexAndLength",
874                                 numVariadicOperands, numNormalOperands,
875                                 rangeSizeCall, attrSizedOperands, sizeAttrInit,
876                                 const_cast<Operator &>(op).getOperands());
877 
878   auto *m = opClass.addMethodAndPrune(rangeType, "getODSOperands", "unsigned",
879                                       "index");
880   auto &body = m->body();
881   body << formatv(valueRangeReturnCode, rangeBeginCall,
882                   "getODSOperandIndexAndLength(index)");
883 
884   // Then we emit nicer named getter methods by redirecting to the "sink" getter
885   // method.
886   for (int i = 0; i != numOperands; ++i) {
887     const auto &operand = op.getOperand(i);
888     if (operand.name.empty())
889       continue;
890 
891     if (operand.isOptional()) {
892       m = opClass.addMethodAndPrune("::mlir::Value", operand.name);
893       m->body()
894           << "  auto operands = getODSOperands(" << i << ");\n"
895           << "  return operands.empty() ? ::mlir::Value() : *operands.begin();";
896     } else if (operand.isVariadic()) {
897       m = opClass.addMethodAndPrune(rangeType, operand.name);
898       m->body() << "  return getODSOperands(" << i << ");";
899     } else {
900       m = opClass.addMethodAndPrune("::mlir::Value", operand.name);
901       m->body() << "  return *getODSOperands(" << i << ").begin();";
902     }
903   }
904 }
905 
906 void OpEmitter::genNamedOperandGetters() {
907   generateNamedOperandGetters(
908       op, opClass,
909       /*sizeAttrInit=*/
910       formatv(opSegmentSizeAttrInitCode, "operand_segment_sizes").str(),
911       /*rangeType=*/"::mlir::Operation::operand_range",
912       /*rangeBeginCall=*/"getOperation()->operand_begin()",
913       /*rangeSizeCall=*/"getOperation()->getNumOperands()",
914       /*getOperandCallPattern=*/"getOperation()->getOperand({0})");
915 }
916 
917 void OpEmitter::genNamedOperandSetters() {
918   auto *attrSizedOperands =
919       op.getTrait("::mlir::OpTrait::AttrSizedOperandSegments");
920   for (int i = 0, e = op.getNumOperands(); i != e; ++i) {
921     const auto &operand = op.getOperand(i);
922     if (operand.name.empty())
923       continue;
924     auto *m = opClass.addMethodAndPrune("::mlir::MutableOperandRange",
925                                         (operand.name + "Mutable").str());
926     auto &body = m->body();
927     body << "  auto range = getODSOperandIndexAndLength(" << i << ");\n"
928          << "  return ::mlir::MutableOperandRange(getOperation(), "
929             "range.first, range.second";
930     if (attrSizedOperands)
931       body << ", ::mlir::MutableOperandRange::OperandSegment(" << i
932            << "u, *getOperation()->getAttrDictionary().getNamed("
933               "\"operand_segment_sizes\"))";
934     body << ");\n";
935   }
936 }
937 
938 void OpEmitter::genNamedResultGetters() {
939   const int numResults = op.getNumResults();
940   const int numVariadicResults = op.getNumVariableLengthResults();
941   const int numNormalResults = numResults - numVariadicResults;
942 
943   // If we have more than one variadic results, we need more complicated logic
944   // to calculate the value range for each result.
945 
946   const auto *sameVariadicSize =
947       op.getTrait("::mlir::OpTrait::SameVariadicResultSize");
948   const auto *attrSizedResults =
949       op.getTrait("::mlir::OpTrait::AttrSizedResultSegments");
950 
951   if (numVariadicResults > 1 && !sameVariadicSize && !attrSizedResults) {
952     PrintFatalError(op.getLoc(), "op has multiple variadic results but no "
953                                  "specification over their sizes");
954   }
955 
956   if (numVariadicResults < 2 && attrSizedResults) {
957     PrintFatalError(op.getLoc(), "op must have at least two variadic results "
958                                  "to use 'AttrSizedResultSegments' trait");
959   }
960 
961   if (attrSizedResults && sameVariadicSize) {
962     PrintFatalError(op.getLoc(),
963                     "op cannot have both 'AttrSizedResultSegments' and "
964                     "'SameVariadicResultSize' traits");
965   }
966 
967   generateValueRangeStartAndEnd(
968       opClass, "getODSResultIndexAndLength", numVariadicResults,
969       numNormalResults, "getOperation()->getNumResults()", attrSizedResults,
970       formatv(opSegmentSizeAttrInitCode, "result_segment_sizes").str(),
971       op.getResults());
972 
973   auto *m = opClass.addMethodAndPrune("::mlir::Operation::result_range",
974                                       "getODSResults", "unsigned", "index");
975   m->body() << formatv(valueRangeReturnCode, "getOperation()->result_begin()",
976                        "getODSResultIndexAndLength(index)");
977 
978   for (int i = 0; i != numResults; ++i) {
979     const auto &result = op.getResult(i);
980     if (result.name.empty())
981       continue;
982 
983     if (result.isOptional()) {
984       m = opClass.addMethodAndPrune("::mlir::Value", result.name);
985       m->body()
986           << "  auto results = getODSResults(" << i << ");\n"
987           << "  return results.empty() ? ::mlir::Value() : *results.begin();";
988     } else if (result.isVariadic()) {
989       m = opClass.addMethodAndPrune("::mlir::Operation::result_range",
990                                     result.name);
991       m->body() << "  return getODSResults(" << i << ");";
992     } else {
993       m = opClass.addMethodAndPrune("::mlir::Value", result.name);
994       m->body() << "  return *getODSResults(" << i << ").begin();";
995     }
996   }
997 }
998 
999 void OpEmitter::genNamedRegionGetters() {
1000   unsigned numRegions = op.getNumRegions();
1001   for (unsigned i = 0; i < numRegions; ++i) {
1002     const auto &region = op.getRegion(i);
1003     if (region.name.empty())
1004       continue;
1005 
1006     // Generate the accessors for a variadic region.
1007     if (region.isVariadic()) {
1008       auto *m = opClass.addMethodAndPrune(
1009           "::mlir::MutableArrayRef<::mlir::Region>", region.name);
1010       m->body() << formatv("  return (*this)->getRegions().drop_front({0});",
1011                            i);
1012       continue;
1013     }
1014 
1015     auto *m = opClass.addMethodAndPrune("::mlir::Region &", region.name);
1016     m->body() << formatv("  return (*this)->getRegion({0});", i);
1017   }
1018 }
1019 
1020 void OpEmitter::genNamedSuccessorGetters() {
1021   unsigned numSuccessors = op.getNumSuccessors();
1022   for (unsigned i = 0; i < numSuccessors; ++i) {
1023     const NamedSuccessor &successor = op.getSuccessor(i);
1024     if (successor.name.empty())
1025       continue;
1026 
1027     // Generate the accessors for a variadic successor list.
1028     if (successor.isVariadic()) {
1029       auto *m =
1030           opClass.addMethodAndPrune("::mlir::SuccessorRange", successor.name);
1031       m->body() << formatv(
1032           "  return {std::next((*this)->successor_begin(), {0}), "
1033           "(*this)->successor_end()};",
1034           i);
1035       continue;
1036     }
1037 
1038     auto *m = opClass.addMethodAndPrune("::mlir::Block *", successor.name);
1039     m->body() << formatv("  return (*this)->getSuccessor({0});", i);
1040   }
1041 }
1042 
1043 static bool canGenerateUnwrappedBuilder(Operator &op) {
1044   // If this op does not have native attributes at all, return directly to avoid
1045   // redefining builders.
1046   if (op.getNumNativeAttributes() == 0)
1047     return false;
1048 
1049   bool canGenerate = false;
1050   // We are generating builders that take raw values for attributes. We need to
1051   // make sure the native attributes have a meaningful "unwrapped" value type
1052   // different from the wrapped mlir::Attribute type to avoid redefining
1053   // builders. This checks for the op has at least one such native attribute.
1054   for (int i = 0, e = op.getNumNativeAttributes(); i < e; ++i) {
1055     NamedAttribute &namedAttr = op.getAttribute(i);
1056     if (canUseUnwrappedRawValue(namedAttr.attr)) {
1057       canGenerate = true;
1058       break;
1059     }
1060   }
1061   return canGenerate;
1062 }
1063 
1064 static bool canInferType(Operator &op) {
1065   return op.getTrait("::mlir::InferTypeOpInterface::Trait") &&
1066          op.getNumRegions() == 0;
1067 }
1068 
1069 void OpEmitter::genSeparateArgParamBuilder() {
1070   SmallVector<AttrParamKind, 2> attrBuilderType;
1071   attrBuilderType.push_back(AttrParamKind::WrappedAttr);
1072   if (canGenerateUnwrappedBuilder(op))
1073     attrBuilderType.push_back(AttrParamKind::UnwrappedValue);
1074 
1075   // Emit with separate builders with or without unwrapped attributes and/or
1076   // inferring result type.
1077   auto emit = [&](AttrParamKind attrType, TypeParamKind paramKind,
1078                   bool inferType) {
1079     llvm::SmallVector<OpMethodParameter, 4> paramList;
1080     llvm::SmallVector<std::string, 4> resultNames;
1081     buildParamList(paramList, resultNames, paramKind, attrType);
1082 
1083     auto *m = opClass.addMethodAndPrune("void", "build", OpMethod::MP_Static,
1084                                         std::move(paramList));
1085     // If the builder is redundant, skip generating the method.
1086     if (!m)
1087       return;
1088     auto &body = m->body();
1089     genCodeForAddingArgAndRegionForBuilder(
1090         body, /*isRawValueAttr=*/attrType == AttrParamKind::UnwrappedValue);
1091 
1092     // Push all result types to the operation state
1093 
1094     if (inferType) {
1095       // Generate builder that infers type too.
1096       // TODO: Subsume this with general checking if type can be
1097       // inferred automatically.
1098       // TODO: Expand to handle regions.
1099       body << formatv(R"(
1100         ::llvm::SmallVector<::mlir::Type, 2> inferredReturnTypes;
1101         if (succeeded({0}::inferReturnTypes(odsBuilder.getContext(),
1102                       {1}.location, {1}.operands,
1103                       {1}.attributes.getDictionary({1}.getContext()),
1104                       /*regions=*/{{}, inferredReturnTypes)))
1105           {1}.addTypes(inferredReturnTypes);
1106         else
1107           ::llvm::report_fatal_error("Failed to infer result type(s).");)",
1108                       opClass.getClassName(), builderOpState);
1109       return;
1110     }
1111 
1112     switch (paramKind) {
1113     case TypeParamKind::None:
1114       return;
1115     case TypeParamKind::Separate:
1116       for (int i = 0, e = op.getNumResults(); i < e; ++i) {
1117         if (op.getResult(i).isOptional())
1118           body << "  if (" << resultNames[i] << ")\n  ";
1119         body << "  " << builderOpState << ".addTypes(" << resultNames[i]
1120              << ");\n";
1121       }
1122       return;
1123     case TypeParamKind::Collective: {
1124       int numResults = op.getNumResults();
1125       int numVariadicResults = op.getNumVariableLengthResults();
1126       int numNonVariadicResults = numResults - numVariadicResults;
1127       bool hasVariadicResult = numVariadicResults != 0;
1128 
1129       // Avoid emitting "resultTypes.size() >= 0u" which is always true.
1130       if (!(hasVariadicResult && numNonVariadicResults == 0))
1131         body << "  "
1132              << "assert(resultTypes.size() "
1133              << (hasVariadicResult ? ">=" : "==") << " "
1134              << numNonVariadicResults
1135              << "u && \"mismatched number of results\");\n";
1136       body << "  " << builderOpState << ".addTypes(resultTypes);\n";
1137     }
1138       return;
1139     }
1140     llvm_unreachable("unhandled TypeParamKind");
1141   };
1142 
1143   // Some of the build methods generated here may be ambiguous, but TableGen's
1144   // ambiguous function detection will elide those ones.
1145   for (auto attrType : attrBuilderType) {
1146     emit(attrType, TypeParamKind::Separate, /*inferType=*/false);
1147     if (canInferType(op))
1148       emit(attrType, TypeParamKind::None, /*inferType=*/true);
1149     emit(attrType, TypeParamKind::Collective, /*inferType=*/false);
1150   }
1151 }
1152 
1153 void OpEmitter::genUseOperandAsResultTypeCollectiveParamBuilder() {
1154   int numResults = op.getNumResults();
1155 
1156   // Signature
1157   llvm::SmallVector<OpMethodParameter, 4> paramList;
1158   paramList.emplace_back("::mlir::OpBuilder &", "odsBuilder");
1159   paramList.emplace_back("::mlir::OperationState &", builderOpState);
1160   paramList.emplace_back("::mlir::ValueRange", "operands");
1161   // Provide default value for `attributes` when its the last parameter
1162   StringRef attributesDefaultValue = op.getNumVariadicRegions() ? "" : "{}";
1163   paramList.emplace_back("::llvm::ArrayRef<::mlir::NamedAttribute>",
1164                          "attributes", attributesDefaultValue);
1165   if (op.getNumVariadicRegions())
1166     paramList.emplace_back("unsigned", "numRegions");
1167 
1168   auto *m = opClass.addMethodAndPrune("void", "build", OpMethod::MP_Static,
1169                                       std::move(paramList));
1170   // If the builder is redundant, skip generating the method
1171   if (!m)
1172     return;
1173   auto &body = m->body();
1174 
1175   // Operands
1176   body << "  " << builderOpState << ".addOperands(operands);\n";
1177 
1178   // Attributes
1179   body << "  " << builderOpState << ".addAttributes(attributes);\n";
1180 
1181   // Create the correct number of regions
1182   if (int numRegions = op.getNumRegions()) {
1183     body << llvm::formatv(
1184         "  for (unsigned i = 0; i != {0}; ++i)\n",
1185         (op.getNumVariadicRegions() ? "numRegions" : Twine(numRegions)));
1186     body << "    (void)" << builderOpState << ".addRegion();\n";
1187   }
1188 
1189   // Result types
1190   SmallVector<std::string, 2> resultTypes(numResults, "operands[0].getType()");
1191   body << "  " << builderOpState << ".addTypes({"
1192        << llvm::join(resultTypes, ", ") << "});\n\n";
1193 }
1194 
1195 void OpEmitter::genInferredTypeCollectiveParamBuilder() {
1196   // TODO: Expand to support regions.
1197   SmallVector<OpMethodParameter, 4> paramList;
1198   paramList.emplace_back("::mlir::OpBuilder &", "odsBuilder");
1199   paramList.emplace_back("::mlir::OperationState &", builderOpState);
1200   paramList.emplace_back("::mlir::ValueRange", "operands");
1201   paramList.emplace_back("::llvm::ArrayRef<::mlir::NamedAttribute>",
1202                          "attributes", "{}");
1203   auto *m = opClass.addMethodAndPrune("void", "build", OpMethod::MP_Static,
1204                                       std::move(paramList));
1205   // If the builder is redundant, skip generating the method
1206   if (!m)
1207     return;
1208   auto &body = m->body();
1209 
1210   int numResults = op.getNumResults();
1211   int numVariadicResults = op.getNumVariableLengthResults();
1212   int numNonVariadicResults = numResults - numVariadicResults;
1213 
1214   int numOperands = op.getNumOperands();
1215   int numVariadicOperands = op.getNumVariableLengthOperands();
1216   int numNonVariadicOperands = numOperands - numVariadicOperands;
1217 
1218   // Operands
1219   if (numVariadicOperands == 0 || numNonVariadicOperands != 0)
1220     body << "  assert(operands.size()"
1221          << (numVariadicOperands != 0 ? " >= " : " == ")
1222          << numNonVariadicOperands
1223          << "u && \"mismatched number of parameters\");\n";
1224   body << "  " << builderOpState << ".addOperands(operands);\n";
1225   body << "  " << builderOpState << ".addAttributes(attributes);\n";
1226 
1227   // Create the correct number of regions
1228   if (int numRegions = op.getNumRegions()) {
1229     body << llvm::formatv(
1230         "  for (unsigned i = 0; i != {0}; ++i)\n",
1231         (op.getNumVariadicRegions() ? "numRegions" : Twine(numRegions)));
1232     body << "    (void)" << builderOpState << ".addRegion();\n";
1233   }
1234 
1235   // Result types
1236   body << formatv(R"(
1237     ::mlir::SmallVector<::mlir::Type, 2> inferredReturnTypes;
1238     if (succeeded({0}::inferReturnTypes(odsBuilder.getContext(),
1239                   {1}.location, operands,
1240                   {1}.attributes.getDictionary({1}.getContext()),
1241                   /*regions=*/{{}, inferredReturnTypes))) {{)",
1242                   opClass.getClassName(), builderOpState);
1243   if (numVariadicResults == 0 || numNonVariadicResults != 0)
1244     body << "  assert(inferredReturnTypes.size()"
1245          << (numVariadicResults != 0 ? " >= " : " == ") << numNonVariadicResults
1246          << "u && \"mismatched number of return types\");\n";
1247   body << "      " << builderOpState << ".addTypes(inferredReturnTypes);";
1248 
1249   body << formatv(R"(
1250     } else
1251       ::llvm::report_fatal_error("Failed to infer result type(s).");)",
1252                   opClass.getClassName(), builderOpState);
1253 }
1254 
1255 void OpEmitter::genUseOperandAsResultTypeSeparateParamBuilder() {
1256   llvm::SmallVector<OpMethodParameter, 4> paramList;
1257   llvm::SmallVector<std::string, 4> resultNames;
1258   buildParamList(paramList, resultNames, TypeParamKind::None);
1259 
1260   auto *m = opClass.addMethodAndPrune("void", "build", OpMethod::MP_Static,
1261                                       std::move(paramList));
1262   // If the builder is redundant, skip generating the method
1263   if (!m)
1264     return;
1265   auto &body = m->body();
1266   genCodeForAddingArgAndRegionForBuilder(body);
1267 
1268   auto numResults = op.getNumResults();
1269   if (numResults == 0)
1270     return;
1271 
1272   // Push all result types to the operation state
1273   const char *index = op.getOperand(0).isVariadic() ? ".front()" : "";
1274   std::string resultType =
1275       formatv("{0}{1}.getType()", getArgumentName(op, 0), index).str();
1276   body << "  " << builderOpState << ".addTypes({" << resultType;
1277   for (int i = 1; i != numResults; ++i)
1278     body << ", " << resultType;
1279   body << "});\n\n";
1280 }
1281 
1282 void OpEmitter::genUseAttrAsResultTypeBuilder() {
1283   SmallVector<OpMethodParameter, 4> paramList;
1284   paramList.emplace_back("::mlir::OpBuilder &", "odsBuilder");
1285   paramList.emplace_back("::mlir::OperationState &", builderOpState);
1286   paramList.emplace_back("::mlir::ValueRange", "operands");
1287   paramList.emplace_back("::llvm::ArrayRef<::mlir::NamedAttribute>",
1288                          "attributes", "{}");
1289   auto *m = opClass.addMethodAndPrune("void", "build", OpMethod::MP_Static,
1290                                       std::move(paramList));
1291   // If the builder is redundant, skip generating the method
1292   if (!m)
1293     return;
1294 
1295   auto &body = m->body();
1296 
1297   // Push all result types to the operation state
1298   std::string resultType;
1299   const auto &namedAttr = op.getAttribute(0);
1300 
1301   body << "  for (auto attr : attributes) {\n";
1302   body << "    if (attr.first != \"" << namedAttr.name << "\") continue;\n";
1303   if (namedAttr.attr.isTypeAttr()) {
1304     resultType = "attr.second.cast<::mlir::TypeAttr>().getValue()";
1305   } else {
1306     resultType = "attr.second.getType()";
1307   }
1308 
1309   // Operands
1310   body << "  " << builderOpState << ".addOperands(operands);\n";
1311 
1312   // Attributes
1313   body << "  " << builderOpState << ".addAttributes(attributes);\n";
1314 
1315   // Result types
1316   SmallVector<std::string, 2> resultTypes(op.getNumResults(), resultType);
1317   body << "    " << builderOpState << ".addTypes({"
1318        << llvm::join(resultTypes, ", ") << "});\n";
1319   body << "  }\n";
1320 }
1321 
1322 /// Returns a signature of the builder. Updates the context `fctx` to enable
1323 /// replacement of $_builder and $_state in the body.
1324 static std::string getBuilderSignature(const Builder &builder) {
1325   ArrayRef<Builder::Parameter> params(builder.getParameters());
1326 
1327   // Inject builder and state arguments.
1328   llvm::SmallVector<std::string, 8> arguments;
1329   arguments.reserve(params.size() + 2);
1330   arguments.push_back(
1331       llvm::formatv("::mlir::OpBuilder &{0}", odsBuilder).str());
1332   arguments.push_back(
1333       llvm::formatv("::mlir::OperationState &{0}", builderOpState).str());
1334 
1335   for (unsigned i = 0, e = params.size(); i < e; ++i) {
1336     // If no name is provided, generate one.
1337     Optional<StringRef> paramName = params[i].getName();
1338     std::string name =
1339         paramName ? paramName->str() : "odsArg" + std::to_string(i);
1340 
1341     std::string defaultValue;
1342     if (Optional<StringRef> defaultParamValue = params[i].getDefaultValue())
1343       defaultValue = llvm::formatv(" = {0}", *defaultParamValue).str();
1344     arguments.push_back(
1345         llvm::formatv("{0} {1}{2}", params[i].getCppType(), name, defaultValue)
1346             .str());
1347   }
1348 
1349   return llvm::join(arguments, ", ");
1350 }
1351 
1352 void OpEmitter::genBuilder() {
1353   // Handle custom builders if provided.
1354   for (const Builder &builder : op.getBuilders()) {
1355     std::string paramStr = getBuilderSignature(builder);
1356 
1357     Optional<StringRef> body = builder.getBody();
1358     OpMethod::Property properties =
1359         body ? OpMethod::MP_Static : OpMethod::MP_StaticDeclaration;
1360     auto *method =
1361         opClass.addMethodAndPrune("void", "build", properties, paramStr);
1362 
1363     FmtContext fctx;
1364     fctx.withBuilder(odsBuilder);
1365     fctx.addSubst("_state", builderOpState);
1366     if (body)
1367       method->body() << tgfmt(*body, &fctx);
1368   }
1369 
1370   // Generate default builders that requires all result type, operands, and
1371   // attributes as parameters.
1372   if (op.skipDefaultBuilders())
1373     return;
1374 
1375   // We generate three classes of builders here:
1376   // 1. one having a stand-alone parameter for each operand / attribute, and
1377   genSeparateArgParamBuilder();
1378   // 2. one having an aggregated parameter for all result types / operands /
1379   //    attributes, and
1380   genCollectiveParamBuilder();
1381   // 3. one having a stand-alone parameter for each operand and attribute,
1382   //    use the first operand or attribute's type as all result types
1383   //    to facilitate different call patterns.
1384   if (op.getNumVariableLengthResults() == 0) {
1385     if (op.getTrait("::mlir::OpTrait::SameOperandsAndResultType")) {
1386       genUseOperandAsResultTypeSeparateParamBuilder();
1387       genUseOperandAsResultTypeCollectiveParamBuilder();
1388     }
1389     if (op.getTrait("::mlir::OpTrait::FirstAttrDerivedResultType"))
1390       genUseAttrAsResultTypeBuilder();
1391   }
1392 }
1393 
1394 void OpEmitter::genCollectiveParamBuilder() {
1395   int numResults = op.getNumResults();
1396   int numVariadicResults = op.getNumVariableLengthResults();
1397   int numNonVariadicResults = numResults - numVariadicResults;
1398 
1399   int numOperands = op.getNumOperands();
1400   int numVariadicOperands = op.getNumVariableLengthOperands();
1401   int numNonVariadicOperands = numOperands - numVariadicOperands;
1402 
1403   SmallVector<OpMethodParameter, 4> paramList;
1404   paramList.emplace_back("::mlir::OpBuilder &", "");
1405   paramList.emplace_back("::mlir::OperationState &", builderOpState);
1406   paramList.emplace_back("::mlir::TypeRange", "resultTypes");
1407   paramList.emplace_back("::mlir::ValueRange", "operands");
1408   // Provide default value for `attributes` when its the last parameter
1409   StringRef attributesDefaultValue = op.getNumVariadicRegions() ? "" : "{}";
1410   paramList.emplace_back("::llvm::ArrayRef<::mlir::NamedAttribute>",
1411                          "attributes", attributesDefaultValue);
1412   if (op.getNumVariadicRegions())
1413     paramList.emplace_back("unsigned", "numRegions");
1414 
1415   auto *m = opClass.addMethodAndPrune("void", "build", OpMethod::MP_Static,
1416                                       std::move(paramList));
1417   // If the builder is redundant, skip generating the method
1418   if (!m)
1419     return;
1420   auto &body = m->body();
1421 
1422   // Operands
1423   if (numVariadicOperands == 0 || numNonVariadicOperands != 0)
1424     body << "  assert(operands.size()"
1425          << (numVariadicOperands != 0 ? " >= " : " == ")
1426          << numNonVariadicOperands
1427          << "u && \"mismatched number of parameters\");\n";
1428   body << "  " << builderOpState << ".addOperands(operands);\n";
1429 
1430   // Attributes
1431   body << "  " << builderOpState << ".addAttributes(attributes);\n";
1432 
1433   // Create the correct number of regions
1434   if (int numRegions = op.getNumRegions()) {
1435     body << llvm::formatv(
1436         "  for (unsigned i = 0; i != {0}; ++i)\n",
1437         (op.getNumVariadicRegions() ? "numRegions" : Twine(numRegions)));
1438     body << "    (void)" << builderOpState << ".addRegion();\n";
1439   }
1440 
1441   // Result types
1442   if (numVariadicResults == 0 || numNonVariadicResults != 0)
1443     body << "  assert(resultTypes.size()"
1444          << (numVariadicResults != 0 ? " >= " : " == ") << numNonVariadicResults
1445          << "u && \"mismatched number of return types\");\n";
1446   body << "  " << builderOpState << ".addTypes(resultTypes);\n";
1447 
1448   // Generate builder that infers type too.
1449   // TODO: Expand to handle regions and successors.
1450   if (canInferType(op) && op.getNumSuccessors() == 0)
1451     genInferredTypeCollectiveParamBuilder();
1452 }
1453 
1454 void OpEmitter::buildParamList(SmallVectorImpl<OpMethodParameter> &paramList,
1455                                SmallVectorImpl<std::string> &resultTypeNames,
1456                                TypeParamKind typeParamKind,
1457                                AttrParamKind attrParamKind) {
1458   resultTypeNames.clear();
1459   auto numResults = op.getNumResults();
1460   resultTypeNames.reserve(numResults);
1461 
1462   paramList.emplace_back("::mlir::OpBuilder &", "odsBuilder");
1463   paramList.emplace_back("::mlir::OperationState &", builderOpState);
1464 
1465   switch (typeParamKind) {
1466   case TypeParamKind::None:
1467     break;
1468   case TypeParamKind::Separate: {
1469     // Add parameters for all return types
1470     for (int i = 0; i < numResults; ++i) {
1471       const auto &result = op.getResult(i);
1472       std::string resultName = std::string(result.name);
1473       if (resultName.empty())
1474         resultName = std::string(formatv("resultType{0}", i));
1475 
1476       StringRef type =
1477           result.isVariadic() ? "::mlir::TypeRange" : "::mlir::Type";
1478       OpMethodParameter::Property properties = OpMethodParameter::PP_None;
1479       if (result.isOptional())
1480         properties = OpMethodParameter::PP_Optional;
1481 
1482       paramList.emplace_back(type, resultName, properties);
1483       resultTypeNames.emplace_back(std::move(resultName));
1484     }
1485   } break;
1486   case TypeParamKind::Collective: {
1487     paramList.emplace_back("::mlir::TypeRange", "resultTypes");
1488     resultTypeNames.push_back("resultTypes");
1489   } break;
1490   }
1491 
1492   // Add parameters for all arguments (operands and attributes).
1493 
1494   int numOperands = 0;
1495   int numAttrs = 0;
1496 
1497   int defaultValuedAttrStartIndex = op.getNumArgs();
1498   if (attrParamKind == AttrParamKind::UnwrappedValue) {
1499     // Calculate the start index from which we can attach default values in the
1500     // builder declaration.
1501     for (int i = op.getNumArgs() - 1; i >= 0; --i) {
1502       auto *namedAttr = op.getArg(i).dyn_cast<tblgen::NamedAttribute *>();
1503       if (!namedAttr || !namedAttr->attr.hasDefaultValue())
1504         break;
1505 
1506       if (!canUseUnwrappedRawValue(namedAttr->attr))
1507         break;
1508 
1509       // Creating an APInt requires us to provide bitwidth, value, and
1510       // signedness, which is complicated compared to others. Similarly
1511       // for APFloat.
1512       // TODO: Adjust the 'returnType' field of such attributes
1513       // to support them.
1514       StringRef retType = namedAttr->attr.getReturnType();
1515       if (retType == "::llvm::APInt" || retType == "::llvm::APFloat")
1516         break;
1517 
1518       defaultValuedAttrStartIndex = i;
1519     }
1520   }
1521 
1522   for (int i = 0, e = op.getNumArgs(); i < e; ++i) {
1523     auto argument = op.getArg(i);
1524     if (argument.is<tblgen::NamedTypeConstraint *>()) {
1525       const auto &operand = op.getOperand(numOperands);
1526       StringRef type =
1527           operand.isVariadic() ? "::mlir::ValueRange" : "::mlir::Value";
1528       OpMethodParameter::Property properties = OpMethodParameter::PP_None;
1529       if (operand.isOptional())
1530         properties = OpMethodParameter::PP_Optional;
1531 
1532       paramList.emplace_back(type, getArgumentName(op, numOperands),
1533                              properties);
1534       ++numOperands;
1535     } else {
1536       const auto &namedAttr = op.getAttribute(numAttrs);
1537       const auto &attr = namedAttr.attr;
1538 
1539       OpMethodParameter::Property properties = OpMethodParameter::PP_None;
1540       if (attr.isOptional())
1541         properties = OpMethodParameter::PP_Optional;
1542 
1543       StringRef type;
1544       switch (attrParamKind) {
1545       case AttrParamKind::WrappedAttr:
1546         type = attr.getStorageType();
1547         break;
1548       case AttrParamKind::UnwrappedValue:
1549         if (canUseUnwrappedRawValue(attr))
1550           type = attr.getReturnType();
1551         else
1552           type = attr.getStorageType();
1553         break;
1554       }
1555 
1556       std::string defaultValue;
1557       // Attach default value if requested and possible.
1558       if (attrParamKind == AttrParamKind::UnwrappedValue &&
1559           i >= defaultValuedAttrStartIndex) {
1560         bool isString = attr.getReturnType() == "::llvm::StringRef";
1561         if (isString)
1562           defaultValue.append("\"");
1563         defaultValue += attr.getDefaultValue();
1564         if (isString)
1565           defaultValue.append("\"");
1566       }
1567       paramList.emplace_back(type, namedAttr.name, defaultValue, properties);
1568       ++numAttrs;
1569     }
1570   }
1571 
1572   /// Insert parameters for each successor.
1573   for (const NamedSuccessor &succ : op.getSuccessors()) {
1574     StringRef type =
1575         succ.isVariadic() ? "::mlir::BlockRange" : "::mlir::Block *";
1576     paramList.emplace_back(type, succ.name);
1577   }
1578 
1579   /// Insert parameters for variadic regions.
1580   for (const NamedRegion &region : op.getRegions())
1581     if (region.isVariadic())
1582       paramList.emplace_back("unsigned",
1583                              llvm::formatv("{0}Count", region.name).str());
1584 }
1585 
1586 void OpEmitter::genCodeForAddingArgAndRegionForBuilder(OpMethodBody &body,
1587                                                        bool isRawValueAttr) {
1588   // Push all operands to the result.
1589   for (int i = 0, e = op.getNumOperands(); i < e; ++i) {
1590     std::string argName = getArgumentName(op, i);
1591     if (op.getOperand(i).isOptional())
1592       body << "  if (" << argName << ")\n  ";
1593     body << "  " << builderOpState << ".addOperands(" << argName << ");\n";
1594   }
1595 
1596   // If the operation has the operand segment size attribute, add it here.
1597   if (op.getTrait("::mlir::OpTrait::AttrSizedOperandSegments")) {
1598     body << "  " << builderOpState
1599          << ".addAttribute(\"operand_segment_sizes\", "
1600             "odsBuilder.getI32VectorAttr({";
1601     interleaveComma(llvm::seq<int>(0, op.getNumOperands()), body, [&](int i) {
1602       if (op.getOperand(i).isOptional())
1603         body << "(" << getArgumentName(op, i) << " ? 1 : 0)";
1604       else if (op.getOperand(i).isVariadic())
1605         body << "static_cast<int32_t>(" << getArgumentName(op, i) << ".size())";
1606       else
1607         body << "1";
1608     });
1609     body << "}));\n";
1610   }
1611 
1612   // Push all attributes to the result.
1613   for (const auto &namedAttr : op.getAttributes()) {
1614     auto &attr = namedAttr.attr;
1615     if (!attr.isDerivedAttr()) {
1616       bool emitNotNullCheck = attr.isOptional();
1617       if (emitNotNullCheck) {
1618         body << formatv("  if ({0}) ", namedAttr.name) << "{\n";
1619       }
1620       if (isRawValueAttr && canUseUnwrappedRawValue(attr)) {
1621         // If this is a raw value, then we need to wrap it in an Attribute
1622         // instance.
1623         FmtContext fctx;
1624         fctx.withBuilder("odsBuilder");
1625 
1626         std::string builderTemplate =
1627             std::string(attr.getConstBuilderTemplate());
1628 
1629         // For StringAttr, its constant builder call will wrap the input in
1630         // quotes, which is correct for normal string literals, but incorrect
1631         // here given we use function arguments. So we need to strip the
1632         // wrapping quotes.
1633         if (StringRef(builderTemplate).contains("\"$0\""))
1634           builderTemplate = replaceAllSubstrs(builderTemplate, "\"$0\"", "$0");
1635 
1636         std::string value =
1637             std::string(tgfmt(builderTemplate, &fctx, namedAttr.name));
1638         body << formatv("  {0}.addAttribute(\"{1}\", {2});\n", builderOpState,
1639                         namedAttr.name, value);
1640       } else {
1641         body << formatv("  {0}.addAttribute(\"{1}\", {1});\n", builderOpState,
1642                         namedAttr.name);
1643       }
1644       if (emitNotNullCheck) {
1645         body << "  }\n";
1646       }
1647     }
1648   }
1649 
1650   // Create the correct number of regions.
1651   for (const NamedRegion &region : op.getRegions()) {
1652     if (region.isVariadic())
1653       body << formatv("  for (unsigned i = 0; i < {0}Count; ++i)\n  ",
1654                       region.name);
1655 
1656     body << "  (void)" << builderOpState << ".addRegion();\n";
1657   }
1658 
1659   // Push all successors to the result.
1660   for (const NamedSuccessor &namedSuccessor : op.getSuccessors()) {
1661     body << formatv("  {0}.addSuccessors({1});\n", builderOpState,
1662                     namedSuccessor.name);
1663   }
1664 }
1665 
1666 void OpEmitter::genCanonicalizerDecls() {
1667   bool hasCanonicalizeMethod = def.getValueAsBit("hasCanonicalizeMethod");
1668   if (hasCanonicalizeMethod) {
1669     // static LogicResult FooOp::
1670     // canonicalize(FooOp op, PatternRewriter &rewriter);
1671     SmallVector<OpMethodParameter, 2> paramList;
1672     paramList.emplace_back(op.getCppClassName(), "op");
1673     paramList.emplace_back("::mlir::PatternRewriter &", "rewriter");
1674     opClass.addMethodAndPrune("::mlir::LogicalResult", "canonicalize",
1675                               OpMethod::MP_StaticDeclaration,
1676                               std::move(paramList));
1677   }
1678 
1679   // We get a prototype for 'getCanonicalizationPatterns' if requested directly
1680   // or if using a 'canonicalize' method.
1681   bool hasCanonicalizer = def.getValueAsBit("hasCanonicalizer");
1682   if (!hasCanonicalizeMethod && !hasCanonicalizer)
1683     return;
1684 
1685   // We get a body for 'getCanonicalizationPatterns' when using a 'canonicalize'
1686   // method, but not implementing 'getCanonicalizationPatterns' manually.
1687   bool hasBody = hasCanonicalizeMethod && !hasCanonicalizer;
1688 
1689   // Add a signature for getCanonicalizationPatterns if implemented by the
1690   // dialect or if synthesized to call 'canonicalize'.
1691   SmallVector<OpMethodParameter, 2> paramList;
1692   paramList.emplace_back("::mlir::RewritePatternSet &", "results");
1693   paramList.emplace_back("::mlir::MLIRContext *", "context");
1694   auto kind = hasBody ? OpMethod::MP_Static : OpMethod::MP_StaticDeclaration;
1695   auto *method = opClass.addMethodAndPrune(
1696       "void", "getCanonicalizationPatterns", kind, std::move(paramList));
1697 
1698   // If synthesizing the method, fill it it.
1699   if (hasBody)
1700     method->body() << "  results.add(canonicalize);\n";
1701 }
1702 
1703 void OpEmitter::genFolderDecls() {
1704   bool hasSingleResult =
1705       op.getNumResults() == 1 && op.getNumVariableLengthResults() == 0;
1706 
1707   if (def.getValueAsBit("hasFolder")) {
1708     if (hasSingleResult) {
1709       opClass.addMethodAndPrune(
1710           "::mlir::OpFoldResult", "fold", OpMethod::MP_Declaration,
1711           "::llvm::ArrayRef<::mlir::Attribute>", "operands");
1712     } else {
1713       SmallVector<OpMethodParameter, 2> paramList;
1714       paramList.emplace_back("::llvm::ArrayRef<::mlir::Attribute>", "operands");
1715       paramList.emplace_back("::llvm::SmallVectorImpl<::mlir::OpFoldResult> &",
1716                              "results");
1717       opClass.addMethodAndPrune("::mlir::LogicalResult", "fold",
1718                                 OpMethod::MP_Declaration, std::move(paramList));
1719     }
1720   }
1721 }
1722 
1723 void OpEmitter::genOpInterfaceMethods(const tblgen::InterfaceTrait *opTrait) {
1724   Interface interface = opTrait->getInterface();
1725 
1726   // Get the set of methods that should always be declared.
1727   auto alwaysDeclaredMethodsVec = opTrait->getAlwaysDeclaredMethods();
1728   llvm::StringSet<> alwaysDeclaredMethods;
1729   alwaysDeclaredMethods.insert(alwaysDeclaredMethodsVec.begin(),
1730                                alwaysDeclaredMethodsVec.end());
1731 
1732   for (const InterfaceMethod &method : interface.getMethods()) {
1733     // Don't declare if the method has a body.
1734     if (method.getBody())
1735       continue;
1736     // Don't declare if the method has a default implementation and the op
1737     // didn't request that it always be declared.
1738     if (method.getDefaultImplementation() &&
1739         !alwaysDeclaredMethods.count(method.getName()))
1740       continue;
1741     genOpInterfaceMethod(method);
1742   }
1743 }
1744 
1745 OpMethod *OpEmitter::genOpInterfaceMethod(const InterfaceMethod &method,
1746                                           bool declaration) {
1747   SmallVector<OpMethodParameter, 4> paramList;
1748   for (const InterfaceMethod::Argument &arg : method.getArguments())
1749     paramList.emplace_back(arg.type, arg.name);
1750 
1751   auto properties = method.isStatic() ? OpMethod::MP_Static : OpMethod::MP_None;
1752   if (declaration)
1753     properties =
1754         static_cast<OpMethod::Property>(properties | OpMethod::MP_Declaration);
1755   return opClass.addMethodAndPrune(method.getReturnType(), method.getName(),
1756                                    properties, std::move(paramList));
1757 }
1758 
1759 void OpEmitter::genOpInterfaceMethods() {
1760   for (const auto &trait : op.getTraits()) {
1761     if (const auto *opTrait = dyn_cast<tblgen::InterfaceTrait>(&trait))
1762       if (opTrait->shouldDeclareMethods())
1763         genOpInterfaceMethods(opTrait);
1764   }
1765 }
1766 
1767 void OpEmitter::genSideEffectInterfaceMethods() {
1768   enum EffectKind { Operand, Result, Symbol, Static };
1769   struct EffectLocation {
1770     /// The effect applied.
1771     SideEffect effect;
1772 
1773     /// The index if the kind is not static.
1774     unsigned index : 30;
1775 
1776     /// The kind of the location.
1777     unsigned kind : 2;
1778   };
1779 
1780   StringMap<SmallVector<EffectLocation, 1>> interfaceEffects;
1781   auto resolveDecorators = [&](Operator::var_decorator_range decorators,
1782                                unsigned index, unsigned kind) {
1783     for (auto decorator : decorators)
1784       if (SideEffect *effect = dyn_cast<SideEffect>(&decorator)) {
1785         opClass.addTrait(effect->getInterfaceTrait());
1786         interfaceEffects[effect->getBaseEffectName()].push_back(
1787             EffectLocation{*effect, index, kind});
1788       }
1789   };
1790 
1791   // Collect effects that were specified via:
1792   /// Traits.
1793   for (const auto &trait : op.getTraits()) {
1794     const auto *opTrait = dyn_cast<tblgen::SideEffectTrait>(&trait);
1795     if (!opTrait)
1796       continue;
1797     auto &effects = interfaceEffects[opTrait->getBaseEffectName()];
1798     for (auto decorator : opTrait->getEffects())
1799       effects.push_back(EffectLocation{cast<SideEffect>(decorator),
1800                                        /*index=*/0, EffectKind::Static});
1801   }
1802   /// Attributes and Operands.
1803   for (unsigned i = 0, operandIt = 0, e = op.getNumArgs(); i != e; ++i) {
1804     Argument arg = op.getArg(i);
1805     if (arg.is<NamedTypeConstraint *>()) {
1806       resolveDecorators(op.getArgDecorators(i), operandIt, EffectKind::Operand);
1807       ++operandIt;
1808       continue;
1809     }
1810     const NamedAttribute *attr = arg.get<NamedAttribute *>();
1811     if (attr->attr.getBaseAttr().isSymbolRefAttr())
1812       resolveDecorators(op.getArgDecorators(i), i, EffectKind::Symbol);
1813   }
1814   /// Results.
1815   for (unsigned i = 0, e = op.getNumResults(); i != e; ++i)
1816     resolveDecorators(op.getResultDecorators(i), i, EffectKind::Result);
1817 
1818   // The code used to add an effect instance.
1819   // {0}: The effect class.
1820   // {1}: Optional value or symbol reference.
1821   // {1}: The resource class.
1822   const char *addEffectCode =
1823       "  effects.emplace_back({0}::get(), {1}{2}::get());\n";
1824 
1825   for (auto &it : interfaceEffects) {
1826     // Generate the 'getEffects' method.
1827     std::string type = llvm::formatv("::mlir::SmallVectorImpl<::mlir::"
1828                                      "SideEffects::EffectInstance<{0}>> &",
1829                                      it.first())
1830                            .str();
1831     auto *getEffects =
1832         opClass.addMethodAndPrune("void", "getEffects", type, "effects");
1833     auto &body = getEffects->body();
1834 
1835     // Add effect instances for each of the locations marked on the operation.
1836     for (auto &location : it.second) {
1837       StringRef effect = location.effect.getName();
1838       StringRef resource = location.effect.getResource();
1839       if (location.kind == EffectKind::Static) {
1840         // A static instance has no attached value.
1841         body << llvm::formatv(addEffectCode, effect, "", resource).str();
1842       } else if (location.kind == EffectKind::Symbol) {
1843         // A symbol reference requires adding the proper attribute.
1844         const auto *attr = op.getArg(location.index).get<NamedAttribute *>();
1845         if (attr->attr.isOptional()) {
1846           body << "  if (auto symbolRef = " << attr->name << "Attr())\n  "
1847                << llvm::formatv(addEffectCode, effect, "symbolRef, ", resource)
1848                       .str();
1849         } else {
1850           body << llvm::formatv(addEffectCode, effect, attr->name + "(), ",
1851                                 resource)
1852                       .str();
1853         }
1854       } else {
1855         // Otherwise this is an operand/result, so we need to attach the Value.
1856         body << "  for (::mlir::Value value : getODS"
1857              << (location.kind == EffectKind::Operand ? "Operands" : "Results")
1858              << "(" << location.index << "))\n  "
1859              << llvm::formatv(addEffectCode, effect, "value, ", resource).str();
1860       }
1861     }
1862   }
1863 }
1864 
1865 void OpEmitter::genTypeInterfaceMethods() {
1866   if (!op.allResultTypesKnown())
1867     return;
1868   // Generate 'inferReturnTypes' method declaration using the interface method
1869   // declared in 'InferTypeOpInterface' op interface.
1870   const auto *trait = dyn_cast<InterfaceTrait>(
1871       op.getTrait("::mlir::InferTypeOpInterface::Trait"));
1872   Interface interface = trait->getInterface();
1873   OpMethod *method = [&]() -> OpMethod * {
1874     for (const InterfaceMethod &interfaceMethod : interface.getMethods()) {
1875       if (interfaceMethod.getName() == "inferReturnTypes") {
1876         return genOpInterfaceMethod(interfaceMethod, /*declaration=*/false);
1877       }
1878     }
1879     assert(0 && "unable to find inferReturnTypes interface method");
1880     return nullptr;
1881   }();
1882   auto &body = method->body();
1883   body << "  inferredReturnTypes.resize(" << op.getNumResults() << ");\n";
1884 
1885   FmtContext fctx;
1886   fctx.withBuilder("odsBuilder");
1887   body << "  ::mlir::Builder odsBuilder(context);\n";
1888 
1889   auto emitType =
1890       [&](const tblgen::Operator::ArgOrType &type) -> OpMethodBody & {
1891     if (type.isArg()) {
1892       auto argIndex = type.getArg();
1893       assert(!op.getArg(argIndex).is<NamedAttribute *>());
1894       auto arg = op.getArgToOperandOrAttribute(argIndex);
1895       if (arg.kind() == Operator::OperandOrAttribute::Kind::Operand)
1896         return body << "operands[" << arg.operandOrAttributeIndex()
1897                     << "].getType()";
1898       return body << "attributes[" << arg.operandOrAttributeIndex()
1899                   << "].getType()";
1900     } else {
1901       return body << tgfmt(*type.getType().getBuilderCall(), &fctx);
1902     }
1903   };
1904 
1905   for (int i = 0, e = op.getNumResults(); i != e; ++i) {
1906     body << "  inferredReturnTypes[" << i << "] = ";
1907     auto types = op.getSameTypeAsResult(i);
1908     emitType(types[0]) << ";\n";
1909     if (types.size() == 1)
1910       continue;
1911     // TODO: We could verify equality here, but skipping that for verification.
1912   }
1913   body << "  return ::mlir::success();";
1914 }
1915 
1916 void OpEmitter::genParser() {
1917   if (!hasStringAttribute(def, "parser") ||
1918       hasStringAttribute(def, "assemblyFormat"))
1919     return;
1920 
1921   SmallVector<OpMethodParameter, 2> paramList;
1922   paramList.emplace_back("::mlir::OpAsmParser &", "parser");
1923   paramList.emplace_back("::mlir::OperationState &", "result");
1924   auto *method =
1925       opClass.addMethodAndPrune("::mlir::ParseResult", "parse",
1926                                 OpMethod::MP_Static, std::move(paramList));
1927 
1928   FmtContext fctx;
1929   fctx.addSubst("cppClass", opClass.getClassName());
1930   auto parser = def.getValueAsString("parser").ltrim().rtrim(" \t\v\f\r");
1931   method->body() << "  " << tgfmt(parser, &fctx);
1932 }
1933 
1934 void OpEmitter::genPrinter() {
1935   if (hasStringAttribute(def, "assemblyFormat"))
1936     return;
1937 
1938   auto valueInit = def.getValueInit("printer");
1939   StringInit *stringInit = dyn_cast<StringInit>(valueInit);
1940   if (!stringInit)
1941     return;
1942 
1943   auto *method =
1944       opClass.addMethodAndPrune("void", "print", "::mlir::OpAsmPrinter &", "p");
1945   FmtContext fctx;
1946   fctx.addSubst("cppClass", opClass.getClassName());
1947   auto printer = stringInit->getValue().ltrim().rtrim(" \t\v\f\r");
1948   method->body() << "  " << tgfmt(printer, &fctx);
1949 }
1950 
1951 void OpEmitter::genVerifier() {
1952   auto *method = opClass.addMethodAndPrune("::mlir::LogicalResult", "verify");
1953   auto &body = method->body();
1954   body << "  if (failed(" << op.getAdaptorName()
1955        << "(*this).verify((*this)->getLoc()))) "
1956        << "return ::mlir::failure();\n";
1957 
1958   auto *valueInit = def.getValueInit("verifier");
1959   StringInit *stringInit = dyn_cast<StringInit>(valueInit);
1960   bool hasCustomVerify = stringInit && !stringInit->getValue().empty();
1961   populateSubstitutions(op, "(*this)->getAttr", "this->getODSOperands",
1962                         "this->getODSResults", verifyCtx);
1963 
1964   genAttributeVerifier(op, "(*this)->getAttr", "emitOpError(",
1965                        /*emitVerificationRequiringOp=*/true, verifyCtx, body);
1966   genOperandResultVerifier(body, op.getOperands(), "operand");
1967   genOperandResultVerifier(body, op.getResults(), "result");
1968 
1969   for (auto &trait : op.getTraits()) {
1970     if (auto *t = dyn_cast<tblgen::PredTrait>(&trait)) {
1971       body << tgfmt("  if (!($0))\n    "
1972                     "return emitOpError(\"failed to verify that $1\");\n",
1973                     &verifyCtx, tgfmt(t->getPredTemplate(), &verifyCtx),
1974                     t->getSummary());
1975     }
1976   }
1977 
1978   genRegionVerifier(body);
1979   genSuccessorVerifier(body);
1980 
1981   if (hasCustomVerify) {
1982     FmtContext fctx;
1983     fctx.addSubst("cppClass", opClass.getClassName());
1984     auto printer = stringInit->getValue().ltrim().rtrim(" \t\v\f\r");
1985     body << "  " << tgfmt(printer, &fctx);
1986   } else {
1987     body << "  return ::mlir::success();\n";
1988   }
1989 }
1990 
1991 void OpEmitter::genOperandResultVerifier(OpMethodBody &body,
1992                                          Operator::value_range values,
1993                                          StringRef valueKind) {
1994   FmtContext fctx;
1995 
1996   body << "  {\n";
1997   body << "    unsigned index = 0; (void)index;\n";
1998 
1999   for (auto staticValue : llvm::enumerate(values)) {
2000     bool hasPredicate = staticValue.value().hasPredicate();
2001     bool isOptional = staticValue.value().isOptional();
2002     if (!hasPredicate && !isOptional)
2003       continue;
2004     body << formatv("    auto valueGroup{2} = getODS{0}{1}s({2});\n",
2005                     // Capitalize the first letter to match the function name
2006                     valueKind.substr(0, 1).upper(), valueKind.substr(1),
2007                     staticValue.index());
2008 
2009     // If the constraint is optional check that the value group has at most 1
2010     // value.
2011     if (isOptional) {
2012       body << formatv("    if (valueGroup{0}.size() > 1)\n"
2013                       "      return emitOpError(\"{1} group starting at #\") "
2014                       "<< index << \" requires 0 or 1 element, but found \" << "
2015                       "valueGroup{0}.size();\n",
2016                       staticValue.index(), valueKind);
2017     }
2018 
2019     // Otherwise, if there is no predicate there is nothing left to do.
2020     if (!hasPredicate)
2021       continue;
2022     // Emit a loop to check all the dynamic values in the pack.
2023     StringRef constraintFn = staticVerifierEmitter.getTypeConstraintFn(
2024         staticValue.value().constraint);
2025     body << "    for (::mlir::Value v : valueGroup" << staticValue.index()
2026          << ") {\n"
2027          << "      if (::mlir::failed(" << constraintFn
2028          << "(getOperation(), v.getType(), \"" << valueKind << "\", index)))\n"
2029          << "        return ::mlir::failure();\n"
2030          << "      ++index;\n"
2031          << "    }\n";
2032   }
2033 
2034   body << "  }\n";
2035 }
2036 
2037 void OpEmitter::genRegionVerifier(OpMethodBody &body) {
2038   // If we have no regions, there is nothing more to do.
2039   unsigned numRegions = op.getNumRegions();
2040   if (numRegions == 0)
2041     return;
2042 
2043   body << "{\n";
2044   body << "    unsigned index = 0; (void)index;\n";
2045 
2046   for (unsigned i = 0; i < numRegions; ++i) {
2047     const auto &region = op.getRegion(i);
2048     if (region.constraint.getPredicate().isNull())
2049       continue;
2050 
2051     body << "    for (::mlir::Region &region : ";
2052     body << formatv(region.isVariadic()
2053                         ? "{0}()"
2054                         : "::mlir::MutableArrayRef<::mlir::Region>((*this)"
2055                           "->getRegion({1}))",
2056                     region.name, i);
2057     body << ") {\n";
2058     auto constraint = tgfmt(region.constraint.getConditionTemplate(),
2059                             &verifyCtx.withSelf("region"))
2060                           .str();
2061 
2062     body << formatv("      (void)region;\n"
2063                     "      if (!({0})) {\n        "
2064                     "return emitOpError(\"region #\") << index << \" {1}"
2065                     "failed to "
2066                     "verify constraint: {2}\";\n      }\n",
2067                     constraint,
2068                     region.name.empty() ? "" : "('" + region.name + "') ",
2069                     region.constraint.getSummary())
2070          << "      ++index;\n"
2071          << "    }\n";
2072   }
2073   body << "  }\n";
2074 }
2075 
2076 void OpEmitter::genSuccessorVerifier(OpMethodBody &body) {
2077   // If we have no successors, there is nothing more to do.
2078   unsigned numSuccessors = op.getNumSuccessors();
2079   if (numSuccessors == 0)
2080     return;
2081 
2082   body << "{\n";
2083   body << "    unsigned index = 0; (void)index;\n";
2084 
2085   for (unsigned i = 0; i < numSuccessors; ++i) {
2086     const auto &successor = op.getSuccessor(i);
2087     if (successor.constraint.getPredicate().isNull())
2088       continue;
2089 
2090     if (successor.isVariadic()) {
2091       body << formatv("    for (::mlir::Block *successor : {0}()) {\n",
2092                       successor.name);
2093     } else {
2094       body << "    {\n";
2095       body << formatv("      ::mlir::Block *successor = {0}();\n",
2096                       successor.name);
2097     }
2098     auto constraint = tgfmt(successor.constraint.getConditionTemplate(),
2099                             &verifyCtx.withSelf("successor"))
2100                           .str();
2101 
2102     body << formatv("      (void)successor;\n"
2103                     "      if (!({0})) {\n        "
2104                     "return emitOpError(\"successor #\") << index << \"('{1}') "
2105                     "failed to "
2106                     "verify constraint: {2}\";\n      }\n",
2107                     constraint, successor.name,
2108                     successor.constraint.getSummary())
2109          << "      ++index;\n"
2110          << "    }\n";
2111   }
2112   body << "  }\n";
2113 }
2114 
2115 /// Add a size count trait to the given operation class.
2116 static void addSizeCountTrait(OpClass &opClass, StringRef traitKind,
2117                               int numTotal, int numVariadic) {
2118   if (numVariadic != 0) {
2119     if (numTotal == numVariadic)
2120       opClass.addTrait("::mlir::OpTrait::Variadic" + traitKind + "s");
2121     else
2122       opClass.addTrait("::mlir::OpTrait::AtLeastN" + traitKind + "s<" +
2123                        Twine(numTotal - numVariadic) + ">::Impl");
2124     return;
2125   }
2126   switch (numTotal) {
2127   case 0:
2128     opClass.addTrait("::mlir::OpTrait::Zero" + traitKind);
2129     break;
2130   case 1:
2131     opClass.addTrait("::mlir::OpTrait::One" + traitKind);
2132     break;
2133   default:
2134     opClass.addTrait("::mlir::OpTrait::N" + traitKind + "s<" + Twine(numTotal) +
2135                      ">::Impl");
2136     break;
2137   }
2138 }
2139 
2140 void OpEmitter::genTraits() {
2141   // Add region size trait.
2142   unsigned numRegions = op.getNumRegions();
2143   unsigned numVariadicRegions = op.getNumVariadicRegions();
2144   addSizeCountTrait(opClass, "Region", numRegions, numVariadicRegions);
2145 
2146   // Add result size traits.
2147   int numResults = op.getNumResults();
2148   int numVariadicResults = op.getNumVariableLengthResults();
2149   addSizeCountTrait(opClass, "Result", numResults, numVariadicResults);
2150 
2151   // For single result ops with a known specific type, generate a OneTypedResult
2152   // trait.
2153   if (numResults == 1 && numVariadicResults == 0) {
2154     auto cppName = op.getResults().begin()->constraint.getCPPClassName();
2155     opClass.addTrait("::mlir::OpTrait::OneTypedResult<" + cppName + ">::Impl");
2156   }
2157 
2158   // Add successor size trait.
2159   unsigned numSuccessors = op.getNumSuccessors();
2160   unsigned numVariadicSuccessors = op.getNumVariadicSuccessors();
2161   addSizeCountTrait(opClass, "Successor", numSuccessors, numVariadicSuccessors);
2162 
2163   // Add variadic size trait and normal op traits.
2164   int numOperands = op.getNumOperands();
2165   int numVariadicOperands = op.getNumVariableLengthOperands();
2166 
2167   // Add operand size trait.
2168   if (numVariadicOperands != 0) {
2169     if (numOperands == numVariadicOperands)
2170       opClass.addTrait("::mlir::OpTrait::VariadicOperands");
2171     else
2172       opClass.addTrait("::mlir::OpTrait::AtLeastNOperands<" +
2173                        Twine(numOperands - numVariadicOperands) + ">::Impl");
2174   } else {
2175     switch (numOperands) {
2176     case 0:
2177       opClass.addTrait("::mlir::OpTrait::ZeroOperands");
2178       break;
2179     case 1:
2180       opClass.addTrait("::mlir::OpTrait::OneOperand");
2181       break;
2182     default:
2183       opClass.addTrait("::mlir::OpTrait::NOperands<" + Twine(numOperands) +
2184                        ">::Impl");
2185       break;
2186     }
2187   }
2188 
2189   // Add the native and interface traits.
2190   for (const auto &trait : op.getTraits()) {
2191     if (auto opTrait = dyn_cast<tblgen::NativeTrait>(&trait))
2192       opClass.addTrait(opTrait->getFullyQualifiedTraitName());
2193     else if (auto opTrait = dyn_cast<tblgen::InterfaceTrait>(&trait))
2194       opClass.addTrait(opTrait->getFullyQualifiedTraitName());
2195   }
2196 }
2197 
2198 void OpEmitter::genOpNameGetter() {
2199   auto *method = opClass.addMethodAndPrune(
2200       "::llvm::StringLiteral", "getOperationName",
2201       OpMethod::Property(OpMethod::MP_Static | OpMethod::MP_Constexpr));
2202   method->body() << "  return ::llvm::StringLiteral(\"" << op.getOperationName()
2203                  << "\");";
2204 }
2205 
2206 void OpEmitter::genOpAsmInterface() {
2207   // If the user only has one results or specifically added the Asm trait,
2208   // then don't generate it for them. We specifically only handle multi result
2209   // operations, because the name of a single result in the common case is not
2210   // interesting(generally 'result'/'output'/etc.).
2211   // TODO: We could also add a flag to allow operations to opt in to this
2212   // generation, even if they only have a single operation.
2213   int numResults = op.getNumResults();
2214   if (numResults <= 1 || op.getTrait("::mlir::OpAsmOpInterface::Trait"))
2215     return;
2216 
2217   SmallVector<StringRef, 4> resultNames(numResults);
2218   for (int i = 0; i != numResults; ++i)
2219     resultNames[i] = op.getResultName(i);
2220 
2221   // Don't add the trait if none of the results have a valid name.
2222   if (llvm::all_of(resultNames, [](StringRef name) { return name.empty(); }))
2223     return;
2224   opClass.addTrait("::mlir::OpAsmOpInterface::Trait");
2225 
2226   // Generate the right accessor for the number of results.
2227   auto *method = opClass.addMethodAndPrune(
2228       "void", "getAsmResultNames", "::mlir::OpAsmSetValueNameFn", "setNameFn");
2229   auto &body = method->body();
2230   for (int i = 0; i != numResults; ++i) {
2231     body << "  auto resultGroup" << i << " = getODSResults(" << i << ");\n"
2232          << "  if (!llvm::empty(resultGroup" << i << "))\n"
2233          << "    setNameFn(*resultGroup" << i << ".begin(), \""
2234          << resultNames[i] << "\");\n";
2235   }
2236 }
2237 
2238 //===----------------------------------------------------------------------===//
2239 // OpOperandAdaptor emitter
2240 //===----------------------------------------------------------------------===//
2241 
2242 namespace {
2243 // Helper class to emit Op operand adaptors to an output stream.  Operand
2244 // adaptors are wrappers around ArrayRef<Value> that provide named operand
2245 // getters identical to those defined in the Op.
2246 class OpOperandAdaptorEmitter {
2247 public:
2248   static void emitDecl(const Operator &op, raw_ostream &os);
2249   static void emitDef(const Operator &op, raw_ostream &os);
2250 
2251 private:
2252   explicit OpOperandAdaptorEmitter(const Operator &op);
2253 
2254   // Add verification function. This generates a verify method for the adaptor
2255   // which verifies all the op-independent attribute constraints.
2256   void addVerification();
2257 
2258   const Operator &op;
2259   Class adaptor;
2260 };
2261 } // end namespace
2262 
2263 OpOperandAdaptorEmitter::OpOperandAdaptorEmitter(const Operator &op)
2264     : op(op), adaptor(op.getAdaptorName()) {
2265   adaptor.newField("::mlir::ValueRange", "odsOperands");
2266   adaptor.newField("::mlir::DictionaryAttr", "odsAttrs");
2267   adaptor.newField("::mlir::RegionRange", "odsRegions");
2268   const auto *attrSizedOperands =
2269       op.getTrait("::mlir::OpTrait::AttrSizedOperandSegments");
2270   {
2271     SmallVector<OpMethodParameter, 2> paramList;
2272     paramList.emplace_back("::mlir::ValueRange", "values");
2273     paramList.emplace_back("::mlir::DictionaryAttr", "attrs",
2274                            attrSizedOperands ? "" : "nullptr");
2275     paramList.emplace_back("::mlir::RegionRange", "regions", "{}");
2276     auto *constructor = adaptor.addConstructorAndPrune(std::move(paramList));
2277 
2278     constructor->addMemberInitializer("odsOperands", "values");
2279     constructor->addMemberInitializer("odsAttrs", "attrs");
2280     constructor->addMemberInitializer("odsRegions", "regions");
2281   }
2282 
2283   {
2284     auto *constructor = adaptor.addConstructorAndPrune(
2285         llvm::formatv("{0}&", op.getCppClassName()).str(), "op");
2286     constructor->addMemberInitializer("odsOperands", "op->getOperands()");
2287     constructor->addMemberInitializer("odsAttrs", "op->getAttrDictionary()");
2288     constructor->addMemberInitializer("odsRegions", "op->getRegions()");
2289   }
2290 
2291   {
2292     auto *m = adaptor.addMethodAndPrune("::mlir::ValueRange", "getOperands");
2293     m->body() << "  return odsOperands;";
2294   }
2295   std::string sizeAttrInit =
2296       formatv(adapterSegmentSizeAttrInitCode, "operand_segment_sizes");
2297   generateNamedOperandGetters(op, adaptor, sizeAttrInit,
2298                               /*rangeType=*/"::mlir::ValueRange",
2299                               /*rangeBeginCall=*/"odsOperands.begin()",
2300                               /*rangeSizeCall=*/"odsOperands.size()",
2301                               /*getOperandCallPattern=*/"odsOperands[{0}]");
2302 
2303   FmtContext fctx;
2304   fctx.withBuilder("::mlir::Builder(odsAttrs.getContext())");
2305 
2306   auto emitAttr = [&](StringRef name, Attribute attr) {
2307     auto &body = adaptor.addMethodAndPrune(attr.getStorageType(), name)->body();
2308     body << "  assert(odsAttrs && \"no attributes when constructing adapter\");"
2309          << "\n  " << attr.getStorageType() << " attr = "
2310          << "odsAttrs.get(\"" << name << "\").";
2311     if (attr.hasDefaultValue() || attr.isOptional())
2312       body << "dyn_cast_or_null<";
2313     else
2314       body << "cast<";
2315     body << attr.getStorageType() << ">();\n";
2316 
2317     if (attr.hasDefaultValue()) {
2318       // Use the default value if attribute is not set.
2319       // TODO: this is inefficient, we are recreating the attribute for every
2320       // call. This should be set instead.
2321       std::string defaultValue = std::string(
2322           tgfmt(attr.getConstBuilderTemplate(), &fctx, attr.getDefaultValue()));
2323       body << "  if (!attr)\n    attr = " << defaultValue << ";\n";
2324     }
2325     body << "  return attr;\n";
2326   };
2327 
2328   {
2329     auto *m =
2330         adaptor.addMethodAndPrune("::mlir::DictionaryAttr", "getAttributes");
2331     m->body() << "  return odsAttrs;";
2332   }
2333   for (auto &namedAttr : op.getAttributes()) {
2334     const auto &name = namedAttr.name;
2335     const auto &attr = namedAttr.attr;
2336     if (!attr.isDerivedAttr())
2337       emitAttr(name, attr);
2338   }
2339 
2340   unsigned numRegions = op.getNumRegions();
2341   if (numRegions > 0) {
2342     auto *m = adaptor.addMethodAndPrune("::mlir::RegionRange", "getRegions");
2343     m->body() << "  return odsRegions;";
2344   }
2345   for (unsigned i = 0; i < numRegions; ++i) {
2346     const auto &region = op.getRegion(i);
2347     if (region.name.empty())
2348       continue;
2349 
2350     // Generate the accessors for a variadic region.
2351     if (region.isVariadic()) {
2352       auto *m = adaptor.addMethodAndPrune("::mlir::RegionRange", region.name);
2353       m->body() << formatv("  return odsRegions.drop_front({0});", i);
2354       continue;
2355     }
2356 
2357     auto *m = adaptor.addMethodAndPrune("::mlir::Region &", region.name);
2358     m->body() << formatv("  return *odsRegions[{0}];", i);
2359   }
2360 
2361   // Add verification function.
2362   addVerification();
2363 }
2364 
2365 void OpOperandAdaptorEmitter::addVerification() {
2366   auto *method = adaptor.addMethodAndPrune("::mlir::LogicalResult", "verify",
2367                                            "::mlir::Location", "loc");
2368   auto &body = method->body();
2369 
2370   const char *checkAttrSizedValueSegmentsCode = R"(
2371   {
2372     auto sizeAttr = odsAttrs.get("{0}").cast<::mlir::DenseIntElementsAttr>();
2373     auto numElements = sizeAttr.getType().cast<::mlir::ShapedType>().getNumElements();
2374     if (numElements != {1})
2375       return emitError(loc, "'{0}' attribute for specifying {2} segments "
2376                        "must have {1} elements, but got ") << numElements;
2377   }
2378   )";
2379 
2380   // Verify a few traits first so that we can use
2381   // getODSOperands()/getODSResults() in the rest of the verifier.
2382   for (auto &trait : op.getTraits()) {
2383     if (auto *t = dyn_cast<tblgen::NativeTrait>(&trait)) {
2384       if (t->getFullyQualifiedTraitName() ==
2385           "::mlir::OpTrait::AttrSizedOperandSegments") {
2386         body << formatv(checkAttrSizedValueSegmentsCode,
2387                         "operand_segment_sizes", op.getNumOperands(),
2388                         "operand");
2389       } else if (t->getFullyQualifiedTraitName() ==
2390                  "::mlir::OpTrait::AttrSizedResultSegments") {
2391         body << formatv(checkAttrSizedValueSegmentsCode, "result_segment_sizes",
2392                         op.getNumResults(), "result");
2393       }
2394     }
2395   }
2396 
2397   FmtContext verifyCtx;
2398   populateSubstitutions(op, "odsAttrs.get", "getODSOperands",
2399                         "<no results should be generated>", verifyCtx);
2400   genAttributeVerifier(op, "odsAttrs.get",
2401                        Twine("emitError(loc, \"'") + op.getOperationName() +
2402                            "' op \"",
2403                        /*emitVerificationRequiringOp*/ false, verifyCtx, body);
2404 
2405   body << "  return ::mlir::success();";
2406 }
2407 
2408 void OpOperandAdaptorEmitter::emitDecl(const Operator &op, raw_ostream &os) {
2409   OpOperandAdaptorEmitter(op).adaptor.writeDeclTo(os);
2410 }
2411 
2412 void OpOperandAdaptorEmitter::emitDef(const Operator &op, raw_ostream &os) {
2413   OpOperandAdaptorEmitter(op).adaptor.writeDefTo(os);
2414 }
2415 
2416 // Emits the opcode enum and op classes.
2417 static void emitOpClasses(const RecordKeeper &recordKeeper,
2418                           const std::vector<Record *> &defs, raw_ostream &os,
2419                           bool emitDecl) {
2420   // First emit forward declaration for each class, this allows them to refer
2421   // to each others in traits for example.
2422   if (emitDecl) {
2423     os << "#if defined(GET_OP_CLASSES) || defined(GET_OP_FWD_DEFINES)\n";
2424     os << "#undef GET_OP_FWD_DEFINES\n";
2425     for (auto *def : defs) {
2426       Operator op(*def);
2427       NamespaceEmitter emitter(os, op.getCppNamespace());
2428       os << "class " << op.getCppClassName() << ";\n";
2429     }
2430     os << "#endif\n\n";
2431   }
2432 
2433   IfDefScope scope("GET_OP_CLASSES", os);
2434   if (defs.empty())
2435     return;
2436 
2437   // Generate all of the locally instantiated methods first.
2438   StaticVerifierFunctionEmitter staticVerifierEmitter(recordKeeper, defs, os,
2439                                                       emitDecl);
2440   for (auto *def : defs) {
2441     Operator op(*def);
2442     NamespaceEmitter emitter(os, op.getCppNamespace());
2443     if (emitDecl) {
2444       os << formatv(opCommentHeader, op.getQualCppClassName(), "declarations");
2445       OpOperandAdaptorEmitter::emitDecl(op, os);
2446       OpEmitter::emitDecl(op, os, staticVerifierEmitter);
2447     } else {
2448       os << formatv(opCommentHeader, op.getQualCppClassName(), "definitions");
2449       OpOperandAdaptorEmitter::emitDef(op, os);
2450       OpEmitter::emitDef(op, os, staticVerifierEmitter);
2451     }
2452   }
2453 }
2454 
2455 // Emits a comma-separated list of the ops.
2456 static void emitOpList(const std::vector<Record *> &defs, raw_ostream &os) {
2457   IfDefScope scope("GET_OP_LIST", os);
2458 
2459   interleave(
2460       // TODO: We are constructing the Operator wrapper instance just for
2461       // getting it's qualified class name here. Reduce the overhead by having a
2462       // lightweight version of Operator class just for that purpose.
2463       defs, [&os](Record *def) { os << Operator(def).getQualCppClassName(); },
2464       [&os]() { os << ",\n"; });
2465 }
2466 
2467 static bool emitOpDecls(const RecordKeeper &recordKeeper, raw_ostream &os) {
2468   emitSourceFileHeader("Op Declarations", os);
2469 
2470   std::vector<Record *> defs = getRequestedOpDefinitions(recordKeeper);
2471   emitOpClasses(recordKeeper, defs, os, /*emitDecl=*/true);
2472 
2473   return false;
2474 }
2475 
2476 static bool emitOpDefs(const RecordKeeper &recordKeeper, raw_ostream &os) {
2477   emitSourceFileHeader("Op Definitions", os);
2478 
2479   std::vector<Record *> defs = getRequestedOpDefinitions(recordKeeper);
2480   emitOpList(defs, os);
2481   emitOpClasses(recordKeeper, defs, os, /*emitDecl=*/false);
2482 
2483   return false;
2484 }
2485 
2486 static mlir::GenRegistration
2487     genOpDecls("gen-op-decls", "Generate op declarations",
2488                [](const RecordKeeper &records, raw_ostream &os) {
2489                  return emitOpDecls(records, os);
2490                });
2491 
2492 static mlir::GenRegistration genOpDefs("gen-op-defs", "Generate op definitions",
2493                                        [](const RecordKeeper &records,
2494                                           raw_ostream &os) {
2495                                          return emitOpDefs(records, os);
2496                                        });
2497