Using BitEnumAttr

Hello.
I would like to report an error when using BitEnumAttr in MLIR.
For example, when we define in TableGen an attribute like this:

      def MyAttrs:
          BitEnumAttr<
              "MyAttrs",
              "Description",
              [
                  BitEnumAttrCase<"ZERO",     0x0>,
                  BitEnumAttrCase<"ONE",      0x1>,
                  BitEnumAttrCase<"TWO",      0x2>,
                  BitEnumAttrCase<"FOUR",     0x4>,
              ]
          > {
          let cppNamespace = "mlir::mydialect";
      }

and we write in the TableGen definition of the Operation using MyAttrs a assemblyFormat like this:

      let assemblyFormat = [{
          attr-dict
          `->` type(results)
      }];

then we get the following difficult to understand error when we parse an MLIR program:

error: [Operation using MyAttrs] op attribute [myfield] failed to satisfy constraint

I was assuming however, this works by specifying our field as part of the attr-dict like this in the input MLIR program:

       MyDialect.MyOp {attr1 = ..., myfield = "ZERO"} -> !MyDialect.OpType

To get rid of this error a bit surprisingly what we had to do was to write explicitly in the above assemblyFormat myfield like this:

      let assemblyFormat = [{
          `myfield` `(` $myfield `)`
          attr-dict
          `->` type(results)
      }];

In this case we can use in our input MLIR program for example:

      MyDialect.MyOp myfield("ZERO") {attr1 = ...} -> !MyDialect.OpType

Also we can use:

      MyDialect.MyOp myfield("ONE|TWO") {attr1 = ...} -> !MyDialect.OpType

or:

      MyDialect.MyOp myfield("ONE|TWO|FOUR") {attr1 = ...} -> !MyDialect.OpType

I can’t explain why it didn’t work before, but writing the assemblyFormat like we did above surely does help to avoid the error with “failed to satisfy constraint”.

Note that to retrieve the value from MyAttrs in our C++ program we can use the following code snippet since MyAttrs is an enum class:

        static_cast<uint32_t>(myOp.myfield()) .

Changing topic, you can use StrEnumAttr similar to BitEnumAttr, with integer values associated to the strings. For example, we can write in TableGen:

      def MyStrAttrs:
          StrEnumAttr<
              "MyStrAttrs",
              "Description...",
              [
                  StrEnumAttrCase<"ZERO",     0x0>,
                  StrEnumAttrCase<"ONE",      0x1>,
              ]
          > {
          let cppNamespace = "mlir::mydialect";
      }

and then later use, similarly, in the C++ program, static_cast<uint32_t>(myOp.myStrField()).

Best regards,
Alex

1 Like