17#include <mlir/TableGen/Attribute.h>
18#include <mlir/TableGen/GenInfo.h>
20#include <llvm/Support/CommandLine.h>
21#include <llvm/Support/FormatVariadic.h>
22#include <llvm/TableGen/Record.h>
23#include <llvm/TableGen/TableGenBackend.h>
26using namespace mlir::tblgen;
32 using HeaderGenerator::HeaderGenerator;
33 ~EnumHeaderGenerator()
override =
default;
35 void setEnumName(StringRef enumCppNamespace, StringRef enumClassName) {
36 std::string classNamePascal =
toPascalCase(enumClassName);
38 this->cEnumAltName =
toPascalCase(enumCppNamespace) + classNamePascal;
39 this->cppQualifiedPrefix = enumCppNamespace.str() +
"::" + enumClassName.str() +
"::";
44 void genCaseLabel(
const EnumAttrCase &enumCase) {
45 static constexpr char fmt[] =
" /// `{0}{2}`\n {1}_{2} = {3}";
46 assert(!cEnumName.empty() &&
"cEnumName must be set");
47 assert(!cppQualifiedPrefix.empty() &&
"cppQualifiedPrefix must be set");
48 this->caseLabels.push_back(
49 llvm::formatv(fmt, cppQualifiedPrefix, cEnumName, enumCase.getSymbol(), enumCase.getValue())
54 void genEnumDeclaration()
const {
55 static constexpr char fmt[] = R
"(
59// type name based on prefix + dialect + enum class name
61// type name based on cpp namespace + enum class name
64 assert(!cEnumName.empty() && "cEnumName must be set");
65 os << llvm::formatv(fmt, cEnumName, cEnumAltName, llvm::join(caseLabels,
",\n"));
69 std::string cEnumName;
73 std::string cEnumAltName;
75 std::string cppQualifiedPrefix;
77 SmallVector<std::string> caseLabels;
82 using ImplementationGenerator::ImplementationGenerator;
83 ~EnumImplementationGenerator()
override =
default;
85 void setEnumName(StringRef , StringRef enumClassName) {
86 std::string classNamePascal =
toPascalCase(enumClassName);
92 void genWrapAndUnwrapDeclaration(StringRef enumCppNamespace, StringRef enumClassName)
const {
93 static constexpr char fmt[] = R
"(
94 static inline {0} wrap({1} cpp) {
97 static inline {1} unwrap({0} c) {
101 assert(!cEnumName.empty() && "cEnumName must be set");
102 os << llvm::formatv(fmt, cEnumName, enumCppNamespace +
"::" + enumClassName);
106 std::string cEnumName;
112static bool emitEnumCAPIHeader(
const llvm::RecordKeeper &records, raw_ostream &os) {
113 emitSourceFileHeader(
"Enum C API Declarations", os, records);
115 EnumHeaderGenerator generator(
"Enum", os);
116 generator.genPrologue();
119 for (
const auto *def : records.getAllDerivedDefinitionsIfDefined(
"EnumAttrInfo")) {
120 const EnumAttr enumInfo(def);
121 StringRef enumCppNamespace = enumInfo.getCppNamespace();
129 std::vector<EnumAttrCase> enumCases = enumInfo.getAllCases();
130 if (enumCases.empty()) {
134 generator.setEnumName(enumCppNamespace, enumInfo.getEnumClassName());
135 for (EnumAttrCase &enumCase : enumCases) {
136 generator.genCaseLabel(enumCase);
138 generator.genEnumDeclaration();
141 generator.genEpilogue();
146static bool emitEnumCAPIImpl(
const llvm::RecordKeeper &records, raw_ostream &os) {
147 emitSourceFileHeader(
"Enum C API Implementations", os, records);
149 EnumImplementationGenerator generator(
"Enum", os);
152 for (
const auto *def : records.getAllDerivedDefinitionsIfDefined(
"EnumAttrInfo")) {
153 const EnumAttr enumInfo(def);
154 StringRef enumCppNamespace = enumInfo.getCppNamespace();
162 std::vector<EnumAttrCase> enumCases = enumInfo.getAllCases();
163 if (enumCases.empty()) {
167 generator.setEnumName(enumCppNamespace, enumInfo.getEnumClassName());
168 generator.genWrapAndUnwrapDeclaration(enumCppNamespace, enumInfo.getEnumClassName());
173static mlir::GenRegistration genEnumCAPIHeader(
174 "gen-enum-capi-header",
"Generate C API enum declarations from EnumAttr definitions",
178static mlir::GenRegistration genEnumCAPIImpl(
179 "gen-enum-capi-impl",
"Generate enum C API wrap/unwrap implementations", &emitEnumCAPIImpl
llvm::cl::opt< std::string > DialectName
llvm::cl::opt< std::string > FunctionPrefix
std::string toPascalCase(mlir::StringRef str)
Convert names separated by underscore or colon to PascalCase.
Generator for common C implementation file elements.