Skip generating C++ for "DeclareOpInterfaceMethods" in op interface gen.
authorJing Pu <jingpu@google.com>
Fri, 13 Dec 2019 21:57:49 +0000 (13:57 -0800)
committerA. Unique TensorFlower <gardener@tensorflow.org>
Sat, 14 Dec 2019 01:08:33 +0000 (17:08 -0800)
This is needed for calling the generator on a .td file that contains both OpInterface definitions and op definitions with DeclareOpInterfaceMethods<...> Traits.

PiperOrigin-RevId: 285465784

mlir/test/mlir-tblgen/op-interface.td [new file with mode: 0644]
mlir/tools/mlir-tblgen/OpInterfacesGen.cpp

diff --git a/mlir/test/mlir-tblgen/op-interface.td b/mlir/test/mlir-tblgen/op-interface.td
new file mode 100644 (file)
index 0000000..7cda61d
--- /dev/null
@@ -0,0 +1,34 @@
+// RUN: mlir-tblgen -gen-op-interface-decls -I %S/../../include %s | FileCheck %s --check-prefix=DECL --dump-input-on-failure
+
+include "mlir/IR/OpBase.td"
+
+def TestOpInterface : OpInterface<"TestOpInterface"> {
+  let description = [{some op interface description}];
+
+  let methods = [
+    InterfaceMethod<
+      /*desc=*/[{some function comment}],
+      /*retTy=*/"int",
+      /*methodName=*/"foo",
+      /*args=*/(ins "int":$input)
+    >,
+  ];
+}
+
+// Define Ops with TestOpInterface and
+// DeclareOpInterfaceMethods<TestOpInterface> traits to check that there
+// are not duplicated C++ classes generated.
+def TestDialect : Dialect {
+  let name = "test";
+}
+
+def OpInterfaceOp : Op<TestDialect, "op_interface_op", [TestOpInterface]>;
+
+def DeclareMethodsOp : Op<TestDialect, "declare_methods_op",
+                          [DeclareOpInterfaceMethods<TestOpInterface>]>;
+
+// DECL-LABEL: TestOpInterfaceInterfaceTraits
+// DECL: class TestOpInterface : public OpInterface<TestOpInterface, detail::TestOpInterfaceInterfaceTraits>
+// DECL: int foo(int input);
+
+// DECL-NOT: TestOpInterface
index 4da412c..4c22d62 100644 (file)
@@ -51,6 +51,19 @@ static void emitMethodNameAndArgs(const OpInterfaceMethod &method,
   os << ')';
 }
 
+// Get an array of all OpInterface definitions but exclude those subclassing
+// "DeclareOpInterfaceMethods".
+static std::vector<Record *>
+getAllOpInterfaceDefinitions(const RecordKeeper &recordKeeper) {
+  std::vector<Record *> defs =
+      recordKeeper.getAllDerivedDefinitions("OpInterface");
+
+  llvm::erase_if(defs, [](const Record *def) {
+    return def->isSubClassOf("DeclareOpInterfaceMethods");
+  });
+  return defs;
+}
+
 //===----------------------------------------------------------------------===//
 // GEN: Interface definitions
 //===----------------------------------------------------------------------===//
@@ -78,8 +91,7 @@ static bool emitInterfaceDefs(const RecordKeeper &recordKeeper,
                               raw_ostream &os) {
   llvm::emitSourceFileHeader("Operation Interface Definitions", os);
 
-  auto defs = recordKeeper.getAllDerivedDefinitions("OpInterface");
-  for (const auto *def : defs) {
+  for (const auto *def : getAllOpInterfaceDefinitions(recordKeeper)) {
     OpInterface interface(def);
     emitInterfaceDef(interface, os);
   }
@@ -169,8 +181,7 @@ static bool emitInterfaceDecls(const RecordKeeper &recordKeeper,
                                raw_ostream &os) {
   llvm::emitSourceFileHeader("Operation Interface Declarations", os);
 
-  auto defs = recordKeeper.getAllDerivedDefinitions("OpInterface");
-  for (const auto *def : defs) {
+  for (const auto *def : getAllOpInterfaceDefinitions(recordKeeper)) {
     OpInterface interface(def);
     emitInterfaceDecl(interface, os);
   }
@@ -230,8 +241,7 @@ static bool emitInterfaceDocs(const RecordKeeper &recordKeeper,
   os << "<!-- Autogenerated by mlir-tblgen; don't manually edit -->\n";
   os << "# Operation Interface definition\n";
 
-  auto defs = recordKeeper.getAllDerivedDefinitions("OpInterface");
-  for (const auto *def : defs)
+  for (const auto *def : getAllOpInterfaceDefinitions(recordKeeper))
     emitInterfaceDoc(*def, os);
   return false;
 }