[Mlir-commits] [mlir] [MLIR][IRDL] Relax the restrictions on IRDL-defined names (PR #187911)
llvmlistbot at llvm.org
llvmlistbot at llvm.org
Sun Mar 22 00:05:48 PDT 2026
https://github.com/PragmaTwice updated https://github.com/llvm/llvm-project/pull/187911
>From e44547c3402d066846fca640acbe98e24f0d4f97 Mon Sep 17 00:00:00 2001
From: PragmaTwice <twice at apache.org>
Date: Sun, 22 Mar 2026 13:54:32 +0800
Subject: [PATCH 1/3] [MLIR][IRDL] Relax the restrictions on IRDL-defined names
---
mlir/lib/Dialect/IRDL/IR/IRDL.cpp | 36 ++++++------
mlir/lib/Target/IRDLToCpp/IRDLToCpp.cpp | 57 +++++++++++++------
mlir/test/Dialect/IRDL/invalid.irdl.mlir | 12 ++--
.../test/Dialect/IRDL/invalid_names.irdl.mlir | 51 +++--------------
mlir/test/Dialect/IRDL/regions-ops.irdl.mlir | 4 +-
.../TestIRDLToCpp/test_irdl_to_cpp.irdl.mlir | 7 +++
6 files changed, 79 insertions(+), 88 deletions(-)
diff --git a/mlir/lib/Dialect/IRDL/IR/IRDL.cpp b/mlir/lib/Dialect/IRDL/IR/IRDL.cpp
index 278113fc6e966..4d1663932f736 100644
--- a/mlir/lib/Dialect/IRDL/IR/IRDL.cpp
+++ b/mlir/lib/Dialect/IRDL/IR/IRDL.cpp
@@ -77,25 +77,23 @@ static llvm::LogicalResult isValidName(llvm::StringRef in, mlir::Operation *loc,
if (in.empty())
return loc->emitError("name of ") << label << " is empty";
- bool allowUnderscore = false;
- for (auto &elem : in) {
- if (elem == '_') {
- if (!allowUnderscore)
- return loc->emitError("name of ")
- << label << " should not contain leading or double underscores";
- } 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";
- }
-
- allowUnderscore = elem != '_';
+ // The syntax of a name should follow `bare-id` defined in MLIR LangRef:
+ // bare-id ::= (letter|[_]) (letter|digit|[_$.])*
+ // For easier handling in irdl-to-cpp, we impose two extra restrictions:
+ // - the first character must be a letter;
+ // - only lowercase letters are allowed.
+
+ if (!llvm::isLower(in.front()))
+ return loc->emitError("name of ")
+ << label << " must start with a lowercase letter";
+
+ for (char c : in.drop_front()) {
+ if (!llvm::isLower(c) && !llvm::isDigit(c) && c != '_' && c != '$' &&
+ c != '.')
+ return loc->emitError("name of ")
+ << label
+ << " must contain only lowercase letters, digits, "
+ "underscores, dollar signs or dots";
}
return success();
diff --git a/mlir/lib/Target/IRDLToCpp/IRDLToCpp.cpp b/mlir/lib/Target/IRDLToCpp/IRDLToCpp.cpp
index 046c7dd0fccff..77bf78866520b 100644
--- a/mlir/lib/Target/IRDLToCpp/IRDLToCpp.cpp
+++ b/mlir/lib/Target/IRDLToCpp/IRDLToCpp.cpp
@@ -65,16 +65,43 @@ static std::string joinNameList(llvm::ArrayRef<std::string> names) {
return nameArray;
}
+// Convert a operation/type/attribute name to a valid identifier in C++.
+// The conversion is done by removing dots, underscores and dollar signs and
+// capitalizing the following character. For example, `name.with.dots` will be
+// converted to `nameWithDots` with `capitalizeFirst = false`.
+static std::string toCppName(StringRef input, bool capitalizeFirst = false) {
+ if (input.empty())
+ return "";
+
+ std::string output;
+ output.reserve(input.size());
+
+ // Push the first character, capatilizing if necessary.
+ if (capitalizeFirst && std::islower(input.front()))
+ output.push_back(llvm::toUpper(input.front()));
+ else
+ output.push_back(input.front());
+
+ // Walk the input converting any `*[._$][a-z]` snake case into `*[A-Z]`
+ // camelCase.
+ for (size_t pos = 1, e = input.size(); pos < e; ++pos) {
+ if ((input[pos] == '_' || input[pos] == '.' || input[pos] == '$') &&
+ pos != (e - 1) && std::islower(input[pos + 1]))
+ output.push_back(llvm::toUpper(input[++pos]));
+ else
+ output.push_back(input[pos]);
+ }
+ return output;
+}
+
/// 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", toCppName(type.getSymName(), true));
}
/// Generates the C++ class name for an OperationOp
static std::string opToCppName(irdl::OperationOp op) {
- return llvm::formatv("{0}Op",
- convertToCamelFromSnakeCase(op.getSymName(), true));
+ return llvm::formatv("{0}Op", toCppName(op.getSymName(), true));
}
/// Generates TypeStrings from a TypeOp
@@ -193,15 +220,13 @@ static void generateOpGetterDeclarations(irdl::detail::dictionary &dict,
auto regionAdaptorGetters = std::string{};
for (size_t i = 0, end = opStrings.opOperandNames.size(); i < end; ++i) {
- const auto op =
- llvm::convertToCamelFromSnakeCase(opStrings.opOperandNames[i], true);
+ const auto op = toCppName(opStrings.opOperandNames[i], true);
opGetters += llvm::formatv("::mlir::Value get{0}() { return "
"getStructuredOperands({1}).front(); }\n ",
op, i);
}
for (size_t i = 0, end = opStrings.opResultNames.size(); i < end; ++i) {
- const auto op =
- llvm::convertToCamelFromSnakeCase(opStrings.opResultNames[i], true);
+ const auto op = toCppName(opStrings.opResultNames[i], true);
resGetters += llvm::formatv(
R"(::mlir::Value get{0}() { return ::llvm::cast<::mlir::Value>(getStructuredResults({1}).front()); }
)",
@@ -209,8 +234,7 @@ static void generateOpGetterDeclarations(irdl::detail::dictionary &dict,
}
for (size_t i = 0, end = opStrings.opRegionNames.size(); i < end; ++i) {
- const auto op =
- llvm::convertToCamelFromSnakeCase(opStrings.opRegionNames[i], true);
+ const auto op = toCppName(opStrings.opRegionNames[i], true);
regionAdaptorGetters += llvm::formatv(
R"(::mlir::Region &get{0}() { return *getRegions()[{1}]; }
)",
@@ -235,18 +259,16 @@ static void generateOpBuilderDeclarations(irdl::detail::dictionary &dict,
auto resultParams =
llvm::join(llvm::map_range(opStrings.opResultNames,
[](StringRef name) -> std::string {
- return llvm::formatv(
- "::mlir::Type {0}, ",
- llvm::convertToCamelFromSnakeCase(name));
+ return llvm::formatv("::mlir::Type {0}, ",
+ toCppName(name));
}),
"");
auto operandParams =
llvm::join(llvm::map_range(opStrings.opOperandNames,
[](StringRef name) -> std::string {
- return llvm::formatv(
- "::mlir::Value {0}, ",
- llvm::convertToCamelFromSnakeCase(name));
+ return llvm::formatv("::mlir::Value {0}, ",
+ toCppName(name));
}),
"");
@@ -716,8 +738,7 @@ irdl::translateIRDLDialectToCpp(llvm::ArrayRef<irdl::DialectOp> dialects,
for (auto &pathElement : llvm::reverse(namespaceAbsolutePath))
namespaceCloseStream << "} // namespace " << pathElement << "\n";
- std::string cppShortName =
- llvm::convertToCamelFromSnakeCase(dialectName, true);
+ std::string cppShortName = toCppName(dialectName, true);
std::string dialectBaseTypeName = llvm::formatv("{0}Type", cppShortName);
std::string cppName = llvm::formatv("{0}Dialect", cppShortName);
diff --git a/mlir/test/Dialect/IRDL/invalid.irdl.mlir b/mlir/test/Dialect/IRDL/invalid.irdl.mlir
index 4ff7445c80de8..f40d2e2a98334 100644
--- a/mlir/test/Dialect/IRDL/invalid.irdl.mlir
+++ b/mlir/test/Dialect/IRDL/invalid.irdl.mlir
@@ -25,8 +25,8 @@ irdl.dialect @testd {
irdl.dialect @testd {
irdl.type @type {
%0 = irdl.any
- // expected-error at +1 {{name of parameter #0 must contain only lowercase letters, digits and underscores}}
- irdl.parameters(test$test: %0)
+ // expected-error at +1 {{name of parameter #0 must contain only lowercase letters, digits, underscores, dollar signs or dots}}
+ irdl.parameters(testTest: %0)
}
}
@@ -35,8 +35,8 @@ irdl.dialect @testd {
irdl.dialect @testd {
irdl.operation @op {
%0 = irdl.any
- // expected-error at +1 {{name of result #0 must contain only lowercase letters, digits and underscores}}
- irdl.results(test$test: %0)
+ // expected-error at +1 {{name of result #0 must contain only lowercase letters, digits, underscores, dollar signs or dots}}
+ irdl.results(testTest: %0)
}
}
@@ -45,8 +45,8 @@ irdl.dialect @testd {
irdl.dialect @testd {
irdl.operation @op {
%0 = irdl.any
- // expected-error at +1 {{name of operand #0 must contain only lowercase letters, digits and underscores}}
- irdl.operands(test$test: %0)
+ // expected-error at +1 {{name of operand #0 must contain only lowercase letters, digits, underscores, dollar signs or dots}}
+ irdl.operands(testTest: %0)
}
}
diff --git a/mlir/test/Dialect/IRDL/invalid_names.irdl.mlir b/mlir/test/Dialect/IRDL/invalid_names.irdl.mlir
index 20729e836866b..5dac7c42f1309 100644
--- a/mlir/test/Dialect/IRDL/invalid_names.irdl.mlir
+++ b/mlir/test/Dialect/IRDL/invalid_names.irdl.mlir
@@ -1,30 +1,18 @@
// RUN: mlir-irdl-to-cpp %s --verify-diagnostics --split-input-file
-// expected-error at +1 {{name of dialect should not contain leading or double underscores}}
+// expected-error at +1 {{name of dialect must start with a lowercase letter}}
irdl.dialect @_no_leading_underscore {
}
// -----
-// expected-error at +1 {{name of dialect should not contain leading or double underscores}}
-irdl.dialect @no__double__underscores {
-}
-
-// -----
-
-// expected-error at +1 {{name of dialect should not contain uppercase letters}}
+// expected-error at +1 {{name of dialect must start with a lowercase letter}}
irdl.dialect @NoUpperCase {
}
// -----
-// expected-error at +1 {{name of dialect must contain only lowercase letters, digits and underscores}}
-irdl.dialect @no_weird_symbol$ {
-}
-
-// -----
-
irdl.dialect @test_dialect {
- // expected-error at +1 {{name of operation should not contain leading or double underscores}}
+ // expected-error at +1 {{name of operation must start with a lowercase letter}}
irdl.operation @_no_leading_underscore {
%0 = irdl.any
irdl.results(res: %0)
@@ -34,17 +22,14 @@ irdl.dialect @test_dialect {
// -----
irdl.dialect @test_dialect {
- // expected-error at +1 {{name of operation should not contain leading or double underscores}}
- irdl.operation @no__double__underscores {
- %0 = irdl.any
- irdl.results(res: %0)
- }
+ // expected-error at +1 {{name of operation must contain only lowercase letters, digits, underscores, dollar signs or dots}}
+ irdl.operation @noUpperCase {}
}
// -----
irdl.dialect @test_dialect {
- // expected-error at +1 {{name of operation should not contain uppercase letters}}
+ // expected-error at +1 {{name of operation must start with a lowercase letter}}
irdl.operation @NoUpperCase {
%0 = irdl.any
irdl.results(res: %0)
@@ -53,20 +38,10 @@ irdl.dialect @test_dialect {
// -----
-irdl.dialect @test_dialect {
- // expected-error at +1 {{name of operation must contain only lowercase letters, digits and underscores}}
- irdl.operation @no_weird_symbol$ {
- %0 = irdl.any
- irdl.results(res: %0)
- }
-}
-
-// -----
-
irdl.dialect @test_dialect {
irdl.operation @test_op {
%0 = irdl.any
- // expected-error at +1 {{name of result #0 should not contain leading or double underscores}}
+ // expected-error at +1 {{name of result #0 must start with a lowercase letter}}
irdl.results(_no_leading_underscore: %0)
}
}
@@ -76,17 +51,7 @@ irdl.dialect @test_dialect {
irdl.dialect @test_dialect {
irdl.operation @test_op {
%0 = irdl.any
- // expected-error at +1 {{name of result #0 should not contain leading or double underscores}}
- irdl.results(no__double__underscores: %0)
- }
-}
-
-// -----
-
-irdl.dialect @test_dialect {
- irdl.operation @test_op {
- %0 = irdl.any
- // expected-error at +1 {{name of result #0 should not contain uppercase letters}}
+ // expected-error at +1 {{name of result #0 must start with a lowercase letter}}
irdl.results(NoUpperCase: %0)
}
}
diff --git a/mlir/test/Dialect/IRDL/regions-ops.irdl.mlir b/mlir/test/Dialect/IRDL/regions-ops.irdl.mlir
index e5f884c99e5f4..d61f76cb1befb 100644
--- a/mlir/test/Dialect/IRDL/regions-ops.irdl.mlir
+++ b/mlir/test/Dialect/IRDL/regions-ops.irdl.mlir
@@ -22,8 +22,8 @@ irdl.dialect @test_regions_op_missing_name {
irdl.dialect @test_regions_op_wrong_name {
irdl.operation @op {
%r1 = irdl.region
- // expected-error @below {{name of region #0 must contain only lowercase letters, digits and underscores}}
- irdl.regions(test$test: %r1)
+ // expected-error @below {{name of region #0 must contain only lowercase letters, digits, underscores, dollar signs or dots}}
+ irdl.regions(testTest: %r1)
}
}
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..5c2f700d56fd0 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,13 @@ irdl.dialect @test_irdl_to_cpp {
// CHECK: class FooType
irdl.type @foo
+ // CHECK: class NameWithDotsType
+ irdl.type @name.with.dots
+ // CHECK: class NameWithDollarsType
+ irdl.type @name$with$dollars
+ // CHECK: class NameWithUnderscoresType
+ irdl.type @name_with_underscores
+
// CHECK: class BarOp
// CHECK: ::mlir::Value getRes()
irdl.operation @bar {
>From a95239e646b419550c3fcd942d3c952ea1900d7f Mon Sep 17 00:00:00 2001
From: PragmaTwice <twice at apache.org>
Date: Sun, 22 Mar 2026 14:10:34 +0800
Subject: [PATCH 2/3] fix comment
---
mlir/lib/Target/IRDLToCpp/IRDLToCpp.cpp | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/mlir/lib/Target/IRDLToCpp/IRDLToCpp.cpp b/mlir/lib/Target/IRDLToCpp/IRDLToCpp.cpp
index 77bf78866520b..5f089de3abf05 100644
--- a/mlir/lib/Target/IRDLToCpp/IRDLToCpp.cpp
+++ b/mlir/lib/Target/IRDLToCpp/IRDLToCpp.cpp
@@ -65,7 +65,7 @@ static std::string joinNameList(llvm::ArrayRef<std::string> names) {
return nameArray;
}
-// Convert a operation/type/attribute name to a valid identifier in C++.
+// Convert a dialect/operation/type/attribute name to a valid identifier in C++.
// The conversion is done by removing dots, underscores and dollar signs and
// capitalizing the following character. For example, `name.with.dots` will be
// converted to `nameWithDots` with `capitalizeFirst = false`.
>From d491004f29aaf580a36f0454801ea4031cbbb15d Mon Sep 17 00:00:00 2001
From: PragmaTwice <twice at apache.org>
Date: Sun, 22 Mar 2026 15:05:28 +0800
Subject: [PATCH 3/3] fix
---
mlir/lib/Target/IRDLToCpp/IRDLToCpp.cpp | 17 ++++++++++-------
1 file changed, 10 insertions(+), 7 deletions(-)
diff --git a/mlir/lib/Target/IRDLToCpp/IRDLToCpp.cpp b/mlir/lib/Target/IRDLToCpp/IRDLToCpp.cpp
index 5f089de3abf05..7b80344c88646 100644
--- a/mlir/lib/Target/IRDLToCpp/IRDLToCpp.cpp
+++ b/mlir/lib/Target/IRDLToCpp/IRDLToCpp.cpp
@@ -82,14 +82,17 @@ static std::string toCppName(StringRef input, bool capitalizeFirst = false) {
else
output.push_back(input.front());
- // Walk the input converting any `*[._$][a-z]` snake case into `*[A-Z]`
+ // Walk the input converting any `*[._$]+[a-z]` snake case into `*[A-Z]`
// camelCase.
- for (size_t pos = 1, e = input.size(); pos < e; ++pos) {
- if ((input[pos] == '_' || input[pos] == '.' || input[pos] == '$') &&
- pos != (e - 1) && std::islower(input[pos + 1]))
- output.push_back(llvm::toUpper(input[++pos]));
- else
- output.push_back(input[pos]);
+ bool isSpecial = false;
+ for (char c : input.drop_front()) {
+ if (c == '_' || c == '.' || c == '$')
+ isSpecial = true;
+ else if (isSpecial) {
+ output.push_back(llvm::toUpper(c));
+ isSpecial = false;
+ } else
+ output.push_back(c);
}
return output;
}
More information about the Mlir-commits
mailing list