15#include <mlir/TableGen/Attribute.h>
16#include <mlir/TableGen/GenInfo.h>
18#include <llvm/Support/CommandLine.h>
19#include <llvm/Support/FormatVariadic.h>
20#include <llvm/TableGen/Record.h>
21#include <llvm/TableGen/TableGenBackend.h>
26using namespace mlir::tblgen;
32 using HeaderGenerator::HeaderGenerator;
33 virtual ~EnumHeaderGenerator() =
default;
35 void setEnumName(StringRef enumCppNamespace, StringRef enumClassName) {
36 std::string classNamePascal =
toPascalCase(enumClassName);
37 this->cEnumName = cEnumName =
39 this->cEnumAltName =
toPascalCase(enumCppNamespace) + classNamePascal;
44 void genCaseLabel(
const EnumAttrCase &enumCase) {
45 static constexpr char fmt[] =
" {0}_{1} = {2}";
46 assert(!cEnumName.empty() &&
"cEnumName must be set");
47 this->caseLabels.push_back(
48 llvm::formatv(fmt, cEnumName, enumCase.getSymbol().upper(), enumCase.getValue()).str()
52 void genEnumDeclaration()
const {
53 static constexpr char fmt[] = R
"(
57// type name based on prefix + dialect + enum class name
59// type name based on cpp namespace + enum class name
62 assert(!cEnumName.empty() && "cEnumName must be set");
63 os << llvm::formatv(fmt, cEnumName, cEnumAltName, llvm::join(caseLabels,
",\n"));
68 void genWrapAndUnwrapDeclaration(StringRef enumCppNamespace, StringRef enumClassName)
const {
69 static constexpr char fmt[] = R
"(
70static inline {0} wrap({1} cpp) {
73static inline {1} unwrap({0} c) {
77 assert(!cEnumName.empty() && "cEnumName must be set");
78 os << llvm::formatv(fmt, cEnumName, enumCppNamespace +
"::" + enumClassName);
82 std::string cEnumName;
86 std::string cEnumAltName;
88 SmallVector<std::string> caseLabels;
94static bool emitEnumCAPIHeader(
const llvm::RecordKeeper &records, raw_ostream &os) {
95 emitSourceFileHeader(
"Enum C API Declarations", os, records);
97 EnumHeaderGenerator generator(
"Enum", os);
98 generator.genPrologue();
101 for (
const auto *def : records.getAllDerivedDefinitionsIfDefined(
"EnumAttrInfo")) {
102 const EnumAttr enumInfo(def);
103 StringRef enumCppNamespace = enumInfo.getCppNamespace();
111 std::vector<EnumAttrCase> enumCases = enumInfo.getAllCases();
112 if (enumCases.empty()) {
116 generator.setEnumName(enumCppNamespace, enumInfo.getEnumClassName());
117 for (EnumAttrCase &enumCase : enumCases) {
118 generator.genCaseLabel(enumCase);
120 generator.genEnumDeclaration();
121 generator.genWrapAndUnwrapDeclaration(enumCppNamespace, enumInfo.getEnumClassName());
124 generator.genEpilogue();
128static mlir::GenRegistration genEnumCAPIHeader(
129 "gen-enum-capi-header",
"Generate C API enum declarations from EnumAttr definitions",
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.