[Mlir-commits] [mlir] [mlir] Populate properties before parser-time inferReturnTypes (PR #194658)
llvmlistbot at llvm.org
llvmlistbot at llvm.org
Tue Apr 28 08:49:13 PDT 2026
llvmbot wrote:
<!--LLVM PR SUMMARY COMMENT-->
@llvm/pr-subscribers-mlir-core
Author: Zmicier Prybysh (dimp-pl)
<details>
<summary>Changes</summary>
Fixes #<!-- -->193284.
In inferReturnTypes it's possible to segfault when accessing an attribute that's stored as property under specific conditions:
- Attribute must be inherent.
- `DeclareOpInterfaceMethods<InferTypeOpInterface, ["inferReturnTypes"]>`.
- Attribute is read in `inferReturnTypes` via `Adaptor`.
- Op omits `type($result)` from assembly format.
The fix works by emitting an additional `setInherentAttr` per each attribute before the `inferReturnTypes` call.
This kind of repeats what `Operation::setAttrs` is doing in runtime, but only in parser-time so that `inferReturnTypes` sees a populated property.
Assisted-By: Claude Code
---
Full diff: https://github.com/llvm/llvm-project/pull/194658.diff
4 Files Affected:
- (modified) mlir/test/lib/Dialect/Test/TestOpDefs.cpp (+13)
- (modified) mlir/test/lib/Dialect/Test/TestOps.td (+9)
- (modified) mlir/test/mlir-tblgen/op-format.mlir (+4)
- (modified) mlir/tools/mlir-tblgen/OpFormatGen.cpp (+16-1)
``````````diff
diff --git a/mlir/test/lib/Dialect/Test/TestOpDefs.cpp b/mlir/test/lib/Dialect/Test/TestOpDefs.cpp
index 340b44b14dd96..38177d22c8bd0 100644
--- a/mlir/test/lib/Dialect/Test/TestOpDefs.cpp
+++ b/mlir/test/lib/Dialect/Test/TestOpDefs.cpp
@@ -1295,6 +1295,19 @@ LogicalResult TestOpWithPropertiesAndInferredType::inferReturnTypes(
return success();
}
+//===----------------------------------------------------------------------===//
+// TestOpWithAttrInferredType
+//===----------------------------------------------------------------------===//
+
+LogicalResult TestOpWithAttrInferredType::inferReturnTypes(
+ MLIRContext *context, std::optional<Location>, ValueRange operands,
+ DictionaryAttr attributes, PropertyRef properties, RegionRange regions,
+ SmallVectorImpl<Type> &inferredReturnTypes) {
+ Adaptor adaptor(operands, attributes, properties, regions);
+ inferredReturnTypes.push_back(IntegerType::get(context, adaptor.getLhs()));
+ return success();
+}
+
//===----------------------------------------------------------------------===//
// LoopBlockOp
//===----------------------------------------------------------------------===//
diff --git a/mlir/test/lib/Dialect/Test/TestOps.td b/mlir/test/lib/Dialect/Test/TestOps.td
index 348ff5d7f4ea0..5ac64ada612f7 100644
--- a/mlir/test/lib/Dialect/Test/TestOps.td
+++ b/mlir/test/lib/Dialect/Test/TestOps.td
@@ -3527,6 +3527,15 @@ def TestOpWithPropertiesAndInferredType
let results = (outs AnyType:$result);
}
+def TestOpWithAttrInferredType
+ : TEST_Op<"with_attr_inferred_type", [
+ DeclareOpInterfaceMethods<InferTypeOpInterface, ["inferReturnTypes"]>
+ ]> {
+ let assemblyFormat = "$input attr-dict `:` type($input)";
+ let arguments = (ins I32:$input, I32Attr:$lhs);
+ let results = (outs AnyType:$output);
+}
+
// Demonstrate how to wrap an existing C++ class named MyPropStruct.
def MyStructProperty : Property<"MyPropStruct"> {
let convertToAttribute = "return $_storage.asAttribute($_ctxt);";
diff --git a/mlir/test/mlir-tblgen/op-format.mlir b/mlir/test/mlir-tblgen/op-format.mlir
index 7ff9091d5500d..3e8ee9ed330b4 100644
--- a/mlir/test/mlir-tblgen/op-format.mlir
+++ b/mlir/test/mlir-tblgen/op-format.mlir
@@ -534,6 +534,10 @@ test.with_properties_and_attr 16 <{rhs = 16 : i64}>
// Assert through the verifier that its inferred as i32.
test.format_all_types_match_var %should_be_i32, %i32 : i32
+// CHECK: test.with_attr_inferred_type %[[I32]] {lhs = 32 : i32} : i32
+%attr_inferred_i32 = test.with_attr_inferred_type %i32 {lhs = 32 : i32} : i32
+test.format_all_types_match_var %attr_inferred_i32, %i32 : i32
+
// CHECK: test.using_property_in_custom_and_other [1, 4, 20] <{other = 16 : i64}>
test.using_property_in_custom_and_other [1, 4, 20] <{other = 16 : i64}>
diff --git a/mlir/tools/mlir-tblgen/OpFormatGen.cpp b/mlir/tools/mlir-tblgen/OpFormatGen.cpp
index cbcbc8e9bc102..30a9b50986224 100644
--- a/mlir/tools/mlir-tblgen/OpFormatGen.cpp
+++ b/mlir/tools/mlir-tblgen/OpFormatGen.cpp
@@ -676,6 +676,17 @@ const char *const inferReturnTypesParserCode = R"(
result.addTypes(inferredReturnTypes);
)";
+/// The code snippet used to copy attribute-form inherent attributes from
+/// `result.attributes` into the inline properties storage.
+///
+/// {0}: The operation class name
+const char *const inferReturnTypesPopulatePropertiesCode = R"(
+ auto &inferRetTypesProps = result.getOrAddProperties<{0}::Properties>();
+ for (const ::mlir::NamedAttribute &namedAttr : result.attributes)
+ {0}::setInherentAttr(inferRetTypesProps, namedAttr.getName().getValue(),
+ namedAttr.getValue());
+)";
+
/// The code snippet used to generate a parser call for a region list.
///
/// {0}: The name for the region list.
@@ -1782,8 +1793,12 @@ void OperationFormat::genParserTypeResolution(Operator &op, MethodBody &body) {
genParserOperandTypeResolution(op, body, emitTypeResolver);
// Handle return type inference once all operands have been resolved
- if (infersResultTypes)
+ if (infersResultTypes) {
+ if (useProperties)
+ body << formatv(inferReturnTypesPopulatePropertiesCode,
+ op.getCppClassName());
body << formatv(inferReturnTypesParserCode, op.getCppClassName());
+ }
}
void OperationFormat::genParserOperandTypeResolution(
``````````
</details>
https://github.com/llvm/llvm-project/pull/194658
More information about the Mlir-commits
mailing list