[llvm] 4178ef4 - TableGen: Introduce `llvm::TableGen::Emitter` to register backends

NAKAMURA Takumi via llvm-commits llvm-commits at lists.llvm.org
Tue Mar 21 00:22:24 PDT 2023


Author: NAKAMURA Takumi
Date: 2023-03-21T16:21:27+09:00
New Revision: 4178ef43b2f12171639e3ef2bf02e5b7efd34688

URL: https://github.com/llvm/llvm-project/commit/4178ef43b2f12171639e3ef2bf02e5b7efd34688
DIFF: https://github.com/llvm/llvm-project/commit/4178ef43b2f12171639e3ef2bf02e5b7efd34688.diff

LOG: TableGen: Introduce `llvm::TableGen::Emitter` to register backends

`Opt(flag, func, desc)` registers an option into `Action`.

`OptClass<EmitterC>` is also available if `EmitterC(RK).run(OS)` is capable.

`Action` is defined as `ManagedStatic<cl::opt>` to guarantee to be created
when each registration of emitter is invoked.

`llvm::TableGenMain(argv0, MainFn)` invokes `Action` instead of `MainFn`

Differential Revision: https://reviews.llvm.org/D144351

Added: 
    

Modified: 
    llvm/docs/TableGen/BackGuide.rst
    llvm/include/llvm/TableGen/TableGenBackend.h
    llvm/lib/TableGen/Main.cpp
    llvm/lib/TableGen/TableGenBackend.cpp
    llvm/lib/TableGen/TableGenBackendSkeleton.cpp

Removed: 
    


################################################################################
diff  --git a/llvm/docs/TableGen/BackGuide.rst b/llvm/docs/TableGen/BackGuide.rst
index 7da39bf0d5713..e1413c1c73a79 100644
--- a/llvm/docs/TableGen/BackGuide.rst
+++ b/llvm/docs/TableGen/BackGuide.rst
@@ -452,20 +452,6 @@ The following steps are required to create a new backend for TableGen.
    one instance for Clang and another for LLVM. Or you may be building
    your own instance.
 
-#. Modify the selected ``tablegen.cpp`` to include your new backend.
-
-  a. Add the name to the enumerated type ``ActionType``.
-
-  #. Add a keyword to the ``ActionType`` command option using the
-     ``clEnumValN()`` function.
-
-  #. Add a case to the ``switch`` statement in the *xxx*\ ``TableGenMain()``
-     function. It should invoke the "main function" of your backend, which
-     in this case, according to convention, is named ``EmitAddressModes``.
-
-5. Add a declaration of your "main function" to the corresponding
-   ``TableGenBackends.h`` header file.
-
 #. Add your backend C++ file to the appropriate ``CMakeLists.txt`` file so
    that it will be built.
 
@@ -498,11 +484,14 @@ unit for writing a new TableGen backend. Here are a few notes on the file.
 * The ``run`` function should use the ``emitSourceFileHeader`` helper function
   to include a standard header in the emitted file.
 
-* The only function in the ``llvm`` namespace is the backend "main function."
-  In this example, it is named ``EmitAddressModes``. It creates an instance
-  of the ``AddressModesEmitter`` class, passing the ``RecordKeeper``
-  instance, then invokes the ``run`` function, passing the ``raw_ostream``
-  instance.
+* Register the class or the function as the command line option
+  with ``llvm/TableGen/TableGenBackend.h``.
+
+  * Use ``llvm::TableGen::Emitter::OptClass<AddressModesEmitter>``
+    if the class has the constructor ``(RK)`` and
+    the method ``run(OS)``.
+
+  * Otherwise, use ``llvm::TableGen::Emitter::Opt``.
 
 All the examples in the remainder of this document will assume the naming
 conventions used in the skeleton file.

diff  --git a/llvm/include/llvm/TableGen/TableGenBackend.h b/llvm/include/llvm/TableGen/TableGenBackend.h
index a426e42175784..09e60cb3c203d 100644
--- a/llvm/include/llvm/TableGen/TableGenBackend.h
+++ b/llvm/include/llvm/TableGen/TableGenBackend.h
@@ -13,11 +13,41 @@
 #ifndef LLVM_TABLEGEN_TABLEGENBACKEND_H
 #define LLVM_TABLEGEN_TABLEGENBACKEND_H
 
