diff --git a/mlir/examples/toy/Ch2/include/toy/CMakeLists.txt b/mlir/examples/toy/Ch2/include/toy/CMakeLists.txt --- a/mlir/examples/toy/Ch2/include/toy/CMakeLists.txt +++ b/mlir/examples/toy/Ch2/include/toy/CMakeLists.txt @@ -2,4 +2,5 @@ mlir_tablegen(Ops.h.inc -gen-op-decls) mlir_tablegen(Ops.cpp.inc -gen-op-defs) mlir_tablegen(Dialect.h.inc -gen-dialect-decls) +mlir_tablegen(Dialect.cpp.inc -gen-dialect-defs) add_public_tablegen_target(ToyCh2OpsIncGen) diff --git a/mlir/examples/toy/Ch3/include/toy/CMakeLists.txt b/mlir/examples/toy/Ch3/include/toy/CMakeLists.txt --- a/mlir/examples/toy/Ch3/include/toy/CMakeLists.txt +++ b/mlir/examples/toy/Ch3/include/toy/CMakeLists.txt @@ -2,4 +2,5 @@ mlir_tablegen(Ops.h.inc -gen-op-decls) mlir_tablegen(Ops.cpp.inc -gen-op-defs) mlir_tablegen(Dialect.h.inc -gen-dialect-decls) +mlir_tablegen(Dialect.cpp.inc -gen-dialect-defs) add_public_tablegen_target(ToyCh3OpsIncGen) diff --git a/mlir/examples/toy/Ch4/include/toy/CMakeLists.txt b/mlir/examples/toy/Ch4/include/toy/CMakeLists.txt --- a/mlir/examples/toy/Ch4/include/toy/CMakeLists.txt +++ b/mlir/examples/toy/Ch4/include/toy/CMakeLists.txt @@ -3,6 +3,7 @@ mlir_tablegen(Ops.h.inc -gen-op-decls) mlir_tablegen(Ops.cpp.inc -gen-op-defs) mlir_tablegen(Dialect.h.inc -gen-dialect-decls) +mlir_tablegen(Dialect.cpp.inc -gen-dialect-defs) add_public_tablegen_target(ToyCh4OpsIncGen) # Most dialects should use add_mlir_interfaces(). diff --git a/mlir/examples/toy/Ch5/include/toy/CMakeLists.txt b/mlir/examples/toy/Ch5/include/toy/CMakeLists.txt --- a/mlir/examples/toy/Ch5/include/toy/CMakeLists.txt +++ b/mlir/examples/toy/Ch5/include/toy/CMakeLists.txt @@ -3,6 +3,7 @@ mlir_tablegen(Ops.h.inc -gen-op-decls) mlir_tablegen(Ops.cpp.inc -gen-op-defs) mlir_tablegen(Dialect.h.inc -gen-dialect-decls) +mlir_tablegen(Dialect.cpp.inc -gen-dialect-defs) add_public_tablegen_target(ToyCh5OpsIncGen) # Most dialects should use add_mlir_interfaces(). diff --git a/mlir/examples/toy/Ch6/include/toy/CMakeLists.txt b/mlir/examples/toy/Ch6/include/toy/CMakeLists.txt --- a/mlir/examples/toy/Ch6/include/toy/CMakeLists.txt +++ b/mlir/examples/toy/Ch6/include/toy/CMakeLists.txt @@ -3,6 +3,7 @@ mlir_tablegen(Ops.h.inc -gen-op-decls) mlir_tablegen(Ops.cpp.inc -gen-op-defs) mlir_tablegen(Dialect.h.inc -gen-dialect-decls) +mlir_tablegen(Dialect.cpp.inc -gen-dialect-defs) add_public_tablegen_target(ToyCh6OpsIncGen) # Most dialects should use add_mlir_interfaces(). diff --git a/mlir/examples/toy/Ch7/include/toy/CMakeLists.txt b/mlir/examples/toy/Ch7/include/toy/CMakeLists.txt --- a/mlir/examples/toy/Ch7/include/toy/CMakeLists.txt +++ b/mlir/examples/toy/Ch7/include/toy/CMakeLists.txt @@ -3,6 +3,7 @@ mlir_tablegen(Ops.h.inc -gen-op-decls) mlir_tablegen(Ops.cpp.inc -gen-op-defs) mlir_tablegen(Dialect.h.inc -gen-dialect-decls) +mlir_tablegen(Dialect.cpp.inc -gen-dialect-defs) add_public_tablegen_target(ToyCh7OpsIncGen) # Most dialects should use add_mlir_interfaces(). diff --git a/mlir/include/mlir/Dialect/LLVMIR/CMakeLists.txt b/mlir/include/mlir/Dialect/LLVMIR/CMakeLists.txt --- a/mlir/include/mlir/Dialect/LLVMIR/CMakeLists.txt +++ b/mlir/include/mlir/Dialect/LLVMIR/CMakeLists.txt @@ -9,6 +9,7 @@ mlir_tablegen(LLVMOps.h.inc -gen-op-decls) mlir_tablegen(LLVMOps.cpp.inc -gen-op-defs) mlir_tablegen(LLVMOpsDialect.h.inc -gen-dialect-decls) +mlir_tablegen(LLVMOpsDialect.cpp.inc -gen-dialect-defs) mlir_tablegen(LLVMOpsEnums.h.inc -gen-enum-decls) mlir_tablegen(LLVMOpsEnums.cpp.inc -gen-enum-defs) add_public_tablegen_target(MLIRLLVMOpsIncGen) diff --git a/mlir/include/mlir/Dialect/StandardOps/IR/CMakeLists.txt b/mlir/include/mlir/Dialect/StandardOps/IR/CMakeLists.txt --- a/mlir/include/mlir/Dialect/StandardOps/IR/CMakeLists.txt +++ b/mlir/include/mlir/Dialect/StandardOps/IR/CMakeLists.txt @@ -2,6 +2,7 @@ mlir_tablegen(Ops.h.inc -gen-op-decls) mlir_tablegen(Ops.cpp.inc -gen-op-defs) mlir_tablegen(OpsDialect.h.inc -gen-dialect-decls) +mlir_tablegen(OpsDialect.cpp.inc -gen-dialect-defs) mlir_tablegen(OpsEnums.h.inc -gen-enum-decls) mlir_tablegen(OpsEnums.cpp.inc -gen-enum-defs) add_public_tablegen_target(MLIRStandardOpsIncGen) diff --git a/mlir/include/mlir/IR/CMakeLists.txt b/mlir/include/mlir/IR/CMakeLists.txt --- a/mlir/include/mlir/IR/CMakeLists.txt +++ b/mlir/include/mlir/IR/CMakeLists.txt @@ -9,6 +9,7 @@ set(LLVM_TARGET_DEFINITIONS BuiltinDialect.td) mlir_tablegen(BuiltinDialect.h.inc -gen-dialect-decls) +mlir_tablegen(BuiltinDialect.cpp.inc -gen-dialect-defs) add_public_tablegen_target(MLIRBuiltinDialectIncGen) set(LLVM_TARGET_DEFINITIONS BuiltinLocationAttributes.td) 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 @@ -267,6 +267,10 @@ // If this dialect overrides the hook for materializing constants. bit hasConstantMaterializer = 0; + // If this dialect provides its own destructor definition (true) vs having + // one generated (false). + bit hasExplicitDestructor = 0; + // If this dialect overrides the hook for verifying operation attributes. bit hasOperationAttrVerify = 0; diff --git a/mlir/include/mlir/TableGen/Dialect.h b/mlir/include/mlir/TableGen/Dialect.h --- a/mlir/include/mlir/TableGen/Dialect.h +++ b/mlir/include/mlir/TableGen/Dialect.h @@ -54,9 +54,13 @@ /// Returns true if this dialect has a canonicalizer. bool hasCanonicalizer() const; - // Returns true if this dialect has a constant materializer. + /// Returns true if this dialect has a constant materializer. bool hasConstantMaterializer() const; + /// Returns true if the destructor definition is provided explicitly or + /// false if a default should be generated. + bool hasExplicitDestructor() const; + /// Returns true if this dialect has an operation attribute verifier. bool hasOperationAttrVerify() const; diff --git a/mlir/lib/Dialect/StandardOps/IR/Ops.cpp b/mlir/lib/Dialect/StandardOps/IR/Ops.cpp --- a/mlir/lib/Dialect/StandardOps/IR/Ops.cpp +++ b/mlir/lib/Dialect/StandardOps/IR/Ops.cpp @@ -28,6 +28,8 @@ #include "llvm/Support/FormatVariadic.h" #include "llvm/Support/raw_ostream.h" +#include "mlir/Dialect/StandardOps/IR/OpsDialect.cpp.inc" + // Pull in all enum type definitions and utility function declarations. #include "mlir/Dialect/StandardOps/IR/OpsEnums.cpp.inc" diff --git a/mlir/lib/IR/BuiltinDialect.cpp b/mlir/lib/IR/BuiltinDialect.cpp --- a/mlir/lib/IR/BuiltinDialect.cpp +++ b/mlir/lib/IR/BuiltinDialect.cpp @@ -27,6 +27,8 @@ // Builtin Dialect //===----------------------------------------------------------------------===// +#include "mlir/IR/BuiltinDialect.cpp.inc" + namespace { struct BuiltinOpAsmDialectInterface : public OpAsmDialectInterface { using OpAsmDialectInterface::OpAsmDialectInterface; diff --git a/mlir/lib/TableGen/Dialect.cpp b/mlir/lib/TableGen/Dialect.cpp --- a/mlir/lib/TableGen/Dialect.cpp +++ b/mlir/lib/TableGen/Dialect.cpp @@ -69,6 +69,10 @@ return def->getValueAsBit("hasConstantMaterializer"); } +bool Dialect::hasExplicitDestructor() const { + return def->getValueAsBit("hasExplicitDestructor"); +} + bool Dialect::hasOperationAttrVerify() const { return def->getValueAsBit("hasOperationAttrVerify"); } diff --git a/mlir/test/lib/Dialect/Test/CMakeLists.txt b/mlir/test/lib/Dialect/Test/CMakeLists.txt --- a/mlir/test/lib/Dialect/Test/CMakeLists.txt +++ b/mlir/test/lib/Dialect/Test/CMakeLists.txt @@ -28,6 +28,7 @@ mlir_tablegen(TestOps.h.inc -gen-op-decls) mlir_tablegen(TestOps.cpp.inc -gen-op-defs) mlir_tablegen(TestOpsDialect.h.inc -gen-dialect-decls -dialect=test) +mlir_tablegen(TestOpsDialect.cpp.inc -gen-dialect-defs -dialect=test) mlir_tablegen(TestOpEnums.h.inc -gen-enum-decls) mlir_tablegen(TestOpEnums.cpp.inc -gen-enum-defs) mlir_tablegen(TestOpStructs.h.inc -gen-struct-attr-decls) diff --git a/mlir/test/lib/Dialect/Test/TestDialect.cpp b/mlir/test/lib/Dialect/Test/TestDialect.cpp --- a/mlir/test/lib/Dialect/Test/TestDialect.cpp +++ b/mlir/test/lib/Dialect/Test/TestDialect.cpp @@ -26,6 +26,8 @@ using namespace mlir; using namespace mlir::test; +#include "TestOpsDialect.cpp.inc" + void mlir::test::registerTestDialect(DialectRegistry ®istry) { registry.insert(); } diff --git a/mlir/test/lib/Dialect/Test/TestOps.td b/mlir/test/lib/Dialect/Test/TestOps.td --- a/mlir/test/lib/Dialect/Test/TestOps.td +++ b/mlir/test/lib/Dialect/Test/TestOps.td @@ -31,6 +31,7 @@ let hasRegionArgAttrVerify = 1; let hasRegionResultAttrVerify = 1; let hasOperationInterfaceFallback = 1; + let hasExplicitDestructor = 1; let dependentDialects = ["::mlir::DLTIDialect"]; let extraClassDeclaration = [{ @@ -47,8 +48,6 @@ getParseOperationHook(StringRef opName) const override; LogicalResult printOperation(Operation *op, OpAsmPrinter &printer) const override; - - ~TestDialect(); private: // Storage for a custom fallback interface. void *fallbackEffectOpInterfaces; diff --git a/mlir/tools/mlir-tblgen/DialectGen.cpp b/mlir/tools/mlir-tblgen/DialectGen.cpp --- a/mlir/tools/mlir-tblgen/DialectGen.cpp +++ b/mlir/tools/mlir-tblgen/DialectGen.cpp @@ -17,6 +17,7 @@ #include "mlir/TableGen/OpClass.h" #include "mlir/TableGen/Operator.h" #include "mlir/TableGen/Trait.h" +#include "llvm/ADT/Optional.h" #include "llvm/ADT/Sequence.h" #include "llvm/ADT/StringExtras.h" #include "llvm/Support/CommandLine.h" @@ -54,6 +55,29 @@ DialectFilterIterator(records.end(), records.end(), filterFn)}; } +static Optional +findSelectedDialect(ArrayRef dialectDefs) { + // Select the dialect to gen for. + if (dialectDefs.size() == 1 && selectedDialect.getNumOccurrences() == 0) { + return Dialect(dialectDefs.front()); + } + + if (selectedDialect.getNumOccurrences() == 0) { + llvm::errs() << "when more than 1 dialect is present, one must be selected " + "via '-dialect'\n"; + return llvm::None; + } + + auto dialectIt = llvm::find_if(dialectDefs, [](const llvm::Record *def) { + return Dialect(def).getName() == selectedDialect; + }); + if (dialectIt == dialectDefs.end()) { + llvm::errs() << "selected dialect with '-dialect' does not exist\n"; + return llvm::None; + } + return Dialect(*dialectIt); +} + //===----------------------------------------------------------------------===// // GEN: Dialect declarations //===----------------------------------------------------------------------===// @@ -72,9 +96,11 @@ {2} initialize(); } + void initialize(); friend class ::mlir::MLIRContext; public: + ~{0}() override; static constexpr ::llvm::StringLiteral getDialectNamespace() { return ::llvm::StringLiteral("{1}"); } @@ -210,34 +236,52 @@ raw_ostream &os) { emitSourceFileHeader("Dialect Declarations", os); - auto defs = recordKeeper.getAllDerivedDefinitions("Dialect"); - if (defs.empty()) + auto dialectDefs = recordKeeper.getAllDerivedDefinitions("Dialect"); + if (dialectDefs.empty()) return false; - // Select the dialect to gen for. - const llvm::Record *dialectDef = nullptr; - if (defs.size() == 1 && selectedDialect.getNumOccurrences() == 0) { - dialectDef = defs.front(); - } else if (selectedDialect.getNumOccurrences() == 0) { - llvm::errs() << "when more than 1 dialect is present, one must be selected " - "via '-dialect'"; + Optional dialect = findSelectedDialect(dialectDefs); + if (!dialect) return true; - } else { - auto dialectIt = llvm::find_if(defs, [](const llvm::Record *def) { - return Dialect(def).getName() == selectedDialect; - }); - if (dialectIt == defs.end()) { - llvm::errs() << "selected dialect with '-dialect' does not exist"; - return true; - } - dialectDef = *dialectIt; - } - auto attrDefs = recordKeeper.getAllDerivedDefinitions("DialectAttr"); auto typeDefs = recordKeeper.getAllDerivedDefinitions("DialectType"); - Dialect dialect(dialectDef); - emitDialectDecl(dialect, filterForDialect(attrDefs, dialect), - filterForDialect(typeDefs, dialect), os); + emitDialectDecl(*dialect, filterForDialect(attrDefs, *dialect), + filterForDialect(typeDefs, *dialect), os); + return false; +} + +//===----------------------------------------------------------------------===// +// GEN: Dialect definitions +//===----------------------------------------------------------------------===// + +/// The code block to generate a default desturctor definition. +/// +/// {0}: The name of the dialect class. +static const char *const dialectDestructorStr = R"( +{0}::~{0}() = default; + +)"; + +static void emitDialectDef(Dialect &dialect, raw_ostream &os) { + // Emit all nested namespaces. + NamespaceEmitter nsEmitter(os, dialect); + + if (!dialect.hasExplicitDestructor()) + os << llvm::formatv(dialectDestructorStr, dialect.getCppClassName()); +} + +static bool emitDialectDefs(const llvm::RecordKeeper &recordKeeper, + raw_ostream &os) { + emitSourceFileHeader("Dialect Definitions", os); + + auto dialectDefs = recordKeeper.getAllDerivedDefinitions("Dialect"); + if (dialectDefs.empty()) + return false; + + Optional dialect = findSelectedDialect(dialectDefs); + if (!dialect) + return true; + emitDialectDef(*dialect, os); return false; } @@ -250,3 +294,9 @@ [](const llvm::RecordKeeper &records, raw_ostream &os) { return emitDialectDecls(records, os); }); + +static mlir::GenRegistration + genDialectDefs("gen-dialect-defs", "Generate dialect definitions", + [](const llvm::RecordKeeper &records, raw_ostream &os) { + return emitDialectDefs(records, os); + });