Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[mlir][tblgen] Expose more of MLIRTableGen as library #92709

Open
wants to merge 3 commits into
base: main
Choose a base branch
from

Conversation

makslevental
Copy link
Contributor

@makslevental makslevental commented May 19, 2024

I would like to expose/make available more (all?) of the tblgen utility code as a library. This will enable downstream projects/users to extend that code to implement such things as C API generation.

The strategy here is:

  1. Move all impls currently in mlir/tools/mlir-tblgen/*.cpp to mlir/lib/TableGen;
  2. Add headers and put various emitDefs* into them;
  3. Move static mlir::GenRegistrations and llvm::cl::opts to mlir-tblgen.cpp.

Nothing revolutionary but unfortunately lots of touched lines.

The plan is to move more things into the headers as needed - I plan to experiment with downstream generation in the coming weeks.

Feel free to bikeshed homes of various emitDefs* and names of headers - I tried to group stuff that was related while still splitting somewhat.

Copy link

github-actions bot commented May 19, 2024

✅ With the latest revision this PR passed the C/C++ code formatter.

@makslevental makslevental changed the title [mlir][tblgen] Expose all of TableGen as library [mlir][tblgen] Expose all of MLIRTableGen as library May 20, 2024
@makslevental makslevental force-pushed the tblgen_lib branch 6 times, most recently from eb30884 to 3cfd075 Compare May 20, 2024 03:25
@makslevental makslevental force-pushed the tblgen_lib branch 2 times, most recently from c34cae3 to 67f6fa3 Compare May 20, 2024 04:32
@makslevental makslevental marked this pull request as ready for review May 20, 2024 04:35
@llvmbot
Copy link
Collaborator

llvmbot commented May 20, 2024

@llvm/pr-subscribers-backend-webassembly
@llvm/pr-subscribers-mlir-core
@llvm/pr-subscribers-mlir-llvm

@llvm/pr-subscribers-mlir

Author: Maksim Levental (makslevental)

Changes

I would like to expose/make available more (all?) of the tblgen utility code as a library. This will enable downstream projects/users to extend that code to implement such things as C API generation.

The strategy here is:

  1. Move all impls currently in mlir/tools/mlir-tblgen/*.cpp to mlir/lib/TableGen;
  2. Add headers and put various emitDefs* into them;
  3. Move static mlir::GenRegistrations and llvm::cl::opts to mlir-tblgen.cpp.

Nothing revolutionary. The plan is to move more things into the headers over the coming weeks as I begin to experiment with downstream extensions.

Feel free to bikeshed homes of various emitDefs* and names of headers - I tried to group stuff that was related while still splitting somewhat.


Patch is 146.92 KiB, truncated to 20.00 KiB below, full version: https://github.com/llvm/llvm-project/pull/92709.diff

45 Files Affected:

  • (modified) llvm/lib/Target/WebAssembly/WebAssemblyAsmPrinter.cpp (+1-1)
  • (modified) mlir/include/mlir/TableGen/AttrOrTypeDef.h (+62)
  • (renamed) mlir/include/mlir/TableGen/AttrOrTypeFormatGen.h (+1-1)
  • (added) mlir/include/mlir/TableGen/ByteCodeGen.h (+23)
  • (added) mlir/include/mlir/TableGen/CAPIGen.h (+25)
  • (renamed) mlir/include/mlir/TableGen/DialectGenUtilities.h (+12-1)
  • (renamed) mlir/include/mlir/TableGen/DocGenUtilities.h (+17)
  • (added) mlir/include/mlir/TableGen/EnumGen.h (+23)
  • (renamed) mlir/include/mlir/TableGen/FormatGen.h (-3)
  • (added) mlir/include/mlir/TableGen/LLVMGen.h (+36)
  • (renamed) mlir/include/mlir/TableGen/OpClass.h ()
  • (renamed) mlir/include/mlir/TableGen/OpFormatGen.h (+2-1)
  • (renamed) mlir/include/mlir/TableGen/OpGenHelpers.h (+13-2)
  • (added) mlir/include/mlir/TableGen/OpInterfacesGen.h (+142)
  • (added) mlir/include/mlir/TableGen/PassGen.h (+24)
  • (added) mlir/include/mlir/TableGen/PythonGen.h (+25)
  • (added) mlir/include/mlir/TableGen/SPIRVGen.h (+37)
  • (renamed) mlir/lib/TableGen/AttrOrTypeDefGen.cpp (+11-111)
  • (renamed) mlir/lib/TableGen/AttrOrTypeFormatGen.cpp (+4-5)
  • (renamed) mlir/lib/TableGen/BytecodeDialectGen.cpp (+8-16)
  • (modified) mlir/lib/TableGen/CMakeLists.txt (+23-1)
  • (modified) mlir/lib/TableGen/Constraint.cpp (+1-1)
  • (renamed) mlir/lib/TableGen/DialectGen.cpp (+19-34)
  • (renamed) mlir/lib/TableGen/DirectiveCommonGen.cpp (+9-23)
  • (renamed) mlir/lib/TableGen/EnumPythonBindingGen.cpp (+5-11)
  • (renamed) mlir/lib/TableGen/EnumsGen.cpp (+7-18)
  • (renamed) mlir/lib/TableGen/FormatGen.cpp (+1-10)
  • (renamed) mlir/lib/TableGen/LLVMIRConversionGen.cpp (+16-38)
  • (renamed) mlir/lib/TableGen/LLVMIRIntrinsicGen.cpp (+13-35)
  • (renamed) mlir/lib/TableGen/OpClass.cpp (+1-1)
  • (renamed) mlir/lib/TableGen/OpDefinitionsGen.cpp (+49-45)
  • (renamed) mlir/lib/TableGen/OpDocGen.cpp (+38-62)
  • (renamed) mlir/lib/TableGen/OpFormatGen.cpp (+5-4)
  • (renamed) mlir/lib/TableGen/OpGenHelpers.cpp (+6-19)
  • (renamed) mlir/lib/TableGen/OpInterfacesGen.cpp (+21-138)
  • (renamed) mlir/lib/TableGen/OpPythonBindingGen.cpp (+10-27)
  • (modified) mlir/lib/TableGen/Operator.cpp (+2-1)
  • (renamed) mlir/lib/TableGen/PassCAPIGen.cpp (+10-26)
  • (renamed) mlir/lib/TableGen/PassDocGen.cpp (+3-9)
  • (renamed) mlir/lib/TableGen/PassGen.cpp (+8-19)
  • (renamed) mlir/lib/TableGen/RewriterGen.cpp (+10-13)
  • (renamed) mlir/lib/TableGen/SPIRVUtilsGen.cpp (+24-106)
  • (modified) mlir/lib/Tools/mlir-tblgen/CMakeLists.txt (+1-1)
  • (modified) mlir/tools/mlir-tblgen/CMakeLists.txt (+1-23)
  • (modified) mlir/tools/mlir-tblgen/mlir-tblgen.cpp (+456-1)
diff --git a/llvm/lib/Target/WebAssembly/WebAssemblyAsmPrinter.cpp b/llvm/lib/Target/WebAssembly/WebAssemblyAsmPrinter.cpp
index 3524abba8990a..2ba3bb6310df9 100644
--- a/llvm/lib/Target/WebAssembly/WebAssemblyAsmPrinter.cpp
+++ b/llvm/lib/Target/WebAssembly/WebAssemblyAsmPrinter.cpp
@@ -387,7 +387,7 @@ void WebAssemblyAsmPrinter::emitDecls(const Module &M) {
 void WebAssemblyAsmPrinter::emitEndOfAsmFile(Module &M) {
   // This is required to emit external declarations (like .functypes) when
   // no functions are defined in the compilation unit and therefore,
-  // emitDecls() is not called until now.
+  // emitDirectiveDecls() is not called until now.
   emitDecls(M);
 
   // When a function's address is taken, a TABLE_INDEX relocation is emitted
diff --git a/mlir/include/mlir/TableGen/AttrOrTypeDef.h b/mlir/include/mlir/TableGen/AttrOrTypeDef.h
index 19c3a9183ec2c..56fd0264774be 100644
--- a/mlir/include/mlir/TableGen/AttrOrTypeDef.h
+++ b/mlir/include/mlir/TableGen/AttrOrTypeDef.h
@@ -17,6 +17,7 @@
 #include "mlir/Support/LLVM.h"
 #include "mlir/TableGen/Builder.h"
 #include "mlir/TableGen/Trait.h"
+#include "llvm/TableGen/Record.h"
 
 namespace llvm {
 class DagInit;
@@ -277,6 +278,67 @@ class TypeDef : public AttrOrTypeDef {
   StringRef getTypeName() const;
 };
 
+//===----------------------------------------------------------------------===//
+// DefGenerator
+//===----------------------------------------------------------------------===//
+
+/// This struct is the base generator used when processing tablegen interfaces.
+class DefGenerator {
+public:
+  bool emitDecls(StringRef selectedDialect);
+  bool emitDefs(StringRef selectedDialect);
+
+protected:
+  DefGenerator(std::vector<llvm::Record *> &&defs, raw_ostream &os,
+               StringRef defType, StringRef valueType, bool isAttrGenerator,
+               bool formatErrorIsFatal)
+      : defRecords(std::move(defs)), os(os), defType(defType),
+        valueType(valueType), isAttrGenerator(isAttrGenerator),
+        formatErrorIsFatal(formatErrorIsFatal) {
+    // Sort by occurrence in file.
+    llvm::sort(defRecords, [](llvm::Record *lhs, llvm::Record *rhs) {
+      return lhs->getID() < rhs->getID();
+    });
+  }
+
+  /// Emit the list of def type names.
+  void emitTypeDefList(ArrayRef<AttrOrTypeDef> defs);
+  /// Emit the code to dispatch between different defs during parsing/printing.
+  void emitParsePrintDispatch(ArrayRef<AttrOrTypeDef> defs);
+
+  /// The set of def records to emit.
+  std::vector<llvm::Record *> defRecords;
+  /// The attribute or type class to emit.
+  /// The stream to emit to.
+  raw_ostream &os;
+  /// The prefix of the tablegen def name, e.g. Attr or Type.
+  StringRef defType;
+  /// The C++ base value type of the def, e.g. Attribute or Type.
+  StringRef valueType;
+  /// Flag indicating if this generator is for Attributes. False if the
+  /// generator is for types.
+  bool isAttrGenerator;
+  /// Whether a failure in parsing the assembly format should be a fatal error.
+  bool formatErrorIsFatal;
+};
+
+/// A specialized generator for AttrDefs.
+struct AttrDefGenerator : public DefGenerator {
+  AttrDefGenerator(const llvm::RecordKeeper &records, raw_ostream &os,
+                   bool formatErrorIsFatal)
+      : DefGenerator(records.getAllDerivedDefinitionsIfDefined("AttrDef"), os,
+                     "Attr", "Attribute", /*isAttrGenerator=*/true,
+                     formatErrorIsFatal) {}
+};
+/// A specialized generator for TypeDefs.
+struct TypeDefGenerator : public DefGenerator {
+  TypeDefGenerator(const llvm::RecordKeeper &records, raw_ostream &os,
+                   bool formatErrorIsFatal)
+      : DefGenerator(records.getAllDerivedDefinitionsIfDefined("TypeDef"), os,
+                     "Type", "Type", /*isAttrGenerator=*/false,
+                     formatErrorIsFatal) {}
+};
+
 } // namespace tblgen
 } // namespace mlir
 
