|
12 | 12 |
|
13 | 13 | #include "llvm/TableGen/TableGenBackend.h" |
14 | 14 | #include "llvm/ADT/Twine.h" |
| 15 | +#include "llvm/Support/CommandLine.h" |
| 16 | +#include "llvm/Support/ManagedStatic.h" |
15 | 17 | #include "llvm/Support/Path.h" |
16 | 18 | #include "llvm/Support/raw_ostream.h" |
17 | 19 | #include <algorithm> |
18 | 20 | #include <cassert> |
19 | 21 | #include <cstddef> |
20 | 22 |
|
21 | 23 | using namespace llvm; |
| 24 | +using namespace TableGen::Emitter; |
22 | 25 |
|
23 | 26 | const size_t MAX_LINE_LEN = 80U; |
24 | 27 |
|
25 | | -namespace llvm::TableGen::Emitter { |
26 | | -ManagedStatic<cl::opt<FnT>, OptCreatorT> Action; |
27 | | -void *OptCreatorT::call() { |
28 | | - return new cl::opt<FnT>(cl::desc("Action to perform:")); |
| 28 | +// CommandLine options of class type are not directly supported with some |
| 29 | +// specific exceptions like std::string which are safe to copy. In our case, |
| 30 | +// the `FnT` function_ref object is also safe to copy. So provide a |
| 31 | +// specialization of `OptionValue` for `FnT` type that stores it as a copy. |
| 32 | +// This is essentially similar to OptionValue<std::string> specialization for |
| 33 | +// strings. |
| 34 | +template <> struct cl::OptionValue<FnT> final : cl::OptionValueCopy<FnT> { |
| 35 | + OptionValue() = default; |
| 36 | + |
| 37 | + OptionValue(const FnT &V) { this->setValue(V); } |
| 38 | + |
| 39 | + OptionValue<FnT> &operator=(const FnT &V) { |
| 40 | + setValue(V); |
| 41 | + return *this; |
| 42 | + } |
| 43 | +}; |
| 44 | + |
| 45 | +namespace { |
| 46 | +struct OptCreatorT { |
| 47 | + static void *call() { |
| 48 | + return new cl::opt<FnT>(cl::desc("Action to perform:")); |
| 49 | + } |
| 50 | +}; |
| 51 | +} // namespace |
| 52 | + |
| 53 | +static ManagedStatic<cl::opt<FnT>, OptCreatorT> CallbackFunction; |
| 54 | + |
| 55 | +Opt::Opt(StringRef Name, FnT CB, StringRef Desc, bool ByDefault) { |
| 56 | + if (ByDefault) |
| 57 | + CallbackFunction->setInitialValue(CB); |
| 58 | + CallbackFunction->getParser().addLiteralOption(Name, CB, Desc); |
| 59 | +} |
| 60 | + |
| 61 | +/// Apply callback specified on the command line. Returns true if no callback |
| 62 | +/// was applied. |
| 63 | +bool llvm::TableGen::Emitter::ApplyCallback(RecordKeeper &Records, |
| 64 | + raw_ostream &OS) { |
| 65 | + FnT Fn = CallbackFunction->getValue(); |
| 66 | + if (!Fn) |
| 67 | + return true; |
| 68 | + Fn(Records, OS); |
| 69 | + return false; |
29 | 70 | } |
30 | | -} // namespace llvm::TableGen::Emitter |
31 | 71 |
|
32 | 72 | static void printLine(raw_ostream &OS, const Twine &Prefix, char Fill, |
33 | 73 | StringRef Suffix) { |
@@ -59,7 +99,7 @@ void llvm::emitSourceFileHeader(StringRef Desc, raw_ostream &OS, |
59 | 99 | printLine(OS, Prefix + "Automatically generated file, do not edit!", ' ', |
60 | 100 | Suffix); |
61 | 101 |
|
62 | | - // Print the filename of source file |
| 102 | + // Print the filename of source file. |
63 | 103 | if (!Record.getInputFilename().empty()) |
64 | 104 | printLine( |
65 | 105 | OS, Prefix + "From: " + sys::path::filename(Record.getInputFilename()), |
|
0 commit comments