[Mlir-commits] [mlir] [MLIR][IRDL] Instantiate "." in IRDL-defined names as nested namespaces (PR #207035)
Ivan Ho
llvmlistbot at llvm.org
Thu Jul 2 09:41:27 PDT 2026
https://github.com/hhkit updated https://github.com/llvm/llvm-project/pull/207035
>From 01d8081c6fd6155074c7874733fb703931fbcad0 Mon Sep 17 00:00:00 2001
From: Ivan Ho <38537881+hhkit at users.noreply.github.com>
Date: Wed, 1 Jul 2026 18:02:15 +0100
Subject: [PATCH 1/2] unit tests for the changes we want to make
---
.../TestIRDLToCpp/test_irdl_to_cpp.irdl.mlir | 44 +++++++++++++++++++
1 file changed, 44 insertions(+)
diff --git a/mlir/test/lib/Dialect/TestIRDLToCpp/test_irdl_to_cpp.irdl.mlir b/mlir/test/lib/Dialect/TestIRDLToCpp/test_irdl_to_cpp.irdl.mlir
index 770cd36cdee33..2a37cfaa3557c 100644
--- a/mlir/test/lib/Dialect/TestIRDLToCpp/test_irdl_to_cpp.irdl.mlir
+++ b/mlir/test/lib/Dialect/TestIRDLToCpp/test_irdl_to_cpp.irdl.mlir
@@ -18,6 +18,32 @@ irdl.dialect @test_irdl_to_cpp {
irdl.results(res: %0)
}
+ // CHECK: // ::mlir::test_irdl_to_cpp::nested::NamespacedOp declarations
+ // CHECK: namespace nested {
+ // CHECK: class NamespacedOp : public ::mlir::Op<NamespacedOp
+ // CHECK: static constexpr ::llvm::StringLiteral getOperationName()
+ // CHECK-NEXT: return ::llvm::StringLiteral("test_irdl_to_cpp.nested.namespaced");
+ // CHECK: } // namespace nested
+ // CHECK: MLIR_DECLARE_EXPLICIT_TYPE_ID(::mlir::test_irdl_to_cpp::nested::NamespacedOp)
+ irdl.operation @nested.namespaced {
+ %0 = irdl.any
+ irdl.results(res: %0)
+ }
+
+ // CHECK: // ::mlir::test_irdl_to_cpp::nested::namespaced::MoreOp declarations
+ // CHECK: namespace nested {
+ // CHECK: namespace namespaced {
+ // CHECK: class MoreOp : public ::mlir::Op<MoreOp
+ // CHECK: static constexpr ::llvm::StringLiteral getOperationName()
+ // CHECK-NEXT: return ::llvm::StringLiteral("test_irdl_to_cpp.nested.namespaced.more");
+ // CHECK: } // namespace namespaced
+ // CHECK: } // namespace nested
+ // CHECK: MLIR_DECLARE_EXPLICIT_TYPE_ID(::mlir::test_irdl_to_cpp::nested::namespaced::MoreOp)
+ irdl.operation @nested.namespaced.more {
+ %0 = irdl.any
+ irdl.results(res: %0)
+ }
+
// CHECK: class BeefOp
// CHECK: ::mlir::Value getLhs()
// CHECK: ::mlir::Value getRhs()
@@ -49,6 +75,20 @@ irdl.dialect @test_irdl_to_cpp {
// CHECK: ::mlir::Region &getThen() { return (*this)->getRegion(1); }
// CHECK: ::mlir::Region &getElse() { return (*this)->getRegion(2); }
+ // CHECK: // ::mlir::test_irdl_to_cpp::nested::NamespacedOp definitions
+ // CHECK: namespace nested {
+ // CHECK: NamespacedOp::build
+ // CHECK: } // namespace nested
+ // CHECK: MLIR_DEFINE_EXPLICIT_TYPE_ID(::mlir::test_irdl_to_cpp::nested::NamespacedOp)
+
+ // CHECK: // ::mlir::test_irdl_to_cpp::nested::namespaced::MoreOp definitions
+ // CHECK: namespace nested {
+ // CHECK: namespace namespaced {
+ // CHECK: MoreOp::build
+ // CHECK: } // namespace namespaced
+ // CHECK: } // namespace nested
+ // CHECK: MLIR_DEFINE_EXPLICIT_TYPE_ID(::mlir::test_irdl_to_cpp::nested::namespaced::MoreOp)
+
// CHECK: ConditionalOp definitions
// CHECK: __mlir_irdl_local_region_constraint_ConditionalOp_cond
// CHECK: if (!(region.getNumArguments() == 1)) {
@@ -73,6 +113,10 @@ irdl.dialect @test_irdl_to_cpp {
// CHECK: __mlir_irdl_local_region_constraint_ConditionalOp_else
// CHECK: failure
// CHECK: success
+
+ // CHECK: void TestIrdlToCppDialect::initialize()
+ // CHECK: ::mlir::test_irdl_to_cpp::nested::NamespacedOp
+ // CHECK: ::mlir::test_irdl_to_cpp::nested::namespaced::MoreOp
irdl.operation @conditional {
%r0 = irdl.region // Unconstrained region
%r1 = irdl.region() // Region with no entry block arguments
>From f78a519928fc14d49c4daa42dd93c995a0cc54d7 Mon Sep 17 00:00:00 2001
From: Ivan Ho <38537881+hhkit at users.noreply.github.com>
Date: Thu, 2 Jul 2026 17:41:13 +0100
Subject: [PATCH 2/2] fix that works but i don't like it
---
mlir/lib/Dialect/IRDL/IR/IRDL.cpp | 9 ++++
mlir/lib/Target/IRDLToCpp/IRDLToCpp.cpp | 61 +++++++++++++++++++------
2 files changed, 57 insertions(+), 13 deletions(-)
diff --git a/mlir/lib/Dialect/IRDL/IR/IRDL.cpp b/mlir/lib/Dialect/IRDL/IR/IRDL.cpp
index 278113fc6e966..b1005b01af86c 100644
--- a/mlir/lib/Dialect/IRDL/IR/IRDL.cpp
+++ b/mlir/lib/Dialect/IRDL/IR/IRDL.cpp
@@ -78,12 +78,19 @@ static llvm::LogicalResult isValidName(llvm::StringRef in, mlir::Operation *loc,
return loc->emitError("name of ") << label << " is empty";
bool allowUnderscore = false;
+ auto prev = '\0';
for (auto &elem : in) {
if (elem == '_') {
if (!allowUnderscore)
return loc->emitError("name of ")
<< label << " should not contain leading or double underscores";
} else {
+ if (elem == '.') {
+ if (prev == '.')
+ return loc->emitError("empty namespace not allowed");
+ }
+ else
+ {
if (!isalnum(elem))
return loc->emitError("name of ")
<< label
@@ -93,9 +100,11 @@ static llvm::LogicalResult isValidName(llvm::StringRef in, mlir::Operation *loc,
if (llvm::isUpper(elem))
return loc->emitError("name of ")
<< label << " should not contain uppercase letters";
+ }
}
allowUnderscore = elem != '_';
+ prev = elem;
}
return success();
diff --git a/mlir/lib/Target/IRDLToCpp/IRDLToCpp.cpp b/mlir/lib/Target/IRDLToCpp/IRDLToCpp.cpp
index 046c7dd0fccff..e8773937fc313 100644
--- a/mlir/lib/Target/IRDLToCpp/IRDLToCpp.cpp
+++ b/mlir/lib/Target/IRDLToCpp/IRDLToCpp.cpp
@@ -13,6 +13,7 @@
#include "llvm/ADT/SmallString.h"
#include "llvm/ADT/SmallVector.h"
#include "llvm/ADT/StringExtras.h"
+#include "llvm/ADT/StringRef.h"
#include "llvm/ADT/TypeSwitch.h"
#include "llvm/Support/FormatVariadic.h"
#include "llvm/Support/raw_ostream.h"
@@ -52,6 +53,8 @@ struct TypeStrings {
struct OpStrings {
StringRef opName;
std::string opCppName;
+ std::string opScopedCppName;
+ SmallVector<std::string> opNameSpaces;
SmallVector<std::string> opResultNames;
SmallVector<std::string> opOperandNames;
SmallVector<std::string> opRegionNames;
@@ -73,8 +76,19 @@ static std::string typeToCppName(irdl::TypeOp type) {
/// Generates the C++ class name for an OperationOp
static std::string opToCppName(irdl::OperationOp op) {
+ const auto opName = op.getSymName();
+ const auto periodIndex = opName.find_last_of(".");
+ const auto nameSubstr = periodIndex == std::string::npos ? opName : opName.substr(periodIndex + 1);
return llvm::formatv("{0}Op",
- convertToCamelFromSnakeCase(op.getSymName(), true));
+ convertToCamelFromSnakeCase(nameSubstr, true));
+}
+
+// Generates the C++ class name for an OperationOp, scoped to the namespace
+static std::string opToScopedCppName(irdl::OperationOp op) {
+ auto names = llvm::SmallVector<std::string>(llvm::split(op.getSymName(), "."));
+ names.pop_back();
+ names.push_back(opToCppName(op));
+ return llvm::join(names, "::");
}
/// Generates TypeStrings from a TypeOp
@@ -92,8 +106,12 @@ static OpStrings getStrings(irdl::OperationOp op) {
auto regionsOp = op.getOp<irdl::RegionsOp>();
OpStrings strings;
+ auto opNameParts = SmallVector<StringRef>(llvm::split(op.getSymName(), "."));
strings.opName = op.getSymName();
+ opNameParts.pop_back();
+ strings.opNameSpaces = llvm::map_to_vector(opNameParts, &StringRef::str);
strings.opCppName = opToCppName(op);
+ strings.opScopedCppName = opToScopedCppName(op);
if (operandOp) {
strings.opOperandNames = SmallVector<std::string>(
@@ -134,6 +152,7 @@ static void fillDict(irdl::detail::dictionary &dict, const OpStrings &strings) {
dict["OP_NAME"] = strings.opName;
dict["OP_CPP_NAME"] = strings.opCppName;
+ dict["OP_SCOPED_CPP_NAME"] = strings.opScopedCppName;
dict["OP_OPERAND_COUNT"] = std::to_string(strings.opOperandNames.size());
dict["OP_RESULT_COUNT"] = std::to_string(strings.opResultNames.size());
dict["OP_OPERAND_INITIALIZER_LIST"] =
@@ -141,6 +160,20 @@ static void fillDict(irdl::detail::dictionary &dict, const OpStrings &strings) {
dict["OP_RESULT_INITIALIZER_LIST"] =
resultCount ? joinNameList(strings.opResultNames) : "{\"\"}";
dict["OP_REGION_COUNT"] = std::to_string(regionCount);
+ dict["NAMESPACE_OPEN"] = (dict["NAMESPACE_OPEN"] + llvm::join(llvm::map_range(strings.opNameSpaces, [](llvm::StringRef ref) -> std::string {
+ return llvm::formatv("namespace {0} {{", ref);
+ }), "\n")).str();
+ dict["NAMESPACE_PATH"] =
+ (dict["NAMESPACE_PATH"] +
+ llvm::join(llvm::map_range(strings.opNameSpaces,
+ [](llvm::StringRef ref) -> std::string {
+ return llvm::formatv("::{0}", ref);
+ }),
+ ""))
+ .str();
+ dict["NAMESPACE_CLOSE"] = (llvm::join(llvm::map_range(llvm::reverse(strings.opNameSpaces), [](llvm::StringRef ref) -> std::string {
+ return llvm::formatv("} // namespace {0}\n", ref);
+ }), "") + dict["NAMESPACE_CLOSE"]).str();
}
/// Fills a dictionary with values from DialectStrings
@@ -166,7 +199,7 @@ static LogicalResult generateTypedefList(irdl::DialectOp &dialect,
static LogicalResult generateOpList(irdl::DialectOp &dialect,
SmallVector<std::string> &opNames) {
auto operationOps = dialect.getOps<irdl::OperationOp>();
- auto range = llvm::map_range(operationOps, opToCppName);
+ auto range = llvm::map_range(operationOps, opToScopedCppName);
opNames = SmallVector<std::string>(range);
return success();
}
@@ -283,24 +316,25 @@ static SmallVector<std::string> generateTraits(irdl::OperationOp op,
static LogicalResult generateOperationInclude(irdl::OperationOp op,
raw_ostream &output,
- irdl::detail::dictionary &dict) {
+ const irdl::detail::dictionary &dict) {
static const auto perOpDeclTemplate = irdl::detail::Template(
#include "Templates/PerOperationDecl.txt"
);
const auto opStrings = getStrings(op);
- fillDict(dict, opStrings);
+ auto opDict = dict;
+ fillDict(opDict, opStrings);
SmallVector<std::string> traitNames = generateTraits(op, opStrings);
if (traitNames.empty())
- dict["OP_TEMPLATE_ARGS"] = opStrings.opCppName;
+ opDict["OP_TEMPLATE_ARGS"] = opStrings.opCppName;
else
- dict["OP_TEMPLATE_ARGS"] = llvm::formatv("{0}, {1}", opStrings.opCppName,
+ opDict["OP_TEMPLATE_ARGS"] = llvm::formatv("{0}, {1}", opStrings.opCppName,
llvm::join(traitNames, ", "));
- generateOpGetterDeclarations(dict, opStrings);
- generateOpBuilderDeclarations(dict, opStrings);
+ generateOpGetterDeclarations(opDict, opStrings);
+ generateOpBuilderDeclarations(opDict, opStrings);
- perOpDeclTemplate.render(output, dict);
+ perOpDeclTemplate.render(output, opDict);
return success();
}
@@ -462,7 +496,8 @@ static std::string generateOpDefinition(irdl::detail::dictionary &dict,
};
auto opStrings = getStrings(op);
- fillDict(dict, opStrings);
+ auto opDict = dict;
+ fillDict(opDict, opStrings);
auto resultTypes = llvm::join(
llvm::map_range(opStrings.opResultNames,
@@ -516,13 +551,13 @@ void {0}::build(::mlir::OpBuilder &opBuilder, ::mlir::OperationState &opState, {
llvm::join(opStrings.opOperandNames, ",") +
(!opStrings.opOperandNames.empty() ? "," : ""));
- dict["OP_BUILD_DEFS"] = buildDefinition;
+ opDict["OP_BUILD_DEFS"] = buildDefinition;
- generateVerifiers(dict, op, opStrings);
+ generateVerifiers(opDict, op, opStrings);
std::string str;
llvm::raw_string_ostream stream{str};
- perOpDefTemplate.render(stream, dict);
+ perOpDefTemplate.render(stream, opDict);
return str;
}
More information about the Mlir-commits
mailing list