@@ -17,14 +17,21 @@ include "mlir/IR/Constraints.td"
17
17
include "mlir/IR/Utils.td"
18
18
19
19
// Base class for defining properties.
20
- class Property<string storageTypeParam = "", string desc = ""> {
21
- // User-readable one line summary used in error reporting messages. If empty,
22
- // a generic message will be used.
23
- string summary = desc;
20
+ // `desc` is the summary, a user-readable one-line description of the property
21
+ // used in error messages. If empty, a generic message will be used.
22
+ // `storageTypeParam` is the type which will be used to store the property in
23
+ // a property struct, while `interfaceTypeParam` (which defaults to `storageTypeParam`)
24
+ // is the type returned from the getter of the property and used as an argument
25
+ // to the property's builder.
26
+ // Properties have a `predicate` field. It defaults to the true predicate since
27
+ // properties always hold their C++ type. Within these predicates, $_self is the
28
+ // **interface** type of the property.
29
+ class Property<string storageTypeParam = "", string desc = "", string interfaceTypeParam = storageTypeParam>
30
+ : PropConstraint<TruePred, desc, interfaceTypeParam> {
24
31
// The full description of this property.
25
32
string description = "";
26
33
code storageType = storageTypeParam;
27
- code interfaceType = storageTypeParam;
34
+ // Note: the interface type is a field on PropConstraint.
28
35
29
36
// The expression to convert from the storage type to the Interface
30
37
// type. For example, an enum can be stored as an int but returned as an
@@ -66,13 +73,6 @@ class Property<string storageTypeParam = "", string desc = ""> {
66
73
return convertFromAttribute($_storage, $_attr, $_diag);
67
74
}];
68
75
69
- // The verification predicate for this property. Defaults to the true predicate,
70
- // since properties are always their expected type.
71
- // Within the predicate, `$_self` is an instance of the **interface**
72
- // type of the property. Setting this field to ? will also result in a
73
- // true predicate but is not recommended, as it breaks composability.
74
- Pred predicate = TruePred;
75
-
76
76
// The call expression to hash the property.
77
77
//
78
78
// Format:
@@ -240,8 +240,7 @@ def I32Property : IntProp<"int32_t">, Deprecated<"moved to shorter name I32Prop"
240
240
def I64Property : IntProp<"int64_t">, Deprecated<"moved to shorter name I64Prop">;
241
241
242
242
// Note: only a class so we can deprecate the old name
243
- class _cls_StringProp : Property<"std::string", "string"> {
244
- let interfaceType = "::llvm::StringRef";
243
+ class _cls_StringProp : Property<"std::string", "string", "::llvm::StringRef"> {
245
244
let convertFromStorage = "::llvm::StringRef{$_storage}";
246
245
let assignToStorage = "$_storage = $_value.str()";
247
246
let optionalParser = [{
@@ -347,7 +346,8 @@ def UnitProperty : _cls_UnitProp, Deprecated<"moved to shorter name UnitProp">;
347
346
/// Class for giving a property a default value.
348
347
/// This doesn't change anything about the property other than giving it a default
349
348
/// which can be used by ODS to elide printing.
350
- class DefaultValuedProp<Property p, string default = "", string storageDefault = ""> : Property<p.storageType, p.summary> {
349
+ class DefaultValuedProp<Property p, string default = "", string storageDefault = "">
350
+ : Property<p.storageType, p.summary, p.interfaceType> {
351
351
let defaultValue = default;
352
352
let storageTypeValueOverride = storageDefault;
353
353
let baseProperty = p;
@@ -375,7 +375,7 @@ class DefaultValuedProperty<Property p, string default = "", string storageDefau
375
375
/// predicates it may already have. If `newSummary` is provided, replace the
376
376
/// summary of `p` with `newSummary`.
377
377
class ConfinedProp<Property p, Pred pred, string newSummary = "">
378
- : Property<p.storageType, !if(!empty(newSummary), p.summary, newSummary)> {
378
+ : Property<p.storageType, !if(!empty(newSummary), p.summary, newSummary), p.interfaceType > {
379
379
let predicate = !if(!ne(p.predicate, TruePred), And<[p.predicate, pred]>, pred);
380
380
let baseProperty = p;
381
381
// Keep up to date with `Property` above.
@@ -441,8 +441,8 @@ class _makeStorageWrapperPred<Property wrappedProp> {
441
441
/// subclass `ArrayProp`.
442
442
class ArrayProp<Property elem = Property<>, string newSummary = ""> :
443
443
Property<"::llvm::SmallVector<" # elem.storageType # ">",
444
- !if(!empty(newSummary), "array of " # elem.summary, newSummary)> {
445
- let interfaceType = "::llvm::ArrayRef<" # elem.storageType # ">";
444
+ !if(!empty(newSummary), "array of " # elem.summary, newSummary),
445
+ "::llvm::ArrayRef<" # elem.storageType # ">"> {
446
446
let convertFromStorage = "::llvm::ArrayRef<" # elem.storageType # ">{$_storage}";
447
447
let assignToStorage = "$_storage.assign($_value.begin(), $_value.end())";
448
448
@@ -585,7 +585,8 @@ class IntArrayProperty<Property elem, string newSummary="">
585
585
/// syntax of the underlying property, or the keyword `none` in the rare cases that
586
586
/// it is needed. This behavior can be disabled by setting `canDelegateParsing` to 0.
587
587
class OptionalProp<Property p, bit canDelegateParsing = 1>
588
- : Property<"std::optional<" # p.storageType # ">", "optional " # p.summary> {
588
+ : Property<"std::optional<" # p.storageType # ">",
589
+ "optional " # p.summary, "std::optional<" # p.interfaceType # ">"> {
589
590
590
591
// In the cases where the underlying attribute is plain old data that's passed by
591
592
// value, the conversion code is trivial.
@@ -596,7 +597,6 @@ class OptionalProp<Property p, bit canDelegateParsing = 1>
596
597
defvar delegatesParsing = !and(!empty(p.defaultValue),
597
598
!not(!empty(p.optionalParser)), canDelegateParsing);
598
599
599
- let interfaceType = "std::optional<" # p.interfaceType # ">";
600
600
let defaultValue = "std::nullopt";
601
601
602
602
let convertFromStorage = !if(hasTrivialStorage,
0 commit comments