diff --git a/mlir/tools/mlir-tblgen/AttrOrTypeFormatGen.h b/mlir/include/mlir/TableGen/AttrOrTypeFormatGen.h
similarity index 91%
rename from mlir/tools/mlir-tblgen/AttrOrTypeFormatGen.h
rename to mlir/include/mlir/TableGen/AttrOrTypeFormatGen.h
index d4711532a79bb..8a3b38f7a1235 100644
--- a/mlir/tools/mlir-tblgen/AttrOrTypeFormatGen.h
+++ b/mlir/include/mlir/TableGen/AttrOrTypeFormatGen.h
@@ -18,7 +18,7 @@ class AttrOrTypeDef;
 /// Generate a parser and printer based on a custom assembly format for an
 /// attribute or type.
 void generateAttrOrTypeFormat(const AttrOrTypeDef &def, MethodBody &parser,
-                              MethodBody &printer);
+                              MethodBody &printer, bool formatErrorIsFatal);
 
 } // namespace tblgen
 } // namespace mlir
diff --git a/mlir/include/mlir/TableGen/ByteCodeGen.h b/mlir/include/mlir/TableGen/ByteCodeGen.h
new file mode 100644
index 0000000000000..4c3c89f1fd799
--- /dev/null
+++ b/mlir/include/mlir/TableGen/ByteCodeGen.h
@@ -0,0 +1,23 @@
+//===- ByteCodeGen.h - Generator info ---------------------------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef MLIR_TABLEGEN_BYTECODEGEN_H_
+#define MLIR_TABLEGEN_BYTECODEGEN_H_
+
+#include "mlir/Support/LLVM.h"
+#include "llvm/ADT/StringRef.h"
+#include "llvm/TableGen/Record.h"
+
+namespace mlir::tblgen {
+
+bool emitBCRW(const llvm::RecordKeeper &records, raw_ostream &os,
+              const std::string &selectedBcDialect);
+
+} // namespace mlir::tblgen
+
+#endif // MLIR_TABLEGEN_BYTECODEGEN_H_
diff --git a/mlir/include/mlir/TableGen/CAPIGen.h b/mlir/include/mlir/TableGen/CAPIGen.h
new file mode 100644
index 0000000000000..ea687aee35d60
--- /dev/null
+++ b/mlir/include/mlir/TableGen/CAPIGen.h
@@ -0,0 +1,25 @@
+//===- CAPIGen.h - Generator info -------------------------------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef MLIR_TABLEGEN_CAPIGEN_H_
+#define MLIR_TABLEGEN_CAPIGEN_H_
+
+#include "mlir/Support/LLVM.h"
+#include "llvm/ADT/StringRef.h"
+#include "llvm/TableGen/Record.h"
+
+namespace mlir::tblgen {
+
+bool emitCAPIHeader(const llvm::RecordKeeper &records, raw_ostream &os,
+                    std::string groupPrefix);
+bool emitCAPIImpl(const llvm::RecordKeeper &records, raw_ostream &os,
+                  std::string groupPrefix);
+
+} // namespace mlir::tblgen
+
+#endif // MLIR_TABLEGEN_CAPIGEN_H_
diff --git a/mlir/tools/mlir-tblgen/DialectGenUtilities.h b/mlir/include/mlir/TableGen/DialectGenUtilities.h
similarity index 57%
rename from mlir/tools/mlir-tblgen/DialectGenUtilities.h
rename to mlir/include/mlir/TableGen/DialectGenUtilities.h
index 979a9d67b4047..2ef3a3a157d54 100644
--- a/mlir/tools/mlir-tblgen/DialectGenUtilities.h
+++ b/mlir/include/mlir/TableGen/DialectGenUtilities.h
@@ -10,6 +10,8 @@
 #define MLIR_TOOLS_MLIRTBLGEN_DIALECTGENUTILITIES_H_
 
 #include "mlir/Support/LLVM.h"
