|
10 | 10 | #define ENUMATTR_TD |
11 | 11 |
|
12 | 12 | include "mlir/IR/AttrTypeBase.td" |
| 13 | +include "mlir/IR/Properties.td" |
13 | 14 |
|
14 | 15 | //===----------------------------------------------------------------------===// |
15 | 16 | // Enum attribute kinds |
@@ -552,6 +553,141 @@ class EnumAttr<Dialect dialect, EnumInfo enumInfo, string name = "", |
552 | 553 | let assemblyFormat = "$value"; |
553 | 554 | } |
554 | 555 |
|
| 556 | +// A property wrapping by a C++ enum. This class will automatically create bytecode |
| 557 | +// serialization logic for the given enum, as well as arranging for parser and |
| 558 | +// printer calls. |
| 559 | +class EnumProp<EnumInfo enumInfo> : Property<enumInfo.cppType, enumInfo.summary> { |
| 560 | + EnumInfo enum = enumInfo; |
| 561 | + |
| 562 | + let description = enum.description; |
| 563 | + let predicate = !if( |
| 564 | + !isa<BitEnumBase>(enum), |
| 565 | + CPred<"(static_cast<" # enum.underlyingType # ">($_self) & ~" # !cast<BitEnumBase>(enum).validBits # ") == 0">, |
| 566 | + Or<!foreach(case, enum.enumerants, CPred<"$_self == " # enum.cppType # "::" # case.symbol>)>); |
| 567 | + |
| 568 | + let convertFromAttribute = [{ |
| 569 | + auto intAttr = ::mlir::dyn_cast_if_present<::mlir::IntegerAttr>($_attr); |
| 570 | + if (!intAttr) { |
| 571 | + return $_diag() << "expected IntegerAttr storage for }] # |
| 572 | + enum.cppType # [{"; |
| 573 | + } |
| 574 | + $_storage = static_cast<}] # enum.cppType # [{>(intAttr.getValue().getZExtValue()); |
| 575 | + return ::mlir::success(); |
| 576 | + }]; |
| 577 | + |
| 578 | + let convertToAttribute = [{ |
| 579 | + return ::mlir::IntegerAttr::get(::mlir::IntegerType::get($_ctxt, }] # enum.bitwidth |
| 580 | + # [{), static_cast<}] # enum.underlyingType #[{>($_storage)); |
| 581 | + }]; |
| 582 | + |
| 583 | + let writeToMlirBytecode = [{ |
| 584 | + $_writer.writeVarInt(static_cast<uint64_t>($_storage)); |
| 585 | + }]; |
| 586 | + |
| 587 | + let readFromMlirBytecode = [{ |
| 588 | + uint64_t rawValue; |
| 589 | + if (::mlir::failed($_reader.readVarInt(rawValue))) |
| 590 | + return ::mlir::failure(); |
| 591 | + if (rawValue > std::numeric_limits<}] # enum.underlyingType # [{>::max()) |
| 592 | + return ::mlir::failure(); |
| 593 | + $_storage = static_cast<}] # enum.cppType # [{>(rawValue); |
| 594 | + }]; |
| 595 | + |
| 596 | + let optionalParser = [{ |
| 597 | + auto value = ::mlir::FieldParser<std::optional<}] # enum.cppType # [{>>::parse($_parser); |
| 598 | + if (::mlir::failed(value)) |
| 599 | + return ::mlir::failure(); |
| 600 | + if (!(value->has_value())) |
| 601 | + return std::nullopt; |
| 602 | + $_storage = std::move(**value); |
| 603 | + }]; |
| 604 | +} |
| 605 | + |
| 606 | +// Enum property that can have been (or, if `storeInCustomAttribute` is true, will also |
| 607 | +// be stored as) an attribute, in addition to being stored as an integer attribute. |
| 608 | +class EnumPropWithAttrForm<EnumInfo enumInfo, Attr attributeForm> |
| 609 | + : EnumProp<enumInfo> { |
| 610 | + Attr attrForm = attributeForm; |
| 611 | + bit storeInCustomAttribute = 0; |
| 612 | + |
| 613 | + let convertFromAttribute = [{ |
| 614 | + auto customAttr = ::mlir::dyn_cast_if_present<}] |
| 615 | + # attrForm.storageType # [{>($_attr); |
| 616 | + if (customAttr) { |
| 617 | + $_storage = customAttr.getValue(); |
| 618 | + return ::mlir::success(); |
| 619 | + } |
| 620 | + auto intAttr = ::mlir::dyn_cast_if_present<::mlir::IntegerAttr>($_attr); |
| 621 | + if (!intAttr) { |
| 622 | + return $_diag() << "expected }] # attrForm.storageType |
| 623 | + # [{ or IntegerAttr storage for }] # enum.cppType # [{"; |
| 624 | + } |
| 625 | + $_storage = static_cast<}] # enum.cppType # [{>(intAttr.getValue().getZExtValue()); |
| 626 | + return ::mlir::success(); |
| 627 | + }]; |
| 628 | + |
| 629 | + let convertToAttribute = !if(storeInCustomAttribute, [{ |
| 630 | + return }] # attrForm.storageType # [{::get($_ctxt, $_storage); |
| 631 | + }], [{ |
| 632 | + return ::mlir::IntegerAttr::get(::mlir::IntegerType::get($_ctxt, }] # enumInfo.bitwidth |
| 633 | + # [{), static_cast<}] # enum.underlyingType #[{>($_storage)); |
| 634 | + }]); |
| 635 | +} |
| 636 | + |
| 637 | +class _namedEnumPropFields<string cppType, string mnemonic> { |
| 638 | + code parser = [{ |
| 639 | + if ($_parser.parseKeyword("}] # mnemonic # [{") |
| 640 | + || $_parser.parseLess()) { |
| 641 | + return ::mlir::failure(); |
| 642 | + } |
| 643 | + auto parseRes = ::mlir::FieldParser<}] # cppType # [{>::parse($_parser); |
| 644 | + if (::mlir::failed(parseRes) || |
| 645 | + ::mlir::failed($_parser.parseGreater())) { |
| 646 | + return ::mlir::failure(); |
| 647 | + } |
| 648 | + $_storage = *parseRes; |
| 649 | + }]; |
| 650 | + |
| 651 | + code optionalParser = [{ |
| 652 | + if ($_parser.parseOptionalKeyword("}] # mnemonic # [{")) { |
| 653 | + return std::nullopt; |
| 654 | + } |
| 655 | + if ($_parser.parseLess()) { |
| 656 | + return ::mlir::failure(); |
| 657 | + } |
| 658 | + auto parseRes = ::mlir::FieldParser<}] # cppType # [{>::parse($_parser); |
| 659 | + if (::mlir::failed(parseRes) || |
| 660 | + ::mlir::failed($_parser.parseGreater())) { |
| 661 | + return ::mlir::failure(); |
| 662 | + } |
| 663 | + $_storage = *parseRes; |
| 664 | + }]; |
| 665 | + |
| 666 | + code printer = [{ |
| 667 | + $_printer << "}] # mnemonic # [{<" << $_storage << ">"; |
| 668 | + }]; |
| 669 | +} |
| 670 | + |
| 671 | +// An EnumProp which, when printed, is surrounded by mnemonic<>. |
| 672 | +// For example, if the enum can be a, b, or c, and the mnemonic is foo, |
| 673 | +// the format of this property will be "foo<a>", "foo<b>", or "foo<c>". |
| 674 | +class NamedEnumProp<EnumInfo enumInfo, string name> |
| 675 | + : EnumProp<enumInfo> { |
| 676 | + string mnemonic = name; |
| 677 | + let parser = _namedEnumPropFields<enum.cppType, mnemonic>.parser; |
| 678 | + let optionalParser = _namedEnumPropFields<enum.cppType, mnemonic>.optionalParser; |
| 679 | + let printer = _namedEnumPropFields<enum.cppType, mnemonic>.printer; |
| 680 | +} |
| 681 | + |
| 682 | +// A `NamedEnumProp` with an attribute form as in `EnumPropWithAttrForm`. |
| 683 | +class NamedEnumPropWithAttrForm<EnumInfo enumInfo, string name, Attr attributeForm> |
| 684 | + : EnumPropWithAttrForm<enumInfo, attributeForm> { |
| 685 | + string mnemonic = name; |
| 686 | + let parser = _namedEnumPropFields<enum.cppType, mnemonic>.parser; |
| 687 | + let optionalParser = _namedEnumPropFields<enum.cppType, mnemonic>.optionalParser; |
| 688 | + let printer = _namedEnumPropFields<enumInfo.cppType, mnemonic>.printer; |
| 689 | +} |
| 690 | + |
555 | 691 | class _symbolToValue<EnumInfo enumInfo, string case> { |
556 | 692 | defvar cases = |
557 | 693 | !filter(iter, enumInfo.enumerants, !eq(iter.str, case)); |
|
0 commit comments