[Mlir-commits] [mlir] [MLIR][IRDL] Instantiate "." in IRDL-defined names as nested namespaces (PR #207035)
Ivan Ho
llvmlistbot at llvm.org
Mon Sep 14 08:54:32 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/6] 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/6] 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;
}
>From cfef33ed74483fa19e3f9c2a2ba5bad33fd6faca Mon Sep 17 00:00:00 2001
From: Ivan Ho <38537881+hhkit at users.noreply.github.com>
Date: Mon, 14 Sep 2026 14:19:31 +0100
Subject: [PATCH 3/6] clang format
---
mlir/lib/Dialect/IRDL/IR/IRDL.cpp | 22 ++++++-------
mlir/lib/Target/IRDLToCpp/IRDLToCpp.cpp | 42 ++++++++++++++++---------
2 files changed, 38 insertions(+), 26 deletions(-)
diff --git a/mlir/lib/Dialect/IRDL/IR/IRDL.cpp b/mlir/lib/Dialect/IRDL/IR/IRDL.cpp
index b1005b01af86c..170acb97df47a 100644
--- a/mlir/lib/Dialect/IRDL/IR/IRDL.cpp
+++ b/mlir/lib/Dialect/IRDL/IR/IRDL.cpp
@@ -88,18 +88,16 @@ static llvm::LogicalResult isValidName(llvm::StringRef in, mlir::Operation *loc,
if (elem == '.') {
if (prev == '.')
return loc->emitError("empty namespace not allowed");
- }
- else
- {
- if (!isalnum(elem))
- return loc->emitError("name of ")
- << label
- << " must contain only lowercase letters, digits and "
- "underscores";
-
- if (llvm::isUpper(elem))
- return loc->emitError("name of ")
- << label << " should not contain uppercase letters";
+ } else {
+ if (!isalnum(elem))
+ return loc->emitError("name of ")
+ << label
+ << " must contain only lowercase letters, digits and "
+ "underscores";
+
+ if (llvm::isUpper(elem))
+ return loc->emitError("name of ")
+ << label << " should not contain uppercase letters";
}
}
diff --git a/mlir/lib/Target/IRDLToCpp/IRDLToCpp.cpp b/mlir/lib/Target/IRDLToCpp/IRDLToCpp.cpp
index 6a33f564bd798..e953baf08fdc2 100644
--- a/mlir/lib/Target/IRDLToCpp/IRDLToCpp.cpp
+++ b/mlir/lib/Target/IRDLToCpp/IRDLToCpp.cpp
@@ -78,14 +78,16 @@ static std::string typeToCppName(irdl::TypeOp type) {
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(nameSubstr, true));
+ const auto nameSubstr = periodIndex == std::string::npos
+ ? opName
+ : opName.substr(periodIndex + 1);
+ return llvm::formatv("{0}Op", 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(), "."));
+ auto names =
+ llvm::SmallVector<std::string>(llvm::split(op.getSymName(), "."));
names.pop_back();
names.push_back(opToCppName(op));
return llvm::join(names, "::");
@@ -160,9 +162,15 @@ 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_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,
@@ -171,9 +179,15 @@ static void fillDict(irdl::detail::dictionary &dict, const OpStrings &strings) {
}),
""))
.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();
+ 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
@@ -314,9 +328,9 @@ static SmallVector<std::string> generateTraits(irdl::OperationOp op,
return cppTraitNames;
}
-static LogicalResult generateOperationInclude(irdl::OperationOp op,
- raw_ostream &output,
- const irdl::detail::dictionary &dict) {
+static LogicalResult
+generateOperationInclude(irdl::OperationOp op, raw_ostream &output,
+ const irdl::detail::dictionary &dict) {
static const auto perOpDeclTemplate = irdl::detail::Template(
#include "Templates/PerOperationDecl.txt"
);
@@ -329,7 +343,7 @@ static LogicalResult generateOperationInclude(irdl::OperationOp op,
opDict["OP_TEMPLATE_ARGS"] = opStrings.opCppName;
else
opDict["OP_TEMPLATE_ARGS"] = llvm::formatv("{0}, {1}", opStrings.opCppName,
- llvm::join(traitNames, ", "));
+ llvm::join(traitNames, ", "));
generateOpGetterDeclarations(opDict, opStrings);
generateOpBuilderDeclarations(opDict, opStrings);
>From 9fd7d878a0cf6f6b382feb37983cef177056c5c1 Mon Sep 17 00:00:00 2001
From: Ivan Ho <38537881+hhkit at users.noreply.github.com>
Date: Mon, 14 Sep 2026 15:00:09 +0100
Subject: [PATCH 4/6] fix failing CI
---
mlir/lib/Target/IRDLToCpp/IRDLToCpp.cpp | 14 ++++++++++----
.../TestIRDLToCpp/test_irdl_to_cpp.irdl.mlir | 9 +++++++++
2 files changed, 19 insertions(+), 4 deletions(-)
diff --git a/mlir/lib/Target/IRDLToCpp/IRDLToCpp.cpp b/mlir/lib/Target/IRDLToCpp/IRDLToCpp.cpp
index e953baf08fdc2..95efd4e301128 100644
--- a/mlir/lib/Target/IRDLToCpp/IRDLToCpp.cpp
+++ b/mlir/lib/Target/IRDLToCpp/IRDLToCpp.cpp
@@ -381,10 +381,16 @@ static LogicalResult generateInclude(irdl::DialectOp dialect,
return failure();
auto classDeclarations =
- llvm::join(llvm::map_range(opNames,
- [](llvm::StringRef name) -> std::string {
- return llvm::formatv("class {0};", name);
- }),
+ llvm::join(llvm::map_range(
+ opNames,
+ [](llvm::StringRef name) -> std::string {
+ if (name.contains("::")) {
+ auto [scope, className] = name.rsplit("::");
+ return llvm::formatv("namespace {0} {{\nclass {1};\n}",
+ scope, className);
+ }
+ return llvm::formatv("class {0};", name);
+ }),
"\n");
const auto forwardDeclarations = llvm::formatv(
"{1}\n{0}\n{2}", std::move(classDeclarations),
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 2a37cfaa3557c..e4a88dc59fa91 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
@@ -11,6 +11,15 @@ irdl.dialect @test_irdl_to_cpp {
// CHECK: class FooType
irdl.type @foo
+ // CHECK: class BarOp;
+ // CHECK-NEXT: namespace nested {
+ // CHECK-NEXT: class NamespacedOp;
+ // CHECK-NEXT: }
+ // CHECK-NEXT: namespace nested::namespaced {
+ // CHECK-NEXT: class MoreOp;
+ // CHECK-NEXT: }
+ // CHECK-NEXT: class BeefOp;
+
// CHECK: class BarOp
// CHECK: ::mlir::Value getRes()
irdl.operation @bar {
>From b093d8d8ec7aff450fd1b93c37fc10ac0d53c094 Mon Sep 17 00:00:00 2001
From: Ivan Ho <38537881+hhkit at users.noreply.github.com>
Date: Mon, 14 Sep 2026 16:42:38 +0100
Subject: [PATCH 5/6] simplify underscore check
---
mlir/lib/Dialect/IRDL/IR/IRDL.cpp | 8 +++-----
1 file changed, 3 insertions(+), 5 deletions(-)
diff --git a/mlir/lib/Dialect/IRDL/IR/IRDL.cpp b/mlir/lib/Dialect/IRDL/IR/IRDL.cpp
index 170acb97df47a..10319687cd134 100644
--- a/mlir/lib/Dialect/IRDL/IR/IRDL.cpp
+++ b/mlir/lib/Dialect/IRDL/IR/IRDL.cpp
@@ -77,11 +77,10 @@ static llvm::LogicalResult isValidName(llvm::StringRef in, mlir::Operation *loc,
if (in.empty())
return loc->emitError("name of ") << label << " is empty";
- bool allowUnderscore = false;
- auto prev = '\0';
- for (auto &elem : in) {
+ char prev = '_'; // treat the initial as _ to eliminate leading underscores
+ for (const auto &elem : in) {
if (elem == '_') {
- if (!allowUnderscore)
+ if (prev == '_')
return loc->emitError("name of ")
<< label << " should not contain leading or double underscores";
} else {
@@ -101,7 +100,6 @@ static llvm::LogicalResult isValidName(llvm::StringRef in, mlir::Operation *loc,
}
}
- allowUnderscore = elem != '_';
prev = elem;
}
>From 5def9e879024703253dd0a279a08f26ff422e4ce Mon Sep 17 00:00:00 2001
From: Ivan Ho <38537881+hhkit at users.noreply.github.com>
Date: Mon, 14 Sep 2026 16:54:14 +0100
Subject: [PATCH 6/6] prefix digit-leading symbols with underscore
---
mlir/lib/Target/IRDLToCpp/IRDLToCpp.cpp | 29 +++++---
.../TestIRDLToCpp/test_irdl_to_cpp.irdl.mlir | 71 +++++++++++++++----
2 files changed, 78 insertions(+), 22 deletions(-)
diff --git a/mlir/lib/Target/IRDLToCpp/IRDLToCpp.cpp b/mlir/lib/Target/IRDLToCpp/IRDLToCpp.cpp
index 95efd4e301128..53d19fb5b8e80 100644
--- a/mlir/lib/Target/IRDLToCpp/IRDLToCpp.cpp
+++ b/mlir/lib/Target/IRDLToCpp/IRDLToCpp.cpp
@@ -68,10 +68,17 @@ static std::string joinNameList(llvm::ArrayRef<std::string> names) {
return nameArray;
}
+/// Prefix identifiers that start with a digit to make them valid C++ names.
+static std::string legalizeCppName(StringRef name) {
+ if (!name.empty() && llvm::isDigit(name.front()))
+ return ("_" + name).str();
+ return name.str();
+}
+
/// Generates the C++ type name for a TypeOp
static std::string typeToCppName(irdl::TypeOp type) {
- return llvm::formatv("{0}Type",
- convertToCamelFromSnakeCase(type.getSymName(), true));
+ return llvm::formatv("{0}Type", legalizeCppName(convertToCamelFromSnakeCase(
+ type.getSymName(), true)));
}
/// Generates the C++ class name for an OperationOp
@@ -81,14 +88,20 @@ static std::string opToCppName(irdl::OperationOp op) {
const auto nameSubstr = periodIndex == std::string::npos
? opName
: opName.substr(periodIndex + 1);
- return llvm::formatv("{0}Op", convertToCamelFromSnakeCase(nameSubstr, true));
+ return llvm::formatv(
+ "{0}Op", legalizeCppName(convertToCamelFromSnakeCase(nameSubstr, true)));
+}
+
+/// Generates the C++ namespace components for an OperationOp.
+static SmallVector<std::string> opToCppNamespaces(irdl::OperationOp op) {
+ auto parts = SmallVector<StringRef>(llvm::split(op.getSymName(), "."));
+ parts.pop_back();
+ return llvm::map_to_vector(parts, legalizeCppName);
}
// 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();
+ auto names = opToCppNamespaces(op);
names.push_back(opToCppName(op));
return llvm::join(names, "::");
}
@@ -108,10 +121,8 @@ 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.opNameSpaces = opToCppNamespaces(op);
strings.opCppName = opToCppName(op);
strings.opScopedCppName = opToScopedCppName(op);
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 e4a88dc59fa91..35a973656d999 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
@@ -11,6 +11,9 @@ irdl.dialect @test_irdl_to_cpp {
// CHECK: class FooType
irdl.type @foo
+ // CHECK: class _8Type
+ irdl.type @"8"
+
// CHECK: class BarOp;
// CHECK-NEXT: namespace nested {
// CHECK-NEXT: class NamespacedOp;
@@ -20,6 +23,14 @@ irdl.dialect @test_irdl_to_cpp {
// CHECK-NEXT: }
// CHECK-NEXT: class BeefOp;
+ // CHECK: namespace wmma::f16::_16x16x64 {
+ // CHECK-NEXT: class Bf8BfOp;
+ // CHECK-NEXT: }
+ // CHECK-NEXT: namespace _7::_8 {
+ // CHECK-NEXT: class _9Op;
+ // CHECK-NEXT: }
+ // CHECK-NEXT: class _10Op;
+
// CHECK: class BarOp
// CHECK: ::mlir::Value getRes()
irdl.operation @bar {
@@ -84,6 +95,42 @@ irdl.dialect @test_irdl_to_cpp {
// CHECK: ::mlir::Region &getThen() { return (*this)->getRegion(1); }
// CHECK: ::mlir::Region &getElse() { return (*this)->getRegion(2); }
+ irdl.operation @conditional {
+ %r0 = irdl.region // Unconstrained region
+ %r1 = irdl.region() // Region with no entry block arguments
+
+ // TODO(#161018): support irdl.is in irdl-to-cpp
+ // %v0 = irdl.is i1 // Type constraint: i1 (boolean)
+ %v0 = irdl.any
+ %r2 = irdl.region(%v0) // Region with one i1 entry block argument
+ irdl.regions(cond: %r2, then: %r0, else: %r1)
+
+ %0 = irdl.any
+ irdl.operands(input: %0)
+ }
+
+ // CHECK: // ::mlir::test_irdl_to_cpp::wmma::f16::_16x16x64::Bf8BfOp declarations
+ // CHECK: namespace wmma {
+ // CHECK-NEXT: namespace f16 {
+ // CHECK-NEXT: namespace _16x16x64 {
+ // CHECK: class Bf8BfOp : public ::mlir::Op<Bf8BfOp
+ // CHECK: return ::llvm::StringLiteral("test_irdl_to_cpp.wmma.f16.16x16x64.bf8_bf");
+ // CHECK: } // namespace _16x16x64
+ // CHECK: MLIR_DECLARE_EXPLICIT_TYPE_ID(::mlir::test_irdl_to_cpp::wmma::f16::_16x16x64::Bf8BfOp)
+ irdl.operation @wmma.f16.16x16x64.bf8_bf
+
+ // CHECK: // ::mlir::test_irdl_to_cpp::_7::_8::_9Op declarations
+ // CHECK: namespace _7 {
+ // CHECK-NEXT: namespace _8 {
+ // CHECK: class _9Op : public ::mlir::Op<_9Op
+ // CHECK: return ::llvm::StringLiteral("test_irdl_to_cpp.7.8.9");
+ // CHECK: MLIR_DECLARE_EXPLICIT_TYPE_ID(::mlir::test_irdl_to_cpp::_7::_8::_9Op)
+ irdl.operation @"7.8.9"
+
+ // CHECK: class _10Op : public ::mlir::Op<_10Op
+ // CHECK: return ::llvm::StringLiteral("test_irdl_to_cpp.10");
+ irdl.operation @"10"
+
// CHECK: // ::mlir::test_irdl_to_cpp::nested::NamespacedOp definitions
// CHECK: namespace nested {
// CHECK: NamespacedOp::build
@@ -123,20 +170,18 @@ irdl.dialect @test_irdl_to_cpp {
// CHECK: failure
// CHECK: success
+ // CHECK: // ::mlir::test_irdl_to_cpp::wmma::f16::_16x16x64::Bf8BfOp definitions
+ // CHECK: namespace _16x16x64 {
+ // CHECK: Bf8BfOp::build
+ // CHECK: } // namespace _16x16x64
+ // CHECK: MLIR_DEFINE_EXPLICIT_TYPE_ID(::mlir::test_irdl_to_cpp::wmma::f16::_16x16x64::Bf8BfOp)
+ // CHECK: _9Op::build
+ // CHECK: MLIR_DEFINE_EXPLICIT_TYPE_ID(::mlir::test_irdl_to_cpp::_7::_8::_9Op)
+ // CHECK: _10Op::build
// 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
-
- // TODO(#161018): support irdl.is in irdl-to-cpp
- // %v0 = irdl.is i1 // Type constraint: i1 (boolean)
- %v0 = irdl.any
- %r2 = irdl.region(%v0) // Region with one i1 entry block argument
- irdl.regions(cond: %r2, then: %r0, else: %r1)
-
- %0 = irdl.any
- irdl.operands(input: %0)
- }
+ // CHECK: ::mlir::test_irdl_to_cpp::wmma::f16::_16x16x64::Bf8BfOp,
+ // CHECK-NEXT: ::mlir::test_irdl_to_cpp::_7::_8::_9Op,
+ // CHECK-NEXT: ::mlir::test_irdl_to_cpp::_10Op
}
More information about the Mlir-commits
mailing list