diff --git a/mlir/include/mlir/IR/OpBase.td b/mlir/include/mlir/IR/OpBase.td --- a/mlir/include/mlir/IR/OpBase.td +++ b/mlir/include/mlir/IR/OpBase.td @@ -958,8 +958,8 @@ // Base attribute definition // Base class for all attributes. -class Attr : - AttrConstraint { +class Attr : + AttrConstraint { code storageType = ?; // The backing mlir::Attribute type code returnType = ?; // The underlying C++ value type @@ -1007,11 +1007,14 @@ // 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 : - Attr { +class DialectAttr : + Attr { Dialect dialect = d; let cppNamespace = d.cppNamespace; } diff --git a/mlir/include/mlir/TableGen/Attribute.h b/mlir/include/mlir/TableGen/Attribute.h --- a/mlir/include/mlir/TableGen/Attribute.h +++ b/mlir/include/mlir/TableGen/Attribute.h @@ -113,6 +113,9 @@ // 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 --- a/mlir/lib/TableGen/Attribute.cpp +++ b/mlir/lib/TableGen/Attribute.cpp @@ -132,6 +132,10 @@ 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 --- a/mlir/test/mlir-tblgen/gen-dialect-doc.td +++ b/mlir/test/mlir-tblgen/gen-dialect-doc.td @@ -14,9 +14,28 @@ } def AOp : Op]>; +def TestAttr : DialectAttr> { + let summary = "attribute summary"; + let description = "attribute description"; +} + +def TestType : DialectType> { + 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 // CHECK: Interfaces: NoSideEffect (MemoryEffectOpInterface) diff --git a/mlir/tools/mlir-tblgen/OpDocGen.cpp b/mlir/tools/mlir-tblgen/OpDocGen.cpp --- a/mlir/tools/mlir-tblgen/OpDocGen.cpp +++ b/mlir/tools/mlir-tblgen/OpDocGen.cpp @@ -210,14 +210,24 @@ 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 @@ // Dialect Documentation //===----------------------------------------------------------------------===// -static void emitDialectDoc(const Dialect &dialect, ArrayRef attrDefs, - ArrayRef ops, ArrayRef types, - ArrayRef typeDefs, raw_ostream &os) { +static void emitDialectDoc(const Dialect &dialect, + ArrayRef attributes, + ArrayRef attrDefs, ArrayRef ops, + ArrayRef types, ArrayRef typeDefs, + raw_ostream &os) { if (selectedDialect.getNumOccurrences() && dialect.getName() != selectedDialect) return; @@ -307,6 +319,12 @@ 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 RecordKeeper &recordKeeper, raw_ostream &os) { std::vector opDefs = getRequestedOpDefinitions(recordKeeper); + std::vector attrDefs = + recordKeeper.getAllDerivedDefinitionsIfDefined("DialectAttr"); std::vector typeDefs = recordKeeper.getAllDerivedDefinitionsIfDefined("DialectType"); std::vector typeDefDefs = @@ -344,26 +364,36 @@ std::set dialectsWithDocs; + llvm::StringMap> dialectAttrs; llvm::StringMap> dialectAttrDefs; llvm::StringMap> dialectOps; llvm::StringMap> dialectTypes; llvm::StringMap> 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 @@ os << "\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); } }