LLZK 3.0.0
An open-source IR for Zero Knowledge (ZK) circuits
Loading...
Searching...
No Matches
CommonCAPIGen.h
Go to the documentation of this file.
1//===- CommonCAPIGen.h - Common utilities for C API generation ------------===//
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// Common utilities shared between all CAPI generators (ops, attrs, types)
11//
12//===----------------------------------------------------------------------===//
13
14#pragma once
15
16#include <mlir/TableGen/Dialect.h>
17
18#include <llvm/ADT/StringExtras.h>
19#include <llvm/ADT/StringRef.h>
20#include <llvm/ADT/StringSwitch.h>
21#include <llvm/Support/CommandLine.h>
22#include <llvm/Support/FormatVariadic.h>
23
24#include <memory>
25#include <string>
26
27constexpr bool WARN_SKIPPED_METHODS = false;
28
30template <typename S> inline void warnSkipped(const S &methodName, const std::string &message) {
32 llvm::errs() << "Warning: Skipping method '" << methodName << "' - " << message << '\n';
33 }
34}
35
37template <typename S>
38inline void warnSkippedNoConversion(const S &methodName, const std::string &cppType) {
40 warnSkipped(methodName, "no conversion to C API type for '" + cppType + '\'');
41 }
42}
43
44// Forward declarations for Clang classes
45namespace clang {
46class Lexer;
47class SourceManager;
48} // namespace clang
49
50namespace mlir::tblgen {
51class Operator;
52} // namespace mlir::tblgen
53
55llvm::cl::opt<std::string> &getDialectName();
56
58llvm::cl::opt<std::string> &getFunctionPrefix();
59
61llvm::cl::opt<bool> &getGenIsA();
62
64llvm::cl::opt<bool> &getGenOpBuild();
65
67llvm::cl::opt<bool> &getGenOpOperandGetters();
68
70llvm::cl::opt<bool> &getGenOpOperandSetters();
71
73llvm::cl::opt<bool> &getGenOpAttributeGetters();
74
76llvm::cl::opt<bool> &getGenOpAttributeSetters();
77
79llvm::cl::opt<bool> &getGenOpRegionGetters();
80
82llvm::cl::opt<bool> &getGenOpResultGetters();
83
85llvm::cl::opt<bool> &getGenTypeOrAttrGet();
86
88llvm::cl::opt<bool> &getGenTypeOrAttrParamGetters();
89
91llvm::cl::opt<bool> &getGenExtraClassMethods();
92
100inline std::string toPascalCase(mlir::StringRef str) {
101 if (str.empty()) {
102 return "";
103 }
104
105 std::string result;
106 result.reserve(str.size());
107 llvm::raw_string_ostream resultStream(result);
108 bool capitalizeNext = true;
109
110 for (char c : str) {
111 if (c == '_' || c == ':') {
112 capitalizeNext = true;
113 } else {
114 resultStream << (capitalizeNext ? llvm::toUpper(c) : c);
115 capitalizeNext = false;
116 }
117 }
118
119 return result;
120}
121
125inline bool isIntegerType(mlir::StringRef type) {
126 // Consume optional root namespace token
127 type.consume_front("::");
128 // Handle special names first
129 if (type == "signed" || type == "unsigned" || type == "size_t" || type == "char32_t" ||
130 type == "char16_t" || type == "char8_t" || type == "wchar_t") {
131 return true;
132 }
133 // Handle standard integer types with optional signed/unsigned prefix
134 type.consume_front("signed ") || type.consume_front("unsigned ");
135 if (type == "char" || type == "int" || type == "short" || type == "short int" || type == "long" ||
136 type == "long int" || type == "long long" || type == "long long int") {
137 return true;
138 }
139 // Handle fixed-width integer types (https://cppreference.com/w/cpp/types/integer.html)
140 type.consume_front("std::"); // optional
141 if (type.consume_back("_t") && (type.consume_front("int") || type.consume_front("uint"))) {
142 // intmax_t, intptr_t, uintmax_t, uintptr_t
143 if (type == "max" || type == "ptr") {
144 return true;
145 }
146 // Optional "_fast" or "_least" followed by bit width to cover the rest
147 type.consume_front("_fast") || type.consume_front("_least");
148 if (type == "8" || type == "16" || type == "32" || type == "64") {
149 return true;
150 }
151 }
152 return false;
153}
154
161inline bool isPrimitiveType(mlir::StringRef cppType) {
162 cppType.consume_front("::");
163 return cppType == "void" || cppType == "bool" || cppType == "float" || cppType == "double" ||
164 cppType == "long double" || isIntegerType(cppType);
165}
166
170inline bool isCppModifierKeyword(mlir::StringRef tokenText) {
171 return llvm::StringSwitch<bool>(tokenText)
172 .Case("inline", true)
173 .Case("static", true)
174 .Case("virtual", true)
175 .Case("explicit", true)
176 .Case("constexpr", true)
177 .Case("consteval", true)
178 .Case("extern", true)
179 .Case("mutable", true)
180 .Case("friend", true)
181 .Default(false);
182}
183
187inline bool isCppLanguageConstruct(mlir::StringRef methodName) {
188 return llvm::StringSwitch<bool>(methodName)
189 .Case("if", true)
190 .Case("for", true)
191 .Case("while", true)
192 .Case("switch", true)
193 .Case("return", true)
194 .Case("sizeof", true)
195 .Case("decltype", true)
196 .Case("alignof", true)
197 .Case("typeid", true)
198 .Case("static_assert", true)
199 .Case("noexcept", true)
200 .Default(false);
201}
202
204inline bool isDynamicAPIntType(mlir::StringRef cppType) {
205 cppType.consume_front("::");
206 return cppType == "llzk::DynamicAPIntValue" || cppType == "llvm::DynamicAPInt";
207}
208
212inline bool isArrayRefType(mlir::StringRef cppType) {
213 cppType.consume_front("::");
214 cppType.consume_front("llvm::") || cppType.consume_front("mlir::");
215 return cppType.starts_with("ArrayRef<");
216}
217
219inline mlir::StringRef extractArrayRefElementType(mlir::StringRef cppType) {
220 assert(isArrayRefType(cppType) && "must check `isArrayRefType()` outside");
221
222 // Remove "ArrayRef<" prefix and ">" suffix
223 cppType.consume_front("::");
224 cppType.consume_front("llvm::") || cppType.consume_front("mlir::");
225 cppType.consume_front("ArrayRef<") && cppType.consume_back(">");
226 return cppType;
227}
228
238public:
242 explicit ClangLexerContext(mlir::StringRef source, mlir::StringRef bufferName = "input");
243
246 clang::Lexer &getLexer() const;
247
250 clang::SourceManager &getSourceManager() const;
251
254 bool isValid() const { return lexer != nullptr; }
255
256private:
257 struct Impl;
258 std::unique_ptr<Impl> impl;
259 clang::Lexer *lexer = nullptr;
260};
261
266 std::string type;
268 std::string name;
269
273 MethodParameter(const std::string &paramType, const std::string &paramName)
274 : type(mlir::StringRef(paramType).trim().str()),
275 name(mlir::StringRef(paramName).trim().str()) {}
276};
277
284 std::string returnType;
286 std::string methodName;
288 std::string documentation;
290 bool isConst = false;
292 bool hasParameters = false;
294 std::vector<MethodParameter> parameters;
295};
296
305llvm::SmallVector<ExtraMethod> getCAPIExposedOpMethods(const mlir::tblgen::Operator &op);
306
333llvm::SmallVector<ExtraMethod> parseExtraMethods(mlir::StringRef extraDecl);
334
339bool matchesMLIRClass(mlir::StringRef cppType, mlir::StringRef typeName);
340
344std::optional<std::string> tryCppTypeToCapiType(mlir::StringRef cppType);
345
352std::string mapCppTypeToCapiType(mlir::StringRef cppType);
353
359std::optional<std::string> mapCapiTypeToBasicCppType(mlir::StringRef capiType);
360
362struct Generator {
363 Generator(std::string_view recordKind, llvm::raw_ostream &outputStream)
364 : kind(recordKind), os(outputStream), dialectNameCapitalized(toPascalCase(getDialectName())) {
365 }
366 virtual ~Generator() = default;
367
371 virtual void
372 setNamespaceAndClassName(const mlir::tblgen::Dialect &d, mlir::StringRef cppClassName) {
373 this->dialectNamespace = d.getCppNamespace();
374 this->className = cppClassName;
375 }
376
379 virtual void genExtraMethods(mlir::StringRef extraDecl) const {
380 if (extraDecl.empty()) {
381 return;
382 }
383 for (const ExtraMethod &method : parseExtraMethods(extraDecl)) {
384 genExtraMethod(method);
385 }
386 }
387
390 virtual void genExtraMethod(const ExtraMethod &method) const = 0;
391
392protected:
393 std::string kind;
394 llvm::raw_ostream &os;
396 mlir::StringRef dialectNamespace;
397 mlir::StringRef className;
398};
399
401struct HeaderGenerator : public Generator {
403 ~HeaderGenerator() override = default;
404
405 virtual void genPrologue() const {
406 os << R"(
407#include "llzk-c/Builder.h"
408#include <mlir-c/IR.h>
410#ifdef __cplusplus
411extern "C" {
412#endif
413)";
414 }
415
416 virtual void genEpilogue() const {
417 os << R"(
418#ifdef __cplusplus
419}
420#endif
421)";
422 }
423
424 virtual void genIsADecl() const {
425 static constexpr char fmt[] = R"(
427MLIR_CAPI_EXPORTED bool {0}{1}IsA_{2}_{3}(Mlir{1});
428)";
429 assert(!dialectNamespace.empty() && "Dialect must be set");
430 os << llvm::formatv(
431 fmt,
432 getFunctionPrefix(), // {0}
433 kind, // {1}
435 className, // {3}
436 dialectNamespace // {4}
437 );
438 }
439
441 void genExtraMethod(const ExtraMethod &method) const override {
442 // Convert return type to C API type, skip if it can't be converted
443 std::optional<std::string> capiReturnTypeOpt = tryCppTypeToCapiType(method.returnType);
444 if (!capiReturnTypeOpt.has_value()) {
446 return;
447 }
448 std::string capiReturnType = capiReturnTypeOpt.value();
449
450 // Build parameter list
451 std::string paramList;
452 llvm::raw_string_ostream paramListStream(paramList);
453 paramListStream << llvm::formatv("Mlir{0} inp", kind);
454 for (const auto &param : method.parameters) {
455 // Convert C++ type to C API type for parameter, skip if it can't be converted
456 std::optional<std::string> capiParamTypeOpt = tryCppTypeToCapiType(param.type);
457 if (!capiParamTypeOpt.has_value()) {
458 warnSkippedNoConversion(method.methodName, param.type);
459 return;
460 }
461 const std::string &capiParamType = capiParamTypeOpt.value();
462 paramListStream << ", " << capiParamType << ' ' << param.name;
463 }
464
465 // Dynamic integers are returned through a callback to avoid dangling text.
466 if (isDynamicAPIntType(method.returnType)) {
467 capiReturnType = "void";
468 paramListStream << ", MlirStringCallback callback, void *userData";
469 }
470
471 // Generate declaration
472 if (method.documentation.empty()) {
473 os << llvm::formatv("\n/// {0}\n", method.methodName);
474 } else {
475 os << llvm::formatv("\n{0}\n", method.documentation);
476 }
477 os << llvm::formatv(
478 "MLIR_CAPI_EXPORTED {0} {1}{2}_{3}{4}({5});\n",
479 capiReturnType, // {0}
480 getFunctionPrefix(), // {1}
482 className, // {3}
483 toPascalCase(method.methodName), // {4}
484 paramList // {5}
485 );
486 }
487};
488
492 ~ImplementationGenerator() override = default;
493
494 virtual void genPrologue() const {}
495
496 virtual void genIsAImpl() const {
497 static constexpr char fmt[] = R"(
498bool {0}{1}IsA_{2}_{3}(Mlir{1} inp) {{
499 return llvm::isa<{3}>(unwrap(inp));
500}
501)";
502 assert(!className.empty() && "className must be set");
504 }
505
507 void genExtraMethod(const ExtraMethod &method) const override {
508 // Convert return type to C API type, skip if it can't be converted
509 std::optional<std::string> capiReturnTypeOpt = tryCppTypeToCapiType(method.returnType);
510 if (!capiReturnTypeOpt.has_value()) {
512 return;
513 }
514 std::string capiReturnType = capiReturnTypeOpt.value();
515
516 // Build the return statement prefix and suffix
517 std::string returnPrefix;
518 std::string returnSuffix;
519 mlir::StringRef cppReturnType = method.returnType;
520
521 if (cppReturnType == "void") {
522 // "void" type doesn't even need "return"
523 returnPrefix = "";
524 returnSuffix = "";
525 } else if (isDynamicAPIntType(cppReturnType)) {
526 capiReturnType = "void";
527 returnPrefix = "std::string text;\n llvm::raw_string_ostream(text) << ";
528 returnSuffix = ";\n callback(wrap(llvm::StringRef(text)), userData)";
529 } else {
530 // Check if return needs wrapping
531 if (isPrimitiveType(cppReturnType)) {
532 // Primitive types don't need wrapping
533 returnPrefix = "return ";
534 returnSuffix = "";
535 } else if (capiReturnType.starts_with("Mlir")) {
536 // MLIR C API types need wrapping
537 returnPrefix = "return wrap(";
538 returnSuffix = ")";
539 } else {
540 return;
541 }
542 }
543
544 // Build parameter list for C API function signature
545 std::string paramList;
546 llvm::raw_string_ostream paramListStream(paramList);
547 paramListStream << llvm::formatv("Mlir{0} inp", kind);
548 for (const auto &param : method.parameters) {
549 // Convert C++ type to C API type for parameter, skip if it can't be converted
550 std::optional<std::string> capiParamTypeOpt = tryCppTypeToCapiType(param.type);
551 if (!capiParamTypeOpt.has_value()) {
552 warnSkippedNoConversion(method.methodName, param.type);
553 return;
554 }
555 const std::string &capiParamType = capiParamTypeOpt.value();
556 paramListStream << ", " << capiParamType << ' ' << param.name;
557 }
558
559 if (isDynamicAPIntType(cppReturnType)) {
560 paramListStream << ", MlirStringCallback callback, void *userData";
561 }
562
563 // Build argument list for C++ method call
564 std::string argList;
565 llvm::raw_string_ostream argListStream(argList);
566 for (size_t i = 0; i < method.parameters.size(); ++i) {
567 if (i > 0) {
568 argListStream << ", ";
569 }
570 const auto &param = method.parameters[i];
571
572 // Check if parameter needs unwrapping
573 mlir::StringRef cppParamType = param.type;
574 if (isPrimitiveType(cppParamType)) {
575 // Primitive types don't need unwrapping
576 argListStream << param.name;
577 } else {
578 // Convert C++ type to C API type for parameter, skip if it can't be converted
579 std::optional<std::string> capiParamTypeOpt = tryCppTypeToCapiType(cppParamType);
580 if (capiParamTypeOpt.has_value() && capiParamTypeOpt->starts_with("Mlir")) {
581 // MLIR C API types need unwrapping
582 argListStream << "unwrap(" << param.name << ')';
583 } else {
584 warnSkippedNoConversion(method.methodName, cppParamType.str());
585 return;
586 }
587 }
588 }
589
590 // Generate implementation
591 os << '\n';
592 os << llvm::formatv(
593 "{0} {1}{2}_{3}{4}({5}) {{\n",
594 capiReturnType, // {0}
595 getFunctionPrefix(), // {1}
597 className, // {3}
598 toPascalCase(method.methodName), // {4}
599 paramList // {5}
600 );
601 os << llvm::formatv(
602 " {0}llvm::cast<{1}>(unwrap(inp)).{2}({3}){4};\n",
603 returnPrefix, // {0}
604 className, // {1}
605 method.methodName, // {2}
606 argList, // {3}
607 returnSuffix // {4}
608 );
609 os << "}\n";
610 }
611};
612
614struct TestGenerator : public Generator {
616 ~TestGenerator() override = default;
617
619 virtual void genTestClassPrologue() const {
620 static constexpr char fmt[] = "class {0}{1}LinkTests : public CAPITest {{};\n";
621 os << llvm::formatv(fmt, dialectNameCapitalized, kind);
622 }
623
625 virtual void genIsATest() const {
626 static constexpr char fmt[] = R"(
628TEST_F({2}{1}LinkTests, IsA_{2}_{3}) {{
629 auto test{1} = createIndex{1}();
630
631 // This will always return false since `createIndex*` returns an MLIR builtin
632 EXPECT_FALSE({0}{1}IsA_{2}_{3}(test{1}));
633
634 {4}(test{1});
635}
636)";
637 assert(!className.empty() && "className must be set");
638 os << llvm::formatv(
639 fmt,
640 getFunctionPrefix(), // {0}
641 kind, // {1}
643 className, // {3}
644 genCleanup() // {4}
645 );
646 }
647
649 void genExtraMethod(const ExtraMethod &method) const override {
650 // Convert return type to C API type, skip if it can't be converted
651 std::optional<std::string> capiReturnTypeOpt = tryCppTypeToCapiType(method.returnType);
652 if (!capiReturnTypeOpt.has_value()) {
654 return;
655 }
656
657 // Build parameter list for dummy values
658 std::string dummyParams;
659 llvm::raw_string_ostream dummyParamsStream(dummyParams);
660 std::string paramList;
661 llvm::raw_string_ostream paramListStream(paramList);
662
663 for (const auto &param : method.parameters) {
664 // Convert C++ type to C API type for parameter, skip if it can't be converted
665 std::optional<std::string> capiParamTypeOpt = tryCppTypeToCapiType(param.type);
666 if (!capiParamTypeOpt.has_value()) {
667 warnSkippedNoConversion(method.methodName, param.type);
668 return;
669 }
670 const std::string &capiParamType = capiParamTypeOpt.value();
671 std::string name = param.name;
672
673 // Generate dummy value creation for each parameter
674 if (capiParamType == "bool") {
675 dummyParamsStream << " bool " << name << " = false;\n";
676 } else if (capiParamType == "MlirValue") {
677 dummyParamsStream << " auto " << name << " = mlirOperationGetResult(testOp, 0);\n";
678 } else if (capiParamType == "MlirType") {
679 dummyParamsStream << " auto " << name << " = createIndexType();\n";
680 } else if (capiParamType == "MlirAttribute") {
681 dummyParamsStream << " auto " << name << " = createIndexAttribute();\n";
682 } else if (capiParamType == "MlirStringRef") {
683 dummyParamsStream << " auto " << name << " = mlirStringRefCreateFromCString(\"\");\n";
684 } else if (isIntegerType(capiParamType)) {
685 dummyParamsStream << " " << capiParamType << ' ' << name << " = 0;\n";
686 } else {
687 // For unknown types, create a default-initialized variable
688 dummyParamsStream << " " << capiParamType << ' ' << name << " = {};\n";
689 }
690
691 paramListStream << ", " << name;
692 }
693
694 if (isDynamicAPIntType(method.returnType)) {
695 paramListStream << ", [](MlirStringRef, void *) {}, nullptr";
696 }
697
698 static constexpr char fmt[] = R"(
700TEST_F({2}{1}LinkTests, {0}_{3}_{4}) {{
701 auto test{1} = createIndex{1}();
702
703 if ({0}{1}IsA_{2}_{3}(test{1})) {{
704{5}
705 (void){0}{2}_{3}{4}(test{1}{6});
706 }
707
708 {7}(test{1});
709}
710)";
711 assert(!className.empty() && "className must be set");
712 os << llvm::formatv(
713 fmt,
714 getFunctionPrefix(), // {0}
715 kind, // {1}
717 className, // {3}
718 toPascalCase(method.methodName), // {4}
719 dummyParams, // {5}
720 paramList, // {6}
721 genCleanup() // {7}
722 );
723 }
724
734 virtual std::string genCleanup() const {
735 // The default case is to just comment out the rest of the cleanup line
736 return "//";
737 }
738};
mlir::StringRef extractArrayRefElementType(mlir::StringRef cppType)
Extract element type from ArrayRef<...>.
llvm::cl::opt< bool > & getGenOpOperandGetters()
Return the GenOpOperandGetters option, registering it on first access.
llvm::cl::opt< std::string > & getFunctionPrefix()
Return the FunctionPrefix option, registering it on first access.
bool isPrimitiveType(mlir::StringRef cppType)
Check if a C++ type is a known primitive type.
bool isDynamicAPIntType(mlir::StringRef cppType)
Whether a parameter represents an arbitrary-precision mathematical integer.
llvm::cl::opt< bool > & getGenOpRegionGetters()
Return the GenOpRegionGetters option, registering it on first access.
void warnSkippedNoConversion(const S &methodName, const std::string &cppType)
Print warning about skipping a function due to no conversion of C++ type to C API type.
llvm::cl::opt< bool > & getGenOpResultGetters()
Return the GenOpResultGetters option, registering it on first access.
llvm::cl::opt< std::string > & getDialectName()
Return the DialectName option, registering it on first access.
std::string mapCppTypeToCapiType(mlir::StringRef cppType)
Map C++ type to corresponding C API type.
bool isCppModifierKeyword(mlir::StringRef tokenText)
Check if a token text represents a C++ modifier/specifier keyword.
std::optional< std::string > tryCppTypeToCapiType(mlir::StringRef cppType)
Convert C++ type to MLIR C API type.
bool isArrayRefType(mlir::StringRef cppType)
Check if a C++ type is an ArrayRef type.
constexpr bool WARN_SKIPPED_METHODS
bool isIntegerType(mlir::StringRef type)
Check if a C++ type is a known integer type.
bool matchesMLIRClass(mlir::StringRef cppType, mlir::StringRef typeName)
Check if a C++ type matches an MLIR type pattern.
llvm::cl::opt< bool > & getGenOpAttributeSetters()
Return the GenOpAttributeSetters option, registering it on first access.
std::optional< std::string > mapCapiTypeToBasicCppType(mlir::StringRef capiType)
Map C API type to corresponding basic (not dialect-defined) C++ type.
llvm::cl::opt< bool > & getGenOpBuild()
Return the GenOpBuild option, registering it on first access.
llvm::cl::opt< bool > & getGenOpAttributeGetters()
Return the GenOpAttributeGetters option, registering it on first access.
llvm::SmallVector< ExtraMethod > getCAPIExposedOpMethods(const mlir::tblgen::Operator &op)
Return public operation methods explicitly requested by DeclareOpInterfaceMethods traits and declared...
llvm::cl::opt< bool > & getGenExtraClassMethods()
Return the GenExtraClassMethods option, registering it on first access.
llvm::cl::opt< bool > & getGenTypeOrAttrParamGetters()
Return the GenTypeOrAttrParamGetters option, registering it on first access.
llvm::cl::opt< bool > & getGenIsA()
Return the GenIsA option, registering it on first access.
llvm::cl::opt< bool > & getGenOpOperandSetters()
Return the GenOpOperandSetters option, registering it on first access.
llvm::cl::opt< bool > & getGenTypeOrAttrGet()
Return the GenTypeOrAttrGet option, registering it on first access.
llvm::SmallVector< ExtraMethod > parseExtraMethods(mlir::StringRef extraDecl)
Parse method declarations from an extraClassDeclaration using Clang's Lexer.
std::string toPascalCase(mlir::StringRef str)
Convert names separated by underscore or colon to PascalCase.
void warnSkipped(const S &methodName, const std::string &message)
Print warning about skipping a function.
bool isCppLanguageConstruct(mlir::StringRef methodName)
Check if a method name represents a C++ control flow keyword or language construct.
Apache License January AND DISTRIBUTION Definitions License shall mean the terms and conditions for and distribution as defined by Sections through of this document Licensor shall mean the copyright owner or entity authorized by the copyright owner that is granting the License Legal Entity shall mean the union of the acting entity and all other entities that control are controlled by or are under common control with that entity For the purposes of this definition control direct or to cause the direction or management of such whether by contract or including but not limited to software source documentation source
Definition LICENSE.txt:28
clang::SourceManager & getSourceManager() const
Get the source manager instance.
bool isValid() const
Check if the lexer was successfully created.
ClangLexerContext(mlir::StringRef source, mlir::StringRef bufferName="input")
Construct a lexer context for the given source code.
clang::Lexer & getLexer() const
Get the lexer instance.
Structure to represent a parsed method signature from an extraClassDeclaration.
bool isConst
Whether the method is const-qualified.
bool hasParameters
Whether the method has parameters (unsupported for now).
std::vector< MethodParameter > parameters
The parameters of the method.
std::string returnType
The C++ return type of the method.
std::string methodName
The name of the method.
std::string documentation
Properly escaped documentation comment (if any).
virtual ~Generator()=default
Generator(std::string_view recordKind, llvm::raw_ostream &outputStream)
mlir::StringRef className
mlir::StringRef dialectNamespace
virtual void genExtraMethods(mlir::StringRef extraDecl) const
Generate code for extra methods from an extraClassDeclaration.
virtual void setNamespaceAndClassName(const mlir::tblgen::Dialect &d, mlir::StringRef cppClassName)
Set the dialect and class name for code generation.
virtual void genExtraMethod(const ExtraMethod &method) const =0
Generate code for an extra method.
std::string dialectNameCapitalized
llvm::raw_ostream & os
std::string kind
Generator for common C header file elements.
Generator(std::string_view recordKind, llvm::raw_ostream &outputStream)
virtual void genPrologue() const
void genExtraMethod(const ExtraMethod &method) const override
Generate declaration for an extra method from an extraClassDeclaration.
~HeaderGenerator() override=default
virtual void genEpilogue() const
virtual void genIsADecl() const
Generator for common C implementation file elements.
Generator(std::string_view recordKind, llvm::raw_ostream &outputStream)
virtual void genIsAImpl() const
void genExtraMethod(const ExtraMethod &method) const override
Generate implementation for an extra method from an extraClassDeclaration.
virtual void genPrologue() const
~ImplementationGenerator() override=default
std::string name
The name of the parameter.
std::string type
The C++ type of the parameter.
MethodParameter(const std::string &paramType, const std::string &paramName)
Construct a new Method Parameter object.
Generator for common test implementation file elements.
virtual void genTestClassPrologue() const
Generate the test class prologue.
Generator(std::string_view recordKind, llvm::raw_ostream &outputStream)
~TestGenerator() override=default
void genExtraMethod(const ExtraMethod &method) const override
Generate test for an extra method from extraClassDeclaration.
virtual void genIsATest() const
Generate IsA test for a class.
virtual std::string genCleanup() const
Generate cleanup code for test methods.