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