+#include "llvm/Support/CommandLine.h"
+#include "llvm/TableGen/Record.h"
 
 namespace mlir {
 namespace tblgen {
@@ -17,7 +19,16 @@ class Dialect;
 
 /// Find the dialect selected by the user to generate for. Returns std::nullopt
 /// if no dialect was found, or if more than one potential dialect was found.
-std::optional<Dialect> findDialectToGenerate(ArrayRef<Dialect> dialects);
+std::optional<Dialect>
+findDialectToGenerate(ArrayRef<Dialect> dialects,
+                      const std::string &selectedDialect);
+bool emitDialectDecls(const llvm::RecordKeeper &recordKeeper, raw_ostream &os,
+                      const std::string &selectedDialect);
+bool emitDialectDefs(const llvm::RecordKeeper &recordKeeper, raw_ostream &os,
+                     const std::string &selectedDialect);
+bool emitDirectiveDecls(const llvm::RecordKeeper &recordKeeper,
+                        llvm::StringRef dialect, raw_ostream &os);
+
 } // namespace tblgen
 } // namespace mlir
 
diff --git a/mlir/tools/mlir-tblgen/DocGenUtilities.h b/mlir/include/mlir/TableGen/DocGenUtilities.h
similarity index 64%
rename from mlir/tools/mlir-tblgen/DocGenUtilities.h
rename to mlir/include/mlir/TableGen/DocGenUtilities.h
index dd1dbbe243911..90296062917bb 100644
--- a/mlir/tools/mlir-tblgen/DocGenUtilities.h
+++ b/mlir/include/mlir/TableGen/DocGenUtilities.h
@@ -15,6 +15,7 @@
 #define MLIR_TOOLS_MLIRTBLGEN_DOCGENUTILITIES_H_
 
 #include "llvm/ADT/StringRef.h"
