[Mlir-commits] [mlir] 0be38d4 - [mlir][ods] Add description to Attr and ensure doc generation

Alex Zinenko llvmlistbot at llvm.org
Tue Apr 5 01:40:22 PDT 2022


Author: Alex Zinenko
Date: 2022-04-05T10:40:15+02:00
New Revision: 0be38d4f32d54bc01cea54d8f9e7e9d059620d79

URL: https://github.com/llvm/llvm-project/commit/0be38d4f32d54bc01cea54d8f9e7e9d059620d79
DIFF: https://github.com/llvm/llvm-project/commit/0be38d4f32d54bc01cea54d8f9e7e9d059620d79.diff

LOG: [mlir][ods] Add description to Attr and ensure doc generation

Add the description textual field to the Attr ODS class to mirror an
identical field in the Type ODS class. Add support for generating
documentation for attribute constraints defined using this field. This
ensures mlir-tblgen produces at least some documentation for dialects
that only define attribute constraints, such as DLTI.

Reviewed By: rriddle

Differential Revision: https://reviews.llvm.org/D123024

Added: 
    

Modified: 
    mlir/include/mlir/IR/OpBase.td
    mlir/include/mlir/TableGen/Attribute.h
    mlir/lib/TableGen/Attribute.cpp
    mlir/test/mlir-tblgen/gen-dialect-doc.td
    mlir/tools/mlir-tblgen/OpDocGen.cpp

Removed: 
    


