Skip to content

Commit

Permalink
Emit the boilerplate for Attribute printer/parser dialect dispatching…
Browse files Browse the repository at this point in the history
… from ODS

Add a new `useDefaultAttributePrinterParser` boolean settings on the dialect
(default to false for now) that emits the boilerplate to dispatch attribute
parsing/printing to the auto-generated method.
We will likely turn this on by default in the future.

Differential Revision: https://reviews.llvm.org/D113329
  • Loading branch information
joker-eph committed Nov 10, 2021
1 parent 9d506ae commit fd6b404
Show file tree
Hide file tree
Showing 7 changed files with 48 additions and 22 deletions.
4 changes: 4 additions & 0 deletions mlir/include/mlir/IR/OpBase.td
Expand Up @@ -298,6 +298,10 @@ class Dialect {
// If this dialect overrides the hook for op interface fallback.
bit hasOperationInterfaceFallback = 0;

// If this dialect should use default generated attribute parser boilerplate:
// it'll dispatch the parsing to every individual attributes directly.
bit useDefaultAttributePrinterParser = 0;

// If this dialect overrides the hook for canonicalization patterns.
bit hasCanonicalizer = 0;

Expand Down
4 changes: 4 additions & 0 deletions mlir/include/mlir/TableGen/Dialect.h
Expand Up @@ -74,6 +74,10 @@ class Dialect {
/// Returns true if this dialect has fallback interfaces for its operations.
bool hasOperationInterfaceFallback() const;

/// Returns true if this dialect should generate the default dispatch for
/// attribute printing/parsing.
bool useDefaultAttributePrinterParser() const;

// Returns whether two dialects are equal by checking the equality of the
// underlying record.
bool operator==(const Dialect &other) const;
Expand Down
4 changes: 4 additions & 0 deletions mlir/lib/TableGen/Dialect.cpp
Expand Up @@ -90,6 +90,10 @@ bool Dialect::hasOperationInterfaceFallback() const {
return def->getValueAsBit("hasOperationInterfaceFallback");
}

bool Dialect::useDefaultAttributePrinterParser() const {
return def->getValueAsBit("useDefaultAttributePrinterParser");
}

Dialect::EmitPrefix Dialect::getEmitAccessorPrefix() const {
int prefix = def->getValueAsInt("emitAccessorPrefix");
if (prefix < 0 || prefix > static_cast<int>(EmitPrefix::Both))
Expand Down
21 changes: 0 additions & 21 deletions mlir/test/lib/Dialect/Test/TestAttributes.cpp
Expand Up @@ -229,24 +229,3 @@ void TestDialect::registerAttributes() {
#include "TestAttrDefs.cpp.inc"
>();
}

Attribute TestDialect::parseAttribute(DialectAsmParser &parser,
Type type) const {
StringRef attrTag;
if (failed(parser.parseKeyword(&attrTag)))
return Attribute();
{
Attribute attr;
auto parseResult = generatedAttributeParser(parser, attrTag, type, attr);
if (parseResult.hasValue())
return attr;
}
parser.emitError(parser.getNameLoc(), "unknown test attribute");
return Attribute();
}

void TestDialect::printAttribute(Attribute attr,
DialectAsmPrinter &printer) const {
if (succeeded(generatedAttributePrinter(attr, printer)))
return;
}
1 change: 1 addition & 0 deletions mlir/test/lib/Dialect/Test/TestOps.td
Expand Up @@ -34,6 +34,7 @@ def Test_Dialect : Dialect {
let hasRegionResultAttrVerify = 1;
let hasOperationInterfaceFallback = 1;
let hasNonDefaultDestructor = 1;
let useDefaultAttributePrinterParser = 1;
let dependentDialects = ["::mlir::DLTIDialect"];

let extraClassDeclaration = [{
Expand Down
34 changes: 34 additions & 0 deletions mlir/tools/mlir-tblgen/AttrOrTypeDefGen.cpp
Expand Up @@ -500,6 +500,34 @@ static ::mlir::OptionalParseResult generated{0}Parser(
::mlir::{0} &value) {{
)";

/// The code block for default attribute parser/printer dispatch boilerplate.
/// {0}: the dialect fully qualified class name.
static const char *const dialectDefaultAttrPrinterParserDispatch = R"(
/// Parse an attribute registered to this dialect.
::mlir::Attribute {0}::parseAttribute(::mlir::DialectAsmParser &parser,
::mlir::Type type) const {{
::llvm::SMLoc typeLoc = parser.getCurrentLocation();
::llvm::StringRef attrTag;
if (failed(parser.parseKeyword(&attrTag)))
return {{};
{{
::mlir::Attribute attr;
auto parseResult = generatedAttributeParser(parser, attrTag, type, attr);
if (parseResult.hasValue())
return attr;
}
parser.emitError(typeLoc) << "unknown attribute `"
<< attrTag << "` in dialect `" << getNamespace() << "`";
return {{};
}
/// Print an attribute registered to this dialect.
void {0}::printAttribute(::mlir::Attribute attr,
::mlir::DialectAsmPrinter &printer) const {{
if (succeeded(generatedAttributePrinter(attr, printer)))
return;
}
)";

/// The code block used to start the auto-generated printer function.
///
/// {0}: The name of the base value type, e.g. Attribute or Type.
Expand Down Expand Up @@ -986,6 +1014,12 @@ bool DefGenerator::emitDefs(StringRef selectedDialect) {
<< "::" << def.getCppClassName() << ")\n";
}

// Emit the default parser/printer for Attributes if the dialect asked for it.
if (valueType == "Attribute" &&
defs.front().getDialect().useDefaultAttributePrinterParser())
os << llvm::formatv(dialectDefaultAttrPrinterParserDispatch,
defs.front().getDialect().getCppClassName());

return false;
}

Expand Down
2 changes: 1 addition & 1 deletion mlir/tools/mlir-tblgen/DialectGen.cpp
Expand Up @@ -208,7 +208,7 @@ static void emitDialectDecl(Dialect &dialect,

// Check for any attributes/types registered to this dialect. If there are,
// add the hooks for parsing/printing.
if (!dialectAttrs.empty())
if (!dialectAttrs.empty() || dialect.useDefaultAttributePrinterParser())
os << attrParserDecl;
if (!dialectTypes.empty())
os << typeParserDecl;
Expand Down

0 comments on commit fd6b404

Please sign in to comment.