+#include "llvm/TableGen/Record.h"
 
 namespace llvm {
 class raw_ostream;
@@ -39,6 +40,22 @@ void emitDescription(llvm::StringRef description, llvm::raw_ostream &os);
 void emitDescriptionComment(llvm::StringRef description, llvm::raw_ostream &os,
                             llvm::StringRef prefix = "");
 
+void emitAttrOrTypeDefDoc(const llvm::RecordKeeper &recordKeeper,
+                          llvm::raw_ostream &os,
+                          llvm::StringRef recordTypeName);
+
+void emitOpDoc(const llvm::RecordKeeper &recordKeeper, llvm::raw_ostream &os,
+               const std::string &emitOpDoc, bool allowHugoSpecificFeatures,
+               const std::string &opIncFilter, const std::string &opExcFilter);
+
+bool emitDialectDoc(const llvm::RecordKeeper &recordKeeper,
+                    llvm::raw_ostream &os, const std::string &selectedDialect,
+                    const std::string &opIncFilter,
+                    const std::string &opExcFilter,
+                    const std::string &stripPrefix,
+                    bool allowHugoSpecificFeatures);
+void emitDocs(const llvm::RecordKeeper &recordKeeper, llvm::raw_ostream &os);
+
 } // namespace tblgen
 } // namespace mlir
 
