[Mlir-commits] [mlir] [mlir] Refactor opaque properties to make them type-safe (PR #185157)
Krzysztof Drewniak
llvmlistbot at llvm.org
Sat Mar 14 23:11:56 PDT 2026
https://github.com/krzysz00 updated https://github.com/llvm/llvm-project/pull/185157
>From c614da57af9a22c1e7fd63cd4bf0b15d7a7ecb76 Mon Sep 17 00:00:00 2001
From: Krzysztof Drewniak <krzysdrewniak at gmail.com>
Date: Mon, 2 Mar 2026 20:44:16 -0800
Subject: [PATCH 1/2] [mlir] Refactor opaque properties to make them type-safe
At its core, this commit changes `OpaqueProperties` (aka a void*) to
`PropertyRef`, which is a {TypeID, void*}, where the TypeID is the ID
of the storage type of the given property (which can, as is often the
case for operations, be a struct of other properties).
Long-term, this change will allow for
1) Some sort of getFooPropertyRef() on property structs, allowing
individual members to be extracted generically
2) By having a property kind that is an OwningProprtyRef, generic
parsing (in combination with a bunch of other changes)
3) Probably a safer C/Python API because we'll be able to indicate
what's supposed to be under a given void*
Co-Authored-By: Claude Opus 4.6 <noreply at anthropic.com>
---
mlir/include/mlir/IR/ExtensibleDialect.h | 18 +--
mlir/include/mlir/IR/OpDefinition.h | 11 +-
mlir/include/mlir/IR/Operation.h | 45 +++---
mlir/include/mlir/IR/OperationSupport.h | 149 ++++++++++--------
.../mlir/Interfaces/InferTypeOpInterface.td | 14 +-
mlir/lib/CAPI/IR/IR.cpp | 6 +-
mlir/lib/CAPI/Interfaces/Interfaces.cpp | 15 +-
mlir/lib/Dialect/AMDGPU/IR/AMDGPUOps.cpp | 2 +-
.../Bufferization/IR/BufferizationOps.cpp | 2 +-
mlir/lib/Dialect/MemRef/IR/MemRefOps.cpp | 2 +-
mlir/lib/Dialect/Ptr/IR/PtrDialect.cpp | 2 +-
mlir/lib/Dialect/SMT/IR/SMTOps.cpp | 4 +-
.../SparseTensor/IR/SparseTensorDialect.cpp | 14 +-
mlir/lib/Dialect/Tosa/IR/TosaOps.cpp | 10 +-
mlir/lib/Dialect/WasmSSA/IR/WasmSSAOps.cpp | 6 +-
mlir/lib/IR/ExtensibleDialect.cpp | 2 +
mlir/lib/IR/MLIRContext.cpp | 22 +--
mlir/lib/IR/Operation.cpp | 21 ++-
mlir/lib/IR/OperationSupport.cpp | 2 +
.../IRDLToCpp/Templates/PerOperationDecl.txt | 2 +-
.../Transforms/Utils/DialectConversion.cpp | 8 +-
mlir/test/lib/Dialect/Test/TestOpDefs.cpp | 12 +-
mlir/test/lib/Dialect/Test/TestOps.td | 4 +-
mlir/test/lib/Dialect/Test/TestOpsSyntax.cpp | 2 +-
mlir/test/lib/Dialect/Test/TestOpsSyntax.td | 8 +-
mlir/test/lib/Dialect/Test/TestPatterns.cpp | 7 +-
mlir/test/mlir-tblgen/op-decl-and-defs.td | 2 +-
mlir/test/python/python_test_ops.td | 6 +-
mlir/tools/mlir-tblgen/OpDefinitionsGen.cpp | 43 +++--
.../FileLineColLocBreakpointManagerTest.cpp | 2 +-
30 files changed, 246 insertions(+), 197 deletions(-)
diff --git a/mlir/include/mlir/IR/ExtensibleDialect.h b/mlir/include/mlir/IR/ExtensibleDialect.h
index dcbf6813506d5..f6b82bffcfffc 100644
--- a/mlir/include/mlir/IR/ExtensibleDialect.h
+++ b/mlir/include/mlir/IR/ExtensibleDialect.h
@@ -550,25 +550,23 @@ class DynamicOpDefinition : public OperationName::Impl {
return success();
}
int getOpPropertyByteSize() final { return 0; }
- void initProperties(OperationName opName, OpaqueProperties storage,
- OpaqueProperties init) final {}
- void deleteProperties(OpaqueProperties prop) final {}
+ void initProperties(OperationName opName, PropertyRef storage,
+ PropertyRef init) final {}
+ void deleteProperties(PropertyRef prop) final {}
void populateDefaultProperties(OperationName opName,
- OpaqueProperties properties) final {}
+ PropertyRef properties) final {}
LogicalResult
- setPropertiesFromAttr(OperationName opName, OpaqueProperties properties,
+ setPropertiesFromAttr(OperationName opName, PropertyRef properties,
Attribute attr,
function_ref<InFlightDiagnostic()> emitError) final {
emitError() << "extensible Dialects don't support properties";
return failure();
}
Attribute getPropertiesAsAttr(Operation *op) final { return {}; }
- void copyProperties(OpaqueProperties lhs, OpaqueProperties rhs) final {}
- bool compareProperties(OpaqueProperties, OpaqueProperties) final {
- return true;
- }
- llvm::hash_code hashProperties(OpaqueProperties prop) final { return {}; }
+ void copyProperties(PropertyRef lhs, PropertyRef rhs) final {}
+ bool compareProperties(PropertyRef, PropertyRef) final { return true; }
+ llvm::hash_code hashProperties(PropertyRef prop) final { return {}; }
private:
DynamicOpDefinition(
diff --git a/mlir/include/mlir/IR/OpDefinition.h b/mlir/include/mlir/IR/OpDefinition.h
index be92fe0a6c7e3..e886ac45675e2 100644
--- a/mlir/include/mlir/IR/OpDefinition.h
+++ b/mlir/include/mlir/IR/OpDefinition.h
@@ -243,9 +243,10 @@ class OpState {
/// so we can cast it away here.
explicit OpState(Operation *state) : state(state) {}
- /// For all op which don't have properties, we keep a single instance of
- /// `EmptyProperties` to be used where a reference to a properties is needed:
- /// this allow to bind a pointer to the reference without triggering UB.
+ /// For all ops which don't have properties, we keep a single instance of
+ /// `EmptyProperties` to be used where a pointer to a struct of properties
+ /// is needed: this allows binding a pointer to the reference without
+ /// triggering UB.
static EmptyProperties &getEmptyProperties() {
static EmptyProperties emptyProperties;
return emptyProperties;
@@ -1978,7 +1979,7 @@ class Op : public OpState, public Traits<ConcreteType>... {
if constexpr (!hasProperties())
return getEmptyProperties();
return *getOperation()
- ->getPropertiesStorageUnsafe()
+ ->getPropertiesStorage()
.template as<InferredProperties<T> *>();
}
@@ -2152,4 +2153,6 @@ struct DenseMapInfo<T,
};
} // namespace llvm
+MLIR_DECLARE_EXPLICIT_TYPE_ID(mlir::EmptyProperties)
+
#endif
diff --git a/mlir/include/mlir/IR/Operation.h b/mlir/include/mlir/IR/Operation.h
index f2c0f354d0ddb..8c53b348f6bf8 100644
--- a/mlir/include/mlir/IR/Operation.h
+++ b/mlir/include/mlir/IR/Operation.h
@@ -92,17 +92,15 @@ class alignas(8) Operation final
/// necessary.
static Operation *create(Location location, OperationName name,
TypeRange resultTypes, ValueRange operands,
- NamedAttrList &&attributes,
- OpaqueProperties properties, BlockRange successors,
- unsigned numRegions);
+ NamedAttrList &&attributes, PropertyRef properties,
+ BlockRange successors, unsigned numRegions);
/// Create a new Operation with the specific fields. This constructor uses an
/// existing attribute dictionary to avoid uniquing a list of attributes.
static Operation *create(Location location, OperationName name,
TypeRange resultTypes, ValueRange operands,
- DictionaryAttr attributes,
- OpaqueProperties properties, BlockRange successors,
- unsigned numRegions);
+ DictionaryAttr attributes, PropertyRef properties,
+ BlockRange successors, unsigned numRegions);
/// Create a new Operation from the fields stored in `state`.
static Operation *create(const OperationState &state);
@@ -110,8 +108,7 @@ class alignas(8) Operation final
/// Create a new Operation with the specific fields.
static Operation *create(Location location, OperationName name,
TypeRange resultTypes, ValueRange operands,
- NamedAttrList &&attributes,
- OpaqueProperties properties,
+ NamedAttrList &&attributes, PropertyRef properties,
BlockRange successors = {},
RegionRange regions = {});
@@ -925,23 +922,29 @@ class alignas(8) Operation final
int getPropertiesStorageSize() const {
return ((int)propertiesStorageSize) * 8;
}
- /// Returns the properties storage.
- OpaqueProperties getPropertiesStorage() {
+
+ /// Return a geeric (but typed) reference to the property type storage.
+ PropertyRef getPropertiesStorage() {
if (propertiesStorageSize)
- return getPropertiesStorageUnsafe();
+ return PropertyRef(name.getOpPropertiesTypeID(),
+ getRawPropertiesStorageUnsafe());
return {nullptr};
}
- OpaqueProperties getPropertiesStorage() const {
+
+ PropertyRef getPropertiesStorage() const {
if (propertiesStorageSize)
- return {reinterpret_cast<void *>(const_cast<detail::OpProperties *>(
- getTrailingObjects<detail::OpProperties>()))};
+ return PropertyRef(
+ name.getOpPropertiesTypeID(),
+ reinterpret_cast<void *>(const_cast<detail::OpProperties *>(
+ getTrailingObjects<detail::OpProperties>())));
return {nullptr};
}
- /// Returns the properties storage without checking whether properties are
- /// present.
- OpaqueProperties getPropertiesStorageUnsafe() {
- return {
- reinterpret_cast<void *>(getTrailingObjects<detail::OpProperties>())};
+
+ /// Returns a pointer to the properties storage (if it exists) with no type
+ /// information.
+ void *getRawPropertiesStorageUnsafe() {
+ return reinterpret_cast<void *>(const_cast<detail::OpProperties *>(
+ getTrailingObjects<detail::OpProperties>()));
}
/// Return the properties converted to an attribute.
@@ -961,7 +964,7 @@ class alignas(8) Operation final
/// Copy properties from an existing other properties object. The two objects
/// must be the same type.
- void copyProperties(OpaqueProperties rhs);
+ void copyProperties(PropertyRef rhs);
/// Compute a hash for the op properties (if any).
llvm::hash_code hashProperties();
@@ -990,7 +993,7 @@ class alignas(8) Operation final
Operation(Location location, OperationName name, unsigned numResults,
unsigned numSuccessors, unsigned numRegions,
int propertiesStorageSize, DictionaryAttr attributes,
- OpaqueProperties properties, bool hasOperandStorage);
+ PropertyRef properties, bool hasOperandStorage);
// Operations are deleted through the destroy() member because they are
// allocated with malloc.
diff --git a/mlir/include/mlir/IR/OperationSupport.h b/mlir/include/mlir/IR/OperationSupport.h
index ac069df1d3e7d..f91661bebce75 100644
--- a/mlir/include/mlir/IR/OperationSupport.h
+++ b/mlir/include/mlir/IR/OperationSupport.h
@@ -63,22 +63,34 @@ template <typename ValueRangeT>
class ValueTypeRange;
//===----------------------------------------------------------------------===//
-// OpaqueProperties
+// PropertyRef
//===----------------------------------------------------------------------===//
-/// Simple wrapper around a void* in order to express generically how to pass
-/// in op properties through APIs.
-class OpaqueProperties {
+/// Type-safe wrapper around a void* for passing properties, including the
+/// properties structs of operations, generically through APIs. Pairs data with
+/// a TypeID for assert-based type checking. Note that the type in the type ID
+/// is the **storage** type of the property, and that the default object has a
+/// null data pointer and a type ID equal to the type ID for `void`.
+class PropertyRef {
public:
- OpaqueProperties(void *prop) : properties(prop) {}
- operator bool() const { return properties != nullptr; }
+ PropertyRef() = default;
+ PropertyRef(std::nullptr_t) {}
+ PropertyRef(TypeID typeID, void *data) : typeID(typeID), data(data) {}
+ operator bool() const { return data != nullptr; }
template <typename Dest>
Dest as() const {
- return static_cast<Dest>(const_cast<void *>(properties));
+ static_assert(std::is_pointer_v<Dest>,
+ "PropertyRef::as<T>() requires T to be a pointer type");
+ using RawType = std::remove_cv_t<std::remove_pointer_t<Dest>>;
+ assert((!data || typeID == TypeID::get<RawType>()) &&
+ "Property type mismatch: TypeID does not match requested type");
+ return static_cast<Dest>(data);
}
+ TypeID getTypeID() const { return typeID; }
private:
- void *properties;
+ TypeID typeID;
+ void *data = nullptr;
};
//===----------------------------------------------------------------------===//
@@ -130,18 +142,18 @@ class OperationName {
verifyInherentAttrs(OperationName opName, NamedAttrList &attributes,
function_ref<InFlightDiagnostic()> emitError) = 0;
virtual int getOpPropertyByteSize() = 0;
- virtual void initProperties(OperationName opName, OpaqueProperties storage,
- OpaqueProperties init) = 0;
- virtual void deleteProperties(OpaqueProperties) = 0;
+ virtual void initProperties(OperationName opName, PropertyRef storage,
+ PropertyRef init) = 0;
+ virtual void deleteProperties(PropertyRef) = 0;
virtual void populateDefaultProperties(OperationName opName,
- OpaqueProperties properties) = 0;
+ PropertyRef properties) = 0;
virtual LogicalResult
- setPropertiesFromAttr(OperationName, OpaqueProperties, Attribute,
+ setPropertiesFromAttr(OperationName, PropertyRef, Attribute,
function_ref<InFlightDiagnostic()> emitError) = 0;
virtual Attribute getPropertiesAsAttr(Operation *) = 0;
- virtual void copyProperties(OpaqueProperties, OpaqueProperties) = 0;
- virtual bool compareProperties(OpaqueProperties, OpaqueProperties) = 0;
- virtual llvm::hash_code hashProperties(OpaqueProperties) = 0;
+ virtual void copyProperties(PropertyRef, PropertyRef) = 0;
+ virtual bool compareProperties(PropertyRef, PropertyRef) = 0;
+ virtual llvm::hash_code hashProperties(PropertyRef) = 0;
};
public:
@@ -160,6 +172,7 @@ class OperationName {
Dialect *getDialect() const { return dialect; }
StringAttr getName() const { return name; }
TypeID getTypeID() const { return typeID; }
+ TypeID getPropertiesTypeID() const { return propertiesTypeID; }
ArrayRef<StringAttr> getAttributeNames() const { return attributeNames; }
protected:
@@ -186,13 +199,20 @@ class OperationName {
/// lookup/creation/etc., as opposed to raw strings.
ArrayRef<StringAttr> attributeNames;
+ /// The TypeID of the Properties struct for this operation.
+ TypeID propertiesTypeID;
+
friend class RegisteredOperationName;
};
protected:
/// Default implementation for unregistered operations.
struct UnregisteredOpModel : public Impl {
- using Impl::Impl;
+ UnregisteredOpModel(StringAttr name, Dialect *dialect, TypeID typeID,
+ detail::InterfaceMap interfaceMap)
+ : Impl(name, dialect, typeID, std::move(interfaceMap)) {
+ propertiesTypeID = TypeID::get<Attribute>();
+ }
LogicalResult foldHook(Operation *, ArrayRef<Attribute>,
SmallVectorImpl<OpFoldResult> &) final;
void getCanonicalizationPatterns(RewritePatternSet &, MLIRContext *) final;
@@ -211,18 +231,18 @@ class OperationName {
verifyInherentAttrs(OperationName opName, NamedAttrList &attributes,
function_ref<InFlightDiagnostic()> emitError) final;
int getOpPropertyByteSize() final;
- void initProperties(OperationName opName, OpaqueProperties storage,
- OpaqueProperties init) final;
- void deleteProperties(OpaqueProperties) final;
+ void initProperties(OperationName opName, PropertyRef storage,
+ PropertyRef init) final;
+ void deleteProperties(PropertyRef) final;
void populateDefaultProperties(OperationName opName,
- OpaqueProperties properties) final;
+ PropertyRef properties) final;
LogicalResult
- setPropertiesFromAttr(OperationName, OpaqueProperties, Attribute,
+ setPropertiesFromAttr(OperationName, PropertyRef, Attribute,
function_ref<InFlightDiagnostic()> emitError) final;
Attribute getPropertiesAsAttr(Operation *) final;
- void copyProperties(OpaqueProperties, OpaqueProperties) final;
- bool compareProperties(OpaqueProperties, OpaqueProperties) final;
- llvm::hash_code hashProperties(OpaqueProperties) final;
+ void copyProperties(PropertyRef, PropertyRef) final;
+ bool compareProperties(PropertyRef, PropertyRef) final;
+ llvm::hash_code hashProperties(PropertyRef) final;
};
public:
@@ -413,18 +433,23 @@ class OperationName {
return getImpl()->getOpPropertyByteSize();
}
+ /// Return the TypeID of the op properties.
+ TypeID getOpPropertiesTypeID() const {
+ return getImpl()->getPropertiesTypeID();
+ }
+
/// This hooks destroy the op properties.
- void destroyOpProperties(OpaqueProperties properties) const {
+ void destroyOpProperties(PropertyRef properties) const {
getImpl()->deleteProperties(properties);
}
/// Initialize the op properties.
- void initOpProperties(OpaqueProperties storage, OpaqueProperties init) const {
+ void initOpProperties(PropertyRef storage, PropertyRef init) const {
getImpl()->initProperties(*this, storage, init);
}
/// Set the default values on the ODS attribute in the properties.
- void populateDefaultProperties(OpaqueProperties properties) const {
+ void populateDefaultProperties(PropertyRef properties) const {
getImpl()->populateDefaultProperties(*this, properties);
}
@@ -435,21 +460,21 @@ class OperationName {
/// Define the op properties from the provided Attribute.
LogicalResult setOpPropertiesFromAttribute(
- OperationName opName, OpaqueProperties properties, Attribute attr,
+ OperationName opName, PropertyRef properties, Attribute attr,
function_ref<InFlightDiagnostic()> emitError) const {
return getImpl()->setPropertiesFromAttr(opName, properties, attr,
emitError);
}
- void copyOpProperties(OpaqueProperties lhs, OpaqueProperties rhs) const {
+ void copyOpProperties(PropertyRef lhs, PropertyRef rhs) const {
return getImpl()->copyProperties(lhs, rhs);
}
- bool compareOpProperties(OpaqueProperties lhs, OpaqueProperties rhs) const {
+ bool compareOpProperties(PropertyRef lhs, PropertyRef rhs) const {
return getImpl()->compareProperties(lhs, rhs);
}
- llvm::hash_code hashOpProperties(OpaqueProperties properties) const {
+ llvm::hash_code hashOpProperties(PropertyRef properties) const {
return getImpl()->hashProperties(properties);
}
@@ -528,9 +553,13 @@ class RegisteredOperationName : public OperationName {
/// to a concrete op implementation.
template <typename ConcreteOp>
struct Model : public Impl {
+ using Properties = std::remove_reference_t<
+ decltype(std::declval<ConcreteOp>().getProperties())>;
Model(Dialect *dialect)
: Impl(ConcreteOp::getOperationName(), dialect,
- TypeID::get<ConcreteOp>(), ConcreteOp::getInterfaceMap()) {}
+ TypeID::get<ConcreteOp>(), ConcreteOp::getInterfaceMap()) {
+ propertiesTypeID = TypeID::get<Properties>();
+ }
LogicalResult foldHook(Operation *op, ArrayRef<Attribute> attrs,
SmallVectorImpl<OpFoldResult> &results) final {
return ConcreteOp::getFoldHookFn()(op, attrs, results);
@@ -560,9 +589,6 @@ class RegisteredOperationName : public OperationName {
/// Implementation for "Properties"
- using Properties = std::remove_reference_t<
- decltype(std::declval<ConcreteOp>().getProperties())>;
-
std::optional<Attribute> getInherentAttr(Operation *op,
StringRef name) final {
if constexpr (hasProperties) {
@@ -606,8 +632,8 @@ class RegisteredOperationName : public OperationName {
return sizeof(Properties);
return 0;
}
- void initProperties(OperationName opName, OpaqueProperties storage,
- OpaqueProperties init) final {
+ void initProperties(OperationName opName, PropertyRef storage,
+ PropertyRef init) final {
using Properties =
typename ConcreteOp::template InferredProperties<ConcreteOp>;
if (init)
@@ -618,18 +644,18 @@ class RegisteredOperationName : public OperationName {
ConcreteOp::populateDefaultProperties(opName,
*storage.as<Properties *>());
}
- void deleteProperties(OpaqueProperties prop) final {
+ void deleteProperties(PropertyRef prop) final {
prop.as<Properties *>()->~Properties();
}
void populateDefaultProperties(OperationName opName,
- OpaqueProperties properties) final {
+ PropertyRef properties) final {
if constexpr (hasProperties)
ConcreteOp::populateDefaultProperties(opName,
*properties.as<Properties *>());
}
LogicalResult
- setPropertiesFromAttr(OperationName opName, OpaqueProperties properties,
+ setPropertiesFromAttr(OperationName opName, PropertyRef properties,
Attribute attr,
function_ref<InFlightDiagnostic()> emitError) final {
if constexpr (hasProperties) {
@@ -647,15 +673,15 @@ class RegisteredOperationName : public OperationName {
}
return {};
}
- bool compareProperties(OpaqueProperties lhs, OpaqueProperties rhs) final {
+ bool compareProperties(PropertyRef lhs, PropertyRef rhs) final {
if constexpr (hasProperties)
return *lhs.as<Properties *>() == *rhs.as<Properties *>();
return true;
}
- void copyProperties(OpaqueProperties lhs, OpaqueProperties rhs) final {
+ void copyProperties(PropertyRef lhs, PropertyRef rhs) final {
*lhs.as<Properties *>() = *rhs.as<Properties *>();
}
- llvm::hash_code hashProperties(OpaqueProperties prop) final {
+ llvm::hash_code hashProperties(PropertyRef prop) final {
if constexpr (hasProperties)
return ConcreteOp::computePropertiesHash(*prop.as<Properties *>());
@@ -959,11 +985,9 @@ struct OperationState {
Attribute propertiesAttr;
private:
- OpaqueProperties properties = nullptr;
- TypeID propertiesId;
- llvm::function_ref<void(OpaqueProperties)> propertiesDeleter;
- llvm::function_ref<void(OpaqueProperties, const OpaqueProperties)>
- propertiesSetter;
+ PropertyRef properties;
+ llvm::function_ref<void(PropertyRef)> propertiesDeleter;
+ llvm::function_ref<void(PropertyRef, const PropertyRef)> propertiesSetter;
friend class Operation;
public:
@@ -984,13 +1008,13 @@ struct OperationState {
OperationState &operator=(const OperationState &other) = delete;
~OperationState();
- /// Get (or create) a properties of the provided type to be set on the
+ /// Get (or create) the properties of the provided type to be set on the
/// operation on creation.
template <typename T>
T &getOrAddProperties() {
if (!properties) {
T *p = new T{};
- properties = p;
+ properties = PropertyRef(TypeID::get<T>(), p);
#if defined(__clang__)
#if __has_warning("-Wdangling-assignment-gsl")
#pragma clang diagnostic push
@@ -998,11 +1022,8 @@ struct OperationState {
#pragma clang diagnostic ignored "-Wdangling-assignment-gsl"
#endif
#endif
- propertiesDeleter = [](OpaqueProperties prop) {
- delete prop.as<const T *>();
- };
- propertiesSetter = [](OpaqueProperties newProp,
- const OpaqueProperties prop) {
+ propertiesDeleter = [](PropertyRef prop) { delete prop.as<const T *>(); };
+ propertiesSetter = [](PropertyRef newProp, const PropertyRef prop) {
*newProp.as<T *>() = *prop.as<const T *>();
};
#if defined(__clang__)
@@ -1010,12 +1031,12 @@ struct OperationState {
#pragma clang diagnostic pop
#endif
#endif
- propertiesId = TypeID::get<T>();
}
- assert(propertiesId == TypeID::get<T>() && "Inconsistent properties");
+ assert(properties.getTypeID() == TypeID::get<T>() &&
+ "Inconsistent properties");
return *properties.as<T *>();
}
- OpaqueProperties getRawProperties() { return properties; }
+ PropertyRef getRawProperties() { return properties; }
// Set the properties defined on this OpState on the given operation,
// optionally emit diagnostics on error through the provided diagnostic.
@@ -1026,13 +1047,13 @@ struct OperationState {
// Make `newProperties` the source of the properties that will be copied into
// the operation. The memory referenced by `newProperties` must remain live
// until after the `Operation` is created, at which time it may be
- // deallocated. Calls to `getOrAddProperties<>() will return references to
+ // deallocated. Calls to `getOrAddProperties<>()` will return references to
// this memory.
template <typename T>
void useProperties(T &newProperties) {
assert(!properties &&
"Can't provide a properties struct when one has been allocated");
- properties = &newProperties;
+ properties = PropertyRef(TypeID::get<T>(), &newProperties);
#if defined(__clang__)
#if __has_warning("-Wdangling-assignment-gsl")
#pragma clang diagnostic push
@@ -1040,9 +1061,8 @@ struct OperationState {
#pragma clang diagnostic ignored "-Wdangling-assignment-gsl"
#endif
#endif
- propertiesDeleter = [](OpaqueProperties) {};
- propertiesSetter = [](OpaqueProperties newProp,
- const OpaqueProperties prop) {
+ propertiesDeleter = [](PropertyRef) {};
+ propertiesSetter = [](PropertyRef newProp, const PropertyRef prop) {
*newProp.as<T *>() = *prop.as<const T *>();
};
#if defined(__clang__)
@@ -1050,7 +1070,6 @@ struct OperationState {
#pragma clang diagnostic pop
#endif
#endif
- propertiesId = TypeID::get<T>();
}
void addOperands(ValueRange newOperands);
diff --git a/mlir/include/mlir/Interfaces/InferTypeOpInterface.td b/mlir/include/mlir/Interfaces/InferTypeOpInterface.td
index 67568f731f597..36397d596aed6 100644
--- a/mlir/include/mlir/Interfaces/InferTypeOpInterface.td
+++ b/mlir/include/mlir/Interfaces/InferTypeOpInterface.td
@@ -53,7 +53,7 @@ def InferTypeOpInterface : OpInterface<"InferTypeOpInterface"> {
"::std::optional<::mlir::Location>":$location,
"::mlir::ValueRange":$operands,
"::mlir::DictionaryAttr":$attributes,
- "::mlir::OpaqueProperties":$properties,
+ "::mlir::PropertyRef":$properties,
"::mlir::RegionRange":$regions,
"::llvm::SmallVectorImpl<::mlir::Type>&":$inferredReturnTypes)
>,
@@ -87,7 +87,7 @@ def InferTypeOpInterface : OpInterface<"InferTypeOpInterface"> {
"::std::optional<::mlir::Location>":$location,
"::mlir::ValueRange":$operands,
"::mlir::DictionaryAttr":$attributes,
- "::mlir::OpaqueProperties":$properties,
+ "::mlir::PropertyRef":$properties,
"::mlir::RegionRange":$regions,
"::llvm::SmallVectorImpl<::mlir::Type>&":$returnTypes),
/*methodBody=*/[{}],
@@ -164,7 +164,7 @@ def InferShapedTypeOpInterface : OpInterface<"InferShapedTypeOpInterface"> {
"::std::optional<::mlir::Location>":$location,
"::mlir::ValueShapeRange":$operands,
"::mlir::DictionaryAttr":$attributes,
- "::mlir::OpaqueProperties":$properties,
+ "::mlir::PropertyRef":$properties,
"::mlir::RegionRange":$regions,
"::llvm::SmallVectorImpl<::mlir::ShapedTypeComponents>&":
$inferredReturnShapes),
@@ -220,7 +220,7 @@ class InferTypeOpAdaptorBase<code additionalDecls = [{}]> : TraitList<
$cppClass::inferReturnTypes(::mlir::MLIRContext *context,
std::optional<::mlir::Location> location,
::mlir::ValueRange operands, ::mlir::DictionaryAttr attributes,
- ::mlir::OpaqueProperties properties, ::mlir::RegionRange regions,
+ ::mlir::PropertyRef properties, ::mlir::RegionRange regions,
::llvm::SmallVectorImpl<::mlir::Type> &inferredReturnTypes) {
$cppClass::Adaptor adaptor(operands, attributes, properties, regions);
return $cppClass::inferReturnTypes(context,
@@ -258,7 +258,7 @@ class InferShapedTypeOpAdaptorBase<list<string> overridenMethods = []> : TraitLi
$cppClass::inferReturnTypeComponents(::mlir::MLIRContext *context,
std::optional<::mlir::Location> location,
::mlir::ValueShapeRange operands, ::mlir::DictionaryAttr attributes,
- ::mlir::OpaqueProperties properties, ::mlir::RegionRange regions,
+ ::mlir::PropertyRef properties, ::mlir::RegionRange regions,
::llvm::SmallVectorImpl<::mlir::ShapedTypeComponents> &inferredReturnShapes) {
$cppClass::Adaptor adaptor(operands, attributes, properties, regions);
return $cppClass::inferReturnTypeComponents(context,
@@ -293,7 +293,7 @@ class InferTensorTypeBase<list<string> overridenMethods = []> : TraitList<
$cppClass::inferReturnTypes(::mlir::MLIRContext *context,
std::optional<::mlir::Location> location,
::mlir::ValueRange operands, ::mlir::DictionaryAttr attributes,
- ::mlir::OpaqueProperties properties, ::mlir::RegionRange regions,
+ ::mlir::PropertyRef properties, ::mlir::RegionRange regions,
::llvm::SmallVectorImpl<::mlir::Type> &inferredReturnTypes) {
::llvm::SmallVector<::mlir::ShapedTypeComponents, 2> retComponents;
if (failed($cppClass::inferReturnTypeComponents(context, location,
@@ -331,7 +331,7 @@ class InferTensorTypeAdaptorBase<list<string> overridenMethods = []> : TraitList
$cppClass::inferReturnTypes(::mlir::MLIRContext *context,
std::optional<::mlir::Location> location,
::mlir::ValueRange operands, ::mlir::DictionaryAttr attributes,
- ::mlir::OpaqueProperties properties, ::mlir::RegionRange regions,
+ ::mlir::PropertyRef properties, ::mlir::RegionRange regions,
::llvm::SmallVectorImpl<::mlir::Type> &inferredReturnTypes) {
SmallVector<ShapedTypeComponents, 2> retComponents;
if (failed($cppClass::inferReturnTypeComponents(context, location,
diff --git a/mlir/lib/CAPI/IR/IR.cpp b/mlir/lib/CAPI/IR/IR.cpp
index 29f9287279b8f..5c5145b0a5acc 100644
--- a/mlir/lib/CAPI/IR/IR.cpp
+++ b/mlir/lib/CAPI/IR/IR.cpp
@@ -552,11 +552,11 @@ static LogicalResult inferOperationTypes(OperationState &state) {
}
DictionaryAttr attributes = state.attributes.getDictionary(context);
- OpaqueProperties properties = state.getRawProperties();
+ PropertyRef properties = state.getRawProperties();
if (!properties && info->getOpPropertyByteSize() > 0 && !attributes.empty()) {
- auto prop = std::make_unique<char[]>(info->getOpPropertyByteSize());
- properties = OpaqueProperties(prop.get());
+ auto propAlloc = std::make_unique<char[]>(info->getOpPropertyByteSize());
+ properties = PropertyRef(info->getOpPropertiesTypeID(), propAlloc.get());
if (properties) {
auto emitError = [&]() {
return mlir::emitError(state.location)
diff --git a/mlir/lib/CAPI/Interfaces/Interfaces.cpp b/mlir/lib/CAPI/Interfaces/Interfaces.cpp
index 437a1dbab9dae..73b5d2505eac5 100644
--- a/mlir/lib/CAPI/Interfaces/Interfaces.cpp
+++ b/mlir/lib/CAPI/Interfaces/Interfaces.cpp
@@ -107,9 +107,15 @@ MlirLogicalResult mlirInferTypeOpInterfaceInferReturnTypes(
unwrapRegions(nRegions, regions);
SmallVector<Type> inferredTypes;
+ // The C API passes an opaque void*; we trust the caller to pass the correct
+ // properties type for this operation.
+ // TODO: Create a C API that's more type-safe.
+ PropertyRef propertyRef =
+ properties ? PropertyRef(info->getOpPropertiesTypeID(), properties)
+ : PropertyRef(nullptr);
if (failed(info->getInterface<InferTypeOpInterface>()->inferReturnTypes(
unwrap(context), maybeLocation, unwrappedOperands, attributeDict,
- properties, unwrappedRegions, inferredTypes)))
+ propertyRef, unwrappedRegions, inferredTypes)))
return mlirLogicalResultFailure();
SmallVector<MlirType> wrappedInferredTypes;
@@ -141,11 +147,16 @@ MlirLogicalResult mlirInferShapedTypeOpInterfaceInferReturnTypes(
unwrapRegions(nRegions, regions);
SmallVector<ShapedTypeComponents> inferredTypeComponents;
+ // The C API passes an opaque void*; we trust the caller to pass the correct
+ // properties type for this operation.
+ PropertyRef propertyRef =
+ properties ? PropertyRef(info->getOpPropertiesTypeID(), properties)
+ : PropertyRef(nullptr);
if (failed(info->getInterface<InferShapedTypeOpInterface>()
->inferReturnTypeComponents(
unwrap(context), maybeLocation,
mlir::ValueRange(llvm::ArrayRef(unwrappedOperands)),
- attributeDict, properties, unwrappedRegions,
+ attributeDict, propertyRef, unwrappedRegions,
inferredTypeComponents)))
return mlirLogicalResultFailure();
diff --git a/mlir/lib/Dialect/AMDGPU/IR/AMDGPUOps.cpp b/mlir/lib/Dialect/AMDGPU/IR/AMDGPUOps.cpp
index b715f4ab93231..54ab55a0fcc1d 100644
--- a/mlir/lib/Dialect/AMDGPU/IR/AMDGPUOps.cpp
+++ b/mlir/lib/Dialect/AMDGPU/IR/AMDGPUOps.cpp
@@ -103,7 +103,7 @@ static FailureOr<MemRefType> getFatRawBufferTypeLike(MemRefType source,
LogicalResult FatRawBufferCastOp::inferReturnTypes(
MLIRContext *context, std::optional<Location> location, ValueRange operands,
- DictionaryAttr attributes, OpaqueProperties properties, RegionRange regions,
+ DictionaryAttr attributes, PropertyRef properties, RegionRange regions,
SmallVectorImpl<Type> &inferredReturnTypes) {
Adaptor adaptor(operands, attributes, properties, regions);
auto sourceType =
diff --git a/mlir/lib/Dialect/Bufferization/IR/BufferizationOps.cpp b/mlir/lib/Dialect/Bufferization/IR/BufferizationOps.cpp
index 71ad8bbf91c3b..c525ec116f699 100644
--- a/mlir/lib/Dialect/Bufferization/IR/BufferizationOps.cpp
+++ b/mlir/lib/Dialect/Bufferization/IR/BufferizationOps.cpp
@@ -908,7 +908,7 @@ std::optional<Value> CloneOp::buildClone(OpBuilder &builder, Value alloc) {
LogicalResult DeallocOp::inferReturnTypes(
MLIRContext *context, std::optional<::mlir::Location> location,
- ValueRange operands, DictionaryAttr attributes, OpaqueProperties properties,
+ ValueRange operands, DictionaryAttr attributes, PropertyRef properties,
RegionRange regions, SmallVectorImpl<Type> &inferredReturnTypes) {
DeallocOpAdaptor adaptor(operands, attributes, properties, regions);
inferredReturnTypes = SmallVector<Type>(adaptor.getRetained().size(),
diff --git a/mlir/lib/Dialect/MemRef/IR/MemRefOps.cpp b/mlir/lib/Dialect/MemRef/IR/MemRefOps.cpp
index 404b2aacf1450..d5d17234aedf3 100644
--- a/mlir/lib/Dialect/MemRef/IR/MemRefOps.cpp
+++ b/mlir/lib/Dialect/MemRef/IR/MemRefOps.cpp
@@ -634,7 +634,7 @@ LogicalResult DistinctObjectsOp::verify() {
LogicalResult DistinctObjectsOp::inferReturnTypes(
MLIRContext * /*context*/, std::optional<Location> /*location*/,
ValueRange operands, DictionaryAttr /*attributes*/,
- OpaqueProperties /*properties*/, RegionRange /*regions*/,
+ PropertyRef /*properties*/, RegionRange /*regions*/,
SmallVectorImpl<Type> &inferredReturnTypes) {
llvm::copy(operands.getTypes(), std::back_inserter(inferredReturnTypes));
return success();
diff --git a/mlir/lib/Dialect/Ptr/IR/PtrDialect.cpp b/mlir/lib/Dialect/Ptr/IR/PtrDialect.cpp
index 51f25f755a8a6..444197d12097f 100644
--- a/mlir/lib/Dialect/Ptr/IR/PtrDialect.cpp
+++ b/mlir/lib/Dialect/Ptr/IR/PtrDialect.cpp
@@ -355,7 +355,7 @@ OpFoldResult PtrAddOp::fold(FoldAdaptor adaptor) {
LogicalResult PtrAddOp::inferReturnTypes(
MLIRContext *context, std::optional<Location> location, ValueRange operands,
- DictionaryAttr attributes, OpaqueProperties properties, RegionRange regions,
+ DictionaryAttr attributes, PropertyRef properties, RegionRange regions,
SmallVectorImpl<Type> &inferredReturnTypes) {
// Get the base pointer and offset types.
Type baseType = operands[0].getType();
diff --git a/mlir/lib/Dialect/SMT/IR/SMTOps.cpp b/mlir/lib/Dialect/SMT/IR/SMTOps.cpp
index c517ef2b18f6f..06ad4ab51b88b 100644
--- a/mlir/lib/Dialect/SMT/IR/SMTOps.cpp
+++ b/mlir/lib/Dialect/SMT/IR/SMTOps.cpp
@@ -22,7 +22,7 @@ using namespace mlir;
LogicalResult BVConstantOp::inferReturnTypes(
mlir::MLIRContext *context, std::optional<mlir::Location> location,
::mlir::ValueRange operands, ::mlir::DictionaryAttr attributes,
- ::mlir::OpaqueProperties properties, ::mlir::RegionRange regions,
+ ::mlir::PropertyRef properties, ::mlir::RegionRange regions,
::llvm::SmallVectorImpl<::mlir::Type> &inferredReturnTypes) {
inferredReturnTypes.push_back(
properties.as<Properties *>()->getValue().getType());
@@ -173,7 +173,7 @@ LogicalResult ExtractOp::verify() {
LogicalResult ConcatOp::inferReturnTypes(
MLIRContext *context, std::optional<Location> location, ValueRange operands,
- DictionaryAttr attributes, OpaqueProperties properties, RegionRange regions,
+ DictionaryAttr attributes, PropertyRef properties, RegionRange regions,
SmallVectorImpl<Type> &inferredReturnTypes) {
inferredReturnTypes.push_back(BitVectorType::get(
context, cast<BitVectorType>(operands[0].getType()).getWidth() +
diff --git a/mlir/lib/Dialect/SparseTensor/IR/SparseTensorDialect.cpp b/mlir/lib/Dialect/SparseTensor/IR/SparseTensorDialect.cpp
index 05b2e07b88ba5..b77a536861d2a 100644
--- a/mlir/lib/Dialect/SparseTensor/IR/SparseTensorDialect.cpp
+++ b/mlir/lib/Dialect/SparseTensor/IR/SparseTensorDialect.cpp
@@ -1605,8 +1605,7 @@ OpFoldResult ReinterpretMapOp::fold(FoldAdaptor adaptor) {
template <typename ToBufferOp>
static LogicalResult inferSparseBufferType(ValueRange ops, DictionaryAttr attr,
- OpaqueProperties prop,
- RegionRange region,
+ PropertyRef prop, RegionRange region,
SmallVectorImpl<mlir::Type> &ret) {
typename ToBufferOp::Adaptor adaptor(ops, attr, prop, region);
SparseTensorType stt = getSparseTensorType(adaptor.getTensor());
@@ -1647,7 +1646,7 @@ LogicalResult ToPositionsOp::verify() {
LogicalResult
ToPositionsOp::inferReturnTypes(MLIRContext *ctx, std::optional<Location> loc,
ValueRange ops, DictionaryAttr attr,
- OpaqueProperties prop, RegionRange region,
+ PropertyRef prop, RegionRange region,
SmallVectorImpl<mlir::Type> &ret) {
return inferSparseBufferType<ToPositionsOp>(ops, attr, prop, region, ret);
}
@@ -1664,7 +1663,7 @@ LogicalResult ToCoordinatesOp::verify() {
LogicalResult
ToCoordinatesOp::inferReturnTypes(MLIRContext *ctx, std::optional<Location> loc,
ValueRange ops, DictionaryAttr attr,
- OpaqueProperties prop, RegionRange region,
+ PropertyRef prop, RegionRange region,
SmallVectorImpl<mlir::Type> &ret) {
return inferSparseBufferType<ToCoordinatesOp>(ops, attr, prop, region, ret);
}
@@ -1678,7 +1677,7 @@ LogicalResult ToCoordinatesBufferOp::verify() {
LogicalResult ToCoordinatesBufferOp::inferReturnTypes(
MLIRContext *ctx, std::optional<Location> loc, ValueRange ops,
- DictionaryAttr attr, OpaqueProperties prop, RegionRange region,
+ DictionaryAttr attr, PropertyRef prop, RegionRange region,
SmallVectorImpl<mlir::Type> &ret) {
return inferSparseBufferType<ToCoordinatesBufferOp>(ops, attr, prop, region,
ret);
@@ -1695,8 +1694,7 @@ LogicalResult ToValuesOp::verify() {
LogicalResult ToValuesOp::inferReturnTypes(MLIRContext *ctx,
std::optional<Location> loc,
ValueRange ops, DictionaryAttr attr,
- OpaqueProperties prop,
- RegionRange region,
+ PropertyRef prop, RegionRange region,
SmallVectorImpl<mlir::Type> &ret) {
return inferSparseBufferType<ToValuesOp>(ops, attr, prop, region, ret);
}
@@ -2367,7 +2365,7 @@ parseSparseCoIterateLoop(OpAsmParser &parser, OperationState &state,
LogicalResult ExtractIterSpaceOp::inferReturnTypes(
MLIRContext *ctx, std::optional<Location> loc, ValueRange ops,
- DictionaryAttr attr, OpaqueProperties prop, RegionRange region,
+ DictionaryAttr attr, PropertyRef prop, RegionRange region,
SmallVectorImpl<mlir::Type> &ret) {
ExtractIterSpaceOp::Adaptor adaptor(ops, attr, prop, region);
diff --git a/mlir/lib/Dialect/Tosa/IR/TosaOps.cpp b/mlir/lib/Dialect/Tosa/IR/TosaOps.cpp
index 6072aecdf347b..aeb9bd737fa6a 100644
--- a/mlir/lib/Dialect/Tosa/IR/TosaOps.cpp
+++ b/mlir/lib/Dialect/Tosa/IR/TosaOps.cpp
@@ -1831,8 +1831,8 @@ LogicalResult tosa::ConcatOp::verify() {
LogicalResult tosa::EqualOp::inferReturnTypeComponents(
MLIRContext *context, ::std::optional<Location> location,
- ValueShapeRange operands, DictionaryAttr attributes,
- OpaqueProperties properties, RegionRange regions,
+ ValueShapeRange operands, DictionaryAttr attributes, PropertyRef properties,
+ RegionRange regions,
SmallVectorImpl<ShapedTypeComponents> &inferredReturnShapes) {
auto elementType = IntegerType::get(context, /*width=*/1);
@@ -2332,8 +2332,8 @@ LogicalResult tosa::SliceOp::verify() {
LogicalResult tosa::MulOp::inferReturnTypeComponents(
MLIRContext *context, ::std::optional<Location> location,
- ValueShapeRange operands, DictionaryAttr attributes,
- OpaqueProperties properties, RegionRange regions,
+ ValueShapeRange operands, DictionaryAttr attributes, PropertyRef properties,
+ RegionRange regions,
SmallVectorImpl<ShapedTypeComponents> &inferredReturnShapes) {
// mul op's output shape only depend on input1 and input2, not on shift
ValueShapeRange twoInputs = operands.drop_back();
@@ -3372,7 +3372,7 @@ static LogicalResult NAryInferReturnTypes(
LogicalResult OP::inferReturnTypeComponents( \
MLIRContext *context, ::std::optional<Location> location, \
ValueShapeRange operands, DictionaryAttr attributes, \
- OpaqueProperties properties, RegionRange regions, \
+ PropertyRef properties, RegionRange regions, \
SmallVectorImpl<ShapedTypeComponents> &inferredReturnShapes) { \
return NAryInferReturnTypes(operands, inferredReturnShapes); \
}
diff --git a/mlir/lib/Dialect/WasmSSA/IR/WasmSSAOps.cpp b/mlir/lib/Dialect/WasmSSA/IR/WasmSSAOps.cpp
index a514ea9218bd7..f3eb601bed5c3 100644
--- a/mlir/lib/Dialect/WasmSSA/IR/WasmSSAOps.cpp
+++ b/mlir/lib/Dialect/WasmSSA/IR/WasmSSAOps.cpp
@@ -362,7 +362,7 @@ Block *IfOp::getLabelTarget() { return getTarget(); }
LogicalResult LocalOp::inferReturnTypes(
MLIRContext *context, ::std::optional<Location> location,
- ValueRange operands, DictionaryAttr attributes, OpaqueProperties properties,
+ ValueRange operands, DictionaryAttr attributes, PropertyRef properties,
RegionRange regions, SmallVectorImpl<Type> &inferredReturnTypes) {
LocalOp::GenericAdaptor<ValueRange> adaptor{operands, attributes, properties,
regions};
@@ -380,7 +380,7 @@ LogicalResult LocalOp::inferReturnTypes(
LogicalResult LocalGetOp::inferReturnTypes(
MLIRContext *context, ::std::optional<Location> location,
- ValueRange operands, DictionaryAttr attributes, OpaqueProperties properties,
+ ValueRange operands, DictionaryAttr attributes, PropertyRef properties,
RegionRange regions, SmallVectorImpl<Type> &inferredReturnTypes) {
return inferTeeGetResType(operands, inferredReturnTypes);
}
@@ -401,7 +401,7 @@ LogicalResult LocalSetOp::verify() {
LogicalResult LocalTeeOp::inferReturnTypes(
MLIRContext *context, ::std::optional<Location> location,
- ValueRange operands, DictionaryAttr attributes, OpaqueProperties properties,
+ ValueRange operands, DictionaryAttr attributes, PropertyRef properties,
RegionRange regions, SmallVectorImpl<Type> &inferredReturnTypes) {
return inferTeeGetResType(operands, inferredReturnTypes);
}
diff --git a/mlir/lib/IR/ExtensibleDialect.cpp b/mlir/lib/IR/ExtensibleDialect.cpp
index 3312549ddfcd4..b51d330160646 100644
--- a/mlir/lib/IR/ExtensibleDialect.cpp
+++ b/mlir/lib/IR/ExtensibleDialect.cpp
@@ -304,6 +304,8 @@ DynamicOpDefinition::DynamicOpDefinition(
getCanonicalizationPatternsFn(std::move(getCanonicalizationPatternsFn)),
populateDefaultAttrsFn(std::move(populateDefaultAttrsFn)) {
typeID = dialect->allocateTypeID();
+ // DynamicOpDefinition doesn't support properties, so use the ID of void.
+ propertiesTypeID = TypeID();
}
std::unique_ptr<DynamicOpDefinition> DynamicOpDefinition::get(
diff --git a/mlir/lib/IR/MLIRContext.cpp b/mlir/lib/IR/MLIRContext.cpp
index f5edd81862299..21891db11aa65 100644
--- a/mlir/lib/IR/MLIRContext.cpp
+++ b/mlir/lib/IR/MLIRContext.cpp
@@ -902,20 +902,20 @@ LogicalResult OperationName::UnregisteredOpModel::verifyInherentAttrs(
int OperationName::UnregisteredOpModel::getOpPropertyByteSize() {
return sizeof(Attribute);
}
-void OperationName::UnregisteredOpModel::initProperties(
- OperationName opName, OpaqueProperties storage, OpaqueProperties init) {
+void OperationName::UnregisteredOpModel::initProperties(OperationName opName,
+ PropertyRef storage,
+ PropertyRef init) {
new (storage.as<Attribute *>()) Attribute();
if (init)
*storage.as<Attribute *>() = *init.as<Attribute *>();
}
-void OperationName::UnregisteredOpModel::deleteProperties(
- OpaqueProperties prop) {
+void OperationName::UnregisteredOpModel::deleteProperties(PropertyRef prop) {
prop.as<Attribute *>()->~Attribute();
}
void OperationName::UnregisteredOpModel::populateDefaultProperties(
- OperationName opName, OpaqueProperties properties) {}
+ OperationName opName, PropertyRef properties) {}
LogicalResult OperationName::UnregisteredOpModel::setPropertiesFromAttr(
- OperationName opName, OpaqueProperties properties, Attribute attr,
+ OperationName opName, PropertyRef properties, Attribute attr,
function_ref<InFlightDiagnostic()> emitError) {
*properties.as<Attribute *>() = attr;
return success();
@@ -924,16 +924,16 @@ Attribute
OperationName::UnregisteredOpModel::getPropertiesAsAttr(Operation *op) {
return *op->getPropertiesStorage().as<Attribute *>();
}
-void OperationName::UnregisteredOpModel::copyProperties(OpaqueProperties lhs,
- OpaqueProperties rhs) {
+void OperationName::UnregisteredOpModel::copyProperties(PropertyRef lhs,
+ PropertyRef rhs) {
*lhs.as<Attribute *>() = *rhs.as<Attribute *>();
}
-bool OperationName::UnregisteredOpModel::compareProperties(
- OpaqueProperties lhs, OpaqueProperties rhs) {
+bool OperationName::UnregisteredOpModel::compareProperties(PropertyRef lhs,
+ PropertyRef rhs) {
return *lhs.as<Attribute *>() == *rhs.as<Attribute *>();
}
llvm::hash_code
-OperationName::UnregisteredOpModel::hashProperties(OpaqueProperties prop) {
+OperationName::UnregisteredOpModel::hashProperties(PropertyRef prop) {
return llvm::hash_combine(*prop.as<Attribute *>());
}
diff --git a/mlir/lib/IR/Operation.cpp b/mlir/lib/IR/Operation.cpp
index 46030936a3910..7267c84048463 100644
--- a/mlir/lib/IR/Operation.cpp
+++ b/mlir/lib/IR/Operation.cpp
@@ -50,9 +50,8 @@ Operation *Operation::create(const OperationState &state) {
/// Create a new Operation with the specific fields.
Operation *Operation::create(Location location, OperationName name,
TypeRange resultTypes, ValueRange operands,
- NamedAttrList &&attributes,
- OpaqueProperties properties, BlockRange successors,
- RegionRange regions) {
+ NamedAttrList &&attributes, PropertyRef properties,
+ BlockRange successors, RegionRange regions) {
unsigned numRegions = regions.size();
Operation *op =
create(location, name, resultTypes, operands, std::move(attributes),
@@ -66,9 +65,8 @@ Operation *Operation::create(Location location, OperationName name,
/// Create a new Operation with the specific fields.
Operation *Operation::create(Location location, OperationName name,
TypeRange resultTypes, ValueRange operands,
- NamedAttrList &&attributes,
- OpaqueProperties properties, BlockRange successors,
- unsigned numRegions) {
+ NamedAttrList &&attributes, PropertyRef properties,
+ BlockRange successors, unsigned numRegions) {
// Populate default attributes.
name.populateDefaultAttrs(attributes);
@@ -81,9 +79,8 @@ Operation *Operation::create(Location location, OperationName name,
/// unnecessarily uniquing a list of attributes.
Operation *Operation::create(Location location, OperationName name,
TypeRange resultTypes, ValueRange operands,
- DictionaryAttr attributes,
- OpaqueProperties properties, BlockRange successors,
- unsigned numRegions) {
+ DictionaryAttr attributes, PropertyRef properties,
+ BlockRange successors, unsigned numRegions) {
assert(llvm::all_of(resultTypes, [](Type t) { return t; }) &&
"unexpected null result type");
@@ -146,7 +143,7 @@ Operation *Operation::create(Location location, OperationName name,
for (unsigned i = 0; i != numSuccessors; ++i)
new (&blockOperands[i]) BlockOperand(op, successors[i]);
- // This must be done after properties are initalized.
+ // This must be done after properties are initialized.
op->setAttrs(attributes);
return op;
@@ -155,7 +152,7 @@ Operation *Operation::create(Location location, OperationName name,
Operation::Operation(Location location, OperationName name, unsigned numResults,
unsigned numSuccessors, unsigned numRegions,
int fullPropertiesStorageSize, DictionaryAttr attributes,
- OpaqueProperties properties, bool hasOperandStorage)
+ PropertyRef properties, bool hasOperandStorage)
: location(location), numResults(numResults), numSuccs(numSuccessors),
numRegions(numRegions), hasOperandStorage(hasOperandStorage),
propertiesStorageSize((fullPropertiesStorageSize + 7) / 8), name(name) {
@@ -363,7 +360,7 @@ LogicalResult Operation::setPropertiesFromAttribute(
this->getName(), this->getPropertiesStorage(), attr, emitError);
}
-void Operation::copyProperties(OpaqueProperties rhs) {
+void Operation::copyProperties(PropertyRef rhs) {
name.copyOpProperties(getPropertiesStorage(), rhs);
}
diff --git a/mlir/lib/IR/OperationSupport.cpp b/mlir/lib/IR/OperationSupport.cpp
index 3ff61daaac60b..804a825218390 100644
--- a/mlir/lib/IR/OperationSupport.cpp
+++ b/mlir/lib/IR/OperationSupport.cpp
@@ -966,3 +966,5 @@ OperationFingerPrint::OperationFingerPrint(Operation *topOp,
hash = hasher.result();
}
+
+MLIR_DEFINE_EXPLICIT_TYPE_ID(mlir::EmptyProperties)
diff --git a/mlir/lib/Target/IRDLToCpp/Templates/PerOperationDecl.txt b/mlir/lib/Target/IRDLToCpp/Templates/PerOperationDecl.txt
index 93ce0bef1f269..18edc17f8a28a 100644
--- a/mlir/lib/Target/IRDLToCpp/Templates/PerOperationDecl.txt
+++ b/mlir/lib/Target/IRDLToCpp/Templates/PerOperationDecl.txt
@@ -54,7 +54,7 @@ class __OP_CPP_NAME__GenericAdaptor
using Base = detail::__OP_CPP_NAME__GenericAdaptorBase;
public:
__OP_CPP_NAME__GenericAdaptor(RangeT values, ::mlir::DictionaryAttr attrs,
- ::mlir::OpaqueProperties properties,
+ ::mlir::PropertyRef properties,
::mlir::RegionRange regions = {})
: __OP_CPP_NAME__GenericAdaptor(values, attrs,
(properties ? *properties.as<::mlir::EmptyProperties *>()
diff --git a/mlir/lib/Transforms/Utils/DialectConversion.cpp b/mlir/lib/Transforms/Utils/DialectConversion.cpp
index cf59234ded233..e106b7c1b7cd7 100644
--- a/mlir/lib/Transforms/Utils/DialectConversion.cpp
+++ b/mlir/lib/Transforms/Utils/DialectConversion.cpp
@@ -687,10 +687,10 @@ class ModifyOperationRewrite : public OperationRewrite {
name(op->getName()), loc(op->getLoc()), attrs(op->getAttrDictionary()),
operands(op->operand_begin(), op->operand_end()),
successors(op->successor_begin(), op->successor_end()) {
- if (OpaqueProperties prop = op->getPropertiesStorage()) {
+ if (PropertyRef prop = op->getPropertiesStorage()) {
// Make a copy of the properties.
propertiesStorage = operator new(op->getPropertiesStorageSize());
- OpaqueProperties propCopy(propertiesStorage);
+ PropertyRef propCopy(name.getOpPropertiesTypeID(), propertiesStorage);
name.initOpProperties(propCopy, /*init=*/prop);
}
}
@@ -711,7 +711,7 @@ class ModifyOperationRewrite : public OperationRewrite {
listener->notifyOperationModified(op);
if (propertiesStorage) {
- OpaqueProperties propCopy(propertiesStorage);
+ PropertyRef propCopy(name.getOpPropertiesTypeID(), propertiesStorage);
// Note: The operation may have been erased in the mean time, so
// OperationName must be stored in this object.
name.destroyOpProperties(propCopy);
@@ -727,7 +727,7 @@ class ModifyOperationRewrite : public OperationRewrite {
for (const auto &it : llvm::enumerate(successors))
op->setSuccessor(it.value(), it.index());
if (propertiesStorage) {
- OpaqueProperties propCopy(propertiesStorage);
+ PropertyRef propCopy(name.getOpPropertiesTypeID(), propertiesStorage);
op->copyProperties(propCopy);
name.destroyOpProperties(propCopy);
operator delete(propertiesStorage);
diff --git a/mlir/test/lib/Dialect/Test/TestOpDefs.cpp b/mlir/test/lib/Dialect/Test/TestOpDefs.cpp
index bd825c858a615..c53f003daf3f0 100644
--- a/mlir/test/lib/Dialect/Test/TestOpDefs.cpp
+++ b/mlir/test/lib/Dialect/Test/TestOpDefs.cpp
@@ -256,7 +256,7 @@ OpFoldResult TestOpInPlaceFold::fold(FoldAdaptor adaptor) {
LogicalResult OpWithInferTypeInterfaceOp::inferReturnTypes(
MLIRContext *, std::optional<Location> location, ValueRange operands,
- DictionaryAttr attributes, OpaqueProperties properties, RegionRange regions,
+ DictionaryAttr attributes, PropertyRef properties, RegionRange regions,
SmallVectorImpl<Type> &inferredReturnTypes) {
if (operands[0].getType() != operands[1].getType()) {
return emitOptionalError(location, "operand type mismatch ",
@@ -273,8 +273,8 @@ LogicalResult OpWithInferTypeInterfaceOp::inferReturnTypes(
LogicalResult OpWithShapedTypeInferTypeInterfaceOp::inferReturnTypeComponents(
MLIRContext *context, std::optional<Location> location,
- ValueShapeRange operands, DictionaryAttr attributes,
- OpaqueProperties properties, RegionRange regions,
+ ValueShapeRange operands, DictionaryAttr attributes, PropertyRef properties,
+ RegionRange regions,
SmallVectorImpl<ShapedTypeComponents> &inferredReturnShapes) {
// Create return type consisting of the last element of the first operand.
auto operandType = operands.front().getType();
@@ -1178,7 +1178,7 @@ LogicalResult OpWithInferTypeAdaptorInterfaceOp::inferReturnTypes(
// refineReturnType, currently only refineReturnType can be omitted.
LogicalResult OpWithRefineTypeInterfaceOp::inferReturnTypes(
MLIRContext *context, std::optional<Location> location, ValueRange operands,
- DictionaryAttr attributes, OpaqueProperties properties, RegionRange regions,
+ DictionaryAttr attributes, PropertyRef properties, RegionRange regions,
SmallVectorImpl<Type> &returnTypes) {
returnTypes.clear();
return OpWithRefineTypeInterfaceOp::refineReturnTypes(
@@ -1188,7 +1188,7 @@ LogicalResult OpWithRefineTypeInterfaceOp::inferReturnTypes(
LogicalResult OpWithRefineTypeInterfaceOp::refineReturnTypes(
MLIRContext *, std::optional<Location> location, ValueRange operands,
- DictionaryAttr attributes, OpaqueProperties properties, RegionRange regions,
+ DictionaryAttr attributes, PropertyRef properties, RegionRange regions,
SmallVectorImpl<Type> &returnTypes) {
if (operands[0].getType() != operands[1].getType()) {
return emitOptionalError(location, "operand type mismatch ",
@@ -1270,7 +1270,7 @@ OpWithShapedTypeInferTypeAdaptorInterfaceOp::reifyReturnTypeShapes(
LogicalResult TestOpWithPropertiesAndInferredType::inferReturnTypes(
MLIRContext *context, std::optional<Location>, ValueRange operands,
- DictionaryAttr attributes, OpaqueProperties properties, RegionRange regions,
+ DictionaryAttr attributes, PropertyRef properties, RegionRange regions,
SmallVectorImpl<Type> &inferredReturnTypes) {
Adaptor adaptor(operands, attributes, properties, regions);
diff --git a/mlir/test/lib/Dialect/Test/TestOps.td b/mlir/test/lib/Dialect/Test/TestOps.td
index 02bac016eeed1..ea32ea77d943d 100644
--- a/mlir/test/lib/Dialect/Test/TestOps.td
+++ b/mlir/test/lib/Dialect/Test/TestOps.td
@@ -546,7 +546,7 @@ def VariadicRegionInferredTypesOp : TEST_Op<"variadic_region_inferred",
let extraClassDeclaration = [{
static llvm::LogicalResult inferReturnTypes(mlir::MLIRContext *context,
std::optional<::mlir::Location> location, mlir::ValueRange operands,
- mlir::DictionaryAttr attributes, mlir::OpaqueProperties properties, mlir::RegionRange regions,
+ mlir::DictionaryAttr attributes, mlir::PropertyRef properties, mlir::RegionRange regions,
llvm::SmallVectorImpl<mlir::Type> &inferredReturnTypes) {
inferredReturnTypes.assign({mlir::IntegerType::get(context, 16)});
return mlir::success();
@@ -2814,7 +2814,7 @@ class TableGenBuildInferReturnTypeBaseOp<string mnemonic,
let extraClassDeclaration = [{
static ::llvm::LogicalResult inferReturnTypes(::mlir::MLIRContext *,
::std::optional<::mlir::Location> location, ::mlir::ValueRange operands,
- ::mlir::DictionaryAttr attributes, mlir::OpaqueProperties properties, ::mlir::RegionRange regions,
+ ::mlir::DictionaryAttr attributes, mlir::PropertyRef properties, ::mlir::RegionRange regions,
::llvm::SmallVectorImpl<::mlir::Type> &inferredReturnTypes) {
inferredReturnTypes.assign({operands[0].getType()});
return ::mlir::success();
diff --git a/mlir/test/lib/Dialect/Test/TestOpsSyntax.cpp b/mlir/test/lib/Dialect/Test/TestOpsSyntax.cpp
index cc131ad9757f9..5880c2a2302b0 100644
--- a/mlir/test/lib/Dialect/Test/TestOpsSyntax.cpp
+++ b/mlir/test/lib/Dialect/Test/TestOpsSyntax.cpp
@@ -285,7 +285,7 @@ void ParseB64BytesOp::print(OpAsmPrinter &p) {
::llvm::LogicalResult FormatInferType2Op::inferReturnTypes(
::mlir::MLIRContext *context, ::std::optional<::mlir::Location> location,
::mlir::ValueRange operands, ::mlir::DictionaryAttr attributes,
- OpaqueProperties properties, ::mlir::RegionRange regions,
+ PropertyRef properties, ::mlir::RegionRange regions,
::llvm::SmallVectorImpl<::mlir::Type> &inferredReturnTypes) {
inferredReturnTypes.assign({::mlir::IntegerType::get(context, 16)});
return ::mlir::success();
diff --git a/mlir/test/lib/Dialect/Test/TestOpsSyntax.td b/mlir/test/lib/Dialect/Test/TestOpsSyntax.td
index 6b10ec6173a50..936f744855a08 100644
--- a/mlir/test/lib/Dialect/Test/TestOpsSyntax.td
+++ b/mlir/test/lib/Dialect/Test/TestOpsSyntax.td
@@ -689,7 +689,7 @@ def FormatInferTypeOp : TEST_Op<"format_infer_type", [InferTypeOpInterface]> {
let extraClassDeclaration = [{
static ::llvm::LogicalResult inferReturnTypes(::mlir::MLIRContext *context,
::std::optional<::mlir::Location> location, ::mlir::ValueRange operands,
- ::mlir::DictionaryAttr attributes, mlir::OpaqueProperties properties, ::mlir::RegionRange regions,
+ ::mlir::DictionaryAttr attributes, mlir::PropertyRef properties, ::mlir::RegionRange regions,
::llvm::SmallVectorImpl<::mlir::Type> &inferredReturnTypes) {
inferredReturnTypes.assign({::mlir::IntegerType::get(context, 16)});
return ::mlir::success();
@@ -712,7 +712,7 @@ class FormatInferAllTypesBaseOp<string mnemonic, list<Trait> traits = []>
let extraClassDeclaration = [{
static ::llvm::LogicalResult inferReturnTypes(::mlir::MLIRContext *context,
::std::optional<::mlir::Location> location, ::mlir::ValueRange operands,
- ::mlir::DictionaryAttr attributes, mlir::OpaqueProperties properties, ::mlir::RegionRange regions,
+ ::mlir::DictionaryAttr attributes, mlir::PropertyRef properties, ::mlir::RegionRange regions,
::llvm::SmallVectorImpl<::mlir::Type> &inferredReturnTypes) {
::mlir::TypeRange operandTypes = operands.getTypes();
inferredReturnTypes.assign(operandTypes.begin(), operandTypes.end());
@@ -759,7 +759,7 @@ def FormatInferTypeRegionsOp
let extraClassDeclaration = [{
static ::llvm::LogicalResult inferReturnTypes(::mlir::MLIRContext *context,
::std::optional<::mlir::Location> location, ::mlir::ValueRange operands,
- ::mlir::DictionaryAttr attributes, mlir::OpaqueProperties properties, ::mlir::RegionRange regions,
+ ::mlir::DictionaryAttr attributes, mlir::PropertyRef properties, ::mlir::RegionRange regions,
::llvm::SmallVectorImpl<::mlir::Type> &inferredReturnTypes) {
if (regions.empty())
return ::mlir::failure();
@@ -780,7 +780,7 @@ def FormatInferTypeVariadicOperandsOp
let extraClassDeclaration = [{
static ::llvm::LogicalResult inferReturnTypes(::mlir::MLIRContext *context,
::std::optional<::mlir::Location> location, ::mlir::ValueRange operands,
- ::mlir::DictionaryAttr attributes, mlir::OpaqueProperties properties, ::mlir::RegionRange regions,
+ ::mlir::DictionaryAttr attributes, mlir::PropertyRef properties, ::mlir::RegionRange regions,
::llvm::SmallVectorImpl<::mlir::Type> &inferredReturnTypes) {
FormatInferTypeVariadicOperandsOpAdaptor adaptor(
operands, attributes, *properties.as<Properties *>(), {});
diff --git a/mlir/test/lib/Dialect/Test/TestPatterns.cpp b/mlir/test/lib/Dialect/Test/TestPatterns.cpp
index 6c44ace831e96..1714289991ceb 100644
--- a/mlir/test/lib/Dialect/Test/TestPatterns.cpp
+++ b/mlir/test/lib/Dialect/Test/TestPatterns.cpp
@@ -744,10 +744,13 @@ static void invokeCreateWithInferredReturnType(Operation *op) {
for (int j = 0; j < e; ++j) {
std::array<Value, 2> values = {{fop.getArgument(i), fop.getArgument(j)}};
SmallVector<Type, 2> inferredReturnTypes;
+ // Only pass properties if the op's properties type matches OpTy's.
+ PropertyRef properties = op->getPropertiesStorage();
+ if (properties.getTypeID() != TypeID::get<typename OpTy::Properties>())
+ properties = PropertyRef(nullptr);
if (succeeded(OpTy::inferReturnTypes(
context, std::nullopt, values, op->getDiscardableAttrDictionary(),
- op->getPropertiesStorage(), op->getRegions(),
- inferredReturnTypes))) {
+ properties, op->getRegions(), inferredReturnTypes))) {
OperationState state(location, OpTy::getOperationName());
// TODO: Expand to regions.
OpTy::build(b, state, values, op->getAttrs());
diff --git a/mlir/test/mlir-tblgen/op-decl-and-defs.td b/mlir/test/mlir-tblgen/op-decl-and-defs.td
index 80dedb8475b9e..e92b4044668c1 100644
--- a/mlir/test/mlir-tblgen/op-decl-and-defs.td
+++ b/mlir/test/mlir-tblgen/op-decl-and-defs.td
@@ -75,7 +75,7 @@ def NS_AOp : NS_Op<"a_op", [IsolatedFromAbove, IsolatedFromAbove]> {
// CHECK: class AOpGenericAdaptor : public detail::AOpGenericAdaptorBase {
// CHECK: public:
// CHECK: AOpGenericAdaptor(RangeT values, ::mlir::DictionaryAttr attrs, const Properties &properties, ::mlir::RegionRange regions = {}) : Base(attrs, properties, regions), odsOperands(values) {}
-// CHECK: AOpGenericAdaptor(RangeT values, ::mlir::DictionaryAttr attrs, ::mlir::OpaqueProperties properties, ::mlir::RegionRange regions = {}) : AOpGenericAdaptor(values, attrs, (properties ? *properties.as<Properties *>() : Properties{}), regions) {}
+// CHECK: AOpGenericAdaptor(RangeT values, ::mlir::DictionaryAttr attrs, ::mlir::PropertyRef properties, ::mlir::RegionRange regions = {}) : AOpGenericAdaptor(values, attrs, (properties ? *properties.as<Properties *>() : Properties{}), regions) {}
// CHECK: AOpGenericAdaptor(RangeT values, ::mlir::DictionaryAttr attrs = nullptr) : AOpGenericAdaptor(values, attrs, Properties{}, {}) {}
// CHECK: AOpGenericAdaptor(RangeT values, const AOpGenericAdaptorBase &base) : Base(base), odsOperands(values) {}
// CHECK: RangeT getODSOperands(unsigned index) {
diff --git a/mlir/test/python/python_test_ops.td b/mlir/test/python/python_test_ops.td
index cfc1d72bb479d..96e951424ca51 100644
--- a/mlir/test/python/python_test_ops.td
+++ b/mlir/test/python/python_test_ops.td
@@ -135,7 +135,7 @@ def InferResultsOp : TestOp<"infer_results_op", [InferTypeOpInterface]> {
static ::llvm::LogicalResult inferReturnTypes(
::mlir::MLIRContext *context, ::std::optional<::mlir::Location> location,
::mlir::ValueRange operands, ::mlir::DictionaryAttr attributes,
- ::mlir::OpaqueProperties,
+ ::mlir::PropertyRef,
::mlir::RegionRange regions,
::llvm::SmallVectorImpl<::mlir::Type> &inferredReturnTypes) {
::mlir::Builder b(context);
@@ -158,7 +158,7 @@ def InferResultsVariadicInputsOp : TestOp<"infer_results_variadic_inputs_op",
static ::llvm::LogicalResult inferReturnTypes(
::mlir::MLIRContext *context, ::std::optional<::mlir::Location> location,
::mlir::ValueRange operands, ::mlir::DictionaryAttr attributes,
- ::mlir::OpaqueProperties,
+ ::mlir::PropertyRef,
::mlir::RegionRange regions,
::llvm::SmallVectorImpl<::mlir::Type> &inferredReturnTypes) {
::mlir::Builder b(context);
@@ -187,7 +187,7 @@ def InferShapedTypeComponentsOp : TestOp<"infer_shaped_type_components_op",
::llvm::LogicalResult $cppClass::inferReturnTypeComponents(
::mlir::MLIRContext *context, ::std::optional<::mlir::Location> location,
::mlir::ValueShapeRange operands, ::mlir::DictionaryAttr attributes,
- ::mlir::OpaqueProperties properties, ::mlir::RegionRange regions,
+ ::mlir::PropertyRef properties, ::mlir::RegionRange regions,
::llvm::SmallVectorImpl<
::mlir::ShapedTypeComponents>& inferredShapedTypeComponents) {
$cppClass::Adaptor adaptor(operands, attributes, properties, regions);
diff --git a/mlir/tools/mlir-tblgen/OpDefinitionsGen.cpp b/mlir/tools/mlir-tblgen/OpDefinitionsGen.cpp
index e93f91bb540c2..edb009938f005 100644
--- a/mlir/tools/mlir-tblgen/OpDefinitionsGen.cpp
+++ b/mlir/tools/mlir-tblgen/OpDefinitionsGen.cpp
@@ -2852,8 +2852,8 @@ void OpEmitter::genInferredTypeCollectiveParamBuilder(
// function.
body << formatv(R"(
if (!attributes.empty()) {
- ::mlir::OpaqueProperties properties =
- &{1}.getOrAddProperties<{0}::Properties>();
+ (void){1}.getOrAddProperties<{0}::Properties>();
+ ::mlir::PropertyRef properties = {1}.getRawProperties();
std::optional<::mlir::RegisteredOperationName> info =
{1}.name.getRegisteredInfo();
if (failed(info->setOpPropertiesFromAttribute({1}.name, properties,
@@ -3145,8 +3145,8 @@ void OpEmitter::genCollectiveParamBuilder(CollectiveBuilderKind kind) {
// function.
body << formatv(R"(
if (!attributes.empty()) {
- ::mlir::OpaqueProperties properties =
- &{1}.getOrAddProperties<{0}::Properties>();
+ (void){1}.getOrAddProperties<{0}::Properties>();
+ ::mlir::PropertyRef properties = {1}.getRawProperties();
std::optional<::mlir::RegisteredOperationName> info =
{1}.name.getRegisteredInfo();
if (failed(info->setOpPropertiesFromAttribute({1}.name, properties,
@@ -4430,22 +4430,22 @@ OpOperandAdaptorEmitter::OpOperandAdaptorEmitter(
constructor->addMemberInitializer("Base", "attrs, properties, regions");
constructor->addMemberInitializer("odsOperands", "values");
- // Add a forwarding constructor to the previous one that accepts
- // OpaqueProperties instead and check for null and perform the cast to the
- // actual properties type.
+ // Add a forwarding constructor that accepts PropertyRef instead of a
+ // concrete properties struct. It checks for null and casts to the actual
+ // properties type.
paramList[1] = MethodParameter("::mlir::DictionaryAttr", "attrs");
- paramList[2] = MethodParameter("::mlir::OpaqueProperties", "properties");
- auto *opaquePropertiesConstructor =
+ paramList[2] = MethodParameter("::mlir::PropertyRef", "properties");
+ auto *propertyRefConstructor =
genericAdaptor.addConstructor(std::move(paramList));
if (useProperties) {
- opaquePropertiesConstructor->addMemberInitializer(
+ propertyRefConstructor->addMemberInitializer(
genericAdaptor.getClassName(),
"values, "
"attrs, "
"(properties ? *properties.as<Properties *>() : Properties{}), "
"regions");
} else {
- opaquePropertiesConstructor->addMemberInitializer(
+ propertyRefConstructor->addMemberInitializer(
genericAdaptor.getClassName(),
"values, "
"attrs, "
@@ -4702,6 +4702,7 @@ static void emitOpClasses(
for (auto *def : defs) {
Operator op(*def);
+ OpOrAdaptorHelper emitHelper(op, /*emitForOp=*/true);
if (emitDecl) {
{
NamespaceEmitter emitter(os, op.getCppNamespace());
@@ -4711,9 +4712,15 @@ static void emitOpClasses(
OpEmitter::emitDecl(op, os, staticVerifierEmitter);
}
// Emit the TypeID explicit specialization to have a single definition.
- if (!op.getCppNamespace().empty())
+ if (!op.getCppNamespace().empty()) {
os << "MLIR_DECLARE_EXPLICIT_TYPE_ID(" << op.getCppNamespace()
- << "::" << op.getCppClassName() << ")\n\n";
+ << "::" << op.getCppClassName() << ")\n";
+ if (emitHelper.hasNonEmptyPropertiesStruct())
+ os << "MLIR_DECLARE_EXPLICIT_TYPE_ID(" << op.getCppNamespace()
+ << "::detail::" << op.getCppClassName()
+ << "GenericAdaptorBase::Properties)\n";
+ os << "\n";
+ }
} else {
{
NamespaceEmitter emitter(os, op.getCppNamespace());
@@ -4722,9 +4729,15 @@ static void emitOpClasses(
OpEmitter::emitDef(op, os, staticVerifierEmitter);
}
// Emit the TypeID explicit specialization to have a single definition.
- if (!op.getCppNamespace().empty())
+ if (!op.getCppNamespace().empty()) {
os << "MLIR_DEFINE_EXPLICIT_TYPE_ID(" << op.getCppNamespace()
- << "::" << op.getCppClassName() << ")\n\n";
+ << "::" << op.getCppClassName() << ")\n";
+ if (emitHelper.hasNonEmptyPropertiesStruct())
+ os << "MLIR_DEFINE_EXPLICIT_TYPE_ID(" << op.getCppNamespace()
+ << "::detail::" << op.getCppClassName()
+ << "GenericAdaptorBase::Properties)\n";
+ os << "\n";
+ }
}
}
}
diff --git a/mlir/unittests/Debug/FileLineColLocBreakpointManagerTest.cpp b/mlir/unittests/Debug/FileLineColLocBreakpointManagerTest.cpp
index 6a81422b6b66b..d33aa46b6e48d 100644
--- a/mlir/unittests/Debug/FileLineColLocBreakpointManagerTest.cpp
+++ b/mlir/unittests/Debug/FileLineColLocBreakpointManagerTest.cpp
@@ -24,7 +24,7 @@ static Operation *createOp(MLIRContext *context, Location loc,
unsigned int numRegions = 0) {
context->allowUnregisteredDialects();
return Operation::create(loc, OperationName(operationName, context), {}, {},
- NamedAttrList(), OpaqueProperties(nullptr), {},
+ NamedAttrList(), PropertyRef(nullptr), {},
numRegions);
}
>From 28ee9c1cac1ff025973328b0528c2c20b8cd151e Mon Sep 17 00:00:00 2001
From: Krzysztof Drewniak <krzysdrewniak at gmail.com>
Date: Sat, 14 Mar 2026 23:11:42 -0700
Subject: [PATCH 2/2] Review feedback
---
mlir/include/mlir/IR/Operation.h | 2 +-
mlir/include/mlir/IR/OperationSupport.h | 2 +-
2 files changed, 2 insertions(+), 2 deletions(-)
diff --git a/mlir/include/mlir/IR/Operation.h b/mlir/include/mlir/IR/Operation.h
index 8c53b348f6bf8..06c9695fc7cf7 100644
--- a/mlir/include/mlir/IR/Operation.h
+++ b/mlir/include/mlir/IR/Operation.h
@@ -923,7 +923,7 @@ class alignas(8) Operation final
return ((int)propertiesStorageSize) * 8;
}
- /// Return a geeric (but typed) reference to the property type storage.
+ /// Return a generic (but typed) reference to the property type storage.
PropertyRef getPropertiesStorage() {
if (propertiesStorageSize)
return PropertyRef(name.getOpPropertiesTypeID(),
diff --git a/mlir/include/mlir/IR/OperationSupport.h b/mlir/include/mlir/IR/OperationSupport.h
index f91661bebce75..07898e9c90700 100644
--- a/mlir/include/mlir/IR/OperationSupport.h
+++ b/mlir/include/mlir/IR/OperationSupport.h
@@ -82,7 +82,7 @@ class PropertyRef {
static_assert(std::is_pointer_v<Dest>,
"PropertyRef::as<T>() requires T to be a pointer type");
using RawType = std::remove_cv_t<std::remove_pointer_t<Dest>>;
- assert((!data || typeID == TypeID::get<RawType>()) &&
+ assert((typeID == TypeID::get<RawType>()) &&
"Property type mismatch: TypeID does not match requested type");
return static_cast<Dest>(data);
}
More information about the Mlir-commits
mailing list