[Mlir-commits] [mlir] [mlir] Add property combinators, initial ODS support (PR #94732)

Mehdi Amini llvmlistbot at llvm.org
Thu Jun 13 15:08:59 PDT 2024


================
@@ -133,37 +201,487 @@ defvar writeMlirBytecodeWithConvertToAttribute = [{
 // Primitive property kinds
 
 // Any kind of integer stored as properties.
-class IntProperty<string storageTypeParam = "", string desc = ""> :
+class IntProperty<string storageTypeParam, string desc = ""> :
     Property<storageTypeParam, desc> {
-  code writeToMlirBytecode = [{
+  let summary = !if(!empty(desc), storageTypeParam, desc);
+  let optionalParser = [{
+    return $_parser.parseOptionalInteger($_storage);
+  }];
+  let writeToMlirBytecode = [{
     $_writer.writeVarInt($_storage);
   }];
-  code readFromMlirBytecode = [{
+  let readFromMlirBytecode = [{
     uint64_t val;
     if (failed($_reader.readVarInt(val)))
       return ::mlir::failure();
     $_storage = val;
   }];
 }
 
-class ArrayProperty<string storageTypeParam = "", int n, string desc = ""> :
-  Property<storageTypeParam # "[" # n # "]", desc> {
-  let interfaceType = "::llvm::ArrayRef<" # storageTypeParam # ">";
-  let convertFromStorage = "$_storage";
-  let assignToStorage = "::llvm::copy($_value, $_storage)";
-}
+def I32Property : IntProperty<"int32_t">;
+def I64Property : IntProperty<"int64_t">;
 
-class EnumProperty<string storageTypeParam, string desc = ""> :
+class EnumProperty<string storageTypeParam, string desc = "", string default = ""> :
     Property<storageTypeParam, desc> {
-  code writeToMlirBytecode = [{
+  // TODO: take advantage of EnumAttrInfo and the like to make this share nice
+  // parsing code with EnumAttr.
+  let writeToMlirBytecode = [{
     $_writer.writeVarInt(static_cast<uint64_t>($_storage));
   }];
-  code readFromMlirBytecode = [{
+  let readFromMlirBytecode = [{
     uint64_t val;
     if (failed($_reader.readVarInt(val)))
       return ::mlir::failure();
     $_storage = static_cast<}] # storageTypeParam # [{>(val);
   }];
+  let defaultValue = default;
 }
 
+def StringProperty : Property<"std::string", "string"> {
+  let interfaceType = "::llvm::StringRef";
+  let convertFromStorage = "::llvm::StringRef{$_storage}";
+  let assignToStorage = "$_storage = $_value.str()";
+  let optionalParser = [{
+    if (::mlir::failed($_parser.parseOptionalString(&$_storage)))
+      return std::nullopt;
+  }];
+  let printer = "$_printer.printString($_storage)";
+  let readFromMlirBytecode = [{
+    StringRef val;
+    if (::mlir::failed($_reader.readString(val)))
+      return ::mlir::failure();
+    $_storage = val.str();
+  }];
+  let writeToMlirBytecode = [{
+    $_writer.writeOwnedString($_storage);
+  }];
+}
+
+def BoolProperty : IntProperty<"bool", "boolean"> {
+  let printer = [{ $_printer << ($_storage ? "true" : "false") }];
+  let readFromMlirBytecode = [{
+    return $_reader.readBool($_storage);
+  }];
+  let writeToMlirBytecode = [{
+    $_writer.writeOwnedBool($_storage);
+  }];
+}
+
+def UnitProperty : Property<"bool", "unit property"> {
+  let summary = "unit property";
+  let description = [{
+    A property whose presence or abscence is used as a flag.
+
+    This is stored as a boolean that defaults to false, and is named UnitProperty
+    by analogy with UnitAttr, which has the more comprehensive rationale and
+    explains the less typical syntax.
+
+    Note that this attribute does have a syntax for the false case to allow for its
+    use in contexts where default values shouldn't be elided.
+  }];
+  let defaultValue = "false";
+
+  let convertToAttribute = [{
+    if ($_storage)
+      return ::mlir::UnitAttr::get($_ctxt);
+    else
+      return ::mlir::BoolAttr::get($_ctxt, false);
+  }];
+  let convertFromAttribute = [{
+    if (::llvm::isa<::mlir::UnitAttr>($_attr)) {
+      $_storage = true;
+      return ::mlir::success();
+    }
+    if (auto boolAttr = ::llvm::dyn_cast<::mlir::BoolAttr>($_attr)) {
+      $_storage = boolAttr.getValue();
+      return ::mlir::success();
+    }
+    return ::mlir::failure();
+  }];
+
+  let parser = [{
+    ::llvm::StringRef keyword;
+    if (::mlir::failed($_parser.parseOptionalKeyword(&keyword,
+        {"unit", "unit_absent"})))
+      return $_parser.emitError($_parser.getCurrentLocation(),
+        "expected 'unit' or 'unit_absent'");
+    $_storage = (keyword == "unit");
+  }];
+
+  let optionalParser = [{
+    ::llvm::StringRef keyword;
+    if (::mlir::failed($_parser.parseOptionalKeyword(&keyword,
+        {"unit", "unit_absent"})))
+      return std::nullopt;
+    $_storage = (keyword == "unit");
+  }];
+
+  let printer = [{
+    $_printer << ($_storage ? "unit" : "unit_absent")
+  }];
+
+  let writeToMlirBytecode = [{
+    $_writer.writeOwnedBool($_storage);
+  }];
+  let readFromMlirBytecode = [{
+    if (::mlir::failed($_reader.readBool($_storage)))
+      return ::mlir::failure();
+  }];
+}
+
+//===----------------------------------------------------------------------===//
+// Primitive property combinators
+
+/// Create a variable named `name` of `prop`'s storage type that is initialized
+/// to the correct default value, if there is one.
+class _makePropStorage<Property prop, string name> {
+  code ret = prop.storageType # " " # name
+      # !cond(!not(!empty(prop.storageTypeValueOverride)) : " = " # prop.storageTypeValueOverride,
+        !not(!empty(prop.defaultValue)) : " = " # prop.defaultValue,
+        true : "") # ";";
+}
+
+/// The generic class for arrays of some other property, which is stored as a
+/// `SmallVector` of that property. This uses an `ArrayAttr` as its attribute form
+/// though subclasses can override this, as is the case with IntArrayAttr below.
+class ArrayProperty<Property elem = Property<>, string desc = ""> :
+  Property<"::llvm::SmallVector<" # elem.storageType # ">", desc> {
----------------
joker-eph wrote:

If we use a SmallVector we likely should expose to the user the size to use for the SmallVector I think.

https://github.com/llvm/llvm-project/pull/94732


More information about the Mlir-commits mailing list