[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