// 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
// 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;
}
}
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)
}
//===----------------------------------------------------------------------===//
+// 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";
}
//===----------------------------------------------------------------------===//
// 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;
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)
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 =
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());
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);
}
}