diff --git a/mlir/include/mlir/IR/DialectBase.td b/mlir/include/mlir/IR/DialectBase.td --- a/mlir/include/mlir/IR/DialectBase.td +++ b/mlir/include/mlir/IR/DialectBase.td @@ -103,6 +103,9 @@ // If this dialect can be extended at runtime with new operations or types. bit isExtensible = 0; + + // Whether inherent Attributes defined in ODS will be stored as Properties. + bit usePropertiesForAttributes = 0; } #endif // DIALECTBASE_TD diff --git a/mlir/include/mlir/IR/ExtensibleDialect.h b/mlir/include/mlir/IR/ExtensibleDialect.h --- a/mlir/include/mlir/IR/ExtensibleDialect.h +++ b/mlir/include/mlir/IR/ExtensibleDialect.h @@ -26,6 +26,8 @@ #include "mlir/IR/OpDefinition.h" #include "mlir/Support/TypeID.h" #include "llvm/ADT/StringMap.h" +#include "llvm/Support/ErrorHandling.h" +#include namespace mlir { class AsmParser; @@ -462,6 +464,29 @@ return verifyRegionFn(op); } + // Implementation for properties (unsupported right now here). + std::optional getInherentAttr(Operation *op, + StringRef name) final { + llvm::report_fatal_error("Unsupported getInherentAttr on Dynamic dialects"); + } + void setInherentAttr(Operation *op, StringAttr name, Attribute value) final { + llvm::report_fatal_error("Unsupported setInherentAttr on Dynamic dialects"); + } + void populateInherentAttrs(Operation *op, NamedAttrList &attrs) final {} + int getOpPropertyByteSize() final { return 0; } + void initProperties(OperationName opName, void *storage, void *init) final {} + void deleteProperties(void *prop) final {} + void populateDefaultProperties(OperationName opName, void *properties) final { + } + + LogicalResult setPropertiesFromAttr(Operation *op, Attribute attr, + InFlightDiagnostic *diag) final { + return failure(); + } + Attribute getPropertiesAsAttr(Operation *op) final { return {}; } + void copyProperties(void *lhs, void *rhs) final {} + llvm::hash_code hashProperties(void *prop) final { return {}; } + private: DynamicOpDefinition( StringRef name, ExtensibleDialect *dialect, diff --git a/mlir/include/mlir/IR/OpBase.td b/mlir/include/mlir/IR/OpBase.td --- a/mlir/include/mlir/IR/OpBase.td +++ b/mlir/include/mlir/IR/OpBase.td @@ -179,6 +179,53 @@ string cppClassName = cppClassNameParam; } +// Base class for defining properties. +class Property { + // User-readable one line summary used in error reporting messages. If empty, + // a generic message will be used. + string summary = desc; + // The full description of this property. + string description = ""; + code storageType = storageTypeParam; + code interfaceType = storageTypeParam; + + // The expression to convert from the storage type to the Interface + // type. For example, an enum can be stored as an int but returned as an + // enum class. + // + // Format: `storage` will contain the property in the storage type. + code convertFromStorage = "storage"; + + // The call expression to build a property storage from the interface type. + code assignToStorage = "storage = value"; + + // The call expression to convert from the storage type to an attribute. + // + // Format: `storage` is the storage type value, `ctx` is a MLIRContext*. The + // expression must result in an Attribute. + code convertToAttribute = [{ + convertToAttribute(ctx, storage) + }]; + + // The call expression to convert from an Attribute to the storage type. + // + // Format: `storage` is the storage value, `attr` is the attribute, + // and `diag` is an optional Diagnostic pointer to emit error. + // The expression must return a LogicalResult + code convertFromAttribute = [{ + return convertFromAttribute(storage, attr, diag); + }]; + + // The call expression to hash the property, `storage` is the variable to hash + // and the expression should define a llvm::hash_code. + code hashProperty = [{ + llvm::hash_value(storage); + }]; + + // Default value for the property. + string defaultValue = ?; +} + // Subclass for constraints on an attribute. class AttrConstraint : Constraint; @@ -1090,6 +1137,17 @@ class DefaultValuedOptionalStrAttr : DefaultValuedOptionalAttr; +//===----------------------------------------------------------------------===// +// Primitive property kinds + +class ArrayProperty : + Property { + let interfaceType = "::llvm::ArrayRef<" # storageTypeParam # ">"; + let convertFromStorage = "storage"; + let assignToStorage = "::llvm::copy(value, storage)"; + +} + //===----------------------------------------------------------------------===// // Primitive attribute kinds @@ -2313,6 +2371,9 @@ // Dag containing the arguments of the op. Default to 0 arguments. dag arguments = (ins); + // Dag containing the properties of the op. Default to no properties. + dag properties = (ins); + // The list of results of the op. Default to 0 results. dag results = (outs); @@ -2399,6 +2460,11 @@ // Note: The list of traits will be uniqued by ODS. list traits = props; + // Use an external custom C++ class for this op. + // The class must be fully defined before the ODS generated header is included. + // When a customPropertiesClass is used, no inherent attribute can be defined in ODS. + string customPropertiesClass = ""; + // Additional code that will be added to the public part of the generated // C++ code of the op declaration. code extraClassDeclaration = ?; diff --git a/mlir/include/mlir/IR/OpDefinition.h b/mlir/include/mlir/IR/OpDefinition.h --- a/mlir/include/mlir/IR/OpDefinition.h +++ b/mlir/include/mlir/IR/OpDefinition.h @@ -206,6 +206,13 @@ /// in generic form. static void print(Operation *op, OpAsmPrinter &p, StringRef defaultDialect); + /// Parse properties as a Attribute. + static ParseResult genericParseProperties(OpAsmParser &parser, + Attribute &result); + + /// Print the properties as a Attribute. + static void genericPrintProperties(OpAsmPrinter &p, Attribute properties); + /// Print an operation name, eliding the dialect prefix if necessary. static void printOpName(Operation *op, OpAsmPrinter &p, StringRef defaultDialect); @@ -1463,13 +1470,17 @@ /// Returns true if this given Trait ID matches the IDs of any of the provided /// trait types `Traits`. template