MLIR  19.0.0git
AttrOrTypeDef.cpp
Go to the documentation of this file.
1 //===- AttrOrTypeDef.cpp - AttrOrTypeDef wrapper classes ------------------===//
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 
10 #include "mlir/TableGen/Dialect.h"
11 #include "llvm/ADT/FunctionExtras.h"
12 #include "llvm/ADT/SmallPtrSet.h"
13 #include "llvm/ADT/StringExtras.h"
14 #include "llvm/Support/ErrorHandling.h"
15 #include "llvm/TableGen/Error.h"
16 #include "llvm/TableGen/Record.h"
17 
18 using namespace mlir;
19 using namespace mlir::tblgen;
20 
21 //===----------------------------------------------------------------------===//
22 // AttrOrTypeBuilder
23 //===----------------------------------------------------------------------===//
24 
25 std::optional<StringRef> AttrOrTypeBuilder::getReturnType() const {
26  std::optional<StringRef> type = def->getValueAsOptionalString("returnType");
27  return type && !type->empty() ? type : std::nullopt;
28 }
29 
31  return def->getValueAsBit("hasInferredContextParam");
32 }
33 
34 //===----------------------------------------------------------------------===//
35 // AttrOrTypeDef
36 //===----------------------------------------------------------------------===//
37 
38 AttrOrTypeDef::AttrOrTypeDef(const llvm::Record *def) : def(def) {
39  // Populate the builders.
40  auto *builderList =
41  dyn_cast_or_null<llvm::ListInit>(def->getValueInit("builders"));
42  if (builderList && !builderList->empty()) {
43  for (llvm::Init *init : builderList->getValues()) {
44  AttrOrTypeBuilder builder(cast<llvm::DefInit>(init)->getDef(),
45  def->getLoc());
46 
47  // Ensure that all parameters have names.
48  for (const AttrOrTypeBuilder::Parameter &param :
49  builder.getParameters()) {
50  if (!param.getName())
51  PrintFatalError(def->getLoc(), "builder parameters must have a name");
52  }
53  builders.emplace_back(builder);
54  }
55  }
56 
57  // Populate the traits.
58  if (auto *traitList = def->getValueAsListInit("traits")) {
60  traits.reserve(traitSet.size());
61  llvm::unique_function<void(llvm::ListInit *)> processTraitList =
62  [&](llvm::ListInit *traitList) {
63  for (auto *traitInit : *traitList) {
64  if (!traitSet.insert(traitInit).second)
65  continue;
66 
67  // If this is an interface, add any bases to the trait list.
68  auto *traitDef = cast<llvm::DefInit>(traitInit)->getDef();
69  if (traitDef->isSubClassOf("Interface")) {
70  if (auto *bases = traitDef->getValueAsListInit("baseInterfaces"))
71  processTraitList(bases);
72  }
73 
74  traits.push_back(Trait::create(traitInit));
75  }
76  };
77  processTraitList(traitList);
78  }
79 
80  // Populate the parameters.
81  if (auto *parametersDag = def->getValueAsDag("parameters")) {
82  for (unsigned i = 0, e = parametersDag->getNumArgs(); i < e; ++i)
83  parameters.push_back(AttrOrTypeParameter(parametersDag, i));
84  }
85 
86  // Verify the use of the mnemonic field.
87  bool hasCppFormat = hasCustomAssemblyFormat();
88  bool hasDeclarativeFormat = getAssemblyFormat().has_value();
89  if (getMnemonic()) {
90  if (hasCppFormat && hasDeclarativeFormat) {
91  PrintFatalError(getLoc(), "cannot specify both 'assemblyFormat' "
92  "and 'hasCustomAssemblyFormat'");
93  }
94  if (!parameters.empty() && !hasCppFormat && !hasDeclarativeFormat) {
95  PrintFatalError(getLoc(),
96  "must specify either 'assemblyFormat' or "
97  "'hasCustomAssemblyFormat' when 'mnemonic' is set");
98  }
99  } else if (hasCppFormat || hasDeclarativeFormat) {
100  PrintFatalError(getLoc(),
101  "'assemblyFormat' or 'hasCustomAssemblyFormat' can only be "
102  "used when 'mnemonic' is set");
103  }
104  // Assembly format printer requires accessors to be generated.
105  if (hasDeclarativeFormat && !genAccessors()) {
106  PrintFatalError(getLoc(),
107  "'assemblyFormat' requires 'genAccessors' to be true");
108  }
109  // TODO: Ensure that a suitable builder prototype can be generated:
110  // https://llvm.org/PR56415
111 }
112 
114  auto *dialect = dyn_cast<llvm::DefInit>(def->getValue("dialect")->getValue());
115  return Dialect(dialect ? dialect->getDef() : nullptr);
116 }
117 
118 StringRef AttrOrTypeDef::getName() const { return def->getName(); }
119 
121  return def->getValueAsString("cppClassName");
122 }
123 
125  return def->getValueAsString("cppBaseClassName");
126 }
127 
129  const llvm::RecordVal *desc = def->getValue("description");
130  return desc && isa<llvm::StringInit>(desc->getValue());
131 }
132 
133 StringRef AttrOrTypeDef::getDescription() const {
134  return def->getValueAsString("description");
135 }
136 
138  const llvm::RecordVal *summary = def->getValue("summary");
139  return summary && isa<llvm::StringInit>(summary->getValue());
140 }
141 
142 StringRef AttrOrTypeDef::getSummary() const {
143  return def->getValueAsString("summary");
144 }
145 
147  return def->getValueAsString("storageClass");
148 }
149 
151  return def->getValueAsString("storageNamespace");
152 }
153 
155  return def->getValueAsBit("genStorageClass");
156 }
157 
159  return def->getValueAsBit("hasStorageCustomConstructor");
160 }
161 
163  auto *parametersDag = def->getValueAsDag("parameters");
164  return parametersDag ? parametersDag->getNumArgs() : 0;
165 }
166 
167 std::optional<StringRef> AttrOrTypeDef::getMnemonic() const {
168  return def->getValueAsOptionalString("mnemonic");
169 }
170 
172  return def->getValueAsBit("hasCustomAssemblyFormat");
173 }
174 
175 std::optional<StringRef> AttrOrTypeDef::getAssemblyFormat() const {
176  return def->getValueAsOptionalString("assemblyFormat");
177 }
178 
180  return def->getValueAsBit("genAccessors");
181 }
182 
184  return def->getValueAsBit("genVerifyDecl");
185 }
186 
187 std::optional<StringRef> AttrOrTypeDef::getExtraDecls() const {
188  auto value = def->getValueAsString("extraClassDeclaration");
189  return value.empty() ? std::optional<StringRef>() : value;
190 }
191 
192 std::optional<StringRef> AttrOrTypeDef::getExtraDefs() const {
193  auto value = def->getValueAsString("extraClassDefinition");
194  return value.empty() ? std::optional<StringRef>() : value;
195 }
196 
197 ArrayRef<SMLoc> AttrOrTypeDef::getLoc() const { return def->getLoc(); }
198 
200  return def->getValueAsBit("skipDefaultBuilders");
201 }
202 
203 bool AttrOrTypeDef::operator==(const AttrOrTypeDef &other) const {
204  return def == other.def;
205 }
206 
207 bool AttrOrTypeDef::operator<(const AttrOrTypeDef &other) const {
208  return getName() < other.getName();
209 }
210 
211 //===----------------------------------------------------------------------===//
212 // AttrDef
213 //===----------------------------------------------------------------------===//
214 
215 std::optional<StringRef> AttrDef::getTypeBuilder() const {
216  return def->getValueAsOptionalString("typeBuilder");
217 }
218 
219 bool AttrDef::classof(const AttrOrTypeDef *def) {
220  return def->getDef()->isSubClassOf("AttrDef");
221 }
222 
223 StringRef AttrDef::getAttrName() const {
224  return def->getValueAsString("attrName");
225 }
226 
227 //===----------------------------------------------------------------------===//
228 // TypeDef
229 //===----------------------------------------------------------------------===//
230 
231 bool TypeDef::classof(const AttrOrTypeDef *def) {
232  return def->getDef()->isSubClassOf("TypeDef");
233 }
234 
235 StringRef TypeDef::getTypeName() const {
236  return def->getValueAsString("typeName");
237 }
238 
239 //===----------------------------------------------------------------------===//
240 // AttrOrTypeParameter
241 //===----------------------------------------------------------------------===//
242 
243 template <typename InitT>
244 auto AttrOrTypeParameter::getDefValue(StringRef name) const {
245  std::optional<decltype(std::declval<InitT>().getValue())> result;
246  if (auto *param = dyn_cast<llvm::DefInit>(getDef()))
247  if (auto *init = param->getDef()->getValue(name))
248  if (auto *value = dyn_cast_or_null<InitT>(init->getValue()))
249  result = value->getValue();
250  return result;
251 }
252 
254  return !def->getArgName(index);
255 }
256 
257 StringRef AttrOrTypeParameter::getName() const {
258  return def->getArgName(index)->getValue();
259 }
260 
262  return "get" +
263  llvm::convertToCamelFromSnakeCase(getName(), /*capitalizeFirst=*/true);
264 }
265 
266 std::optional<StringRef> AttrOrTypeParameter::getAllocator() const {
267  return getDefValue<llvm::StringInit>("allocator");
268 }
269 
271  return getDefValue<llvm::StringInit>("comparator").value_or("$_lhs == $_rhs");
272 }
273 
275  if (auto *stringType = dyn_cast<llvm::StringInit>(getDef()))
276  return stringType->getValue();
277  auto cppType = getDefValue<llvm::StringInit>("cppType");
278  if (cppType)
279  return *cppType;
280  if (auto *init = dyn_cast<llvm::DefInit>(getDef()))
281  llvm::PrintFatalError(
282  init->getDef()->getLoc(),
283  Twine("Missing `cppType` field in Attribute/Type parameter: ") +
284  init->getAsString());
285  llvm::report_fatal_error(
286  Twine("Missing `cppType` field in Attribute/Type parameter: ") +
287  getDef()->getAsString(),
288  /*gen_crash_diag=*/false);
289 }
290 
292  return getDefValue<llvm::StringInit>("cppAccessorType")
293  .value_or(getCppType());
294 }
295 
297  return getDefValue<llvm::StringInit>("cppStorageType").value_or(getCppType());
298 }
299 
301  return getDefValue<llvm::StringInit>("convertFromStorage").value_or("$_self");
302 }
303 
304 std::optional<StringRef> AttrOrTypeParameter::getParser() const {
305  return getDefValue<llvm::StringInit>("parser");
306 }
307 
308 std::optional<StringRef> AttrOrTypeParameter::getPrinter() const {
309  return getDefValue<llvm::StringInit>("printer");
310 }
311 
312 std::optional<StringRef> AttrOrTypeParameter::getSummary() const {
313  return getDefValue<llvm::StringInit>("summary");
314 }
315 
317  if (auto *stringType = dyn_cast<llvm::StringInit>(getDef()))
318  return stringType->getValue();
319  return getDefValue<llvm::StringInit>("syntax").value_or(getCppType());
320 }
321 
323  return getDefaultValue().has_value();
324 }
325 
326 std::optional<StringRef> AttrOrTypeParameter::getDefaultValue() const {
327  std::optional<StringRef> result =
328  getDefValue<llvm::StringInit>("defaultValue");
329  return result && !result->empty() ? result : std::nullopt;
330 }
331 
332 llvm::Init *AttrOrTypeParameter::getDef() const { return def->getArg(index); }
333 
334 //===----------------------------------------------------------------------===//
335 // AttributeSelfTypeParameter
336 //===----------------------------------------------------------------------===//
337 
339  llvm::Init *paramDef = param->getDef();
340  if (auto *paramDefInit = dyn_cast<llvm::DefInit>(paramDef))
341  return paramDefInit->getDef()->isSubClassOf("AttributeSelfTypeParameter");
342  return false;
343 }
StringRef getAttrName() const
Get the unique attribute name "dialect.attrname".
std::optional< StringRef > getTypeBuilder() const
Returns the attributes value type builder code block, or std::nullopt if it doesn't have one.
static bool classof(const AttrOrTypeDef *def)
Wrapper class that represents a Tablegen AttrOrTypeBuilder.
Definition: AttrOrTypeDef.h:36
bool hasInferredContextParameter() const
Returns true if this builder is able to infer the MLIRContext parameter.
std::optional< StringRef > getReturnType() const
Returns an optional builder return type.
Wrapper class that contains a TableGen AttrOrTypeDef's record and provides helper methods for accessi...
const llvm::Record * getDef() const
Return the underlying def.
SmallVector< AttrOrTypeParameter > parameters
The parameters of this attribute or type.
bool hasCustomAssemblyFormat() const
Returns if the attribute or type has a custom assembly format implemented in C++.
std::optional< StringRef > getMnemonic() const
Return the keyword/mnemonic to use in the printer/parser methods if we are supposed to auto-generate ...
bool operator==(const AttrOrTypeDef &other) const
Returns whether two AttrOrTypeDefs are equal by checking the equality of the underlying record.
StringRef getCppClassName() const
Returns the name of the C++ class to generate.
AttrOrTypeDef(const llvm::Record *def)
const llvm::Record * def
StringRef getStorageNamespace() const
Returns the C++ namespace for this def's storage class.
bool genVerifyDecl() const
Return true if we need to generate the verify declaration and getChecked method.
ArrayRef< SMLoc > getLoc() const
Get the code location (for error printing).
bool hasDescription() const
Query functions for the documentation of the def.
StringRef getCppBaseClassName() const
Returns the name of the C++ base class to use when generating this def.
Dialect getDialect() const
Get the dialect for which this def belongs.
SmallVector< Trait > traits
The traits of this definition.
std::optional< StringRef > getExtraDefs() const
Returns the def's extra class definition code.
StringRef getSummary() const
bool genStorageClass() const
Returns true if we should generate the storage class.
StringRef getDescription() const
std::optional< StringRef > getExtraDecls() const
Returns the def's extra class declaration code.
StringRef getStorageClassName() const
Returns the name of the storage class for this def.
SmallVector< AttrOrTypeBuilder > builders
The builders of this definition.
bool hasStorageCustomConstructor() const
Indicates whether or not to generate the storage class constructor.
bool skipDefaultBuilders() const
Returns true if the default get/getChecked methods should be skipped during generation.
unsigned getNumParameters() const
Return the number of parameters.
std::optional< StringRef > getAssemblyFormat() const
Returns the custom assembly format, if one was specified.
bool operator<(const AttrOrTypeDef &other) const
Compares two AttrOrTypeDefs by comparing the names of the dialects.
StringRef getName() const
Returns the name of this AttrOrTypeDef record.
bool genAccessors() const
Returns true if the accessors based on the parameters should be generated.
A wrapper class for tblgen AttrOrTypeParameter, arrays of which belong to AttrOrTypeDefs to parameter...
Definition: AttrOrTypeDef.h:53
std::optional< StringRef > getParser() const
Get an optional C++ parameter parser.
StringRef getSyntax() const
Get the assembly syntax documentation.
StringRef getComparator() const
If specified, get the custom comparator code for this parameter.
StringRef getName() const
Get the parameter name.
std::optional< StringRef > getPrinter() const
Get an optional C++ parameter printer.
llvm::Init * getDef() const
Return the underlying def of this parameter.
StringRef getConvertFromStorage() const
Get the C++ code to convert from the storage type to the parameter type.
std::optional< StringRef > getDefaultValue() const
Get the default value of the parameter if it has one.
bool isAnonymous() const
Returns true if the parameter is anonymous (has no name).
std::string getAccessorName() const
Get the parameter accessor name.
StringRef getCppType() const
Get the C++ type of this parameter.
std::optional< StringRef > getSummary() const
Get a description of this parameter for documentation purposes.
StringRef getCppStorageType() const
Get the C++ storage type of this parameter.
bool isOptional() const
Returns true if the parameter is optional.
std::optional< StringRef > getAllocator() const
If specified, get the custom allocator code for this parameter.
StringRef getCppAccessorType() const
Get the C++ accessor type of this parameter.
static bool classof(const AttrOrTypeParameter *param)
This class represents a single parameter to a builder method.
Definition: Builder.h:36
const llvm::Record * def
The TableGen definition of this builder.
Definition: Builder.h:79
ArrayRef< Parameter > getParameters() const
Return a list of parameters used in this build method.
Definition: Builder.h:68
static Trait create(const llvm::Init *init)
Definition: Trait.cpp:28
StringRef getTypeName() const
Get the unique type name "dialect.typename".
static bool classof(const AttrOrTypeDef *def)
Include the generated interface declarations.