LLZK 0.1.0
Veridise's ZK Language IR
Loading...
Searching...
No Matches
EnumCAPIGen.cpp
Go to the documentation of this file.
1//===- EnumCAPIGen.cpp - C API generator for enum attributes --------------===//
2//
3// Part of the LLZK Project, under the Apache License v2.0.
4// See LICENSE.txt for license information.
5// Copyright 2025 Veridise Inc.
6// SPDX-License-Identifier: Apache-2.0
7//
8//===----------------------------------------------------------------------===//
9//
10// EnumCAPIGen generates C API enum declarations from EnumAttr definitions
11// in TableGen files. This allows exposing MLIR enum attributes to C APIs.
12//
13//===----------------------------------------------------------------------===//
14
15#include <mlir/TableGen/Attribute.h>
16#include <mlir/TableGen/GenInfo.h>
17
18#include <llvm/Support/CommandLine.h>
19#include <llvm/Support/FormatVariadic.h>
20#include <llvm/TableGen/Record.h>
21#include <llvm/TableGen/TableGenBackend.h>
22
23#include "CommonCAPIGen.h"
24
25using namespace mlir;
26using namespace mlir::tblgen;
27
28namespace {
29
31struct EnumHeaderGenerator : public HeaderGenerator {
32 using HeaderGenerator::HeaderGenerator;
33 virtual ~EnumHeaderGenerator() = default;
34
35 void setEnumName(StringRef enumCppNamespace, StringRef enumClassName) {
36 std::string classNamePascal = toPascalCase(enumClassName);
37 this->cEnumName = cEnumName =
39 this->cEnumAltName = toPascalCase(enumCppNamespace) + classNamePascal;
40 // Reset case labels for next enum
41 caseLabels.clear();
42 }
43
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()
49 );
50 }
51
52 void genEnumDeclaration() const {
53 static constexpr char fmt[] = R"(
54enum {0} {{
55{2}
56};
57// type name based on prefix + dialect + enum class name
58typedef enum {0} {0};
59// type name based on cpp namespace + enum class name
60typedef enum {0} {1};
61)";
62 assert(!cEnumName.empty() && "cEnumName must be set");
63 os << llvm::formatv(fmt, cEnumName, cEnumAltName, llvm::join(caseLabels, ",\n"));
64 }
65
68 void genWrapAndUnwrapDeclaration(StringRef enumCppNamespace, StringRef enumClassName) const {
69 static constexpr char fmt[] = R"(
70static inline {0} wrap({1} cpp) {
71 return {0}(cpp);
72}
73static inline {1} unwrap({0} c) {
74 return {1}(c);
75}
76)";
77 assert(!cEnumName.empty() && "cEnumName must be set");
78 os << llvm::formatv(fmt, cEnumName, enumCppNamespace + "::" + enumClassName);
79 }
80
81protected:
82 std::string cEnumName;
86 std::string cEnumAltName;
88 SmallVector<std::string> caseLabels;
89};
90
91} // namespace
92
94static bool emitEnumCAPIHeader(const llvm::RecordKeeper &records, raw_ostream &os) {
95 emitSourceFileHeader("Enum C API Declarations", os, records);
96
97 EnumHeaderGenerator generator("Enum", os);
98 generator.genPrologue();
99
100 // Find all EnumAttr definitions
101 for (const auto *def : records.getAllDerivedDefinitionsIfDefined("EnumAttrInfo")) {
102 const EnumAttr enumInfo(def);
103 StringRef enumCppNamespace = enumInfo.getCppNamespace();
104
105 // Generate for the selected dialect only
106 // EnumAttr does not contain a Dialect reference, so filter by C++ namespace instead.
107 if (!DialectName.empty() && !enumCppNamespace.contains_insensitive(DialectName)) {
108 continue;
109 }
110
111 std::vector<EnumAttrCase> enumCases = enumInfo.getAllCases();
112 if (enumCases.empty()) {
113 continue;
114 }
115
116 generator.setEnumName(enumCppNamespace, enumInfo.getEnumClassName());
117 for (EnumAttrCase &enumCase : enumCases) {
118 generator.genCaseLabel(enumCase);
119 }
120 generator.genEnumDeclaration();
121 generator.genWrapAndUnwrapDeclaration(enumCppNamespace, enumInfo.getEnumClassName());
122 }
123
124 generator.genEpilogue();
125 return false;
126}
127
128static mlir::GenRegistration genEnumCAPIHeader(
129 "gen-enum-capi-header", "Generate C API enum declarations from EnumAttr definitions",
130 &emitEnumCAPIHeader
131);
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 header file elements.