+#include "llvm/ADT/StringRef.h"
+#include "llvm/Support/CommandLine.h"
+#include "llvm/Support/ManagedStatic.h"
+
 namespace llvm {
 
-class StringRef;
+class RecordKeeper;
 class raw_ostream;
 
+namespace TableGen::Emitter {
+using FnT = void (*)(RecordKeeper &Records, raw_ostream &OS);
+
+struct OptCreatorT {
+  static void *call();
+};
+
+extern ManagedStatic<cl::opt<FnT>, OptCreatorT> Action;
+
+struct Opt {
+  Opt(StringRef Name, FnT CB, StringRef Desc, bool ByDefault = false) {
+    if (ByDefault)
+      Action->setInitialValue(CB);
+    Action->getParser().addLiteralOption(Name, CB, Desc);
+  }
+};
+
+template <class EmitterC> class OptClass : Opt {
+  static void run(RecordKeeper &RK, raw_ostream &OS) { EmitterC(RK).run(OS); }
+
+public:
+  OptClass(StringRef Name, StringRef Desc) : Opt(Name, run, Desc) {}
+};
+
+} // namespace TableGen::Emitter
+
 /// emitSourceFileHeader - Output an LLVM style file header to the specified
 /// raw_ostream.
 void emitSourceFileHeader(StringRef Desc, raw_ostream &OS);

diff  --git a/llvm/lib/TableGen/Main.cpp b/llvm/lib/TableGen/Main.cpp
index ee72b4b2e9e74..9aee1f8fecd2f 100644
--- a/llvm/lib/TableGen/Main.cpp
+++ b/llvm/lib/TableGen/Main.cpp
@@ -29,6 +29,7 @@
 #include "llvm/Support/raw_ostream.h"
 #include "llvm/TableGen/Error.h"
 #include "llvm/TableGen/Record.h"
+#include "llvm/TableGen/TableGenBackend.h"
 #include <memory>
 #include <string>
 #include <system_error>
@@ -131,7 +132,10 @@ int llvm::TableGenMain(const char *argv0,
   std::string OutString;
   raw_string_ostream Out(OutString);
   unsigned status = 0;
-  if (MainFn)
+  TableGen::Emitter::FnT ActionFn = TableGen::Emitter::Action->getValue();
+  if (ActionFn)
+    ActionFn(Records, Out);
+  else if (MainFn)
     status = MainFn(Out, Records);
   else
     return 1;

diff  --git a/llvm/lib/TableGen/TableGenBackend.cpp b/llvm/lib/TableGen/TableGenBackend.cpp
index 252f126d2d00f..135ec643bc3a7 100644
--- a/llvm/lib/TableGen/TableGenBackend.cpp
+++ b/llvm/lib/TableGen/TableGenBackend.cpp
@@ -13,12 +13,21 @@
 #include "llvm/TableGen/TableGenBackend.h"
 #include "llvm/ADT/Twine.h"
 #include "llvm/Support/raw_ostream.h"
+#include <algorithm>
 #include <cassert>
+#include <cstddef>
 
 using namespace llvm;
 
 const size_t MAX_LINE_LEN = 80U;
 
+namespace llvm::TableGen::Emitter {
+ManagedStatic<cl::opt<FnT>, OptCreatorT> Action;
+void *OptCreatorT::call() {
+  return new cl::opt<FnT>(cl::desc("Action to perform:"));
+}
+} // namespace llvm::TableGen::Emitter
+
 static void printLine(raw_ostream &OS, const Twine &Prefix, char Fill,
                       StringRef Suffix) {
   size_t Pos = (size_t)OS.tell();

diff  --git a/llvm/lib/TableGen/TableGenBackendSkeleton.cpp b/llvm/lib/TableGen/TableGenBackendSkeleton.cpp
index 0ba00c8d8ab1c..2fde4a66727b9 100644
--- a/llvm/lib/TableGen/TableGenBackendSkeleton.cpp
+++ b/llvm/lib/TableGen/TableGenBackendSkeleton.cpp
@@ -46,14 +46,20 @@ void SkeletonEmitter::run(raw_ostream &OS) {
   (void)Records; // To suppress unused variable warning; remove on use.
 }
 
-namespace llvm {
+// Choose either option A or B.
 
-// The only thing that should be in the llvm namespace is the
-// emitter entry point function.
+//===----------------------------------------------------------------------===//
+// Option A: Register the backed as class <SkeletonEmitter>
+static TableGen::Emitter::OptClass<SkeletonEmitter>
+    X("gen-skeleton-class", "Generate example skeleton class");
 
-void EmitSkeleton(RecordKeeper &RK, raw_ostream &OS) {
+//===----------------------------------------------------------------------===//
+// Option B: Register "EmitSkeleton" directly
+// The emitter entry may be private scope.
+static void EmitSkeleton(RecordKeeper &RK, raw_ostream &OS) {
   // Instantiate the emitter class and invoke run().
   SkeletonEmitter(RK).run(OS);
 }
 
-} // namespace llvm
+static TableGen::Emitter::Opt Y("gen-skeleton-entry", EmitSkeleton,
+                                "Generate example skeleton entry");


        


More information about the llvm-commits mailing list