diff --git a/mlir/include/mlir/TableGen/EnumGen.h b/mlir/include/mlir/TableGen/EnumGen.h
new file mode 100644
index 0000000000000..a1b06c64fd367
--- /dev/null
+++ b/mlir/include/mlir/TableGen/EnumGen.h
@@ -0,0 +1,23 @@
+//===- EnumGen.h - Generator info -------------------------------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef MLIR_TABLEGEN_ENUMGEN_H_
+#define MLIR_TABLEGEN_ENUMGEN_H_
+
+#include "mlir/Support/LLVM.h"
+#include "llvm/ADT/StringRef.h"
+#include "llvm/TableGen/Record.h"
+
+namespace mlir::tblgen {
+
+bool emitEnumDecls(const llvm::RecordKeeper &recordKeeper, raw_ostream &os);
+bool emitEnumDefs(const llvm::RecordKeeper &recordKeeper, raw_ostream &os);
+
+} // namespace mlir::tblgen
+
+#endif // MLIR_TABLEGEN_ENUMGEN_H_
diff --git a/mlir/tools/mlir-tblgen/FormatGen.h b/mlir/include/mlir/TableGen/FormatGen.h
similarity index 99%
rename from mlir/tools/mlir-tblgen/FormatGen.h
rename to mlir/include/mlir/TableGen/FormatGen.h
index b061d4d8ea7f0..2a05414e90f29 100644
--- a/mlir/tools/mlir-tblgen/FormatGen.h
+++ b/mlir/include/mlir/TableGen/FormatGen.h
@@ -596,9 +596,6 @@ bool canFormatStringAsKeyword(StringRef value,
 bool isValidLiteral(StringRef value,
                     function_ref<void(Twine)> emitError = nullptr);
 
-/// Whether a failure in parsing the assembly format should be a fatal error.
-extern llvm::cl::opt<bool> formatErrorIsFatal;
-
 } // namespace tblgen
 } // namespace mlir
 
