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
9#include "mlir/TableGen/AttrOrTypeDef.h"
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
18using namespace mlir;
19using namespace mlir::tblgen;
20
21//===----------------------------------------------------------------------===//
22// AttrOrTypeBuilder
23//===----------------------------------------------------------------------===//
24
25std::optional<StringRef> AttrOrTypeBuilder::getReturnType() const {
26 std::optional<StringRef> type = def->getValueAsOptionalString(FieldName: "returnType");
27 return type && !type->empty() ? type : std::nullopt;
28}
29
30bool AttrOrTypeBuilder::hasInferredContextParameter() const {
31 return def->getValueAsBit(FieldName: "hasInferredContextParam");
32}
33
34//===----------------------------------------------------------------------===//
35// AttrOrTypeDef
36//===----------------------------------------------------------------------===//
37
38AttrOrTypeDef::AttrOrTypeDef(const llvm::Record *def) : def(def) {
39 // Populate the builders.
40 auto *builderList =
41 dyn_cast_or_null<llvm::ListInit>(Val: def->getValueInit(FieldName: "builders"));
42 if (builderList && !builderList->empty()) {
43 for (llvm::Init *init : builderList->getValues()) {
44 AttrOrTypeBuilder builder(cast<llvm::DefInit>(Val: 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(ErrorLoc: def->getLoc(), Msg: "builder parameters must have a name");
52 }
53 builders.emplace_back(Args&: builder);
54 }
55 }
56
57 // Populate the traits.
58 if (auto *traitList = def->getValueAsListInit(FieldName: "traits")) {
59 SmallPtrSet<const llvm::Init *, 32> traitSet;
60 traits.reserve(N: traitSet.size());
61 llvm::unique_function<void(llvm::ListInit *)> processTraitList =
62 [&](llvm::ListInit *traitList) {
63 for (auto *traitInit : *traitList) {
64 if (!traitSet.insert(Ptr: traitInit).second)
65 continue;
66
67 // If this is an interface, add any bases to the trait list.
68 auto *traitDef = cast<llvm::DefInit>(Val: traitInit)->getDef();
69 if (traitDef->isSubClassOf(Name: "Interface")) {
70 if (auto *bases = traitDef->getValueAsListInit(FieldName: "baseInterfaces"))
71 processTraitList(bases);
72 }
73
74 traits.push_back(Elt: Trait::create(init: traitInit));
75 }
76 };
77 processTraitList(traitList);
78 }
79
80 // Populate the parameters.
81 if (auto *parametersDag = def->getValueAsDag(FieldName: "parameters")) {
82 for (unsigned i = 0, e = parametersDag->getNumArgs(); i < e; ++i)
83 parameters.push_back(Elt: 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(ErrorLoc: getLoc(), Msg: "cannot specify both 'assemblyFormat' "
92 "and 'hasCustomAssemblyFormat'");
93 }
94 if (!parameters.empty() && !hasCppFormat && !hasDeclarativeFormat) {
95 PrintFatalError(ErrorLoc: getLoc(),
96 Msg: "must specify either 'assemblyFormat' or "
97 "'hasCustomAssemblyFormat' when 'mnemonic' is set");
98 }
99 } else if (hasCppFormat || hasDeclarativeFormat) {
100 PrintFatalError(ErrorLoc: getLoc(),
101 Msg: "'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(ErrorLoc: getLoc(),
107 Msg: "'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
113Dialect AttrOrTypeDef::getDialect() const {
114 auto *dialect = dyn_cast<llvm::DefInit>(Val: def->getValue(Name: "dialect")->getValue());
115 return Dialect(dialect ? dialect->getDef() : nullptr);
116}
117
118StringRef AttrOrTypeDef::getName() const { return def->getName(); }
119
120StringRef AttrOrTypeDef::getCppClassName() const {
121 return def->getValueAsString(FieldName: "cppClassName");
122}
123
124StringRef AttrOrTypeDef::getCppBaseClassName() const {
125 return def->getValueAsString(FieldName: "cppBaseClassName");
126}
127
128bool AttrOrTypeDef::hasDescription() const {
129 const llvm::RecordVal *desc = def->getValue(Name: "description");
130 return desc && isa<llvm::StringInit>(Val: desc->getValue());
131}
132
133StringRef AttrOrTypeDef::getDescription() const {
134 return def->getValueAsString(FieldName: "description");
135}
136
137bool AttrOrTypeDef::hasSummary() const {
138 const llvm::RecordVal *summary = def->getValue(Name: "summary");
139 return summary && isa<llvm::StringInit>(Val: summary->getValue());
140}
141
142StringRef AttrOrTypeDef::getSummary() const {
143 return def->getValueAsString(FieldName: "summary");
144}
145
146StringRef AttrOrTypeDef::getStorageClassName() const {
147 return def->getValueAsString(FieldName: "storageClass");
148}
149
150StringRef AttrOrTypeDef::getStorageNamespace() const {
151 return def->getValueAsString(FieldName: "storageNamespace");
152}
153
154bool AttrOrTypeDef::genStorageClass() const {
155 return def->getValueAsBit(FieldName: "genStorageClass");
156}
157
158bool AttrOrTypeDef::hasStorageCustomConstructor() const {
159 return def->getValueAsBit(FieldName: "hasStorageCustomConstructor");
160}
161
162unsigned AttrOrTypeDef::getNumParameters() const {
163 auto *parametersDag = def->getValueAsDag(FieldName: "parameters");
164 return parametersDag ? parametersDag->getNumArgs() : 0;
165}
166
167std::optional<StringRef> AttrOrTypeDef::getMnemonic() const {
168 return def->getValueAsOptionalString(FieldName: "mnemonic");
169}
170
171bool AttrOrTypeDef::hasCustomAssemblyFormat() const {
172 return def->getValueAsBit(FieldName: "hasCustomAssemblyFormat");
173}
174
175std::optional<StringRef> AttrOrTypeDef::getAssemblyFormat() const {
176 return def->getValueAsOptionalString(FieldName: "assemblyFormat");
177}
178
179bool AttrOrTypeDef::genAccessors() const {
180 return def->getValueAsBit(FieldName: "genAccessors");
181}
182
183bool AttrOrTypeDef::genVerifyDecl() const {
184 return def->getValueAsBit(FieldName: "genVerifyDecl");
185}
186
187std::optional<StringRef> AttrOrTypeDef::getExtraDecls() const {
188 auto value = def->getValueAsString(FieldName: "extraClassDeclaration");
189 return value.empty() ? std::optional<StringRef>() : value;
190}
191
192std::optional<StringRef> AttrOrTypeDef::getExtraDefs() const {
193 auto value = def->getValueAsString(FieldName: "extraClassDefinition");
194 return value.empty() ? std::optional<StringRef>() : value;
195}
196
197ArrayRef<SMLoc> AttrOrTypeDef::getLoc() const { return def->getLoc(); }
198
199bool AttrOrTypeDef::skipDefaultBuilders() const {
200 return def->getValueAsBit(FieldName: "skipDefaultBuilders");
201}
202
203bool AttrOrTypeDef::operator==(const AttrOrTypeDef &other) const {
204 return def == other.def;
205}
206
207bool AttrOrTypeDef::operator<(const AttrOrTypeDef &other) const {
208 return getName() < other.getName();
209}
210
211//===----------------------------------------------------------------------===//
212// AttrDef
213//===----------------------------------------------------------------------===//
214
215std::optional<StringRef> AttrDef::getTypeBuilder() const {
216 return def->getValueAsOptionalString(FieldName: "typeBuilder");
217}
218
219bool AttrDef::classof(const AttrOrTypeDef *def) {
220 return def->getDef()->isSubClassOf(Name: "AttrDef");
221}
222
223StringRef AttrDef::getAttrName() const {
224 return def->getValueAsString(FieldName: "attrName");
225}
226
227//===----------------------------------------------------------------------===//
228// TypeDef
229//===----------------------------------------------------------------------===//
230
231bool TypeDef::classof(const AttrOrTypeDef *def) {
232 return def->getDef()->isSubClassOf(Name: "TypeDef");
233}
234
235StringRef TypeDef::getTypeName() const {
236 return def->getValueAsString(FieldName: "typeName");
237}
238
239//===----------------------------------------------------------------------===//
240// AttrOrTypeParameter
241//===----------------------------------------------------------------------===//
242
243template <typename InitT>
244auto AttrOrTypeParameter::getDefValue(StringRef name) const {
245 std::optional<decltype(std::declval<InitT>().getValue())> result;
246 if (auto *param = dyn_cast<llvm::DefInit>(Val: getDef()))
247 if (auto *init = param->getDef()->getValue(Name: name))
248 if (auto *value = dyn_cast_or_null<InitT>(init->getValue()))
249 result = value->getValue();
250 return result;
251}
252
253bool AttrOrTypeParameter::isAnonymous() const {
254 return !def->getArgName(Num: index);
255}
256
257StringRef AttrOrTypeParameter::getName() const {
258 return def->getArgName(Num: index)->getValue();
259}
260
261std::string AttrOrTypeParameter::getAccessorName() const {
262 return "get" +
263 llvm::convertToCamelFromSnakeCase(input: getName(), /*capitalizeFirst=*/true);
264}
265
266std::optional<StringRef> AttrOrTypeParameter::getAllocator() const {
267 return getDefValue<llvm::StringInit>(name: "allocator");
268}
269
270StringRef AttrOrTypeParameter::getComparator() const {
271 return getDefValue<llvm::StringInit>(name: "comparator").value_or(u: "$_lhs == $_rhs");
272}
273
274StringRef AttrOrTypeParameter::getCppType() const {
275 if (auto *stringType = dyn_cast<llvm::StringInit>(Val: getDef()))
276 return stringType->getValue();
277 auto cppType = getDefValue<llvm::StringInit>(name: "cppType");
278 if (cppType)
279 return *cppType;
280 if (auto *init = dyn_cast<llvm::DefInit>(Val: getDef()))
281 llvm::PrintFatalError(
282 ErrorLoc: init->getDef()->getLoc(),
283 Msg: Twine("Missing `cppType` field in Attribute/Type parameter: ") +
284 init->getAsString());
285 llvm::report_fatal_error(
286 reason: Twine("Missing `cppType` field in Attribute/Type parameter: ") +
287 getDef()->getAsString(),
288 /*gen_crash_diag=*/false);
289}
290
291StringRef AttrOrTypeParameter::getCppAccessorType() const {
292 return getDefValue<llvm::StringInit>(name: "cppAccessorType")
293 .value_or(u: getCppType());
294}
295
296StringRef AttrOrTypeParameter::getCppStorageType() const {
297 return getDefValue<llvm::StringInit>(name: "cppStorageType").value_or(u: getCppType());
298}
299
300StringRef AttrOrTypeParameter::getConvertFromStorage() const {
301 return getDefValue<llvm::StringInit>(name: "convertFromStorage").value_or(u: "$_self");
302}
303
304std::optional<StringRef> AttrOrTypeParameter::getParser() const {
305 return getDefValue<llvm::StringInit>(name: "parser");
306}
307
308std::optional<StringRef> AttrOrTypeParameter::getPrinter() const {
309 return getDefValue<llvm::StringInit>(name: "printer");
310}
311
312std::optional<StringRef> AttrOrTypeParameter::getSummary() const {
313 return getDefValue<llvm::StringInit>(name: "summary");
314}
315
316StringRef AttrOrTypeParameter::getSyntax() const {
317 if (auto *stringType = dyn_cast<llvm::StringInit>(Val: getDef()))
318 return stringType->getValue();
319 return getDefValue<llvm::StringInit>(name: "syntax").value_or(u: getCppType());
320}
321
322bool AttrOrTypeParameter::isOptional() const {
323 return getDefaultValue().has_value();
324}
325
326std::optional<StringRef> AttrOrTypeParameter::getDefaultValue() const {
327 std::optional<StringRef> result =
328 getDefValue<llvm::StringInit>(name: "defaultValue");
329 return result && !result->empty() ? result : std::nullopt;
330}
331
332llvm::Init *AttrOrTypeParameter::getDef() const { return def->getArg(Num: index); }
333
334//===----------------------------------------------------------------------===//
335// AttributeSelfTypeParameter
336//===----------------------------------------------------------------------===//
337
338bool AttributeSelfTypeParameter::classof(const AttrOrTypeParameter *param) {
339 llvm::Init *paramDef = param->getDef();
340 if (auto *paramDefInit = dyn_cast<llvm::DefInit>(Val: paramDef))
341 return paramDefInit->getDef()->isSubClassOf(Name: "AttributeSelfTypeParameter");
342 return false;
343}
344

source code of mlir/lib/TableGen/AttrOrTypeDef.cpp