41#include <mlir/TableGen/GenInfo.h>
42#include <mlir/TableGen/Operator.h>
44#include <llvm/ADT/StringExtras.h>
45#include <llvm/Support/CommandLine.h>
46#include <llvm/Support/FormatVariadic.h>
47#include <llvm/TableGen/Record.h>
48#include <llvm/TableGen/TableGenBackend.h>
63 OpTestGenerator(llvm::raw_ostream &outputStream) : TestGenerator(
"Operation", outputStream) {}
70 std::string genCleanup()
const override {
return "mlirOperationDestroy"; };
74 void genBuildOpTests(
const Operator &op)
const {
75 static constexpr char fmt[] = R
"(
77TEST_F({1}OperationLinkTests, {0}_{2}_Build) {{
78 // Returns an `arith.constant` op, which will never match the {2} dialect check.
79 auto testOp = createIndexOperation();
81 // This condition is always false, so the function is never actually called.
82 // We only verify it compiles and links correctly.
83 if ({0}OperationIsA_{1}_{2}(testOp)) {{
84 MlirOpBuilder builder = mlirOpBuilderCreate(context);
85 MlirLocation location = mlirLocationUnknownGet(context);
87 (void){0}{1}_{2}Build(builder, location{4});
88 // No need to destroy builder or op since this code never runs.
91 mlirOperationDestroy(testOp);
94struct {2}BuildFuncHelper : public TestAnyBuildFuncHelper<CAPITest> {
95 virtual bool callIsA(MlirOperation op) override { return {0}OperationIsA_{1}_{2}(op); }
99 static std::unique_ptr<{2}BuildFuncHelper> get();
102 {2}BuildFuncHelper() = default;
107TEST_F(CAPITest, {1}_{2}_build_pass) { {2}BuildFuncHelper::get()->run(*this); }
110 assert(!className.empty() &&
"className must be set");
114 dialectNameCapitalized,
116 generateBuildDummyParams(op),
117 generateBuildParamList(op)
123 void genOperandTests(
const Operator &op)
const {
124 static constexpr char OperandGetterTest[] = R
"(
125TEST_F({1}OperationLinkTests, {0}_{2}_Get{3}) {{
126 auto testOp = createIndexOperation();
128 if ({0}OperationIsA_{1}_{2}(testOp)) {{
129 (void){0}{1}_{2}Get{3}(testOp);
132 mlirOperationDestroy(testOp);
136 static constexpr char OperandSetterTest[] = R
"(
137TEST_F({1}OperationLinkTests, {0}_{2}_Set{3}) {{
138 auto testOp = createIndexOperation();
140 if ({0}OperationIsA_{1}_{2}(testOp)) {{
141 auto dummyValue = mlirOperationGetResult(testOp, 0);
142 {0}{1}_{2}Set{3}(testOp, dummyValue);
145 mlirOperationDestroy(testOp);
149 static constexpr char VariadicOperandGetterTest[] = R
"(
150TEST_F({1}OperationLinkTests, {0}_{2}_Get{3}Count) {{
151 auto testOp = createIndexOperation();
153 if ({0}OperationIsA_{1}_{2}(testOp)) {{
154 (void){0}{1}_{2}Get{3}Count(testOp);
157 mlirOperationDestroy(testOp);
160TEST_F({1}OperationLinkTests, {0}_{2}_Get{3}At) {{
161 auto testOp = createIndexOperation();
163 if ({0}OperationIsA_{1}_{2}(testOp)) {{
164 (void){0}{1}_{2}Get{3}At(testOp, 0);
167 mlirOperationDestroy(testOp);
171 static constexpr char VariadicOperandSetterTest[] = R
"(
172TEST_F({1}OperationLinkTests, {0}_{2}_Set{3}_Variadic) {{
173 auto testOp = createIndexOperation();
175 if ({0}OperationIsA_{1}_{2}(testOp)) {{
176 auto dummyValue = mlirOperationGetResult(testOp, 0);
177 MlirValue values[] = {{dummyValue};
178 {0}{1}_{2}Set{3}(testOp, 1, values);
181 mlirOperationDestroy(testOp);
185 static constexpr char VariadicOfVariadicOperandSetterTest[] = R
"(
186TEST_F({1}OperationLinkTests, {0}_{2}_Set{3}_VariadicOfVariadic) {{
187 auto testOp = createIndexOperation();
189 if ({0}OperationIsA_{1}_{2}(testOp)) {{
190 auto dummyValue = mlirOperationGetResult(testOp, 0);
191 MlirValueRange groups[1];
192 groups[0].values = &dummyValue;
194 {0}{1}_{2}Set{3}(testOp, 1, groups);
197 mlirOperationDestroy(testOp);
200 assert(!className.empty() && "className must be set");
202 for (
int i = 0, e = op.getNumOperands(); i < e; ++i) {
203 const auto &operand = op.getOperand(i);
205 if (operand.isVariadic()) {
208 VariadicOperandGetterTest,
210 dialectNameCapitalized,
217 operand.isVariadicOfVariadic() ? VariadicOfVariadicOperandSetterTest
218 : VariadicOperandSetterTest,
220 dialectNameCapitalized,
230 dialectNameCapitalized,
239 dialectNameCapitalized,
250 void genAttributeTests(
const Operator &op)
const {
251 static constexpr char AttributeGetterTest[] = R
"(
252TEST_F({1}OperationLinkTests, {0}_{2}_Get{3}Attr) {{
253 auto testOp = createIndexOperation();
255 if ({0}OperationIsA_{1}_{2}(testOp)) {{
256 (void){0}{1}_{2}Get{3}(testOp);
259 mlirOperationDestroy(testOp);
263 static constexpr char AttributeSetterTest[] = R
"(
264TEST_F({1}OperationLinkTests, {0}_{2}_Set{3}Attr) {{
265 auto testOp = createIndexOperation();
267 if ({0}OperationIsA_{1}_{2}(testOp)) {{
268 {0}{1}_{2}Set{3}(testOp, createIndexAttribute());
271 mlirOperationDestroy(testOp);
274 assert(!className.empty() && "className must be set");
276 for (
const auto &namedAttr : op.getAttributes()) {
282 dialectNameCapitalized,
291 dialectNameCapitalized,
301 void genResultTests(
const Operator &op)
const {
302 static constexpr char ResultGetterTest[] = R
"(
303TEST_F({1}OperationLinkTests, {0}_{2}_Get{3}) {{
304 auto testOp = createIndexOperation();
306 if ({0}OperationIsA_{1}_{2}(testOp)) {{
307 (void){0}{1}_{2}Get{3}(testOp);
310 mlirOperationDestroy(testOp);
314 static constexpr char VariadicResultGetterTest[] = R
"(
315TEST_F({1}OperationLinkTests, {0}_{2}_Get{3}Count) {{
316 auto testOp = createIndexOperation();
318 if ({0}OperationIsA_{1}_{2}(testOp)) {{
319 (void){0}{1}_{2}Get{3}Count(testOp);
322 mlirOperationDestroy(testOp);
325TEST_F({1}OperationLinkTests, {0}_{2}_Get{3}At) {{
326 auto testOp = createIndexOperation();
328 if ({0}OperationIsA_{1}_{2}(testOp)) {{
329 (void){0}{1}_{2}Get{3}At(testOp, 0);
332 mlirOperationDestroy(testOp);
335 assert(!className.empty() && "className must be set");
337 for (
int i = 0, e = op.getNumResults(); i < e; ++i) {
338 const auto &result = op.getResult(i);
339 llvm::StringRef name = result.name;
340 std::string capName = name.empty() ? llvm::formatv(
"Result{0}", i).str() :
toPascalCase(name);
342 if (result.isVariadic()) {
344 VariadicResultGetterTest,
346 dialectNameCapitalized,
354 dialectNameCapitalized,
364 void genRegionTests(
const Operator &op)
const {
365 static constexpr char RegionGetterTest[] = R
"(
366TEST_F({1}OperationLinkTests, {0}_{2}_Get{3}Region) {{
367 auto testOp = createIndexOperation();
369 if ({0}OperationIsA_{1}_{2}(testOp)) {{
370 (void){0}{1}_{2}Get{3}(testOp);
373 mlirOperationDestroy(testOp);
377 static constexpr char VariadicRegionGetterTest[] = R
"(
378TEST_F({1}OperationLinkTests, {0}_{2}_Get{3}Count) {{
379 auto testOp = createIndexOperation();
381 if ({0}OperationIsA_{1}_{2}(testOp)) {{
382 (void){0}{1}_{2}Get{3}Count(testOp);
385 mlirOperationDestroy(testOp);
388TEST_F({1}OperationLinkTests, {0}_{2}_Get{3}At) {{
389 auto testOp = createIndexOperation();
391 if ({0}OperationIsA_{1}_{2}(testOp)) {{
392 (void){0}{1}_{2}Get{3}At(testOp, 0);
395 mlirOperationDestroy(testOp);
398 assert(!className.empty() && "className must be set");
400 for (
unsigned int i = 0, e = op.getNumRegions(); i < e; ++i) {
401 const auto ®ion = op.getRegion(i);
402 llvm::StringRef name = region.name;
403 std::string capName = name.empty() ? llvm::formatv(
"Region{0}", i).str() :
toPascalCase(name);
405 if (region.isVariadic()) {
407 VariadicRegionGetterTest,
409 dialectNameCapitalized,
417 dialectNameCapitalized,
427 void genCompleteRecord(
const Operator &op) {
428 const Dialect &defDialect = op.getDialect();
435 this->setNamespaceAndClassName(defDialect, op.getCppClassName());
441 this->genBuildOpTests(op);
444 this->genOperandTests(op);
447 this->genAttributeTests(op);
450 this->genRegionTests(op);
453 this->genResultTests(op);
457 this->genExtraMethod(method);
466 static std::string generateBuildDummyParams(
const Operator &op) {
467 struct : GenStringFromOpPieces {
468 void genHeader(llvm::raw_ostream &os)
override {
470 os <<
" auto dummyValue = mlirOperationGetResult(testOp, 0);\n";
473 llvm::raw_ostream &os,
const NamedTypeConstraint &result,
const std::string &resultName
475 if (result.isVariadic()) {
477 " auto {0}TypeArray = createIndexType();\n"
478 " MlirType {0}Types[] = {{{0}TypeArray};\n"
479 " intptr_t {0}Size = 0;\n",
483 os << llvm::formatv(
" auto {0}Type = createIndexType();\n", resultName);
486 void genOperand(llvm::raw_ostream &os,
const NamedTypeConstraint &operand)
override {
489 if (operand.isVariadic()) {
491 " MlirValue {0}Values[] = {{dummyValue};\n"
492 " intptr_t {0}Size = 0;\n",
497 void genAttribute(llvm::raw_ostream &os,
const NamedAttribute &attr)
override {
500 if (attrType.has_value() && attrType.value() ==
"MlirIdentifier") {
501 rhs =
"mlirOperationGetName(testOp)";
503 rhs =
"createIndexAttribute()";
505 os << llvm::formatv(
" auto {0}Attr = {1};\n", attr.name, rhs);
507 void genRegion(llvm::raw_ostream &os,
const mlir::tblgen::NamedRegion ®ion)
override {
508 if (region.isVariadic()) {
509 os << llvm::formatv(
" unsigned {0}Count = 0;\n", region.name);
512 } paramsStringGenerator;
513 return paramsStringGenerator.gen(op);
519 static std::string generateBuildParamList(
const Operator &op) {
520 struct : GenStringFromOpPieces {
522 llvm::raw_ostream &os,
const NamedTypeConstraint &result,
const std::string &resultName
524 if (result.isVariadic()) {
525 os << llvm::formatv(
", {0}Size, {0}Types", resultName);
527 os << llvm::formatv(
", {0}Type", resultName);
530 void genOperand(llvm::raw_ostream &os,
const NamedTypeConstraint &operand)
override {
531 if (operand.isVariadic()) {
532 os << llvm::formatv(
", {0}Size, {0}Values", operand.name);
534 os <<
", dummyValue";
537 void genAttribute(llvm::raw_ostream &os,
const NamedAttribute &attr)
override {
538 os << llvm::formatv(
", {0}Attr", attr.name);
540 void genRegion(llvm::raw_ostream &os,
const mlir::tblgen::NamedRegion ®ion)
override {
541 if (region.isVariadic()) {
542 os << llvm::formatv(
", {0}Count", region.name);
545 } paramsStringGenerator;
546 return paramsStringGenerator.gen(op);
553static bool emitOpCAPITests(
const llvm::RecordKeeper &records, raw_ostream &os) {
555 emitSourceFileHeader(
"Op C API Tests", os, records);
558 OpTestGenerator generator(os);
561 generator.genTestClassPrologue();
564 for (
const auto *def : records.getAllDerivedDefinitions(
"Op")) {
566 generator.genCompleteRecord(op);
573 static mlir::GenRegistration genOpCAPITests(
574 "gen-op-capi-tests",
"Generate operation C API unit tests", &emitOpCAPITests
llvm::cl::opt< bool > & getGenOpOperandGetters()
Return the GenOpOperandGetters option, registering it on first access.
std::optional< std::string > tryCppTypeToCapiType(StringRef cppType)
Convert C++ type to MLIR C API type.
llvm::cl::opt< std::string > & getFunctionPrefix()
Return the FunctionPrefix option, registering it on first access.
llvm::cl::opt< bool > & getGenOpRegionGetters()
Return the GenOpRegionGetters option, registering it on first access.
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.
llvm::cl::opt< bool > & getGenOpAttributeSetters()
Return the GenOpAttributeSetters option, registering it on first access.
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::cl::opt< bool > & getGenExtraClassMethods()
Return the GenExtraClassMethods 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::SmallVector< ExtraMethod > getCAPIExposedOpMethods(const mlir::tblgen::Operator &op)
Return public operation methods explicitly requested by DeclareOpInterfaceMethods traits and declared...
std::string toPascalCase(mlir::StringRef str)
Convert names separated by underscore or colon to PascalCase.
void registerOpCAPITestGenerator()
Register the operation C API test generator before command-line parsing.
Generator for common test implementation file elements.