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/SmallPtrSet.h"
12 #include "llvm/ADT/StringExtras.h"
13 #include "llvm/TableGen/Error.h"
14 #include "llvm/TableGen/Record.h"
15
16 using namespace mlir;
17 using namespace mlir::tblgen;
18
19 //===----------------------------------------------------------------------===//
20 // AttrOrTypeBuilder
21 //===----------------------------------------------------------------------===//
22
getReturnType() const23 Optional<StringRef> AttrOrTypeBuilder::getReturnType() const {
24 Optional<StringRef> type = def->getValueAsOptionalString("returnType");
25 return type && !type->empty() ? type : llvm::None;
26 }
27
hasInferredContextParameter() const28 bool AttrOrTypeBuilder::hasInferredContextParameter() const {
29 return def->getValueAsBit("hasInferredContextParam");
30 }
31
32 //===----------------------------------------------------------------------===//
33 // AttrOrTypeDef
34 //===----------------------------------------------------------------------===//
35
AttrOrTypeDef(const llvm::Record * def)36 AttrOrTypeDef::AttrOrTypeDef(const llvm::Record *def) : def(def) {
37 // Populate the builders.
38 auto *builderList =
39 dyn_cast_or_null<llvm::ListInit>(def->getValueInit("builders"));
40 if (builderList && !builderList->empty()) {
41 for (llvm::Init *init : builderList->getValues()) {
42 AttrOrTypeBuilder builder(cast<llvm::DefInit>(init)->getDef(),
43 def->getLoc());
44
45 // Ensure that all parameters have names.
46 for (const AttrOrTypeBuilder::Parameter ¶m :
47 builder.getParameters()) {
48 if (!param.getName())
49 PrintFatalError(def->getLoc(), "builder parameters must have a name");
50 }
51 builders.emplace_back(builder);
52 }
53 }
54
55 // Populate the traits.
56 if (auto *traitList = def->getValueAsListInit("traits")) {
57 SmallPtrSet<const llvm::Init *, 32> traitSet;
58 traits.reserve(traitSet.size());
59 for (auto *traitInit : *traitList)
60 if (traitSet.insert(traitInit).second)
61 traits.push_back(Trait::create(traitInit));
62 }
63
64 // Populate the parameters.
65 if (auto *parametersDag = def->getValueAsDag("parameters")) {
66 for (unsigned i = 0, e = parametersDag->getNumArgs(); i < e; ++i)
67 parameters.push_back(AttrOrTypeParameter(parametersDag, i));
68 }
69
70 // Verify the use of the mnemonic field.
71 bool hasCppFormat = hasCustomAssemblyFormat();
72 bool hasDeclarativeFormat = getAssemblyFormat().has_value();
73 if (getMnemonic()) {
74 if (hasCppFormat && hasDeclarativeFormat) {
75 PrintFatalError(getLoc(), "cannot specify both 'assemblyFormat' "
76 "and 'hasCustomAssemblyFormat'");
77 }
78 if (!parameters.empty() && !hasCppFormat && !hasDeclarativeFormat) {
79 PrintFatalError(getLoc(),
80 "must specify either 'assemblyFormat' or "
81 "'hasCustomAssemblyFormat' when 'mnemonic' is set");
82 }
83 } else if (hasCppFormat || hasDeclarativeFormat) {
84 PrintFatalError(getLoc(),
85 "'assemblyFormat' or 'hasCustomAssemblyFormat' can only be "
86 "used when 'mnemonic' is set");
87 }
88 // Assembly format printer requires accessors to be generated.
89 if (hasDeclarativeFormat && !genAccessors()) {
90 PrintFatalError(getLoc(),
91 "'assemblyFormat' requires 'genAccessors' to be true");
92 }
93 // TODO: Ensure that a suitable builder prototype can be generated:
94 // https://llvm.org/PR56415
95 }
96
getDialect() const97 Dialect AttrOrTypeDef::getDialect() const {
98 auto *dialect = dyn_cast<llvm::DefInit>(def->getValue("dialect")->getValue());
99 return Dialect(dialect ? dialect->getDef() : nullptr);
100 }
101
getName() const102 StringRef AttrOrTypeDef::getName() const { return def->getName(); }
103
getCppClassName() const104 StringRef AttrOrTypeDef::getCppClassName() const {
105 return def->getValueAsString("cppClassName");
106 }
107
getCppBaseClassName() const108 StringRef AttrOrTypeDef::getCppBaseClassName() const {
109 return def->getValueAsString("cppBaseClassName");
110 }
111
hasDescription() const112 bool AttrOrTypeDef::hasDescription() const {
113 const llvm::RecordVal *desc = def->getValue("description");
114 return desc && isa<llvm::StringInit>(desc->getValue());
115 }
116
getDescription() const117 StringRef AttrOrTypeDef::getDescription() const {
118 return def->getValueAsString("description");
119 }
120
hasSummary() const121 bool AttrOrTypeDef::hasSummary() const {
122 const llvm::RecordVal *summary = def->getValue("summary");
123 return summary && isa<llvm::StringInit>(summary->getValue());
124 }
125
getSummary() const126 StringRef AttrOrTypeDef::getSummary() const {
127 return def->getValueAsString("summary");
128 }
129
getStorageClassName() const130 StringRef AttrOrTypeDef::getStorageClassName() const {
131 return def->getValueAsString("storageClass");
132 }
133
getStorageNamespace() const134 StringRef AttrOrTypeDef::getStorageNamespace() const {
135 return def->getValueAsString("storageNamespace");
136 }
137
genStorageClass() const138 bool AttrOrTypeDef::genStorageClass() const {
139 return def->getValueAsBit("genStorageClass");
140 }
141
hasStorageCustomConstructor() const142 bool AttrOrTypeDef::hasStorageCustomConstructor() const {
143 return def->getValueAsBit("hasStorageCustomConstructor");
144 }
145
getNumParameters() const146 unsigned AttrOrTypeDef::getNumParameters() const {
147 auto *parametersDag = def->getValueAsDag("parameters");
148 return parametersDag ? parametersDag->getNumArgs() : 0;
149 }
150
getMnemonic() const151 Optional<StringRef> AttrOrTypeDef::getMnemonic() const {
152 return def->getValueAsOptionalString("mnemonic");
153 }
154
hasCustomAssemblyFormat() const155 bool AttrOrTypeDef::hasCustomAssemblyFormat() const {
156 return def->getValueAsBit("hasCustomAssemblyFormat");
157 }
158
getAssemblyFormat() const159 Optional<StringRef> AttrOrTypeDef::getAssemblyFormat() const {
160 return def->getValueAsOptionalString("assemblyFormat");
161 }
162
genAccessors() const163 bool AttrOrTypeDef::genAccessors() const {
164 return def->getValueAsBit("genAccessors");
165 }
166
genVerifyDecl() const167 bool AttrOrTypeDef::genVerifyDecl() const {
168 return def->getValueAsBit("genVerifyDecl");
169 }
170
getExtraDecls() const171 Optional<StringRef> AttrOrTypeDef::getExtraDecls() const {
172 auto value = def->getValueAsString("extraClassDeclaration");
173 return value.empty() ? Optional<StringRef>() : value;
174 }
175
getExtraDefs() const176 Optional<StringRef> AttrOrTypeDef::getExtraDefs() const {
177 auto value = def->getValueAsString("extraClassDefinition");
178 return value.empty() ? Optional<StringRef>() : value;
179 }
180
getLoc() const181 ArrayRef<SMLoc> AttrOrTypeDef::getLoc() const { return def->getLoc(); }
182
skipDefaultBuilders() const183 bool AttrOrTypeDef::skipDefaultBuilders() const {
184 return def->getValueAsBit("skipDefaultBuilders");
185 }
186
operator ==(const AttrOrTypeDef & other) const187 bool AttrOrTypeDef::operator==(const AttrOrTypeDef &other) const {
188 return def == other.def;
189 }
190
operator <(const AttrOrTypeDef & other) const191 bool AttrOrTypeDef::operator<(const AttrOrTypeDef &other) const {
192 return getName() < other.getName();
193 }
194
195 //===----------------------------------------------------------------------===//
196 // AttrDef
197 //===----------------------------------------------------------------------===//
198
getTypeBuilder() const199 Optional<StringRef> AttrDef::getTypeBuilder() const {
200 return def->getValueAsOptionalString("typeBuilder");
201 }
202
classof(const AttrOrTypeDef * def)203 bool AttrDef::classof(const AttrOrTypeDef *def) {
204 return def->getDef()->isSubClassOf("AttrDef");
205 }
206
207 //===----------------------------------------------------------------------===//
208 // AttrOrTypeParameter
209 //===----------------------------------------------------------------------===//
210
211 template <typename InitT>
getDefValue(StringRef name) const212 auto AttrOrTypeParameter::getDefValue(StringRef name) const {
213 Optional<decltype(std::declval<InitT>().getValue())> result;
214 if (auto *param = dyn_cast<llvm::DefInit>(getDef()))
215 if (auto *init = param->getDef()->getValue(name))
216 if (auto *value = dyn_cast_or_null<InitT>(init->getValue()))
217 result = value->getValue();
218 return result;
219 }
220
isAnonymous() const221 bool AttrOrTypeParameter::isAnonymous() const {
222 return !def->getArgName(index);
223 }
224
getName() const225 StringRef AttrOrTypeParameter::getName() const {
226 return def->getArgName(index)->getValue();
227 }
228
getAccessorName() const229 std::string AttrOrTypeParameter::getAccessorName() const {
230 return "get" +
231 llvm::convertToCamelFromSnakeCase(getName(), /*capitalizeFirst=*/true);
232 }
233
getAllocator() const234 Optional<StringRef> AttrOrTypeParameter::getAllocator() const {
235 return getDefValue<llvm::StringInit>("allocator");
236 }
237
getComparator() const238 StringRef AttrOrTypeParameter::getComparator() const {
239 return getDefValue<llvm::StringInit>("comparator").value_or("$_lhs == $_rhs");
240 }
241
getCppType() const242 StringRef AttrOrTypeParameter::getCppType() const {
243 if (auto *stringType = dyn_cast<llvm::StringInit>(getDef()))
244 return stringType->getValue();
245 return getDefValue<llvm::StringInit>("cppType").value();
246 }
247
getCppAccessorType() const248 StringRef AttrOrTypeParameter::getCppAccessorType() const {
249 return getDefValue<llvm::StringInit>("cppAccessorType")
250 .value_or(getCppType());
251 }
252
getCppStorageType() const253 StringRef AttrOrTypeParameter::getCppStorageType() const {
254 return getDefValue<llvm::StringInit>("cppStorageType").value_or(getCppType());
255 }
256
getConvertFromStorage() const257 StringRef AttrOrTypeParameter::getConvertFromStorage() const {
258 return getDefValue<llvm::StringInit>("convertFromStorage").value_or("$_self");
259 }
260
getParser() const261 Optional<StringRef> AttrOrTypeParameter::getParser() const {
262 return getDefValue<llvm::StringInit>("parser");
263 }
264
getPrinter() const265 Optional<StringRef> AttrOrTypeParameter::getPrinter() const {
266 return getDefValue<llvm::StringInit>("printer");
267 }
268
getSummary() const269 Optional<StringRef> AttrOrTypeParameter::getSummary() const {
270 return getDefValue<llvm::StringInit>("summary");
271 }
272
getSyntax() const273 StringRef AttrOrTypeParameter::getSyntax() const {
274 if (auto *stringType = dyn_cast<llvm::StringInit>(getDef()))
275 return stringType->getValue();
276 return getDefValue<llvm::StringInit>("syntax").value_or(getCppType());
277 }
278
isOptional() const279 bool AttrOrTypeParameter::isOptional() const {
280 // Parameters with default values are automatically optional.
281 return getDefValue<llvm::BitInit>("isOptional").value_or(false) ||
282 getDefaultValue();
283 }
284
getDefaultValue() const285 Optional<StringRef> AttrOrTypeParameter::getDefaultValue() const {
286 return getDefValue<llvm::StringInit>("defaultValue");
287 }
288
getDef() const289 llvm::Init *AttrOrTypeParameter::getDef() const { return def->getArg(index); }
290
291 //===----------------------------------------------------------------------===//
292 // AttributeSelfTypeParameter
293 //===----------------------------------------------------------------------===//
294
classof(const AttrOrTypeParameter * param)295 bool AttributeSelfTypeParameter::classof(const AttrOrTypeParameter *param) {
296 llvm::Init *paramDef = param->getDef();
297 if (auto *paramDefInit = dyn_cast<llvm::DefInit>(paramDef))
298 return paramDefInit->getDef()->isSubClassOf("AttributeSelfTypeParameter");
299 return false;
300 }
301