1 //===- Attribute.cpp - Attribute wrapper class ----------------------------===//
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 // Attribute wrapper to simplify using TableGen Record defining a MLIR
10 // Attribute.
11 //
12 //===----------------------------------------------------------------------===//
13 
14 #include "mlir/TableGen/Format.h"
15 #include "mlir/TableGen/Operator.h"
16 #include "llvm/TableGen/Record.h"
17 
18 using namespace mlir;
19 
20 using llvm::CodeInit;
21 using llvm::DefInit;
22 using llvm::Init;
23 using llvm::Record;
24 using llvm::StringInit;
25 
26 // Returns the initializer's value as string if the given TableGen initializer
27 // is a code or string initializer. Returns the empty StringRef otherwise.
28 static StringRef getValueAsString(const Init *init) {
29   if (const auto *code = dyn_cast<CodeInit>(init))
30     return code->getValue().trim();
31   else if (const auto *str = dyn_cast<StringInit>(init))
32     return str->getValue().trim();
33   return {};
34 }
35 
36 tblgen::AttrConstraint::AttrConstraint(const Record *record)
37     : Constraint(Constraint::CK_Attr, record) {
38   assert(isSubClassOf("AttrConstraint") &&
39          "must be subclass of TableGen 'AttrConstraint' class");
40 }
41 
42 bool tblgen::AttrConstraint::isSubClassOf(StringRef className) const {
43   return def->isSubClassOf(className);
44 }
45 
46 tblgen::Attribute::Attribute(const Record *record) : AttrConstraint(record) {
47   assert(record->isSubClassOf("Attr") &&
48          "must be subclass of TableGen 'Attr' class");
49 }
50 
51 tblgen::Attribute::Attribute(const DefInit *init) : Attribute(init->getDef()) {}
52 
53 bool tblgen::Attribute::isDerivedAttr() const {
54   return isSubClassOf("DerivedAttr");
55 }
56 
57 bool tblgen::Attribute::isTypeAttr() const {
58   return isSubClassOf("TypeAttrBase");
59 }
60 
61 bool tblgen::Attribute::isEnumAttr() const {
62   return isSubClassOf("EnumAttrInfo");
63 }
64 
65 StringRef tblgen::Attribute::getStorageType() const {
66   const auto *init = def->getValueInit("storageType");
67   auto type = getValueAsString(init);
68   if (type.empty())
69     return "Attribute";
70   return type;
71 }
72 
73 StringRef tblgen::Attribute::getReturnType() const {
74   const auto *init = def->getValueInit("returnType");
75   return getValueAsString(init);
76 }
77 
78 // Return the type constraint corresponding to the type of this attribute, or
79 // None if this is not a TypedAttr.
80 llvm::Optional<tblgen::Type> tblgen::Attribute::getValueType() const {
81   if (auto *defInit = dyn_cast<llvm::DefInit>(def->getValueInit("valueType")))
82     return tblgen::Type(defInit->getDef());
83   return llvm::None;
84 }
85 
86 StringRef tblgen::Attribute::getConvertFromStorageCall() const {
87   const auto *init = def->getValueInit("convertFromStorage");
88   return getValueAsString(init);
89 }
90 
91 bool tblgen::Attribute::isConstBuildable() const {
92   const auto *init = def->getValueInit("constBuilderCall");
93   return !getValueAsString(init).empty();
94 }
95 
96 StringRef tblgen::Attribute::getConstBuilderTemplate() const {
97   const auto *init = def->getValueInit("constBuilderCall");
98   return getValueAsString(init);
99 }
100 
101 tblgen::Attribute tblgen::Attribute::getBaseAttr() const {
102   if (const auto *defInit =
103           llvm::dyn_cast<llvm::DefInit>(def->getValueInit("baseAttr"))) {
104     return Attribute(defInit).getBaseAttr();
105   }
106   return *this;
107 }
108 
109 bool tblgen::Attribute::hasDefaultValue() const {
110   const auto *init = def->getValueInit("defaultValue");
111   return !getValueAsString(init).empty();
112 }
113 
114 StringRef tblgen::Attribute::getDefaultValue() const {
115   const auto *init = def->getValueInit("defaultValue");
116   return getValueAsString(init);
117 }
118 
119 bool tblgen::Attribute::isOptional() const {
120   return def->getValueAsBit("isOptional");
121 }
122 
123 StringRef tblgen::Attribute::getAttrDefName() const {
124   if (def->isAnonymous()) {
125     return getBaseAttr().def->getName();
126   }
127   return def->getName();
128 }
129 
130 StringRef tblgen::Attribute::getDerivedCodeBody() const {
131   assert(isDerivedAttr() && "only derived attribute has 'body' field");
132   return def->getValueAsString("body");
133 }
134 
135 tblgen::Dialect tblgen::Attribute::getDialect() const {
136   return Dialect(def->getValueAsDef("dialect"));
137 }
138 
139 tblgen::ConstantAttr::ConstantAttr(const DefInit *init) : def(init->getDef()) {
140   assert(def->isSubClassOf("ConstantAttr") &&
141          "must be subclass of TableGen 'ConstantAttr' class");
142 }
143 
144 tblgen::Attribute tblgen::ConstantAttr::getAttribute() const {
145   return Attribute(def->getValueAsDef("attr"));
146 }
147 
148 StringRef tblgen::ConstantAttr::getConstantValue() const {
149   return def->getValueAsString("value");
150 }
151 
152 tblgen::EnumAttrCase::EnumAttrCase(const llvm::Record *record)
153     : Attribute(record) {
154   assert(isSubClassOf("EnumAttrCaseInfo") &&
155          "must be subclass of TableGen 'EnumAttrInfo' class");
156 }
157 
158 tblgen::EnumAttrCase::EnumAttrCase(const llvm::DefInit *init)
159     : EnumAttrCase(init->getDef()) {}
160 
161 bool tblgen::EnumAttrCase::isStrCase() const {
162   return isSubClassOf("StrEnumAttrCase");
163 }
164 
165 StringRef tblgen::EnumAttrCase::getSymbol() const {
166   return def->getValueAsString("symbol");
167 }
168 
169 StringRef tblgen::EnumAttrCase::getStr() const {
170   return def->getValueAsString("str");
171 }
172 
173 int64_t tblgen::EnumAttrCase::getValue() const {
174   return def->getValueAsInt("value");
175 }
176 
177 const llvm::Record &tblgen::EnumAttrCase::getDef() const { return *def; }
178 
179 tblgen::EnumAttr::EnumAttr(const llvm::Record *record) : Attribute(record) {
180   assert(isSubClassOf("EnumAttrInfo") &&
181          "must be subclass of TableGen 'EnumAttr' class");
182 }
183 
184 tblgen::EnumAttr::EnumAttr(const llvm::Record &record) : Attribute(&record) {}
185 
186 tblgen::EnumAttr::EnumAttr(const llvm::DefInit *init)
187     : EnumAttr(init->getDef()) {}
188 
189 bool tblgen::EnumAttr::classof(const Attribute *attr) {
190   return attr->isSubClassOf("EnumAttrInfo");
191 }
192 
193 bool tblgen::EnumAttr::isBitEnum() const { return isSubClassOf("BitEnumAttr"); }
194 
195 StringRef tblgen::EnumAttr::getEnumClassName() const {
196   return def->getValueAsString("className");
197 }
198 
199 StringRef tblgen::EnumAttr::getCppNamespace() const {
200   return def->getValueAsString("cppNamespace");
201 }
202 
203 StringRef tblgen::EnumAttr::getUnderlyingType() const {
204   return def->getValueAsString("underlyingType");
205 }
206 
207 StringRef tblgen::EnumAttr::getUnderlyingToSymbolFnName() const {
208   return def->getValueAsString("underlyingToSymbolFnName");
209 }
210 
211 StringRef tblgen::EnumAttr::getStringToSymbolFnName() const {
212   return def->getValueAsString("stringToSymbolFnName");
213 }
214 
215 StringRef tblgen::EnumAttr::getSymbolToStringFnName() const {
216   return def->getValueAsString("symbolToStringFnName");
217 }
218 
219 StringRef tblgen::EnumAttr::getSymbolToStringFnRetType() const {
220   return def->getValueAsString("symbolToStringFnRetType");
221 }
222 
223 StringRef tblgen::EnumAttr::getMaxEnumValFnName() const {
224   return def->getValueAsString("maxEnumValFnName");
225 }
226 
227 std::vector<tblgen::EnumAttrCase> tblgen::EnumAttr::getAllCases() const {
228   const auto *inits = def->getValueAsListInit("enumerants");
229 
230   std::vector<tblgen::EnumAttrCase> cases;
231   cases.reserve(inits->size());
232 
233   for (const llvm::Init *init : *inits) {
234     cases.push_back(tblgen::EnumAttrCase(cast<llvm::DefInit>(init)));
235   }
236 
237   return cases;
238 }
239 
240 tblgen::StructFieldAttr::StructFieldAttr(const llvm::Record *record)
241     : def(record) {
242   assert(def->isSubClassOf("StructFieldAttr") &&
243          "must be subclass of TableGen 'StructFieldAttr' class");
244 }
245 
246 tblgen::StructFieldAttr::StructFieldAttr(const llvm::Record &record)
247     : StructFieldAttr(&record) {}
248 
249 tblgen::StructFieldAttr::StructFieldAttr(const llvm::DefInit *init)
250     : StructFieldAttr(init->getDef()) {}
251 
252 StringRef tblgen::StructFieldAttr::getName() const {
253   return def->getValueAsString("name");
254 }
255 
256 tblgen::Attribute tblgen::StructFieldAttr::getType() const {
257   auto init = def->getValueInit("type");
258   return tblgen::Attribute(cast<llvm::DefInit>(init));
259 }
260 
261 tblgen::StructAttr::StructAttr(const llvm::Record *record) : Attribute(record) {
262   assert(isSubClassOf("StructAttr") &&
263          "must be subclass of TableGen 'StructAttr' class");
264 }
265 
266 tblgen::StructAttr::StructAttr(const llvm::DefInit *init)
267     : StructAttr(init->getDef()) {}
268 
269 StringRef tblgen::StructAttr::getStructClassName() const {
270   return def->getValueAsString("className");
271 }
272 
273 StringRef tblgen::StructAttr::getCppNamespace() const {
274   Dialect dialect(def->getValueAsDef("structDialect"));
275   return dialect.getCppNamespace();
276 }
277 
278 std::vector<mlir::tblgen::StructFieldAttr>
279 tblgen::StructAttr::getAllFields() const {
280   std::vector<mlir::tblgen::StructFieldAttr> attributes;
281 
282   const auto *inits = def->getValueAsListInit("fields");
283   attributes.reserve(inits->size());
284 
285   for (const llvm::Init *init : *inits) {
286     attributes.emplace_back(cast<llvm::DefInit>(init));
287   }
288 
289   return attributes;
290 }
291