################################################################################
diff  --git a/mlir/include/mlir/IR/OpBase.td b/mlir/include/mlir/IR/OpBase.td
index a5b3ca2f9c89a..416d05d49c39a 100644
--- a/mlir/include/mlir/IR/OpBase.td
+++ b/mlir/include/mlir/IR/OpBase.td
@@ -958,8 +958,8 @@ def SignlessIntegerOrFloatLike : TypeConstraint<Or<[
 // Base attribute definition
 
 // Base class for all attributes.
-class Attr<Pred condition, string descr = ""> :
-    AttrConstraint<condition, descr> {
+class Attr<Pred condition, string summary = ""> :
+    AttrConstraint<condition, summary> {
   code storageType = ?; // The backing mlir::Attribute type
   code returnType = ?;  // The underlying C++ value type
 
@@ -1007,11 +1007,14 @@ class Attr<Pred condition, string descr = ""> :
 
   // The fully-qualified C++ namespace where the generated class lives.
   string cppNamespace = "";
+
+  // The full description of this attribute.
+  string description = "";
 }
 
 // An attribute of a specific dialect.
-class DialectAttr<Dialect d, Pred condition, string descr = ""> :
-    Attr<condition, descr> {
+class DialectAttr<Dialect d, Pred condition, string summary = ""> :
+    Attr<condition, summary> {
   Dialect dialect = d;
   let cppNamespace = d.cppNamespace;
 }

diff  --git a/mlir/include/mlir/TableGen/Attribute.h b/mlir/include/mlir/TableGen/Attribute.h
index 043a3556d1cd9..9e6165a33178a 100644
--- a/mlir/include/mlir/TableGen/Attribute.h
+++ b/mlir/include/mlir/TableGen/Attribute.h
@@ -113,6 +113,9 @@ class Attribute : public AttrConstraint {
 
   // Returns the dialect for the attribute if defined.
   Dialect getDialect() const;
+
+  // Returns the description of the attribute.
+  StringRef getDescription() const;
 };
 
 // Wrapper class providing helper methods for accessing MLIR constant attribute

diff  --git a/mlir/lib/TableGen/Attribute.cpp b/mlir/lib/TableGen/Attribute.cpp
index ac62220d85e47..ae9183fb27c8b 100644
--- a/mlir/lib/TableGen/Attribute.cpp
+++ b/mlir/lib/TableGen/Attribute.cpp
@@ -132,6 +132,10 @@ Dialect Attribute::getDialect() const {
   return Dialect(nullptr);
 }
 
+StringRef Attribute::getDescription() const {
+  return def->getValueAsString("description");
+}
+
 ConstantAttr::ConstantAttr(const DefInit *init) : def(init->getDef()) {
   assert(def->isSubClassOf("ConstantAttr") &&
          "must be subclass of TableGen 'ConstantAttr' class");

diff  --git a/mlir/test/mlir-tblgen/gen-dialect-doc.td b/mlir/test/mlir-tblgen/gen-dialect-doc.td
index 1edb423cee05b..1eda916e814c1 100644
--- a/mlir/test/mlir-tblgen/gen-dialect-doc.td
+++ b/mlir/test/mlir-tblgen/gen-dialect-doc.td
@@ -14,9 +14,28 @@ def Test_Dialect : Dialect {
 }
 def AOp : Op<Test_Dialect, "a", [NoSideEffect, SingleBlockImplicitTerminator<"YieldOp">]>;
 
+def TestAttr : DialectAttr<Test_Dialect, CPred<"true">> {
+  let summary = "attribute summary";
+  let description = "attribute description";
+}
+
+def TestType : DialectType<Test_Dialect, CPred<"true">> {
+  let summary = "type summary";
+  let description = "type description";
+}
+
 // CHECK: Dialect without a [TOC] here.
 // CHECK: TOC added by tool.
 // CHECK: [TOC]
+
+// CHECK: ## Attribute constraint definition
+// CHECK: ### attribute summary
+// CHECK: attribute description
+
+// CHECK: ## Type constraint definition
+// CHECK: ### type summary
+// CHECK: type description
+
 // CHECK-NOT: [TOC]
 // CHECK: Traits: SingleBlockImplicitTerminator<YieldOp>
 // CHECK: Interfaces: NoSideEffect (MemoryEffectOpInterface)

diff  --git a/mlir/tools/mlir-tblgen/OpDocGen.cpp b/mlir/tools/mlir-tblgen/OpDocGen.cpp
index 9b9c64884a360..83229cda37de0 100644
--- a/mlir/tools/mlir-tblgen/OpDocGen.cpp
+++ b/mlir/tools/mlir-tblgen/OpDocGen.cpp
@@ -210,14 +210,24 @@ static void emitOpDoc(const RecordKeeper &recordKeeper, raw_ostream &os) {
     emitOpDoc(Operator(opDef), os);
 }
 
+//===----------------------------------------------------------------------===//
+// Attribute Documentation
+//===----------------------------------------------------------------------===//
+
+static void emitAttrDoc(const Attribute &attr, raw_ostream &os) {
+  os << "### " << attr.getSummary() << "\n\n";
+  emitDescription(attr.getDescription(), os);
+  os << "\n\n";
+}
+
 //===----------------------------------------------------------------------===//
 // Type Documentation
 //===----------------------------------------------------------------------===//
 
 static void emitTypeDoc(const Type &type, raw_ostream &os) {
-  os << "### " << type.getSummary() << "\n";
+  os << "### " << type.getSummary() << "\n\n";
   emitDescription(type.getDescription(), os);
-  os << "\n";
+  os << "\n\n";
 }
 
 //===----------------------------------------------------------------------===//
@@ -292,9 +302,11 @@ static void emitAttrOrTypeDefDoc(const RecordKeeper &recordKeeper,
 // Dialect Documentation
 //===----------------------------------------------------------------------===//
 
-static void emitDialectDoc(const Dialect &dialect, ArrayRef<AttrDef> attrDefs,
-                           ArrayRef<Operator> ops, ArrayRef<Type> types,
-                           ArrayRef<TypeDef> typeDefs, raw_ostream &os) {
+static void emitDialectDoc(const Dialect &dialect,
+                           ArrayRef<Attribute> attributes,
+                           ArrayRef<AttrDef> attrDefs, ArrayRef<Operator> ops,
+                           ArrayRef<Type> types, ArrayRef<TypeDef> typeDefs,
+                           raw_ostream &os) {
   if (selectedDialect.getNumOccurrences() &&
       dialect.getName() != selectedDialect)
     return;
@@ -307,6 +319,12 @@ static void emitDialectDoc(const Dialect &dialect, ArrayRef<AttrDef> attrDefs,
   if (!r.match(dialect.getDescription()))
     os << "[TOC]\n\n";
 
+  if (!attributes.empty()) {
+    os << "## Attribute constraint definition\n\n";
+    for (const Attribute &attr : attributes)
+      emitAttrDoc(attr, os);
+  }
+
   if (!attrDefs.empty()) {
     os << "## Attribute definition\n\n";
     for (const AttrDef &def : attrDefs)
@@ -335,6 +353,8 @@ static void emitDialectDoc(const Dialect &dialect, ArrayRef<AttrDef> attrDefs,
 
 static void emitDialectDoc(const RecordKeeper &recordKeeper, raw_ostream &os) {
   std::vector<Record *> opDefs = getRequestedOpDefinitions(recordKeeper);
+  std::vector<Record *> attrDefs =
+      recordKeeper.getAllDerivedDefinitionsIfDefined("DialectAttr");
   std::vector<Record *> typeDefs =
       recordKeeper.getAllDerivedDefinitionsIfDefined("DialectType");
   std::vector<Record *> typeDefDefs =
@@ -344,26 +364,36 @@ static void emitDialectDoc(const RecordKeeper &recordKeeper, raw_ostream &os) {
 
   std::set<Dialect> dialectsWithDocs;
 
+  llvm::StringMap<std::vector<Attribute>> dialectAttrs;
   llvm::StringMap<std::vector<AttrDef>> dialectAttrDefs;
   llvm::StringMap<std::vector<Operator>> dialectOps;
   llvm::StringMap<std::vector<Type>> dialectTypes;
   llvm::StringMap<std::vector<TypeDef>> dialectTypeDefs;
-  for (auto *attrDef : attrDefDefs) {
+  for (Record *attrDef : attrDefs) {
+    Attribute attr(attrDef);
+    if (const Dialect &dialect = attr.getDialect()) {
+      dialectAttrs[dialect.getName()].push_back(attr);
+      dialectsWithDocs.insert(dialect);
+    }
+  }
+  for (Record *attrDef : attrDefDefs) {
     AttrDef attr(attrDef);
     dialectAttrDefs[attr.getDialect().getName()].push_back(attr);
     dialectsWithDocs.insert(attr.getDialect());
   }
-  for (auto *opDef : opDefs) {
+  for (Record *opDef : opDefs) {
     Operator op(opDef);
     dialectOps[op.getDialect().getName()].push_back(op);
     dialectsWithDocs.insert(op.getDialect());
   }
-  for (auto *typeDef : typeDefs) {
+  for (Record *typeDef : typeDefs) {
     Type type(typeDef);
-    if (auto dialect = type.getDialect())
+    if (const Dialect &dialect = type.getDialect()) {
       dialectTypes[dialect.getName()].push_back(type);
+      dialectsWithDocs.insert(dialect);
+    }
   }
-  for (auto *typeDef : typeDefDefs) {
+  for (Record *typeDef : typeDefDefs) {
     TypeDef type(typeDef);
     dialectTypeDefs[type.getDialect().getName()].push_back(type);
     dialectsWithDocs.insert(type.getDialect());
@@ -372,9 +402,9 @@ static void emitDialectDoc(const RecordKeeper &recordKeeper, raw_ostream &os) {
   os << "<!-- Autogenerated by mlir-tblgen; don't manually edit -->\n";
   for (const Dialect &dialect : dialectsWithDocs) {
     StringRef dialectName = dialect.getName();
-    emitDialectDoc(dialect, dialectAttrDefs[dialectName],
-                   dialectOps[dialectName], dialectTypes[dialectName],
-                   dialectTypeDefs[dialectName], os);
+    emitDialectDoc(dialect, dialectAttrs[dialectName],
+                   dialectAttrDefs[dialectName], dialectOps[dialectName],
+                   dialectTypes[dialectName], dialectTypeDefs[dialectName], os);
   }
 }
 


        


More information about the Mlir-commits mailing list