MLIR  16.0.0git
Operator.cpp
Go to the documentation of this file.
1 //===- Operator.cpp - Operator class --------------------------------------===//
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 // Operator wrapper to simplify using TableGen Record defining a MLIR Op.
10 //
11 //===----------------------------------------------------------------------===//
12 
13 #include "mlir/TableGen/Operator.h"
15 #include "mlir/TableGen/Trait.h"
16 #include "mlir/TableGen/Type.h"
17 #include "llvm/ADT/EquivalenceClasses.h"
18 #include "llvm/ADT/STLExtras.h"
19 #include "llvm/ADT/Sequence.h"
20 #include "llvm/ADT/SmallPtrSet.h"
21 #include "llvm/ADT/StringExtras.h"
22 #include "llvm/ADT/TypeSwitch.h"
23 #include "llvm/Support/Debug.h"
24 #include "llvm/Support/ErrorHandling.h"
25 #include "llvm/Support/FormatVariadic.h"
26 #include "llvm/TableGen/Error.h"
27 #include "llvm/TableGen/Record.h"
28 
29 #define DEBUG_TYPE "mlir-tblgen-operator"
30 
31 using namespace mlir;
32 using namespace mlir::tblgen;
33 
34 using llvm::DagInit;
35 using llvm::DefInit;
36 using llvm::Record;
37 
38 Operator::Operator(const llvm::Record &def)
39  : dialect(def.getValueAsDef("opDialect")), def(def) {
40  // The first `_` in the op's TableGen def name is treated as separating the
41  // dialect prefix and the op class name. The dialect prefix will be ignored if
42  // not empty. Otherwise, if def name starts with a `_`, the `_` is considered
43  // as part of the class name.
44  StringRef prefix;
45  std::tie(prefix, cppClassName) = def.getName().split('_');
46  if (prefix.empty()) {
47  // Class name with a leading underscore and without dialect prefix
48  cppClassName = def.getName();
49  } else if (cppClassName.empty()) {
50  // Class name without dialect prefix
51  cppClassName = prefix;
52  }
53 
54  cppNamespace = def.getValueAsString("cppNamespace");
55 
56  populateOpStructure();
58 }
59 
60 std::string Operator::getOperationName() const {
61  auto prefix = dialect.getName();
62  auto opName = def.getValueAsString("opName");
63  if (prefix.empty())
64  return std::string(opName);
65  return std::string(llvm::formatv("{0}.{1}", prefix, opName));
66 }
67 
68 std::string Operator::getAdaptorName() const {
69  return std::string(llvm::formatv("{0}Adaptor", getCppClassName()));
70 }
71 
73  // Check that the name of arguments/results/regions/successors don't overlap.
74  DenseMap<StringRef, StringRef> existingNames;
75  auto checkName = [&](StringRef name, StringRef entity) {
76  if (name.empty())
77  return;
78  auto insertion = existingNames.insert({name, entity});
79  if (insertion.second)
80  return;
81  if (entity == insertion.first->second)
82  PrintFatalError(getLoc(), "op has a conflict with two " + entity +
83  " having the same name '" + name + "'");
84  PrintFatalError(getLoc(), "op has a conflict with " +
85  insertion.first->second + " and " + entity +
86  " both having an entry with the name '" +
87  name + "'");
88  };
89  // Check operands amongst themselves.
90  for (int i : llvm::seq<int>(0, getNumOperands()))
91  checkName(getOperand(i).name, "operands");
92 
93  // Check results amongst themselves and against operands.
94  for (int i : llvm::seq<int>(0, getNumResults()))
95  checkName(getResult(i).name, "results");
96 
97  // Check regions amongst themselves and against operands and results.
98  for (int i : llvm::seq<int>(0, getNumRegions()))
99  checkName(getRegion(i).name, "regions");
100 
101  // Check successors amongst themselves and against operands, results, and
102  // regions.
103  for (int i : llvm::seq<int>(0, getNumSuccessors()))
104  checkName(getSuccessor(i).name, "successors");
105 }
106 
107 StringRef Operator::getDialectName() const { return dialect.getName(); }
108 
109 StringRef Operator::getCppClassName() const { return cppClassName; }
110 
111 std::string Operator::getQualCppClassName() const {
112  if (cppNamespace.empty())
113  return std::string(cppClassName);
114  return std::string(llvm::formatv("{0}::{1}", cppNamespace, cppClassName));
115 }
116 
117 StringRef Operator::getCppNamespace() const { return cppNamespace; }
118 
120  DagInit *results = def.getValueAsDag("results");
121  return results->getNumArgs();
122 }
123 
125  constexpr auto attr = "extraClassDeclaration";
126  if (def.isValueUnset(attr))
127  return {};
128  return def.getValueAsString(attr);
129 }
130 
132  constexpr auto attr = "extraClassDefinition";
133  if (def.isValueUnset(attr))
134  return {};
135  return def.getValueAsString(attr);
136 }
137 
138 const llvm::Record &Operator::getDef() const { return def; }
139 
141  return def.getValueAsBit("skipDefaultBuilders");
142 }
143 
145  return results.begin();
146 }
147 
149  return results.end();
150 }
151 
153  return {result_begin(), result_end()};
154 }
155 
157  DagInit *results = def.getValueAsDag("results");
158  return TypeConstraint(cast<DefInit>(results->getArg(index)));
159 }
160 
161 StringRef Operator::getResultName(int index) const {
162  DagInit *results = def.getValueAsDag("results");
163  return results->getArgNameStr(index);
164 }
165 
167  Record *result =
168  cast<DefInit>(def.getValueAsDag("results")->getArg(index))->getDef();
169  if (!result->isSubClassOf("OpVariable"))
170  return var_decorator_range(nullptr, nullptr);
171  return *result->getValueAsListInit("decorators");
172 }
173 
175  return llvm::count_if(results, [](const NamedTypeConstraint &c) {
176  return c.constraint.isVariableLength();
177  });
178 }
179 
181  return llvm::count_if(operands, [](const NamedTypeConstraint &c) {
182  return c.constraint.isVariableLength();
183  });
184 }
185 
187  return getNumArgs() == 1 && getArg(0).is<NamedTypeConstraint *>() &&
188  getOperand(0).isVariadic();
189 }
190 
191 Operator::arg_iterator Operator::arg_begin() const { return arguments.begin(); }
192 
193 Operator::arg_iterator Operator::arg_end() const { return arguments.end(); }
194 
196  return {arg_begin(), arg_end()};
197 }
198 
199 StringRef Operator::getArgName(int index) const {
200  DagInit *argumentValues = def.getValueAsDag("arguments");
201  return argumentValues->getArgNameStr(index);
202 }
203 
205  Record *arg =
206  cast<DefInit>(def.getValueAsDag("arguments")->getArg(index))->getDef();
207  if (!arg->isSubClassOf("OpVariable"))
208  return var_decorator_range(nullptr, nullptr);
209  return *arg->getValueAsListInit("decorators");
210 }
211 
212 const Trait *Operator::getTrait(StringRef trait) const {
213  for (const auto &t : traits) {
214  if (const auto *traitDef = dyn_cast<NativeTrait>(&t)) {
215  if (traitDef->getFullyQualifiedTraitName() == trait)
216  return traitDef;
217  } else if (const auto *traitDef = dyn_cast<InternalTrait>(&t)) {
218  if (traitDef->getFullyQualifiedTraitName() == trait)
219  return traitDef;
220  } else if (const auto *traitDef = dyn_cast<InterfaceTrait>(&t)) {
221  if (traitDef->getFullyQualifiedTraitName() == trait)
222  return traitDef;
223  }
224  }
225  return nullptr;
226 }
227 
229  return regions.begin();
230 }
232  return regions.end();
233 }
236  return {region_begin(), region_end()};
237 }
238 
239 unsigned Operator::getNumRegions() const { return regions.size(); }
240 
241 const NamedRegion &Operator::getRegion(unsigned index) const {
242  return regions[index];
243 }
244 
246  return llvm::count_if(regions,
247  [](const NamedRegion &c) { return c.isVariadic(); });
248 }
249 
251  return successors.begin();
252 }
254  return successors.end();
255 }
258  return {successor_begin(), successor_end()};
259 }
260 
261 unsigned Operator::getNumSuccessors() const { return successors.size(); }
262 
263 const NamedSuccessor &Operator::getSuccessor(unsigned index) const {
264  return successors[index];
265 }
266 
268  return llvm::count_if(successors,
269  [](const NamedSuccessor &c) { return c.isVariadic(); });
270 }
271 
273  return traits.begin();
274 }
276  return traits.end();
277 }
279  return {trait_begin(), trait_end()};
280 }
281 
283  return attributes.begin();
284 }
286  return attributes.end();
287 }
290  return {attribute_begin(), attribute_end()};
291 }
292 
294  return operands.begin();
295 }
297  return operands.end();
298 }
300  return {operand_begin(), operand_end()};
301 }
302 
303 auto Operator::getArg(int index) const -> Argument { return arguments[index]; }
304 
305 // Mapping from result index to combined argument and result index. Arguments
306 // are indexed to match getArg index, while the result indexes are mapped to
307 // avoid overlap.
308 static int resultIndex(int i) { return -1 - i; }
309 
310 bool Operator::isVariadic() const {
311  return any_of(llvm::concat<const NamedTypeConstraint>(operands, results),
312  [](const NamedTypeConstraint &op) { return op.isVariadic(); });
313 }
314 
315 void Operator::populateTypeInferenceInfo(
316  const llvm::StringMap<int> &argumentsAndResultsIndex) {
317  // If the type inference op interface is not registered, then do not attempt
318  // to determine if the result types an be inferred.
319  auto &recordKeeper = def.getRecords();
320  auto *inferTrait = recordKeeper.getDef(inferTypeOpInterface);
321  allResultsHaveKnownTypes = false;
322  if (!inferTrait)
323  return;
324 
325  // If there are no results, the skip this else the build method generated
326  // overlaps with another autogenerated builder.
327  if (getNumResults() == 0)
328  return;
329 
330  // Skip ops with variadic or optional results.
331  if (getNumVariableLengthResults() > 0)
332  return;
333 
334  // Skip cases currently being custom generated.
335  // TODO: Remove special cases.
336  if (getTrait("::mlir::OpTrait::SameOperandsAndResultType")) {
337  // Check for a non-variable length operand to use as the type anchor.
338  auto *operandI = llvm::find_if(arguments, [](const Argument &arg) {
339  NamedTypeConstraint *operand = arg.dyn_cast<NamedTypeConstraint *>();
340  return operand && !operand->isVariableLength();
341  });
342  if (operandI == arguments.end())
343  return;
344 
345  // Map each of the result types to the anchor operation.
346  int operandIdx = operandI - arguments.begin();
347  resultTypeMapping.resize(getNumResults());
348  for (int i = 0; i < getNumResults(); ++i)
349  resultTypeMapping[i].emplace_back(operandIdx);
350 
351  allResultsHaveKnownTypes = true;
352  traits.push_back(Trait::create(inferTrait->getDefInit()));
353  return;
354  }
355 
356  // We create equivalence classes of argument/result types where arguments
357  // and results are mapped into the same index space and indices corresponding
358  // to the same type are in the same equivalence class.
359  llvm::EquivalenceClasses<int> ecs;
360  resultTypeMapping.resize(getNumResults());
361  // Captures the argument whose type matches a given result type. Preference
362  // towards capturing operands first before attributes.
363  auto captureMapping = [&](int i) {
364  bool found = false;
365  ecs.insert(resultIndex(i));
366  auto mi = ecs.findLeader(resultIndex(i));
367  for (auto me = ecs.member_end(); mi != me; ++mi) {
368  if (*mi < 0) {
369  auto tc = getResultTypeConstraint(i);
370  if (tc.getBuilderCall()) {
371  resultTypeMapping[i].emplace_back(tc);
372  found = true;
373  }
374  continue;
375  }
376 
377  resultTypeMapping[i].emplace_back(*mi);
378  found = true;
379  }
380  return found;
381  };
382 
383  for (const Trait &trait : traits) {
384  const llvm::Record &def = trait.getDef();
385  // If the infer type op interface was manually added, then treat it as
386  // intention that the op needs special handling.
387  // TODO: Reconsider whether to always generate, this is more conservative
388  // and keeps existing behavior so starting that way for now.
389  if (def.isSubClassOf(
390  llvm::formatv("{0}::Trait", inferTypeOpInterface).str()))
391  return;
392  if (const auto *traitDef = dyn_cast<InterfaceTrait>(&trait))
393  if (&traitDef->getDef() == inferTrait)
394  return;
395 
396  if (!def.isSubClassOf("AllTypesMatch"))
397  continue;
398 
399  auto values = def.getValueAsListOfStrings("values");
400  auto root = argumentsAndResultsIndex.lookup(values.front());
401  for (StringRef str : values)
402  ecs.unionSets(argumentsAndResultsIndex.lookup(str), root);
403  }
404 
405  // Verifies that all output types have a corresponding known input type
406  // and chooses matching operand or attribute (in that order) that
407  // matches it.
408  allResultsHaveKnownTypes =
409  all_of(llvm::seq<int>(0, getNumResults()), captureMapping);
410 
411  // If the types could be computed, then add type inference trait.
412  if (allResultsHaveKnownTypes)
413  traits.push_back(Trait::create(inferTrait->getDefInit()));
414 }
415 
416 void Operator::populateOpStructure() {
417  auto &recordKeeper = def.getRecords();
418  auto *typeConstraintClass = recordKeeper.getClass("TypeConstraint");
419  auto *attrClass = recordKeeper.getClass("Attr");
420  auto *derivedAttrClass = recordKeeper.getClass("DerivedAttr");
421  auto *opVarClass = recordKeeper.getClass("OpVariable");
422  numNativeAttributes = 0;
423 
424  DagInit *argumentValues = def.getValueAsDag("arguments");
425  unsigned numArgs = argumentValues->getNumArgs();
426 
427  // Mapping from name of to argument or result index. Arguments are indexed
428  // to match getArg index, while the results are negatively indexed.
429  llvm::StringMap<int> argumentsAndResultsIndex;
430 
431  // Handle operands and native attributes.
432  for (unsigned i = 0; i != numArgs; ++i) {
433  auto *arg = argumentValues->getArg(i);
434  auto givenName = argumentValues->getArgNameStr(i);
435  auto *argDefInit = dyn_cast<DefInit>(arg);
436  if (!argDefInit)
437  PrintFatalError(def.getLoc(),
438  Twine("undefined type for argument #") + Twine(i));
439  Record *argDef = argDefInit->getDef();
440  if (argDef->isSubClassOf(opVarClass))
441  argDef = argDef->getValueAsDef("constraint");
442 
443  if (argDef->isSubClassOf(typeConstraintClass)) {
444  operands.push_back(
445  NamedTypeConstraint{givenName, TypeConstraint(argDef)});
446  } else if (argDef->isSubClassOf(attrClass)) {
447  if (givenName.empty())
448  PrintFatalError(argDef->getLoc(), "attributes must be named");
449  if (argDef->isSubClassOf(derivedAttrClass))
450  PrintFatalError(argDef->getLoc(),
451  "derived attributes not allowed in argument list");
452  attributes.push_back({givenName, Attribute(argDef)});
453  ++numNativeAttributes;
454  } else {
455  PrintFatalError(def.getLoc(), "unexpected def type; only defs deriving "
456  "from TypeConstraint or Attr are allowed");
457  }
458  if (!givenName.empty())
459  argumentsAndResultsIndex[givenName] = i;
460  }
461 
462  // Handle derived attributes.
463  for (const auto &val : def.getValues()) {
464  if (auto *record = dyn_cast<llvm::RecordRecTy>(val.getType())) {
465  if (!record->isSubClassOf(attrClass))
466  continue;
467  if (!record->isSubClassOf(derivedAttrClass))
468  PrintFatalError(def.getLoc(),
469  "unexpected Attr where only DerivedAttr is allowed");
470 
471  if (record->getClasses().size() != 1) {
472  PrintFatalError(
473  def.getLoc(),
474  "unsupported attribute modelling, only single class expected");
475  }
476  attributes.push_back(
477  {cast<llvm::StringInit>(val.getNameInit())->getValue(),
478  Attribute(cast<DefInit>(val.getValue()))});
479  }
480  }
481 
482  // Populate `arguments`. This must happen after we've finalized `operands` and
483  // `attributes` because we will put their elements' pointers in `arguments`.
484  // SmallVector may perform re-allocation under the hood when adding new
485  // elements.
486  int operandIndex = 0, attrIndex = 0;
487  for (unsigned i = 0; i != numArgs; ++i) {
488  Record *argDef = dyn_cast<DefInit>(argumentValues->getArg(i))->getDef();
489  if (argDef->isSubClassOf(opVarClass))
490  argDef = argDef->getValueAsDef("constraint");
491 
492  if (argDef->isSubClassOf(typeConstraintClass)) {
493  attrOrOperandMapping.push_back(
494  {OperandOrAttribute::Kind::Operand, operandIndex});
495  arguments.emplace_back(&operands[operandIndex++]);
496  } else {
497  assert(argDef->isSubClassOf(attrClass));
498  attrOrOperandMapping.push_back(
500  arguments.emplace_back(&attributes[attrIndex++]);
501  }
502  }
503 
504  auto *resultsDag = def.getValueAsDag("results");
505  auto *outsOp = dyn_cast<DefInit>(resultsDag->getOperator());
506  if (!outsOp || outsOp->getDef()->getName() != "outs") {
507  PrintFatalError(def.getLoc(), "'results' must have 'outs' directive");
508  }
509 
510  // Handle results.
511  for (unsigned i = 0, e = resultsDag->getNumArgs(); i < e; ++i) {
512  auto name = resultsDag->getArgNameStr(i);
513  auto *resultInit = dyn_cast<DefInit>(resultsDag->getArg(i));
514  if (!resultInit) {
515  PrintFatalError(def.getLoc(),
516  Twine("undefined type for result #") + Twine(i));
517  }
518  auto *resultDef = resultInit->getDef();
519  if (resultDef->isSubClassOf(opVarClass))
520  resultDef = resultDef->getValueAsDef("constraint");
521  results.push_back({name, TypeConstraint(resultDef)});
522  if (!name.empty())
523  argumentsAndResultsIndex[name] = resultIndex(i);
524 
525  // We currently only support VariadicOfVariadic operands.
526  if (results.back().constraint.isVariadicOfVariadic()) {
527  PrintFatalError(
528  def.getLoc(),
529  "'VariadicOfVariadic' results are currently not supported");
530  }
531  }
532 
533  // Handle successors
534  auto *successorsDag = def.getValueAsDag("successors");
535  auto *successorsOp = dyn_cast<DefInit>(successorsDag->getOperator());
536  if (!successorsOp || successorsOp->getDef()->getName() != "successor") {
537  PrintFatalError(def.getLoc(),
538  "'successors' must have 'successor' directive");
539  }
540 
541  for (unsigned i = 0, e = successorsDag->getNumArgs(); i < e; ++i) {
542  auto name = successorsDag->getArgNameStr(i);
543  auto *successorInit = dyn_cast<DefInit>(successorsDag->getArg(i));
544  if (!successorInit) {
545  PrintFatalError(def.getLoc(),
546  Twine("undefined kind for successor #") + Twine(i));
547  }
548  Successor successor(successorInit->getDef());
549 
550  // Only support variadic successors if it is the last one for now.
551  if (i != e - 1 && successor.isVariadic())
552  PrintFatalError(def.getLoc(), "only the last successor can be variadic");
553  successors.push_back({name, successor});
554  }
555 
556  // Create list of traits, skipping over duplicates: appending to lists in
557  // tablegen is easy, making them unique less so, so dedupe here.
558  if (auto *traitList = def.getValueAsListInit("traits")) {
559  // This is uniquing based on pointers of the trait.
561  traits.reserve(traitSet.size());
562 
563  // The declaration order of traits imply the verification order of traits.
564  // Some traits may require other traits to be verified first then they can
565  // do further verification based on those verified facts. If you see this
566  // error, fix the traits declaration order by checking the `dependentTraits`
567  // field.
568  auto verifyTraitValidity = [&](Record *trait) {
569  auto *dependentTraits = trait->getValueAsListInit("dependentTraits");
570  for (auto *traitInit : *dependentTraits)
571  if (traitSet.find(traitInit) == traitSet.end())
572  PrintFatalError(
573  def.getLoc(),
574  trait->getValueAsString("trait") + " requires " +
575  cast<DefInit>(traitInit)->getDef()->getValueAsString(
576  "trait") +
577  " to precede it in traits list");
578  };
579 
580  std::function<void(llvm::ListInit *)> insert;
581  insert = [&](llvm::ListInit *traitList) {
582  for (auto *traitInit : *traitList) {
583  auto *def = cast<DefInit>(traitInit)->getDef();
584  if (def->isSubClassOf("TraitList")) {
585  insert(def->getValueAsListInit("traits"));
586  continue;
587  }
588 
589  // Verify if the trait has all the dependent traits declared before
590  // itself.
591  verifyTraitValidity(def);
592 
593  // Keep traits in the same order while skipping over duplicates.
594  if (traitSet.insert(traitInit).second)
595  traits.push_back(Trait::create(traitInit));
596  }
597  };
598  insert(traitList);
599  }
600 
601  populateTypeInferenceInfo(argumentsAndResultsIndex);
602 
603  // Handle regions
604  auto *regionsDag = def.getValueAsDag("regions");
605  auto *regionsOp = dyn_cast<DefInit>(regionsDag->getOperator());
606  if (!regionsOp || regionsOp->getDef()->getName() != "region") {
607  PrintFatalError(def.getLoc(), "'regions' must have 'region' directive");
608  }
609 
610  for (unsigned i = 0, e = regionsDag->getNumArgs(); i < e; ++i) {
611  auto name = regionsDag->getArgNameStr(i);
612  auto *regionInit = dyn_cast<DefInit>(regionsDag->getArg(i));
613  if (!regionInit) {
614  PrintFatalError(def.getLoc(),
615  Twine("undefined kind for region #") + Twine(i));
616  }
617  Region region(regionInit->getDef());
618  if (region.isVariadic()) {
619  // Only support variadic regions if it is the last one for now.
620  if (i != e - 1)
621  PrintFatalError(def.getLoc(), "only the last region can be variadic");
622  if (name.empty())
623  PrintFatalError(def.getLoc(), "variadic regions must be named");
624  }
625 
626  regions.push_back({name, region});
627  }
628 
629  // Populate the builders.
630  auto *builderList =
631  dyn_cast_or_null<llvm::ListInit>(def.getValueInit("builders"));
632  if (builderList && !builderList->empty()) {
633  for (llvm::Init *init : builderList->getValues())
634  builders.emplace_back(cast<llvm::DefInit>(init)->getDef(), def.getLoc());
635  } else if (skipDefaultBuilders()) {
636  PrintFatalError(
637  def.getLoc(),
638  "default builders are skipped and no custom builders provided");
639  }
640 
641  LLVM_DEBUG(print(llvm::dbgs()));
642 }
643 
645  assert(allResultTypesKnown());
646  return resultTypeMapping[index];
647 }
648 
649 ArrayRef<SMLoc> Operator::getLoc() const { return def.getLoc(); }
650 
652  return def.getValue("description") != nullptr;
653 }
654 
655 StringRef Operator::getDescription() const {
656  return def.getValueAsString("description");
657 }
658 
659 bool Operator::hasSummary() const { return def.getValue("summary") != nullptr; }
660 
661 StringRef Operator::getSummary() const {
662  return def.getValueAsString("summary");
663 }
664 
666  auto *valueInit = def.getValueInit("assemblyFormat");
667  return isa<llvm::StringInit>(valueInit);
668 }
669 
670 StringRef Operator::getAssemblyFormat() const {
671  return TypeSwitch<llvm::Init *, StringRef>(def.getValueInit("assemblyFormat"))
672  .Case<llvm::StringInit>([&](auto *init) { return init->getValue(); });
673 }
674 
675 void Operator::print(llvm::raw_ostream &os) const {
676  os << "op '" << getOperationName() << "'\n";
677  for (Argument arg : arguments) {
678  if (auto *attr = arg.dyn_cast<NamedAttribute *>())
679  os << "[attribute] " << attr->name << '\n';
680  else
681  os << "[operand] " << arg.get<NamedTypeConstraint *>()->name << '\n';
682  }
683 }
684 
686  -> VariableDecorator {
687  return VariableDecorator(cast<llvm::DefInit>(init)->getDef());
688 }
689 
691  -> OperandOrAttribute {
692  return attrOrOperandMapping[index];
693 }
694 
695 // Helper to return the names for accessor.
697 getGetterOrSetterNames(bool isGetter, const Operator &op, StringRef name) {
699  std::string prefix;
700  if (prefixType != Dialect::EmitPrefix::Raw)
701  prefix = isGetter ? "get" : "set";
702 
704  bool rawToo = prefixType == Dialect::EmitPrefix::Both;
705 
706  // Whether to skip generating prefixed form for argument. This just does some
707  // basic checks.
708  //
709  // There are a little bit more invasive checks possible for cases where not
710  // all ops have the trait that would cause overlap. For many cases here,
711  // renaming would be better (e.g., we can only guard in limited manner against
712  // methods from traits and interfaces here, so avoiding these in op definition
713  // is safer).
714  auto skip = [&](StringRef newName) {
715  bool shouldSkip = newName == "getAttributeNames" ||
716  newName == "getAttributes" || newName == "getOperation";
717  if (newName == "getOperands") {
718  // To reduce noise, skip generating the prefixed form and the warning if
719  // $operands correspond to single variadic argument.
720  if (op.getNumOperands() == 1 && op.getNumVariableLengthOperands() == 1)
721  return true;
722  shouldSkip = true;
723  }
724  if (newName == "getRegions") {
725  if (op.getNumRegions() == 1 && op.getNumVariadicRegions() == 1)
726  return true;
727  shouldSkip = true;
728  }
729  if (newName == "getType") {
730  if (op.getNumResults() != 1)
731  return false;
732  shouldSkip = true;
733  }
734  if (!shouldSkip)
735  return false;
736 
737  // This note could be avoided where the final function generated would
738  // have been identical. But preferably in the op definition avoiding using
739  // the generic name and then getting a more specialize type is better.
740  PrintNote(op.getLoc(),
741  "Skipping generation of prefixed accessor `" + newName +
742  "` as it overlaps with default one; generating raw form (`" +
743  name + "`) still");
744  return true;
745  };
746 
747  if (!prefix.empty()) {
748  names.push_back(
749  prefix + convertToCamelFromSnakeCase(name, /*capitalizeFirst=*/true));
750  // Skip cases which would overlap with default ones for now.
751  if (skip(names.back())) {
752  rawToo = true;
753  names.clear();
754  } else if (rawToo) {
755  LLVM_DEBUG(llvm::errs() << "WITH_GETTER(\"" << op.getQualCppClassName()
756  << "::" << name << "\")\n"
757  << "WITH_GETTER(\"" << op.getQualCppClassName()
758  << "Adaptor::" << name << "\")\n";);
759  }
760  }
761 
762  if (prefix.empty() || rawToo)
763  names.push_back(name.str());
764  return names;
765 }
766 
768  return getGetterOrSetterNames(/*isGetter=*/true, *this, name);
769 }
770 
772  return getGetterOrSetterNames(/*isGetter=*/false, *this, name);
773 }
StringRef getArgName(int index) const
Definition: Operator.cpp:199
Include the generated interface declarations.
const_region_iterator region_end() const
Definition: Operator.cpp:231
StringRef getName() const
const NamedSuccessor & getSuccessor(unsigned index) const
Definition: Operator.cpp:263
ArrayRef< ArgOrType > getSameTypeAsResult(int index) const
Definition: Operator.cpp:644
SmallVector< std::string, 2 > getSetterNames(StringRef name) const
Definition: Operator.cpp:771
const_successor_iterator successor_end() const
Definition: Operator.cpp:253
The OpAsmOpInterface, see OpAsmInterface.td for more details.
Definition: CallGraph.h:229
TypeConstraint getResultTypeConstraint(int index) const
Definition: Operator.cpp:156
attribute_iterator attribute_end() const
Definition: Operator.cpp:285
std::string getOperationName() const
Definition: Operator.cpp:60
unsigned getNumVariableLengthResults() const
Definition: Operator.cpp:174
Argument getArg(int index) const
Definition: Operator.cpp:303
arg_iterator arg_end() const
Definition: Operator.cpp:193
SmallVector< std::string, 2 > getGetterNames(StringRef name) const
Definition: Operator.cpp:767
const_region_iterator region_begin() const
Definition: Operator.cpp:228
const_value_range getOperands() const
Definition: Operator.cpp:299
NamedTypeConstraint & getOperand(int index)
Definition: Operator.h:153
const_trait_iterator trait_begin() const
Definition: Operator.cpp:272
A class used to represent the decorators of an operator variable, i.e.
Definition: Operator.h:73
const char * inferTypeOpInterface
Definition: Attribute.cpp:244
Operator(const llvm::Record &def)
Definition: Operator.cpp:38
StringRef getCppClassName() const
Definition: Operator.cpp:109
StringRef getExtraClassDeclaration() const
Definition: Operator.cpp:124
var_decorator_range getArgDecorators(int index) const
Definition: Operator.cpp:204
StringRef getDescription() const
Definition: Operator.cpp:655
const_successor_iterator successor_begin() const
Definition: Operator.cpp:250
const_value_range getResults() const
Definition: Operator.cpp:152
std::string getQualCppClassName() const
Definition: Operator.cpp:111
bool hasDescription() const
Definition: Operator.cpp:651
llvm::iterator_range< const_trait_iterator > getTraits() const
Definition: Operator.cpp:278
bool hasSingleVariadicArg() const
Definition: Operator.cpp:186
llvm::iterator_range< const_region_iterator > getRegions() const
Definition: Operator.cpp:234
const llvm::Record & getDef() const
Definition: Operator.cpp:138
attribute_iterator attribute_begin() const
Definition: Operator.cpp:282
llvm::iterator_range< attribute_iterator > getAttributes() const
Definition: Operator.cpp:288
unsigned getNumVariadicRegions() const
Definition: Operator.cpp:245
static Trait create(const llvm::Init *init)
Definition: Trait.cpp:28
NamedTypeConstraint & getResult(int index)
Definition: Operator.h:117
var_decorator_range getResultDecorators(int index) const
Definition: Operator.cpp:166
const_value_iterator operand_begin() const
Definition: Operator.cpp:293
StringRef getSummary() const
Definition: Operator.cpp:661
llvm::iterator_range< const_successor_iterator > getSuccessors() const
Definition: Operator.cpp:256
int getNumOperands() const
Definition: Operator.h:152
ArrayRef< SMLoc > getLoc() const
Definition: Operator.cpp:649
unsigned getNumSuccessors() const
Definition: Operator.cpp:261
OperandOrAttribute getArgToOperandOrAttribute(int index) const
Definition: Operator.cpp:690
bool hasAssemblyFormat() const
Definition: Operator.cpp:665
unsigned getNumVariadicSuccessors() const
Definition: Operator.cpp:267
bool skipDefaultBuilders() const
Definition: Operator.cpp:140
const_value_iterator result_end() const
Definition: Operator.cpp:148
StringRef getAssemblyFormat() const
Definition: Operator.cpp:670
const_value_iterator operand_end() const
Definition: Operator.cpp:296
static SmallVector< std::string, 2 > getGetterOrSetterNames(bool isGetter, const Operator &op, StringRef name)
Definition: Operator.cpp:697
const NamedRegion & getRegion(unsigned index) const
Definition: Operator.cpp:241
int getNumResults() const
Definition: Operator.cpp:119
static int resultIndex(int i)
Definition: Operator.cpp:308
unsigned getNumRegions() const
Definition: Operator.cpp:239
const Dialect & getDialect() const
Definition: Operator.h:250
arg_iterator arg_begin() const
Definition: Operator.cpp:191
llvm::iterator_range< VariableDecoratorIterator > var_decorator_range
Definition: Operator.h:95
const_trait_iterator trait_end() const
Definition: Operator.cpp:275
void print(llvm::raw_ostream &os) const
Definition: Operator.cpp:675
const Trait * getTrait(llvm::StringRef trait) const
Definition: Operator.cpp:212
bool hasSummary() const
Definition: Operator.cpp:659
static VariableDecorator unwrap(llvm::Init *init)
Definition: Operator.cpp:685
const_value_iterator result_begin() const
Definition: Operator.cpp:144
bool isVariadic() const
Definition: Region.h:33
void assertInvariants() const
Definition: Operator.cpp:72
StringRef getResultName(int index) const
Definition: Operator.cpp:161
bool allResultTypesKnown() const
Definition: Operator.h:257
StringRef getDialectName() const
Definition: Operator.cpp:107
EmitPrefix getEmitAccessorPrefix() const
Definition: Dialect.cpp:101
int getNumArgs() const
Definition: Operator.h:162
bool isVariadic() const
Definition: Operator.cpp:310
bool isVariableLength() const
Definition: Type.h:53
StringRef getExtraClassDefinition() const
Definition: Operator.cpp:131
std::string getAdaptorName() const
Definition: Operator.cpp:68
StringRef getCppNamespace() const
Definition: Operator.cpp:117
arg_range getArgs() const
Definition: Operator.cpp:195
unsigned getNumVariableLengthOperands() const
Definition: Operator.cpp:180