diff --git a/llvm/docs/TableGen/BackGuide.rst b/llvm/docs/TableGen/BackGuide.rst --- a/llvm/docs/TableGen/BackGuide.rst +++ b/llvm/docs/TableGen/BackGuide.rst @@ -452,20 +452,6 @@ 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 @@ * 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`` + 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 --- 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, 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 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 --- 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 #include #include @@ -131,7 +132,10 @@ 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 --- 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 #include +#include using namespace llvm; const size_t MAX_LINE_LEN = 80U; +namespace llvm::TableGen::Emitter { +ManagedStatic, OptCreatorT> Action; +void *OptCreatorT::call() { + return new cl::opt(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 --- a/llvm/lib/TableGen/TableGenBackendSkeleton.cpp +++ b/llvm/lib/TableGen/TableGenBackendSkeleton.cpp @@ -46,14 +46,20 @@ (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 +static TableGen::Emitter::OptClass + 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");