1 //===- EnumsGen.cpp - MLIR enum utility generator -------------------------===//
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 // EnumsGen generates common utility functions for enums.
10 //
11 //===----------------------------------------------------------------------===//
12
13 #include "mlir/TableGen/Attribute.h"
14 #include "mlir/TableGen/Format.h"
15 #include "mlir/TableGen/GenInfo.h"
16 #include "llvm/ADT/SmallVector.h"
17 #include "llvm/ADT/StringExtras.h"
18 #include "llvm/Support/FormatVariadic.h"
19 #include "llvm/Support/raw_ostream.h"
20 #include "llvm/TableGen/Error.h"
21 #include "llvm/TableGen/Record.h"
22 #include "llvm/TableGen/TableGenBackend.h"
23
24 using llvm::formatv;
25 using llvm::isDigit;
26 using llvm::PrintFatalError;
27 using llvm::raw_ostream;
28 using llvm::Record;
29 using llvm::RecordKeeper;
30 using llvm::StringRef;
31 using mlir::tblgen::Attribute;
32 using mlir::tblgen::EnumAttr;
33 using mlir::tblgen::EnumAttrCase;
34 using mlir::tblgen::FmtContext;
35 using mlir::tblgen::tgfmt;
36
makeIdentifier(StringRef str)37 static std::string makeIdentifier(StringRef str) {
38 if (!str.empty() && isDigit(static_cast<unsigned char>(str.front()))) {
39 std::string newStr = std::string("_") + str.str();
40 return newStr;
41 }
42 return str.str();
43 }
44
emitEnumClass(const Record & enumDef,StringRef enumName,StringRef underlyingType,StringRef description,const std::vector<EnumAttrCase> & enumerants,raw_ostream & os)45 static void emitEnumClass(const Record &enumDef, StringRef enumName,
46 StringRef underlyingType, StringRef description,
47 const std::vector<EnumAttrCase> &enumerants,
48 raw_ostream &os) {
49 os << "// " << description << "\n";
50 os << "enum class " << enumName;
51
52 if (!underlyingType.empty())
53 os << " : " << underlyingType;
54 os << " {\n";
55
56 for (const auto &enumerant : enumerants) {
57 auto symbol = makeIdentifier(enumerant.getSymbol());
58 auto value = enumerant.getValue();
59 if (value >= 0) {
60 os << formatv(" {0} = {1},\n", symbol, value);
61 } else {
62 os << formatv(" {0},\n", symbol);
63 }
64 }
65 os << "};\n\n";
66 }
67
emitDenseMapInfo(StringRef enumName,std::string underlyingType,StringRef cppNamespace,raw_ostream & os)68 static void emitDenseMapInfo(StringRef enumName, std::string underlyingType,
69 StringRef cppNamespace, raw_ostream &os) {
70 std::string qualName =
71 std::string(formatv("{0}::{1}", cppNamespace, enumName));
72 if (underlyingType.empty())
73 underlyingType =
74 std::string(formatv("std::underlying_type<{0}>::type", qualName));
75
76 const char *const mapInfo = R"(
77 namespace llvm {
78 template<> struct DenseMapInfo<{0}> {{
79 using StorageInfo = ::llvm::DenseMapInfo<{1}>;
80
81 static inline {0} getEmptyKey() {{
82 return static_cast<{0}>(StorageInfo::getEmptyKey());
83 }
84
85 static inline {0} getTombstoneKey() {{
86 return static_cast<{0}>(StorageInfo::getTombstoneKey());
87 }
88
89 static unsigned getHashValue(const {0} &val) {{
90 return StorageInfo::getHashValue(static_cast<{1}>(val));
91 }
92
93 static bool isEqual(const {0} &lhs, const {0} &rhs) {{
94 return lhs == rhs;
95 }
96 };
97 })";
98 os << formatv(mapInfo, qualName, underlyingType);
99 os << "\n\n";
100 }
101
emitMaxValueFn(const Record & enumDef,raw_ostream & os)102 static void emitMaxValueFn(const Record &enumDef, raw_ostream &os) {
103 EnumAttr enumAttr(enumDef);
104 StringRef maxEnumValFnName = enumAttr.getMaxEnumValFnName();
105 auto enumerants = enumAttr.getAllCases();
106
107 unsigned maxEnumVal = 0;
108 for (const auto &enumerant : enumerants) {
109 int64_t value = enumerant.getValue();
110 // Avoid generating the max value function if there is an enumerant without
111 // explicit value.
112 if (value < 0)
113 return;
114
115 maxEnumVal = std::max(maxEnumVal, static_cast<unsigned>(value));
116 }
117
118 // Emit the function to return the max enum value
119 os << formatv("inline constexpr unsigned {0}() {{\n", maxEnumValFnName);
120 os << formatv(" return {0};\n", maxEnumVal);
121 os << "}\n\n";
122 }
123
124 // Returns the EnumAttrCase whose value is zero if exists; returns llvm::None
125 // otherwise.
126 static llvm::Optional<EnumAttrCase>
getAllBitsUnsetCase(llvm::ArrayRef<EnumAttrCase> cases)127 getAllBitsUnsetCase(llvm::ArrayRef<EnumAttrCase> cases) {
128 for (auto attrCase : cases) {
129 if (attrCase.getValue() == 0)
130 return attrCase;
131 }
132 return llvm::None;
133 }
134
135 // Emits the following inline function for bit enums:
136 //
137 // inline <enum-type> operator|(<enum-type> a, <enum-type> b);
138 // inline <enum-type> operator&(<enum-type> a, <enum-type> b);
139 // inline <enum-type> bitEnumContains(<enum-type> a, <enum-type> b);
emitOperators(const Record & enumDef,raw_ostream & os)140 static void emitOperators(const Record &enumDef, raw_ostream &os) {
141 EnumAttr enumAttr(enumDef);
142 StringRef enumName = enumAttr.getEnumClassName();
143 std::string underlyingType = std::string(enumAttr.getUnderlyingType());
144 os << formatv("inline {0} operator|({0} lhs, {0} rhs) {{\n", enumName)
145 << formatv(" return static_cast<{0}>("
146 "static_cast<{1}>(lhs) | static_cast<{1}>(rhs));\n",
147 enumName, underlyingType)
148 << "}\n";
149 os << formatv("inline {0} operator&({0} lhs, {0} rhs) {{\n", enumName)
150 << formatv(" return static_cast<{0}>("
151 "static_cast<{1}>(lhs) & static_cast<{1}>(rhs));\n",
152 enumName, underlyingType)
153 << "}\n";
154 os << formatv(
155 "inline bool bitEnumContains({0} bits, {0} bit) {{\n"
156 " return (static_cast<{1}>(bits) & static_cast<{1}>(bit)) != 0;\n",
157 enumName, underlyingType)
158 << "}\n";
159 }
160
emitSymToStrFnForIntEnum(const Record & enumDef,raw_ostream & os)161 static void emitSymToStrFnForIntEnum(const Record &enumDef, raw_ostream &os) {
162 EnumAttr enumAttr(enumDef);
163 StringRef enumName = enumAttr.getEnumClassName();
164 StringRef symToStrFnName = enumAttr.getSymbolToStringFnName();
165 StringRef symToStrFnRetType = enumAttr.getSymbolToStringFnRetType();
166 auto enumerants = enumAttr.getAllCases();
167
168 os << formatv("{2} {1}({0} val) {{\n", enumName, symToStrFnName,
169 symToStrFnRetType);
170 os << " switch (val) {\n";
171 for (const auto &enumerant : enumerants) {
172 auto symbol = enumerant.getSymbol();
173 auto str = enumerant.getStr();
174 os << formatv(" case {0}::{1}: return \"{2}\";\n", enumName,
175 makeIdentifier(symbol), str);
176 }
177 os << " }\n";
178 os << " return \"\";\n";
179 os << "}\n\n";
180 }
181
emitSymToStrFnForBitEnum(const Record & enumDef,raw_ostream & os)182 static void emitSymToStrFnForBitEnum(const Record &enumDef, raw_ostream &os) {
183 EnumAttr enumAttr(enumDef);
184 StringRef enumName = enumAttr.getEnumClassName();
185 StringRef symToStrFnName = enumAttr.getSymbolToStringFnName();
186 StringRef symToStrFnRetType = enumAttr.getSymbolToStringFnRetType();
187 StringRef separator = enumDef.getValueAsString("separator");
188 auto enumerants = enumAttr.getAllCases();
189 auto allBitsUnsetCase = getAllBitsUnsetCase(enumerants);
190
191 os << formatv("{2} {1}({0} symbol) {{\n", enumName, symToStrFnName,
192 symToStrFnRetType);
193
194 os << formatv(" auto val = static_cast<{0}>(symbol);\n",
195 enumAttr.getUnderlyingType());
196 // If we have unknown bit set, return an empty string to signal errors.
197 int64_t validBits = enumDef.getValueAsInt("validBits");
198 os << formatv(" assert({0}u == ({0}u | val) && \"invalid bits set in bit "
199 "enum\");\n",
200 validBits);
201 if (allBitsUnsetCase) {
202 os << " // Special case for all bits unset.\n";
203 os << formatv(" if (val == 0) return \"{0}\";\n\n",
204 allBitsUnsetCase->getSymbol());
205 }
206 os << " ::llvm::SmallVector<::llvm::StringRef, 2> strs;\n";
207
208 // Add case string if the value has all case bits, and remove them to avoid
209 // printing again. Used only for groups, when printBitEnumPrimaryGroups is 1.
210 const char *const formatCompareRemove = R"(
211 if ({0}u == ({0}u & val)) {{
212 strs.push_back("{1}");
213 val &= ~static_cast<{2}>({0});
214 }
215 )";
216 // Add case string if the value has all case bits. Used for individual bit
217 // cases, and for groups when printBitEnumPrimaryGroups is 0.
218 const char *const formatCompare = R"(
219 if ({0}u == ({0}u & val))
220 strs.push_back("{1}");
221 )";
222 // Optionally elide bits that are members of groups that will also be printed
223 // for more concise output.
224 if (enumAttr.printBitEnumPrimaryGroups()) {
225 os << " // Print bit enum groups before individual bits\n";
226 // Emit comparisons for group bit cases in reverse tablegen declaration
227 // order, removing bits for groups with all bits present.
228 for (const auto &enumerant : llvm::reverse(enumerants)) {
229 if ((enumerant.getValue() != 0) &&
230 enumerant.getDef().isSubClassOf("BitEnumAttrCaseGroup")) {
231 os << formatv(formatCompareRemove, enumerant.getValue(),
232 enumerant.getStr(), enumAttr.getUnderlyingType());
233 }
234 }
235 // Emit comparisons for individual bit cases in tablegen declaration order.
236 for (const auto &enumerant : enumerants) {
237 if ((enumerant.getValue() != 0) &&
238 enumerant.getDef().isSubClassOf("BitEnumAttrCaseBit"))
239 os << formatv(formatCompare, enumerant.getValue(), enumerant.getStr());
240 }
241 } else {
242 // Emit comparisons for ALL nonzero cases (individual bits and groups) in
243 // tablegen declaration order.
244 for (const auto &enumerant : enumerants) {
245 if (enumerant.getValue() != 0)
246 os << formatv(formatCompare, enumerant.getValue(), enumerant.getStr());
247 }
248 }
249 os << formatv(" return ::llvm::join(strs, \"{0}\");\n", separator);
250
251 os << "}\n\n";
252 }
253
emitStrToSymFnForIntEnum(const Record & enumDef,raw_ostream & os)254 static void emitStrToSymFnForIntEnum(const Record &enumDef, raw_ostream &os) {
255 EnumAttr enumAttr(enumDef);
256 StringRef enumName = enumAttr.getEnumClassName();
257 StringRef strToSymFnName = enumAttr.getStringToSymbolFnName();
258 auto enumerants = enumAttr.getAllCases();
259
260 os << formatv("::llvm::Optional<{0}> {1}(::llvm::StringRef str) {{\n",
261 enumName, strToSymFnName);
262 os << formatv(" return ::llvm::StringSwitch<::llvm::Optional<{0}>>(str)\n",
263 enumName);
264 for (const auto &enumerant : enumerants) {
265 auto symbol = enumerant.getSymbol();
266 auto str = enumerant.getStr();
267 os << formatv(" .Case(\"{1}\", {0}::{2})\n", enumName, str,
268 makeIdentifier(symbol));
269 }
270 os << " .Default(::llvm::None);\n";
271 os << "}\n";
272 }
273
emitStrToSymFnForBitEnum(const Record & enumDef,raw_ostream & os)274 static void emitStrToSymFnForBitEnum(const Record &enumDef, raw_ostream &os) {
275 EnumAttr enumAttr(enumDef);
276 StringRef enumName = enumAttr.getEnumClassName();
277 std::string underlyingType = std::string(enumAttr.getUnderlyingType());
278 StringRef strToSymFnName = enumAttr.getStringToSymbolFnName();
279 StringRef separator = enumDef.getValueAsString("separator");
280 StringRef separatorTrimmed = separator.trim();
281 auto enumerants = enumAttr.getAllCases();
282 auto allBitsUnsetCase = getAllBitsUnsetCase(enumerants);
283
284 os << formatv("::llvm::Optional<{0}> {1}(::llvm::StringRef str) {{\n",
285 enumName, strToSymFnName);
286
287 if (allBitsUnsetCase) {
288 os << " // Special case for all bits unset.\n";
289 StringRef caseSymbol = allBitsUnsetCase->getSymbol();
290 os << formatv(" if (str == \"{1}\") return {0}::{2};\n\n", enumName,
291 caseSymbol, makeIdentifier(caseSymbol));
292 }
293
294 // Split the string to get symbols for all the bits.
295 os << " ::llvm::SmallVector<::llvm::StringRef, 2> symbols;\n";
296 // Remove whitespace from the separator string when parsing.
297 os << formatv(" str.split(symbols, \"{0}\");\n\n", separatorTrimmed);
298
299 os << formatv(" {0} val = 0;\n", underlyingType);
300 os << " for (auto symbol : symbols) {\n";
301
302 // Convert each symbol to the bit ordinal and set the corresponding bit.
303 os << formatv(" auto bit = "
304 "llvm::StringSwitch<::llvm::Optional<{0}>>(symbol.trim())\n",
305 underlyingType);
306 for (const auto &enumerant : enumerants) {
307 // Skip the special enumerant for None.
308 if (auto val = enumerant.getValue())
309 os.indent(6) << formatv(".Case(\"{0}\", {1})\n", enumerant.getStr(), val);
310 }
311 os.indent(6) << ".Default(::llvm::None);\n";
312
313 os << " if (bit) { val |= *bit; } else { return ::llvm::None; }\n";
314 os << " }\n";
315
316 os << formatv(" return static_cast<{0}>(val);\n", enumName);
317 os << "}\n\n";
318 }
319
emitUnderlyingToSymFnForIntEnum(const Record & enumDef,raw_ostream & os)320 static void emitUnderlyingToSymFnForIntEnum(const Record &enumDef,
321 raw_ostream &os) {
322 EnumAttr enumAttr(enumDef);
323 StringRef enumName = enumAttr.getEnumClassName();
324 std::string underlyingType = std::string(enumAttr.getUnderlyingType());
325 StringRef underlyingToSymFnName = enumAttr.getUnderlyingToSymbolFnName();
326 auto enumerants = enumAttr.getAllCases();
327
328 // Avoid generating the underlying value to symbol conversion function if
329 // there is an enumerant without explicit value.
330 if (llvm::any_of(enumerants, [](EnumAttrCase enumerant) {
331 return enumerant.getValue() < 0;
332 }))
333 return;
334
335 os << formatv("::llvm::Optional<{0}> {1}({2} value) {{\n", enumName,
336 underlyingToSymFnName,
337 underlyingType.empty() ? std::string("unsigned")
338 : underlyingType)
339 << " switch (value) {\n";
340 for (const auto &enumerant : enumerants) {
341 auto symbol = enumerant.getSymbol();
342 auto value = enumerant.getValue();
343 os << formatv(" case {0}: return {1}::{2};\n", value, enumName,
344 makeIdentifier(symbol));
345 }
346 os << " default: return ::llvm::None;\n"
347 << " }\n"
348 << "}\n\n";
349 }
350
emitSpecializedAttrDef(const Record & enumDef,raw_ostream & os)351 static void emitSpecializedAttrDef(const Record &enumDef, raw_ostream &os) {
352 EnumAttr enumAttr(enumDef);
353 StringRef enumName = enumAttr.getEnumClassName();
354 StringRef attrClassName = enumAttr.getSpecializedAttrClassName();
355 llvm::Record *baseAttrDef = enumAttr.getBaseAttrClass();
356 Attribute baseAttr(baseAttrDef);
357
358 // Emit classof method
359
360 os << formatv("bool {0}::classof(::mlir::Attribute attr) {{\n",
361 attrClassName);
362
363 mlir::tblgen::Pred baseAttrPred = baseAttr.getPredicate();
364 if (baseAttrPred.isNull())
365 PrintFatalError("ERROR: baseAttrClass for EnumAttr has no Predicate\n");
366
367 std::string condition = baseAttrPred.getCondition();
368 FmtContext verifyCtx;
369 verifyCtx.withSelf("attr");
370 os << tgfmt(" return $0;\n", /*ctx=*/nullptr, tgfmt(condition, &verifyCtx));
371
372 os << "}\n";
373
374 // Emit get method
375
376 os << formatv("{0} {0}::get(::mlir::MLIRContext *context, {1} val) {{\n",
377 attrClassName, enumName);
378
379 StringRef underlyingType = enumAttr.getUnderlyingType();
380
381 // Assuming that it is IntegerAttr constraint
382 int64_t bitwidth = 64;
383 if (baseAttrDef->getValue("valueType")) {
384 auto *valueTypeDef = baseAttrDef->getValueAsDef("valueType");
385 if (valueTypeDef->getValue("bitwidth"))
386 bitwidth = valueTypeDef->getValueAsInt("bitwidth");
387 }
388
389 os << formatv(" ::mlir::IntegerType intType = "
390 "::mlir::IntegerType::get(context, {0});\n",
391 bitwidth);
392 os << formatv(" ::mlir::IntegerAttr baseAttr = "
393 "::mlir::IntegerAttr::get(intType, static_cast<{0}>(val));\n",
394 underlyingType);
395 os << formatv(" return baseAttr.cast<{0}>();\n", attrClassName);
396
397 os << "}\n";
398
399 // Emit getValue method
400
401 os << formatv("{0} {1}::getValue() const {{\n", enumName, attrClassName);
402
403 os << formatv(" return static_cast<{0}>(::mlir::IntegerAttr::getInt());\n",
404 enumName);
405
406 os << "}\n";
407 }
408
emitUnderlyingToSymFnForBitEnum(const Record & enumDef,raw_ostream & os)409 static void emitUnderlyingToSymFnForBitEnum(const Record &enumDef,
410 raw_ostream &os) {
411 EnumAttr enumAttr(enumDef);
412 StringRef enumName = enumAttr.getEnumClassName();
413 std::string underlyingType = std::string(enumAttr.getUnderlyingType());
414 StringRef underlyingToSymFnName = enumAttr.getUnderlyingToSymbolFnName();
415 auto enumerants = enumAttr.getAllCases();
416 auto allBitsUnsetCase = getAllBitsUnsetCase(enumerants);
417
418 os << formatv("::llvm::Optional<{0}> {1}({2} value) {{\n", enumName,
419 underlyingToSymFnName, underlyingType);
420 if (allBitsUnsetCase) {
421 os << " // Special case for all bits unset.\n";
422 os << formatv(" if (value == 0) return {0}::{1};\n\n", enumName,
423 makeIdentifier(allBitsUnsetCase->getSymbol()));
424 }
425 llvm::SmallVector<std::string, 8> values;
426 for (const auto &enumerant : enumerants) {
427 if (auto val = enumerant.getValue())
428 values.push_back(std::string(formatv("{0}u", val)));
429 }
430 os << formatv(" if (value & ~static_cast<{0}>({1})) return llvm::None;\n",
431 underlyingType, llvm::join(values, " | "));
432 os << formatv(" return static_cast<{0}>(value);\n", enumName);
433 os << "}\n";
434 }
435
emitEnumDecl(const Record & enumDef,raw_ostream & os)436 static void emitEnumDecl(const Record &enumDef, raw_ostream &os) {
437 EnumAttr enumAttr(enumDef);
438 StringRef enumName = enumAttr.getEnumClassName();
439 StringRef cppNamespace = enumAttr.getCppNamespace();
440 std::string underlyingType = std::string(enumAttr.getUnderlyingType());
441 StringRef description = enumAttr.getSummary();
442 StringRef strToSymFnName = enumAttr.getStringToSymbolFnName();
443 StringRef symToStrFnName = enumAttr.getSymbolToStringFnName();
444 StringRef symToStrFnRetType = enumAttr.getSymbolToStringFnRetType();
445 StringRef underlyingToSymFnName = enumAttr.getUnderlyingToSymbolFnName();
446 auto enumerants = enumAttr.getAllCases();
447
448 llvm::SmallVector<StringRef, 2> namespaces;
449 llvm::SplitString(cppNamespace, namespaces, "::");
450
451 for (auto ns : namespaces)
452 os << "namespace " << ns << " {\n";
453
454 // Emit the enum class definition
455 emitEnumClass(enumDef, enumName, underlyingType, description, enumerants, os);
456
457 // Emit conversion function declarations
458 if (llvm::all_of(enumerants, [](EnumAttrCase enumerant) {
459 return enumerant.getValue() >= 0;
460 })) {
461 os << formatv(
462 "::llvm::Optional<{0}> {1}({2});\n", enumName, underlyingToSymFnName,
463 underlyingType.empty() ? std::string("unsigned") : underlyingType);
464 }
465 os << formatv("{2} {1}({0});\n", enumName, symToStrFnName, symToStrFnRetType);
466 os << formatv("::llvm::Optional<{0}> {1}(::llvm::StringRef);\n", enumName,
467 strToSymFnName);
468
469 if (enumAttr.isBitEnum()) {
470 emitOperators(enumDef, os);
471 } else {
472 emitMaxValueFn(enumDef, os);
473 }
474
475 // Generate a generic `stringifyEnum` function that forwards to the method
476 // specified by the user.
477 const char *const stringifyEnumStr = R"(
478 inline {0} stringifyEnum({1} enumValue) {{
479 return {2}(enumValue);
480 }
481 )";
482 os << formatv(stringifyEnumStr, symToStrFnRetType, enumName, symToStrFnName);
483
484 // Generate a generic `symbolizeEnum` function that forwards to the method
485 // specified by the user.
486 const char *const symbolizeEnumStr = R"(
487 template <typename EnumType>
488 ::llvm::Optional<EnumType> symbolizeEnum(::llvm::StringRef);
489
490 template <>
491 inline ::llvm::Optional<{0}> symbolizeEnum<{0}>(::llvm::StringRef str) {
492 return {1}(str);
493 }
494 )";
495 os << formatv(symbolizeEnumStr, enumName, strToSymFnName);
496
497 const char *const attrClassDecl = R"(
498 class {1} : public ::mlir::{2} {
499 public:
500 using ValueType = {0};
501 using ::mlir::{2}::{2};
502 static bool classof(::mlir::Attribute attr);
503 static {1} get(::mlir::MLIRContext *context, {0} val);
504 {0} getValue() const;
505 };
506 )";
507 if (enumAttr.genSpecializedAttr()) {
508 StringRef attrClassName = enumAttr.getSpecializedAttrClassName();
509 StringRef baseAttrClassName = "IntegerAttr";
510 os << formatv(attrClassDecl, enumName, attrClassName, baseAttrClassName);
511 }
512
513 for (auto ns : llvm::reverse(namespaces))
514 os << "} // namespace " << ns << "\n";
515
516 // Emit DenseMapInfo for this enum class
517 emitDenseMapInfo(enumName, underlyingType, cppNamespace, os);
518 }
519
emitEnumDecls(const RecordKeeper & recordKeeper,raw_ostream & os)520 static bool emitEnumDecls(const RecordKeeper &recordKeeper, raw_ostream &os) {
521 llvm::emitSourceFileHeader("Enum Utility Declarations", os);
522
523 auto defs = recordKeeper.getAllDerivedDefinitions("EnumAttrInfo");
524 for (const auto *def : defs)
525 emitEnumDecl(*def, os);
526
527 return false;
528 }
529
emitEnumDef(const Record & enumDef,raw_ostream & os)530 static void emitEnumDef(const Record &enumDef, raw_ostream &os) {
531 EnumAttr enumAttr(enumDef);
532 StringRef cppNamespace = enumAttr.getCppNamespace();
533
534 llvm::SmallVector<StringRef, 2> namespaces;
535 llvm::SplitString(cppNamespace, namespaces, "::");
536
537 for (auto ns : namespaces)
538 os << "namespace " << ns << " {\n";
539
540 if (enumAttr.isBitEnum()) {
541 emitSymToStrFnForBitEnum(enumDef, os);
542 emitStrToSymFnForBitEnum(enumDef, os);
543 emitUnderlyingToSymFnForBitEnum(enumDef, os);
544 } else {
545 emitSymToStrFnForIntEnum(enumDef, os);
546 emitStrToSymFnForIntEnum(enumDef, os);
547 emitUnderlyingToSymFnForIntEnum(enumDef, os);
548 }
549
550 if (enumAttr.genSpecializedAttr())
551 emitSpecializedAttrDef(enumDef, os);
552
553 for (auto ns : llvm::reverse(namespaces))
554 os << "} // namespace " << ns << "\n";
555 os << "\n";
556 }
557
emitEnumDefs(const RecordKeeper & recordKeeper,raw_ostream & os)558 static bool emitEnumDefs(const RecordKeeper &recordKeeper, raw_ostream &os) {
559 llvm::emitSourceFileHeader("Enum Utility Definitions", os);
560
561 auto defs = recordKeeper.getAllDerivedDefinitions("EnumAttrInfo");
562 for (const auto *def : defs)
563 emitEnumDef(*def, os);
564
565 return false;
566 }
567
568 // Registers the enum utility generator to mlir-tblgen.
569 static mlir::GenRegistration
570 genEnumDecls("gen-enum-decls", "Generate enum utility declarations",
__anon7ff5e8610302(const RecordKeeper &records, raw_ostream &os) 571 [](const RecordKeeper &records, raw_ostream &os) {
572 return emitEnumDecls(records, os);
573 });
574
575 // Registers the enum utility generator to mlir-tblgen.
576 static mlir::GenRegistration
577 genEnumDefs("gen-enum-defs", "Generate enum utility definitions",
__anon7ff5e8610402(const RecordKeeper &records, raw_ostream &os) 578 [](const RecordKeeper &records, raw_ostream &os) {
579 return emitEnumDefs(records, os);
580 });
581