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,12 @@ 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 And<[]>,
69
+ // which is trivially true, since properties are always their expected type.
70
+ // Within the predicate, `$_self` is an instance of the **interface**
71
+ // type of the property.
72
+ Pred predicate = ?;
73
+
66
74
// The call expression to hash the property.
67
75
//
68
76
// Format:
@@ -150,8 +158,8 @@ class Property<string storageTypeParam = "", string desc = ""> {
150
158
return ::mlir::failure();
151
159
}];
152
160
153
- // Base definition for the property. (Will be) used for `OptionalProperty` and
154
- // such cases, analogously to `baseAttr`.
161
+ // Base definition for the property. Used to look through `OptionalProperty`
162
+ // for some format generation, as with the `baseAttr` field on attributes .
155
163
Property baseProperty = ?;
156
164
157
165
// Default value for the property within its storage. This should be an expression
@@ -224,8 +232,7 @@ def I64Property : IntProperty<"int64_t">;
224
232
225
233
class EnumProperty<string storageTypeParam, string desc = "", string default = ""> :
226
234
Property<storageTypeParam, desc> {
227
- // TODO: take advantage of EnumAttrInfo and the like to make this share nice
228
- // parsing code with EnumAttr.
235
+ // TODO: implement predicate for enum validity.
229
236
let writeToMlirBytecode = [{
230
237
$_writer.writeVarInt(static_cast<uint64_t>($_storage));
231
238
}];
@@ -330,6 +337,56 @@ def UnitProperty : Property<"bool", "unit property"> {
330
337
}];
331
338
}
332
339
340
+ //===----------------------------------------------------------------------===//
341
+ // Property field overwrites
342
+
343
+ /// Class for giving a property a default value.
344
+ /// This doesn't change anything about the property other than giving it a default
345
+ /// which can be used by ODS to elide printing.
346
+ class DefaultValuedProperty<Property p, string default = "", string storageDefault = ""> : Property<p.storageType, p.summary> {
347
+ let defaultValue = default;
348
+ let storageTypeValueOverride = storageDefault;
349
+ let baseProperty = p;
350
+ // Keep up to date with `Property` above.
351
+ let summary = p.summary;
352
+ let description = p.description;
353
+ let storageType = p.storageType;
354
+ let interfaceType = p.interfaceType;
355
+ let convertFromStorage = p.convertFromStorage;
356
+ let assignToStorage = p.assignToStorage;
357
+ let convertToAttribute = p.convertToAttribute;
358
+ let convertFromAttribute = p.convertFromAttribute;
359
+ let predicate = p.predicate;
360
+ let hashProperty = p.hashProperty;
361
+ let parser = p.parser;
362
+ let optionalParser = p.optionalParser;
363
+ let printer = p.printer;
364
+ let readFromMlirBytecode = p.readFromMlirBytecode;
365
+ let writeToMlirBytecode = p.writeToMlirBytecode;
366
+ }
367
+
368
+ class ConfinedProperty<Property p, Pred pred, string newSummary = "">
369
+ : Property<p.storageType, !if(!empty(newSummary), p.summary, newSummary)> {
370
+ let predicate = !if(!initialized(p.predicate), And<[p.predicate, pred]>, pred);
371
+ let baseProperty = p;
372
+ // Keep up to date with `Property` above.
373
+ let description = p.description;
374
+ let storageType = p.storageType;
375
+ let interfaceType = p.interfaceType;
376
+ let convertFromStorage = p.convertFromStorage;
377
+ let assignToStorage = p.assignToStorage;
378
+ let convertToAttribute = p.convertToAttribute;
379
+ let convertFromAttribute = p.convertFromAttribute;
380
+ let hashProperty = p.hashProperty;
381
+ let parser = p.parser;
382
+ let optionalParser = p.optionalParser;
383
+ let printer = p.printer;
384
+ let readFromMlirBytecode = p.readFromMlirBytecode;
385
+ let writeToMlirBytecode = p.writeToMlirBytecode;
386
+ let defaultValue = p.defaultValue;
387
+ let storageTypeValueOverride = p.storageTypeValueOverride;
388
+ }
389
+
333
390
//===----------------------------------------------------------------------===//
334
391
// Primitive property combinators
335
392
@@ -342,14 +399,37 @@ class _makePropStorage<Property prop, string name> {
342
399
true : "") # ";";
343
400
}
344
401
402
+ /// Construct a `Pred`icate `ret` that wraps the predicate of the underlying
403
+ /// property `childProp` with:
404
+ ///
405
+ /// [](childProp.storageType& s) {
406
+ /// return [](childProp.interfaceType i) {
407
+ /// return leafSubst(childProp.predicate, "$_self" to "i");
408
+ /// }(childProp.convertFromStorage(s))
409
+ /// }
410
+ ///
411
+ /// and then appends `prefix` and `suffix`.
412
+ class _makeChildWrapperPred<string prefix, Property wrappedProp, string suffix> {
413
+ Pred ret =
414
+ !if(!initialized(wrappedProp.predicate),
415
+ Concat<
416
+ prefix # "[]("
417
+ # "const " # wrappedProp.storageType # "& baseStore) -> bool { return []("
418
+ # wrappedProp.interfaceType # " baseIface) -> bool { return (",
419
+ SubstLeaves<"$_self", "baseIface", wrappedProp.predicate>,
420
+ "); }(" # !subst("$_storage", "baseStore", wrappedProp.convertFromStorage)
421
+ # "); }" # suffix
422
+ >, ?);
423
+ }
424
+
345
425
/// The generic class for arrays of some other property, which is stored as a
346
426
/// `SmallVector` of that property. This uses an `ArrayAttr` as its attribute form
347
427
/// though subclasses can override this, as is the case with IntArrayAttr below.
348
428
/// Those wishing to use a non-default number of SmallVector elements should
349
429
/// subclass `ArrayProperty`.
350
- class ArrayProperty<Property elem = Property<>, string desc = ""> :
351
- Property<"::llvm::SmallVector<" # elem.storageType # ">", desc> {
352
- let summary = "array of " # elem.summary;
430
+ class ArrayProperty<Property elem = Property<>, string newSummary = ""> :
431
+ Property<"::llvm::SmallVector<" # elem.storageType # ">",
432
+ !if(!empty(newSummary), "array of " # elem.summary, newSummary)> {
353
433
let interfaceType = "::llvm::ArrayRef<" # elem.storageType # ">";
354
434
let convertFromStorage = "::llvm::ArrayRef<" # elem.storageType # ">{$_storage}";
355
435
let assignToStorage = "$_storage.assign($_value.begin(), $_value.end())";
@@ -382,6 +462,8 @@ class ArrayProperty<Property elem = Property<>, string desc = ""> :
382
462
return ::mlir::ArrayAttr::get($_ctxt, elems);
383
463
}];
384
464
465
+ let predicate = _makeChildWrapperPred<"::llvm::all_of($_self, ", elem, ")">.ret;
466
+
385
467
defvar theParserBegin = [{
386
468
auto& storage = $_storage;
387
469
auto parseElemFn = [&]() -> ::mlir::ParseResult {
@@ -463,8 +545,8 @@ class ArrayProperty<Property elem = Property<>, string desc = ""> :
463
545
}]);
464
546
}
465
547
466
- class IntArrayProperty<string storageTypeParam = "" , string desc = ""> :
467
- ArrayProperty<IntProperty<storageTypeParam, desc> > {
548
+ class IntArrayProperty<Property elem , string newSummary= ""> :
549
+ ArrayProperty<elem, newSummary > {
468
550
// Bring back the trivial conversions we don't get in the general case.
469
551
let convertFromAttribute = [{
470
552
return convertFromAttribute($_storage, $_attr, $_diag);
@@ -474,30 +556,6 @@ class IntArrayProperty<string storageTypeParam = "", string desc = ""> :
474
556
}];
475
557
}
476
558
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
559
/// An optional property, stored as an std::optional<p.storageType>
502
560
/// interfaced with as an std::optional<p.interfaceType>..
503
561
/// The syntax is `none` (or empty string if elided) for an absent value or
@@ -575,6 +633,11 @@ class OptionalProperty<Property p, bit canDelegateParsing = 1>
575
633
return ::mlir::ArrayAttr::get($_ctxt, {attr});
576
634
}];
577
635
636
+ let predicate = !if(!initialized(p.predicate),
637
+ Or<[CPred<"!$_self.has_value()">,
638
+ SubstLeaves<"$_self", "(*($_self))", p.predicate>]>,
639
+ ?);
640
+
578
641
defvar delegatedParserBegin = [{
579
642
if (::mlir::succeeded($_parser.parseOptionalKeyword("none"))) {
580
643
$_storage = std::nullopt;
0 commit comments