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 
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 
188  return any_of(parameters, [](const AttrOrTypeParameter &p) {
189  return p.getConstraint() != std::nullopt;
190  });
191 }
192 
193 std::optional<StringRef> AttrOrTypeDef::getExtraDecls() const {
194  auto value = def->getValueAsString("extraClassDeclaration");
195  return value.empty() ? std::optional<StringRef>() : value;
196 }
197 
198 std::optional<StringRef> AttrOrTypeDef::getExtraDefs() const {
199  auto value = def->getValueAsString("extraClassDefinition");
200  return value.empty() ? std::optional<StringRef>() : value;
201 }
202 
203 ArrayRef<SMLoc> AttrOrTypeDef::getLoc() const { return def->getLoc(); }
204 
206  return def->getValueAsBit("skipDefaultBuilders");
207 }
208 
209 bool AttrOrTypeDef::operator==(const AttrOrTypeDef &other) const {
210  return def == other.def;
211 }
212 
213 bool AttrOrTypeDef::operator<(const AttrOrTypeDef &other) const {
214  return getName() < other.getName();
215 }
216 
217 //===----------------------------------------------------------------------===//
218 // AttrDef
219 //===----------------------------------------------------------------------===//
220 
221 std::optional<StringRef> AttrDef::getTypeBuilder() const {
222  return def->getValueAsOptionalString("typeBuilder");
223 }
224 
225 bool AttrDef::classof(const AttrOrTypeDef *def) {
226  return def->getDef()->isSubClassOf("AttrDef");
227 }
228 
229 StringRef AttrDef::getAttrName() const {
230  return def->getValueAsString("attrName");
231 }
232 
233 //===----------------------------------------------------------------------===//
234 // TypeDef
235 //===----------------------------------------------------------------------===//
236 
237 bool TypeDef::classof(const AttrOrTypeDef *def) {
238  return def->getDef()->isSubClassOf("TypeDef");
239 }
240 
241 StringRef TypeDef::getTypeName() const {
242  return def->getValueAsString("typeName");
243 }
244 
245 //===----------------------------------------------------------------------===//
246 // AttrOrTypeParameter
247 //===----------------------------------------------------------------------===//
248 
249 template <typename InitT>
250 auto AttrOrTypeParameter::getDefValue(StringRef name) const {
251  std::optional<decltype(std::declval<InitT>().getValue())> result;
252  if (auto *param = dyn_cast<llvm::DefInit>(getDef()))
253  if (auto *init = param->getDef()->getValue(name))
254  if (auto *value = dyn_cast_or_null<InitT>(init->getValue()))
255  result = value->getValue();
256  return result;
257 }
258 
260  return !def->getArgName(index);
261 }
262 
263 StringRef AttrOrTypeParameter::getName() const {
264  return def->getArgName(index)->getValue();
265 }
266 
268  return "get" +
269  llvm::convertToCamelFromSnakeCase(getName(), /*capitalizeFirst=*/true);
270 }
271 
272 std::optional<StringRef> AttrOrTypeParameter::getAllocator() const {
273  return getDefValue<llvm::StringInit>("allocator");
274 }
275 
277  return getDefValue<llvm::StringInit>("comparator").value_or("$_lhs == $_rhs");
278 }
279 
281  if (auto *stringType = dyn_cast<llvm::StringInit>(getDef()))
282  return stringType->getValue();
283  auto cppType = getDefValue<llvm::StringInit>("cppType");
284  if (cppType)
285  return *cppType;
286  if (auto *init = dyn_cast<llvm::DefInit>(getDef()))
287  llvm::PrintFatalError(
288  init->getDef()->getLoc(),
289  Twine("Missing `cppType` field in Attribute/Type parameter: ") +
290  init->getAsString());
291  llvm::report_fatal_error(
292  Twine("Missing `cppType` field in Attribute/Type parameter: ") +
293  getDef()->getAsString(),
294  /*gen_crash_diag=*/false);
295 }
296 
298  return getDefValue<llvm::StringInit>("cppAccessorType")
299  .value_or(getCppType());
300 }
301 
303  return getDefValue<llvm::StringInit>("cppStorageType").value_or(getCppType());
304 }
305 
307  return getDefValue<llvm::StringInit>("convertFromStorage").value_or("$_self");
308 }
309 
310 std::optional<StringRef> AttrOrTypeParameter::getParser() const {
311  return getDefValue<llvm::StringInit>("parser");
312 }
313 
314 std::optional<StringRef> AttrOrTypeParameter::getPrinter() const {
315  return getDefValue<llvm::StringInit>("printer");
316 }
317 
318 std::optional<StringRef> AttrOrTypeParameter::getSummary() const {
319  return getDefValue<llvm::StringInit>("summary");
320 }
321 
323  if (auto *stringType = dyn_cast<llvm::StringInit>(getDef()))
324  return stringType->getValue();
325  return getDefValue<llvm::StringInit>("syntax").value_or(getCppType());
326 }
327 
329  return getDefaultValue().has_value();
330 }
331 
332 std::optional<StringRef> AttrOrTypeParameter::getDefaultValue() const {
333  std::optional<StringRef> result =
334  getDefValue<llvm::StringInit>("defaultValue");
335  return result && !result->empty() ? result : std::nullopt;
336 }
337 
338 llvm::Init *AttrOrTypeParameter::getDef() const { return def->getArg(index); }
339 
340 std::optional<Constraint> AttrOrTypeParameter::getConstraint() const {
341  if (auto *param = dyn_cast<llvm::DefInit>(getDef()))
342  if (param->getDef()->isSubClassOf("Constraint"))
343  return Constraint(param->getDef());
344  return std::nullopt;
345 }
346 
347 //===----------------------------------------------------------------------===//
348 // AttributeSelfTypeParameter
349 //===----------------------------------------------------------------------===//
350 
352  llvm::Init *paramDef = param->getDef();
353  if (auto *paramDefInit = dyn_cast<llvm::DefInit>(paramDef))
354  return paramDefInit->getDef()->isSubClassOf("AttributeSelfTypeParameter");
355  return false;
356 }
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.
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.