13
13
#ifndef PROPERTIES
14
14
#define PROPERTIES
15
15
16
+ include "mlir/IR/Constraints.td"
17
+
16
18
// Base class for defining properties.
17
19
class Property<string storageTypeParam = "", string desc = ""> {
18
20
// User-readable one line summary used in error reporting messages. If empty,
@@ -63,6 +65,13 @@ class Property<string storageTypeParam = "", string desc = ""> {
63
65
return convertFromAttribute($_storage, $_attr, $_diag);
64
66
}];
65
67
68
+ // The verification predicate for this property. Defaults to the true predicate,
69
+ // since properties are always their expected type.
70
+ // Within the predicate, `$_self` is an instance of the **interface**
71
+ // type of the property. Setting this field to ? will also result in a
72
+ // true predicate but is not recommended, as it breaks composability.
73
+ Pred predicate = TruePred;
74
+
66
75
// The call expression to hash the property.
67
76
//
68
77
// Format:
@@ -150,8 +159,8 @@ class Property<string storageTypeParam = "", string desc = ""> {
150
159
return ::mlir::failure();
151
160
}];
152
161
153
- // Base definition for the property. (Will be) used for `OptionalProperty` and
154
- // such cases, analogously to `baseAttr`.
162
+ // Base definition for the property. Used to look through `OptionalProperty`
163
+ // for some format generation, as with the `baseAttr` field on attributes .
155
164
Property baseProperty = ?;
156
165
157
166
// Default value for the property within its storage. This should be an expression
@@ -224,8 +233,7 @@ def I64Property : IntProperty<"int64_t">;
224
233
225
234
class EnumProperty<string storageTypeParam, string desc = "", string default = ""> :
226
235
Property<storageTypeParam, desc> {
227
- // TODO: take advantage of EnumAttrInfo and the like to make this share nice
228
- // parsing code with EnumAttr.
236
+ // TODO: implement predicate for enum validity.
229
237
let writeToMlirBytecode = [{
230
238
$_writer.writeVarInt(static_cast<uint64_t>($_storage));
231
239
}];
@@ -330,6 +338,59 @@ def UnitProperty : Property<"bool", "unit property"> {
330
338
}];
331
339
}
332
340
341
+ //===----------------------------------------------------------------------===//
342
+ // Property field overwrites
343
+
344
+ /// Class for giving a property a default value.
345
+ /// This doesn't change anything about the property other than giving it a default
346
+ /// which can be used by ODS to elide printing.
347
+ class DefaultValuedProperty<Property p, string default = "", string storageDefault = ""> : Property<p.storageType, p.summary> {
348
+ let defaultValue = default;
349
+ let storageTypeValueOverride = storageDefault;
350
+ let baseProperty = p;
351
+ // Keep up to date with `Property` above.
352
+ let summary = p.summary;
353
+ let description = p.description;
354
+ let storageType = p.storageType;
355
+ let interfaceType = p.interfaceType;
356
+ let convertFromStorage = p.convertFromStorage;
357
+ let assignToStorage = p.assignToStorage;
358
+ let convertToAttribute = p.convertToAttribute;
359
+ let convertFromAttribute = p.convertFromAttribute;
360
+ let predicate = p.predicate;
361
+ let hashProperty = p.hashProperty;
362
+ let parser = p.parser;
363
+ let optionalParser = p.optionalParser;
364
+ let printer = p.printer;
365
+ let readFromMlirBytecode = p.readFromMlirBytecode;
366
+ let writeToMlirBytecode = p.writeToMlirBytecode;
367
+ }
368
+
369
+ /// Apply the predicate `pred` to the property `p`, ANDing it with any
370
+ /// predicates it may already have. If `newSummary` is provided, replace the
371
+ /// summary of `p` with `newSummary`.
372
+ class ConfinedProperty<Property p, Pred pred, string newSummary = "">
373
+ : Property<p.storageType, !if(!empty(newSummary), p.summary, newSummary)> {
374
+ let predicate = !if(!ne(p.predicate, TruePred), And<[p.predicate, pred]>, pred);
375
+ let baseProperty = p;
376
+ // Keep up to date with `Property` above.
377
+ let description = p.description;
378
+ let storageType = p.storageType;
379
+ let interfaceType = p.interfaceType;
380
+ let convertFromStorage = p.convertFromStorage;
381
+ let assignToStorage = p.assignToStorage;
382
+ let convertToAttribute = p.convertToAttribute;
383
+ let convertFromAttribute = p.convertFromAttribute;
384
+ let hashProperty = p.hashProperty;
385
+ let parser = p.parser;
386
+ let optionalParser = p.optionalParser;
387
+ let printer = p.printer;
388
+ let readFromMlirBytecode = p.readFromMlirBytecode;
389
+ let writeToMlirBytecode = p.writeToMlirBytecode;
390
+ let defaultValue = p.defaultValue;
391
+ let storageTypeValueOverride = p.storageTypeValueOverride;
392
+ }
393
+
333
394
//===----------------------------------------------------------------------===//
334
395
// Primitive property combinators
335
396
@@ -342,14 +403,35 @@ class _makePropStorage<Property prop, string name> {
342
403
true : "") # ";";
343
404
}
344
405
406
+ /// Construct a `Pred`icate `ret` that wraps the predicate of the underlying
407
+ /// property `childProp` with:
408
+ ///
409
+ /// [](childProp.storageType& s) {
410
+ /// return [](childProp.interfaceType i) {
411
+ /// return leafSubst(childProp.predicate, "$_self" to "i");
412
+ /// }(childProp.convertFromStorage(s))
413
+ /// }
414
+ ///
415
+ /// and then appends `prefix` and `suffix`.
416
+ class _makeStorageWrapperPred<Property wrappedProp> {
417
+ Pred ret =
418
+ Concat<
419
+ "[](" # "const " # wrappedProp.storageType
420
+ # "& baseStore) -> bool { return []("
421
+ # wrappedProp.interfaceType # " baseIface) -> bool { return (",
422
+ SubstLeaves<"$_self", "baseIface", wrappedProp.predicate>,
423
+ "); }(" # !subst("$_storage", "baseStore", wrappedProp.convertFromStorage)
424
+ # "); }">;
425
+ }
426
+
345
427
/// The generic class for arrays of some other property, which is stored as a
346
428
/// `SmallVector` of that property. This uses an `ArrayAttr` as its attribute form
347
429
/// though subclasses can override this, as is the case with IntArrayAttr below.
348
430
/// Those wishing to use a non-default number of SmallVector elements should
349
431
/// subclass `ArrayProperty`.
350
- class ArrayProperty<Property elem = Property<>, string desc = ""> :
351
- Property<"::llvm::SmallVector<" # elem.storageType # ">", desc> {
352
- let summary = "array of " # elem.summary;
432
+ class ArrayProperty<Property elem = Property<>, string newSummary = ""> :
433
+ Property<"::llvm::SmallVector<" # elem.storageType # ">",
434
+ !if(!empty(newSummary), "array of " # elem.summary, newSummary)> {
353
435
let interfaceType = "::llvm::ArrayRef<" # elem.storageType # ">";
354
436
let convertFromStorage = "::llvm::ArrayRef<" # elem.storageType # ">{$_storage}";
355
437
let assignToStorage = "$_storage.assign($_value.begin(), $_value.end())";
@@ -382,6 +464,10 @@ class ArrayProperty<Property elem = Property<>, string desc = ""> :
382
464
return ::mlir::ArrayAttr::get($_ctxt, elems);
383
465
}];
384
466
467
+ let predicate = !if(!eq(elem.predicate, TruePred),
468
+ TruePred,
469
+ Concat<"::llvm::all_of($_self, ", _makeStorageWrapperPred<elem>.ret, ")">);
470
+
385
471
defvar theParserBegin = [{
386
472
auto& storage = $_storage;
387
473
auto parseElemFn = [&]() -> ::mlir::ParseResult {
@@ -463,8 +549,8 @@ class ArrayProperty<Property elem = Property<>, string desc = ""> :
463
549
}]);
464
550
}
465
551
466
- class IntArrayProperty<string storageTypeParam = "" , string desc = ""> :
467
- ArrayProperty<IntProperty<storageTypeParam, desc> > {
552
+ class IntArrayProperty<Property elem , string newSummary= ""> :
553
+ ArrayProperty<elem, newSummary > {
468
554
// Bring back the trivial conversions we don't get in the general case.
469
555
let convertFromAttribute = [{
470
556
return convertFromAttribute($_storage, $_attr, $_diag);
@@ -474,30 +560,6 @@ class IntArrayProperty<string storageTypeParam = "", string desc = ""> :
474
560
}];
475
561
}
476
562
477
- /// Class for giving a property a default value.
478
- /// This doesn't change anything about the property other than giving it a default
479
- /// which can be used by ODS to elide printing.
480
- class DefaultValuedProperty<Property p, string default = "", string storageDefault = ""> : Property<p.storageType, p.summary> {
481
- let defaultValue = default;
482
- let storageTypeValueOverride = storageDefault;
483
- let baseProperty = p;
484
- // Keep up to date with `Property` above.
485
- let summary = p.summary;
486
- let description = p.description;
487
- let storageType = p.storageType;
488
- let interfaceType = p.interfaceType;
489
- let convertFromStorage = p.convertFromStorage;
490
- let assignToStorage = p.assignToStorage;
491
- let convertToAttribute = p.convertToAttribute;
492
- let convertFromAttribute = p.convertFromAttribute;
493
- let hashProperty = p.hashProperty;
494
- let parser = p.parser;
495
- let optionalParser = p.optionalParser;
496
- let printer = p.printer;
497
- let readFromMlirBytecode = p.readFromMlirBytecode;
498
- let writeToMlirBytecode = p.writeToMlirBytecode;
499
- }
500
-
501
563
/// An optional property, stored as an std::optional<p.storageType>
502
564
/// interfaced with as an std::optional<p.interfaceType>..
503
565
/// The syntax is `none` (or empty string if elided) for an absent value or
@@ -575,6 +637,11 @@ class OptionalProperty<Property p, bit canDelegateParsing = 1>
575
637
return ::mlir::ArrayAttr::get($_ctxt, {attr});
576
638
}];
577
639
640
+ let predicate = !if(!ne(p.predicate, TruePred),
641
+ Or<[CPred<"!$_self.has_value()">,
642
+ SubstLeaves<"$_self", "(*($_self))", p.predicate>]>,
643
+ TruePred);
644
+
578
645
defvar delegatedParserBegin = [{
579
646
if (::mlir::succeeded($_parser.parseOptionalKeyword("none"))) {
580
647
$_storage = std::nullopt;
0 commit comments