diff --git a/mlir/include/mlir/TableGen/LLVMGen.h b/mlir/include/mlir/TableGen/LLVMGen.h
new file mode 100644
index 0000000000000..1598b99cbecf3
--- /dev/null
+++ b/mlir/include/mlir/TableGen/LLVMGen.h
@@ -0,0 +1,36 @@
+//===- LLVMGen.h - Generator info -------------------------------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef MLIR_TABLEGEN_LLVMGEN_H_
+#define MLIR_TABLEGEN_LLVMGEN_H_
+
+#include "mlir/Support/LLVM.h"
+#include "llvm/ADT/StringRef.h"
+#include "llvm/TableGen/Record.h"
+
+namespace mlir::tblgen {
+
+bool emitLLVMBuilders(const llvm::RecordKeeper &recordKeeper, raw_ostream &os);
+bool emitLLVMOpMLIRBuilders(const llvm::RecordKeeper &recordKeeper,
+                            raw_ostream &os);
+bool emitLLVMIntrMLIRBuilders(const llvm::RecordKeeper &recordKeeper,
+                              raw_ostream &os);
+template <bool ConvertTo>
+bool emitLLVMEnumConversionDefs(const llvm::RecordKeeper &recordKeeper,
+                                raw_ostream &os);
+bool emitLLVMConvertibleIntrinsics(const llvm::RecordKeeper &recordKeeper,
+                                   raw_ostream &os);
+bool emitLLVMIntrinsics(const llvm::RecordKeeper &records,
+                        llvm::raw_ostream &os, const std::string &nameFilter,
+                        const std::string &accessGroupRegexp,
+                        const std::string &aliasAnalysisRegexp,
+                        const std::string &opBaseClass);
+
+} // namespace mlir::tblgen
+
+#endif // MLIR_TABLEGEN_LLVMGEN_H_
diff --git a/mlir/tools/mlir-tblgen/OpClass.h b/mlir/include/mlir/TableGen/OpClass.h
similarity index 100%
rename from mlir/tools/mlir-tblgen/OpClass.h
rename to mlir/include/mlir/TableGen/OpClass.h
diff --git a/mlir/tools/mlir-tblgen/OpFormatGen.h b/mlir/include/mlir/TableGen/OpFormatGen.h
similarity index 88%
rename from mlir/tools/mlir-tblgen/OpFormatGen.h
rename to mlir/include/mlir/TableGen/OpFormatGen.h
index 88dbc99d9f78e..fc5306031ebe6 100644
--- a/mlir/tools/mlir-tblgen/OpFormatGen.h
+++ b/mlir/include/mlir/TableGen/OpFormatGen.h
@@ -20,7 +20,8 @@ class OpClass;
 class Operator;
 
 // Generate the assembly format for the given operator.
-void generateOpFormat(const Operator &constOp, OpClass &opClass);
+void generateOpFormat(const Operator &constOp, OpClass &opClass,
+                      bool formatErrorIsFatal);
 
 } // namespace tblgen
 } // namespace mlir
diff --git a/mlir/tools/mlir-tblgen/OpGenHelpers.h b/mlir/include/mlir/TableGen/OpGenHelpers.h
similarity index 69%
rename from mlir/tools/mlir-tblgen/OpGenHelpers.h
rename to mlir/include/mlir/TableGen/OpGenHelpers.h
index 1b43d5d3ce3a7..51406f25325f8 100644
--- a/mlir/tools/mlir-tblgen/OpGenHelpers.h
+++ b/mlir/include/mlir/TableGen/OpGenHelpers.h
@@ -23,7 +23,9 @@ namespace tblgen {
 /// Returns all the op definitions filtered by the user. The filtering is via
 /// command-line option "op-include-regex" and "op-exclude-regex".
 std::vector<llvm::Record *>
-getRequestedOpDefinitions(const llvm::RecordKeeper &recordKeeper);
+getRequestedOpDefinitions(const llvm::RecordKeeper &recordKeeper,
+                          const std::string &opIncFilter,
+                          const std::string &opExcFilter);
 
 /// Checks whether `str` is a Python keyword or would shadow builtin function.
 /// Regenerate using python -c"print(set(sorted(__import__('keyword').kwlist)))"
@@ -31,7 +33,16 @@ bool isPythonReserved(llvm::StringRef str);
 
 /// Shard the op defintions into the number of shards set by "op-shard-count".
 void shardOpDefinitions(ArrayRef<llvm::Record *> defs,
-                        SmallVectorImpl<ArrayRef<llvm::Record *>> &shardedDefs);
+                        SmallVectorImpl<ArrayRef<llvm::Record *>> &shardedDefs,
+                        unsigned shardOpDefinitions);
+
+bool emitOpDecls(const llvm::RecordKeeper &recordKeeper, raw_ostream &os,
+                 const std::string &opIncFilter, const std::string &opExcFilter,
+                 unsigned opShardCount, bool formatErrorIsFatal);
+
+bool emitOpDefs(const llvm::RecordKeeper &recordKeeper, raw_ostream &os,
+                const std::string &opIncFilter, const std::string &opExcFilter,
+                unsigned opShardCount, bool formatErrorIsFatal);
 
 } // namespace tblgen
 } // namespace mlir
