MLIR  20.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 using llvm::DefInit;
21 using llvm::Init;
22 using llvm::ListInit;
23 using llvm::Record;
24 using llvm::RecordVal;
25 using llvm::StringInit;
26 
27 //===----------------------------------------------------------------------===//
28 // AttrOrTypeBuilder
29 //===----------------------------------------------------------------------===//
30 
31 std::optional<StringRef> AttrOrTypeBuilder::getReturnType() const {
32  std::optional<StringRef> type = def->getValueAsOptionalString("returnType");
33  return type && !type->empty() ? type : std::nullopt;
34 }
35 
37  return def->getValueAsBit("hasInferredContextParam");
38 }
39 
40 //===----------------------------------------------------------------------===//
41 // AttrOrTypeDef
42 //===----------------------------------------------------------------------===//
43 
44 AttrOrTypeDef::AttrOrTypeDef(const Record *def) : def(def) {
45  // Populate the builders.
46  const auto *builderList =
47  dyn_cast_or_null<ListInit>(def->getValueInit("builders"));
48  if (builderList && !builderList->empty()) {
49  for (const Init *init : builderList->getValues()) {
50  AttrOrTypeBuilder builder(cast<DefInit>(init)->getDef(), def->getLoc());
51 
52  // Ensure that all parameters have names.
53  for (const AttrOrTypeBuilder::Parameter &param :
54  builder.getParameters()) {
55  if (!param.getName())
56  PrintFatalError(def->getLoc(), "builder parameters must have a name");
57  }
58  builders.emplace_back(builder);
59  }
60  }
61 
62  // Populate the traits.
63  if (auto *traitList = def->getValueAsListInit("traits")) {
65  traits.reserve(traitSet.size());
66  llvm::unique_function<void(const ListInit *)> processTraitList =
67  [&](const ListInit *traitList) {
68  for (auto *traitInit : *traitList) {
69  if (!traitSet.insert(traitInit).second)
70  continue;
71 
72  // If this is an interface, add any bases to the trait list.
73  auto *traitDef = cast<DefInit>(traitInit)->getDef();
74  if (traitDef->isSubClassOf("Interface")) {
75  if (auto *bases = traitDef->getValueAsListInit("baseInterfaces"))
76  processTraitList(bases);
77  }
78 
79  traits.push_back(Trait::create(traitInit));
80  }
81  };
82  processTraitList(traitList);
83  }
84 
85  // Populate the parameters.
86  if (auto *parametersDag = def->getValueAsDag("parameters")) {
87  for (unsigned i = 0, e = parametersDag->getNumArgs(); i < e; ++i)
88  parameters.push_back(AttrOrTypeParameter(parametersDag, i));
89  }
90 
91  // Verify the use of the mnemonic field.
92  bool hasCppFormat = hasCustomAssemblyFormat();
93  bool hasDeclarativeFormat = getAssemblyFormat().has_value();
94  if (getMnemonic()) {
95  if (hasCppFormat && hasDeclarativeFormat) {
96  PrintFatalError(getLoc(), "cannot specify both 'assemblyFormat' "
97  "and 'hasCustomAssemblyFormat'");
98  }
99  if (!parameters.empty() && !hasCppFormat && !hasDeclarativeFormat) {
100  PrintFatalError(getLoc(),
101  "must specify either 'assemblyFormat' or "
102  "'hasCustomAssemblyFormat' when 'mnemonic' is set");
103  }
104  } else if (hasCppFormat || hasDeclarativeFormat) {
105  PrintFatalError(getLoc(),
106  "'assemblyFormat' or 'hasCustomAssemblyFormat' can only be "
107  "used when 'mnemonic' is set");
108  }
109  // Assembly format printer requires accessors to be generated.
110  if (hasDeclarativeFormat && !genAccessors()) {
111  PrintFatalError(getLoc(),
112  "'assemblyFormat' requires 'genAccessors' to be true");
113  }
114  // TODO: Ensure that a suitable builder prototype can be generated:
115  // https://llvm.org/PR56415
116 }
117 
119  const auto *dialect = dyn_cast<DefInit>(def->getValue("dialect")->getValue());
120  return Dialect(dialect ? dialect->getDef() : nullptr);
121 }
122 
123 StringRef AttrOrTypeDef::getName() const { return def->getName(); }
124 
126  return def->getValueAsString("cppClassName");
127 }
128 
130  return def->getValueAsString("cppBaseClassName");
131 }
132 
134  const RecordVal *desc = def->getValue("description");
135  return desc && isa<StringInit>(desc->getValue());
136 }
137 
138 StringRef AttrOrTypeDef::getDescription() const {
139  return def->getValueAsString("description");
140 }
141 
143  const RecordVal *summary = def->getValue("summary");
144  return summary && isa<StringInit>(summary->getValue());
145 }
146 
147 StringRef AttrOrTypeDef::getSummary() const {
148  return def->getValueAsString("summary");
149 }
150 
152  return def->getValueAsString("storageClass");
153 }
154 
156  return def->getValueAsString("storageNamespace");
157 }
158 
160  return def->getValueAsBit("genStorageClass");
161 }
162 
164  return def->getValueAsBit("hasStorageCustomConstructor");
165 }
166 
168  auto *parametersDag = def->getValueAsDag("parameters");
169  return parametersDag ? parametersDag->getNumArgs() : 0;
170 }
171 
172 std::optional<StringRef> AttrOrTypeDef::getMnemonic() const {
173  return def->getValueAsOptionalString("mnemonic");
174 }
175 
177  return def->getValueAsBit("hasCustomAssemblyFormat");
178 }
179 
180 std::optional<StringRef> AttrOrTypeDef::getAssemblyFormat() const {
181  return def->getValueAsOptionalString("assemblyFormat");
182 }
183 
185  return def->getValueAsBit("genAccessors");
186 }
187 
189  return def->getValueAsBit("genVerifyDecl");
190 }
191 
193  return any_of(parameters, [](const AttrOrTypeParameter &p) {
194  return p.getConstraint() != std::nullopt;
195  });
196 }
197 
198 std::optional<StringRef> AttrOrTypeDef::getExtraDecls() const {
199  auto value = def->getValueAsString("extraClassDeclaration");
200  return value.empty() ? std::optional<StringRef>() : value;
201 }
202 
203 std::optional<StringRef> AttrOrTypeDef::getExtraDefs() const {
204  auto value = def->getValueAsString("extraClassDefinition");
205  return value.empty() ? std::optional<StringRef>() : value;
206 }
207 
208 ArrayRef<SMLoc> AttrOrTypeDef::getLoc() const { return def->getLoc(); }
209 
211  return def->getValueAsBit("skipDefaultBuilders");
212 }
213 
214 bool AttrOrTypeDef::operator==(const AttrOrTypeDef &other) const {
215  return def == other.def;
216 }
217 
218 bool AttrOrTypeDef::operator<(const AttrOrTypeDef &other) const {
219  return getName() < other.getName();
220 }
221 
222 //===----------------------------------------------------------------------===//
223 // AttrDef
224 //===----------------------------------------------------------------------===//
225 
226 std::optional<StringRef> AttrDef::getTypeBuilder() const {
227  return def->getValueAsOptionalString("typeBuilder");
228 }
229 
230 bool AttrDef::classof(const AttrOrTypeDef *def) {
231  return def->getDef()->isSubClassOf("AttrDef");
232 }
233 
234 StringRef AttrDef::getAttrName() const {
235  return def->getValueAsString("attrName");
236 }
237 
238 //===----------------------------------------------------------------------===//
239 // TypeDef
240 //===----------------------------------------------------------------------===//
241 
242 bool TypeDef::classof(const AttrOrTypeDef *def) {
243  return def->getDef()->isSubClassOf("TypeDef");
244 }
245 
246 StringRef TypeDef::getTypeName() const {
247  return def->getValueAsString("typeName");
248 }
249 
250 //===----------------------------------------------------------------------===//
251 // AttrOrTypeParameter
252 //===----------------------------------------------------------------------===//
253 
254 template <typename InitT>
255 auto AttrOrTypeParameter::getDefValue(StringRef name) const {
256  std::optional<decltype(std::declval<InitT>().getValue())> result;
257  if (const auto *param = dyn_cast<DefInit>(getDef()))
258  if (const auto *init = param->getDef()->getValue(name))
259  if (const auto *value = dyn_cast_or_null<InitT>(init->getValue()))
260  result = value->getValue();
261  return result;
262 }
263 
265  return !def->getArgName(index);
266 }
267 
268 StringRef AttrOrTypeParameter::getName() const {
269  return def->getArgName(index)->getValue();
270 }
271 
273  return "get" +
274  llvm::convertToCamelFromSnakeCase(getName(), /*capitalizeFirst=*/true);
275 }
276 
277 std::optional<StringRef> AttrOrTypeParameter::getAllocator() const {
278  return getDefValue<StringInit>("allocator");
279 }
280 
282  return getDefValue<StringInit>("comparator").value_or("$_lhs == $_rhs");
283 }
284 
286  if (auto *stringType = dyn_cast<StringInit>(getDef()))
287  return stringType->getValue();
288  auto cppType = getDefValue<StringInit>("cppType");
289  if (cppType)
290  return *cppType;
291  if (const auto *init = dyn_cast<DefInit>(getDef()))
292  llvm::PrintFatalError(
293  init->getDef()->getLoc(),
294  Twine("Missing `cppType` field in Attribute/Type parameter: ") +
295  init->getAsString());
296  llvm::report_fatal_error(
297  Twine("Missing `cppType` field in Attribute/Type parameter: ") +
298  getDef()->getAsString(),
299  /*gen_crash_diag=*/false);
300 }
301 
303  return getDefValue<StringInit>("cppAccessorType").value_or(getCppType());
304 }
305 
307  return getDefValue<StringInit>("cppStorageType").value_or(getCppType());
308 }
309 
311  return getDefValue<StringInit>("convertFromStorage").value_or("$_self");
312 }
313 
314 std::optional<StringRef> AttrOrTypeParameter::getParser() const {
315  return getDefValue<StringInit>("parser");
316 }
317 
318 std::optional<StringRef> AttrOrTypeParameter::getPrinter() const {
319  return getDefValue<StringInit>("printer");
320 }
321 
322 std::optional<StringRef> AttrOrTypeParameter::getSummary() const {
323  return getDefValue<StringInit>("summary");
324 }
325 
327  if (auto *stringType = dyn_cast<StringInit>(getDef()))
328  return stringType->getValue();
329  return getDefValue<StringInit>("syntax").value_or(getCppType());
330 }
331 
333  return getDefaultValue().has_value();
334 }
335 
336 std::optional<StringRef> AttrOrTypeParameter::getDefaultValue() const {
337  std::optional<StringRef> result = getDefValue<StringInit>("defaultValue");
338  return result && !result->empty() ? result : std::nullopt;
339 }
340 
341 const Init *AttrOrTypeParameter::getDef() const { return def->getArg(index); }
342 
343 std::optional<Constraint> AttrOrTypeParameter::getConstraint() const {
344  if (const auto *param = dyn_cast<DefInit>(getDef()))
345  if (param->getDef()->isSubClassOf("Constraint"))
346  return Constraint(param->getDef());
347  return std::nullopt;
348 }
349 
350 //===----------------------------------------------------------------------===//
351 // AttributeSelfTypeParameter
352 //===----------------------------------------------------------------------===//
353 
355  const Init *paramDef = param->getDef();
356  if (const auto *paramDefInit = dyn_cast<DefInit>(paramDef))
357  return paramDefInit->getDef()->isSubClassOf("AttributeSelfTypeParameter");
358  return false;
359 }
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:37
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.
bool genVerifyInvariantsImpl() const
Return true if we need to generate any type constraint verification and the getChecked method.
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:54
std::optional< StringRef > getParser() const
Get an optional C++ parameter parser.
StringRef getSyntax() const
Get the assembly syntax documentation.
std::optional< Constraint > getConstraint() const
If this is a type constraint, return it.
StringRef getComparator() const
If specified, get the custom comparator code for this parameter.
StringRef getName() const
Get the parameter name.
const llvm::Init * getDef() const
Return the underlying def of this parameter.
std::optional< StringRef > getPrinter() const
Get an optional C++ parameter printer.
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.