LLZK 3.0.0
An open-source IR for Zero Knowledge (ZK) circuits
Loading...
Searching...
No Matches
DialectCAPITestGen.cpp
Go to the documentation of this file.
1//===- DialectCAPITestGen.cpp - C API test generator for dialects ---------===//
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// DialectCAPITestGen generates unit tests for dialect-level C API functions.
11// These are link-time tests that ensure dialect handle functions compile and
12// link properly.
13//
14// Test Strategy:
15// - Tests verify that mlirGetDialectHandle__<namespace>__() functions can be called
16// - This ensures the dialect handle is properly exported and linkable
17// - The test simply calls the function without asserting anything about the result
18//
19//===----------------------------------------------------------------------===//
20
21#include "CAPIGenRegistration.h"
22#include "CommonCAPIGen.h"
23
24#include <mlir/TableGen/Dialect.h>
25#include <mlir/TableGen/GenInfo.h>
26
27#include <llvm/ADT/StringExtras.h>
28#include <llvm/Support/CommandLine.h>
29#include <llvm/Support/FormatVariadic.h>
30#include <llvm/TableGen/Record.h>
31#include <llvm/TableGen/TableGenBackend.h>
32
33#include <algorithm>
34
35using namespace mlir;
36using namespace mlir::tblgen;
37
38namespace test_templates {
39
40static constexpr char DialectTestTemplate[] = R"(
41#include <mlir-c/IR.h>
42
43class {0}DialectLinkTests : public CAPITest {{};
44
45TEST_F({0}DialectLinkTests, get_dialect_handle_{2}) {{
46 (void)mlirGetDialectHandle{1}__();
47}
48)";
49
50} // namespace test_templates
51
53static bool emitDialectCAPITests(const llvm::RecordKeeper &records, llvm::raw_ostream &os) {
54 // Find the dialect definition
55 const auto &defs = records.getAllDerivedDefinitions("Dialect");
56
57 if (defs.empty()) {
58 llvm::errs() << "Error: No Dialect definition found in the input file\n";
59 return true;
60 }
61
62 if (defs.size() > 1) {
63 llvm::errs() << "Warning: Multiple Dialect definitions found, using the first one\n";
64 }
65
66 Dialect dialect(defs[0]);
67
68 // Use command-line dialect name if provided, otherwise use from definition
69 std::string effectiveDialectName =
70 getDialectName().empty() ? dialect.getName().str() : getDialectName().getValue();
71
72 // Get the C++ namespace from the dialect definition. It's like "::llzk::boolean"
73 // so replace all ':' with '_' to form the handle suffix.
74 std::string cppNamespaceStr = dialect.getCppNamespace().str();
75 std::replace(cppNamespaceStr.begin(), cppNamespaceStr.end(), ':', '_');
76
77 // Generate the test file
78 emitSourceFileHeader("Dialect C API Tests", os, records);
79 os << llvm::formatv(
80 test_templates::DialectTestTemplate,
81 toPascalCase(effectiveDialectName), // {0} - Capitalized dialect name for class/file
82 cppNamespaceStr, // {1} - Dialect handle suffix (e.g., "__llzk__boolean")
83 effectiveDialectName // {2} - Dialect name for test name
84 );
85
86 return false;
87}
88
90 static llvm::cl::OptionCategory dialectTestGenCat("Options for -gen-dialect-capi-tests");
91 static mlir::GenRegistration genDialectCAPITests(
92 "gen-dialect-capi-tests", "Generate dialect-level C API unit tests", &emitDialectCAPITests
93 );
94}
llvm::cl::opt< std::string > & getDialectName()
Return the DialectName option, registering it on first access.
std::string toPascalCase(mlir::StringRef str)
Convert names separated by underscore or colon to PascalCase.
void registerDialectCAPITestGenerator()
Register the dialect C API test generator before command-line parsing.