[Mlir-commits] [mlir] [MLIR][IRDL] Relax the restrictions on IRDL-defined names (PR #187911)
llvmlistbot at llvm.org
llvmlistbot at llvm.org
Sat Mar 21 23:07:28 PDT 2026
llvmbot wrote:
<!--LLVM PR SUMMARY COMMENT-->
@llvm/pr-subscribers-mlir
Author: Twice (PragmaTwice)
<details>
<summary>Changes</summary>
Previously, the irdl-to-cpp PR #<!-- -->141248 added a relatively strong restriction to all IRDL names (for IRDL-defined dialects, operations, types and attributes): only lowercase letters, digits and underscores are allowed.
But actually `.` and `$` are allowed in normal MLIR operation names. Dots `.` are special useful for splitting operations in different categories inside a dialect. (Rolf can provide more context about this : )
Also for users who don't need `irdl-to-cpp`, these restrictions are weird and useless.
In this PR we relax the restrictions on IRDL names, and also modify irdl-to-cpp to generate valid C++ names.
---
Full diff: https://github.com/llvm/llvm-project/pull/187911.diff
6 Files Affected:
- (modified) mlir/lib/Dialect/IRDL/IR/IRDL.cpp (+17-19)
- (modified) mlir/lib/Target/IRDLToCpp/IRDLToCpp.cpp (+39-18)
- (modified) mlir/test/Dialect/IRDL/invalid.irdl.mlir (+6-6)
- (modified) mlir/test/Dialect/IRDL/invalid_names.irdl.mlir (+8-43)
- (modified) mlir/test/Dialect/IRDL/regions-ops.irdl.mlir (+2-2)
- (modified) mlir/test/lib/Dialect/TestIRDLToCpp/test_irdl_to_cpp.irdl.mlir (+7)
``````````diff
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 {
``````````
</details>
https://github.com/llvm/llvm-project/pull/187911
More information about the Mlir-commits
mailing list