diff --git a/mlir/include/mlir/TableGen/OpInterfacesGen.h b/mlir/include/mlir/TableGen/OpInterfacesGen.h
new file mode 100644
index 0000000000000..f5d087941f5d6
--- /dev/null
+++ b/mlir/include/mlir/TableGen/OpInterfacesGen.h
@@ -0,0 +1,142 @@
+//===- OpInterfacesGen.h - MLIR operation generator helpers -----*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// This file defines helpers used in the op interface generators.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef MLIR_TOOLS_MLIRTBLGEN_OPINTERFACESGEN_H_
+#define MLIR_TOOLS_MLIRTBLGEN_OPINTERFACESGEN_H_
+
+#include "mlir/Support/LLVM.h"
+#include "mlir/TableGen/Format.h"
+#include "mlir/TableGen/GenInfo.h"
+#include "mlir/TableGen/Interfaces.h"
+#include "llvm/TableGen/Record.h"
+#include <vector>
+
+namespace mlir {
+namespace tblgen {
+
+template <typename GeneratorT>
+struct InterfaceGenRegistration {
+  InterfaceGenRegistration(StringRef genArg, StringRef genDesc)
+      : genDeclArg(("gen-" + genArg + "-interface-decls").str()),
+        genDefArg(("gen-" + genArg + "-interface-defs").str()),
+        genDocArg(("gen-" + genArg + "-interface-docs").str()),
+        genDeclDesc(("Generate " + genDesc + " interface declarations").str()),
+        genDefDesc(("Generate " + genDesc + " interface definitions").str()),
+        genDocDesc(("Generate " + genDesc + " interface documentation").str()),
+        genDecls(genDeclArg, genDeclDesc,
+                 [](const llvm::RecordKeeper &records, raw_ostream &os) {
+                   return GeneratorT(records, os).emitInterfaceDecls();
+                 }),
+        genDefs(genDefArg, genDefDesc,
+                [](const llvm::RecordKeeper &records, raw_ostream &os) {
+                  return GeneratorT(records, os).emitInterfaceDefs();
+                }),
+        genDocs(genDocArg, genDocDesc,
+                [](const llvm::RecordKeeper &records, raw_ostream &os) {
+                  return GeneratorT(records, os).emitInterfaceDocs();
+                }) {}
+
+  std::string genDeclArg, genDefArg, genDocArg;
+  std::string genDeclDesc, genDefDesc, genDocDesc;
+  mlir::GenRegistration genDecls, genDefs, genDocs;
+};
+
+/// This struct is the base generator used when processing tablegen interfaces.
+class InterfaceGenerator {
+public:
+  bool emitInterfaceDefs();
+  bool emitInterfaceDecls();
+  bool emitInterfaceDocs();
+
+protected:
+  InterfaceGenerator(std::vector<llvm::Record *> &&defs, raw_ostream &os)
+      : defs(std::move(defs)), os(os) {}
+
+  void emitConceptDecl(const Interface &interface);
+  void emitModelDecl(const Interface &interface);
+  void emitModelMethodsDef(const Interface &interface);
+  void emitTraitDecl(const Interface &interface, StringRef interfaceName,
+                     StringRef interfaceTraitsName);
+  void emitInterfaceDecl(const Interface &interface);
+
+  /// The set of interface records to emit.
+  std::vector<llvm::Record *> defs;
+  // The stream to emit to.
+  raw_ostream &os;
+  /// The C++ value type of the interface, e.g. Operation*.
+  StringRef valueType;
+  /// The C++ base interface type.
+  StringRef interfaceBaseType;
+  /// The name of the typename for the value template.
+  StringRef valueTemplate;
+  /// The name of the substituion variable for the value.
+  StringRef substVar;
+  /// The format context to use for methods.
+  tblgen::FmtContext nonStaticMethodFmt;
+  tblgen::FmtContext traitMethodFmt;
+  tblgen::FmtContext extraDeclsFmt;
+};
+
+std::vector<llvm::Record *>
+getAllInterfaceDefinitions(const llvm::RecordKeeper &recordKeeper,
+                           StringRef name);
+
+/// A specialized generator for attribute interfaces.
+struct AttrInterfaceGenerator : public InterfaceGenerator {
+  AttrInterfaceGenerator(const llvm::RecordKeeper &records, raw_ostream &os)
+      : InterfaceGenerator(getAllInterfaceDefinitions(records, "Attr"), os) {
+    valueType = "::mlir::...
[truncated]

@makslevental makslevental changed the title [mlir][tblgen] Expose all of MLIRTableGen as library [mlir][tblgen] Expose more of MLIRTableGen as library May 20, 2024
@joker-eph
Copy link
Collaborator

joker-eph commented May 20, 2024

We have to be careful here, because custom backends for ODS is something that I pushed back really hard from the beginning: the risk is that ODS loses it's aspect of being a clear spec (that is it is the language specification AND the backend) for dialect definitions and ultimately becomes just a "json" of losely defined (from a semantics point of view) constructions (ultimately you could even get to a point where each dialect would have its own backend).

So I'd like to better understand exactly what you're trying to enable here?

@makslevental
Copy link
Contributor Author

that is it is the language specification AND the backend

FWIW I'm fully bought into ODS as the canonical MLIR spec. So I don't intend on changing or influencing in the upstream direction because my whole goal is to assume a fixed canonical spec and develop from that.

Anyway the broad goal is simply to enable building/generating various things that would be deemed too experimental for upstream. The near-term thing is more of the C API (attribute builders, type builders, etc) which we've discussed (at least @jpienaar and I) for quite a long time and now I've carved out some time.

@jpienaar
Copy link
Member

There are two convos here, this change is trying to get mlir-tblgen in line with the other tools wrt where their implementation details live (the new lib/tools place was created after mlir-tblgen) and then a discussion on structuring.

I think we can treat these independent (the PR description makes it seem like its doing both at the same time rather than show potential future steps).

@joker-eph
Copy link
Collaborator

joker-eph commented May 20, 2024

There are two convos here, this change is trying to get mlir-tblgen in line with the other tools wrt where their implementation details live (the new lib/tools place was created after mlir-tblgen) and then a discussion on structuring.

I have been seing the current state as intentionally hiding the implementation (that is: it isn't a public library). My comment was aligned with this, and it's not clear how to treat these completely independently?
(other tools got refactored because of the motivation to expose some APIs publicly / to downstream)

@jpienaar
Copy link
Member

(other tools got refactored because of the motivation to expose some APIs publicly / to downstream)

I'm not sure that holds for mlir-lsp-server :)

We already have a list of APIs exposed for mlir-tblgen. This does expose more and I think valid question as to are too much exposed (I haven't looked yet) and what are the expectations around these. Especially as it is just generating code which is not done in too general a way.

But there is also a different question being asked here: if downstream users want to add new features here & experiment, should they just work, do all their dev and come have the conversation later? Esp if experimental it may not be desirable upstream but if fully fork downstream then incentive/cost of making improvements/moving parts up is low/high (resp.).

I think your guard rail here is that this should not be considered as invitation to make tools that add other semantics to the ops (I don't think upstream or downstream matters much here). Is that correct? The current set up doesn't stop downstream forks of the ODS code, I could see from a maintenance cost it dissuading, but given the speed at which these move, its not a high cost. So it seems to be more of a policy discussion.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

4 participants