diff --git a/llvm/docs/TableGen/index.rst b/llvm/docs/TableGen/index.rst index e334b2e4b23ac..0f1190c54627a 100644 --- a/llvm/docs/TableGen/index.rst +++ b/llvm/docs/TableGen/index.rst @@ -55,6 +55,11 @@ TableGen runs just like any other LLVM tool. The first (optional) argument specifies the file to read. If a filename is not specified, ``llvm-tblgen`` reads from standard input. +The ``-o`` option specifies the output file or ``-`` to output to +stdout. Where TableGen produces multiple output files, the option +specifies the name of the main output file, which also works as the +name prefix for other output files. + To be useful, one of the `backends`_ must be used. These backends are selectable on the command line (type '``llvm-tblgen -help``' for a list). For example, to get a list of all of the definitions that subclass a particular type diff --git a/llvm/include/llvm/TableGen/Main.h b/llvm/include/llvm/TableGen/Main.h index 5f68be188de78..bafce3a463acc 100644 --- a/llvm/include/llvm/TableGen/Main.h +++ b/llvm/include/llvm/TableGen/Main.h @@ -15,19 +15,34 @@ #include "llvm/Support/CommandLine.h" #include +#include namespace llvm { class raw_ostream; class RecordKeeper; -/// Perform the action using Records, and write output to OS. +struct TableGenOutputFiles { + std::string MainFile; + + // Translates additional output file names to their contents. + std::map AdditionalFiles; +}; + /// Returns true on error, false otherwise. using TableGenMainFn = bool(raw_ostream &OS, const RecordKeeper &Records); +/// Perform the action using Records, and store output in OutFiles. +/// Returns true on error, false otherwise. +using MultiFileTableGenMainFn = bool(TableGenOutputFiles &OutFiles, + const RecordKeeper &Records); + int TableGenMain(const char *argv0, std::function MainFn = nullptr); +int TableGenMain(const char *argv0, + std::function MainFn = nullptr); + /// Controls emitting large character arrays as strings or character arrays. /// Typically set to false when building with MSVC. extern cl::opt EmitLongStrLiterals; diff --git a/llvm/include/llvm/TableGen/TableGenBackend.h b/llvm/include/llvm/TableGen/TableGenBackend.h index 7cb540f66ec70..8450a02eb19e7 100644 --- a/llvm/include/llvm/TableGen/TableGenBackend.h +++ b/llvm/include/llvm/TableGen/TableGenBackend.h @@ -15,6 +15,7 @@ #include "llvm/ADT/STLFunctionalExtras.h" #include "llvm/ADT/StringRef.h" +#include "llvm/TableGen/Main.h" #include "llvm/TableGen/Record.h" namespace llvm { @@ -23,7 +24,27 @@ class RecordKeeper; class raw_ostream; namespace TableGen::Emitter { -using FnT = function_ref; + +/// Represents the emitting function. Can produce a single or multple output +/// files. +struct FnT { + using SingleFileGeneratorType = void(const RecordKeeper &Records, + raw_ostream &OS); + using MultiFileGeneratorType = TableGenOutputFiles( + StringRef FilenamePrefix, const RecordKeeper &Records); + + SingleFileGeneratorType *SingleFileGenerator = nullptr; + MultiFileGeneratorType *MultiFileGenerator = nullptr; + + FnT() = default; + FnT(SingleFileGeneratorType *Gen) : SingleFileGenerator(Gen) {} + FnT(MultiFileGeneratorType *Gen) : MultiFileGenerator(Gen) {} + + bool operator==(const FnT &Other) const { + return SingleFileGenerator == Other.SingleFileGenerator && + MultiFileGenerator == Other.MultiFileGenerator; + } +}; /// Creating an `Opt` object registers the command line option \p Name with /// TableGen backend and associates the callback \p CB with that option. If @@ -36,17 +57,33 @@ struct Opt { /// Convienence wrapper around `Opt` that registers `EmitterClass::run` as the /// callback. template class OptClass : Opt { - static void run(const RecordKeeper &RK, raw_ostream &OS) { + static TableGenOutputFiles run(StringRef /*FilenamePrefix*/, + const RecordKeeper &RK) { + std::string S; + raw_string_ostream OS(S); EmitterC(RK).run(OS); + return {S, {}}; } public: OptClass(StringRef Name, StringRef Desc) : Opt(Name, run, Desc) {} }; +/// A version of the wrapper for backends emitting multiple files. +template class MultiFileOptClass : Opt { + static TableGenOutputFiles run(StringRef FilenamePrefix, + const RecordKeeper &RK) { + return EmitterC(RK).run(FilenamePrefix); + } + +public: + MultiFileOptClass(StringRef Name, StringRef Desc) : Opt(Name, run, Desc) {} +}; + /// Apply callback for any command line option registered above. Returns false /// is no callback was applied. -bool ApplyCallback(const RecordKeeper &Records, raw_ostream &OS); +bool ApplyCallback(const RecordKeeper &Records, TableGenOutputFiles &OutFiles, + StringRef FilenamePrefix); } // namespace TableGen::Emitter diff --git a/llvm/lib/TableGen/Main.cpp b/llvm/lib/TableGen/Main.cpp index b1024a8d39e00..c3869c3fb9a5a 100644 --- a/llvm/lib/TableGen/Main.cpp +++ b/llvm/lib/TableGen/Main.cpp @@ -23,6 +23,7 @@ #include "llvm/Support/ErrorOr.h" #include "llvm/Support/FileSystem.h" #include "llvm/Support/MemoryBuffer.h" +#include "llvm/Support/Path.h" #include "llvm/Support/SMLoc.h" #include "llvm/Support/SourceMgr.h" #include "llvm/Support/ToolOutputFile.h" @@ -104,8 +105,30 @@ static int createDependencyFile(const TGParser &Parser, const char *argv0) { return 0; } +static int WriteOutput(const TGParser &Parser, const char *argv0, + StringRef Filename, StringRef Content) { + if (WriteIfChanged) { + // Only updates the real output file if there are any differences. + // This prevents recompilation of all the files depending on it if there + // aren't any. + if (auto ExistingOrErr = MemoryBuffer::getFile(Filename, /*IsText=*/true)) + if (std::move(ExistingOrErr.get())->getBuffer() == Content) + return 0; + } + std::error_code EC; + ToolOutputFile OutFile(Filename, EC, sys::fs::OF_Text); + if (EC) + return reportError(argv0, "error opening " + Filename + ": " + + EC.message() + "\n"); + OutFile.os() << Content; + if (ErrorsPrinted == 0) + OutFile.keep(); + + return 0; +} + int llvm::TableGenMain(const char *argv0, - std::function MainFn) { + std::function MainFn) { RecordKeeper Records; TGTimer &Timer = Records.getTimer(); @@ -144,13 +167,14 @@ int llvm::TableGenMain(const char *argv0, // Write output to memory. Timer.startBackendTimer("Backend overall"); - std::string OutString; - raw_string_ostream Out(OutString); + SmallString<128> FilenamePrefix(OutputFilename); + sys::path::replace_extension(FilenamePrefix, ""); + TableGenOutputFiles OutFiles; unsigned status = 0; // ApplyCallback will return true if it did not apply any callback. In that // case, attempt to apply the MainFn. - if (TableGen::Emitter::ApplyCallback(Records, Out)) - status = MainFn ? MainFn(Out, Records) : 1; + if (TableGen::Emitter::ApplyCallback(Records, OutFiles, FilenamePrefix)) + status = MainFn ? MainFn(OutFiles, Records) : 1; Timer.stopBackendTimer(); if (status) return 1; @@ -165,25 +189,17 @@ int llvm::TableGenMain(const char *argv0, } Timer.startTimer("Write output"); - bool WriteFile = true; - if (WriteIfChanged) { - // Only updates the real output file if there are any differences. - // This prevents recompilation of all the files depending on it if there - // aren't any. - if (auto ExistingOrErr = - MemoryBuffer::getFile(OutputFilename, /*IsText=*/true)) - if (std::move(ExistingOrErr.get())->getBuffer() == OutString) - WriteFile = false; - } - if (WriteFile) { - std::error_code EC; - ToolOutputFile OutFile(OutputFilename, EC, sys::fs::OF_Text); - if (EC) - return reportError(argv0, "error opening " + OutputFilename + ": " + - EC.message() + "\n"); - OutFile.os() << OutString; - if (ErrorsPrinted == 0) - OutFile.keep(); + if (int Ret = WriteOutput(Parser, argv0, OutputFilename, OutFiles.MainFile)) + return Ret; + for (auto [Suffix, Content] : OutFiles.AdditionalFiles) { + SmallString<128> Filename(OutputFilename); + // TODO: Format using the split-file convention when writing to stdout? + if (Filename != "-") { + Filename = FilenamePrefix; + Filename.append(Suffix); + } + if (int Ret = WriteOutput(Parser, argv0, Filename, Content)) + return Ret; } Timer.stopTimer(); @@ -193,3 +209,15 @@ int llvm::TableGenMain(const char *argv0, return reportError(argv0, Twine(ErrorsPrinted) + " errors.\n"); return 0; } + +int llvm::TableGenMain(const char *argv0, + std::function MainFn) { + return TableGenMain(argv0, [&MainFn](TableGenOutputFiles &OutFiles, + const RecordKeeper &Records) { + std::string S; + raw_string_ostream OS(S); + int Res = MainFn(OS, Records); + OutFiles = {S, {}}; + return Res; + }); +} diff --git a/llvm/lib/TableGen/TableGenBackend.cpp b/llvm/lib/TableGen/TableGenBackend.cpp index 153ca39cfba08..116c3fcca8bd8 100644 --- a/llvm/lib/TableGen/TableGenBackend.cpp +++ b/llvm/lib/TableGen/TableGenBackend.cpp @@ -61,12 +61,21 @@ Opt::Opt(StringRef Name, FnT CB, StringRef Desc, bool ByDefault) { /// Apply callback specified on the command line. Returns true if no callback /// was applied. bool llvm::TableGen::Emitter::ApplyCallback(const RecordKeeper &Records, - raw_ostream &OS) { + TableGenOutputFiles &OutFiles, + StringRef FilenamePrefix) { FnT Fn = CallbackFunction->getValue(); - if (!Fn) - return true; - Fn(Records, OS); - return false; + if (Fn.SingleFileGenerator) { + std::string S; + raw_string_ostream OS(S); + Fn.SingleFileGenerator(Records, OS); + OutFiles = {S, {}}; + return false; + } + if (Fn.MultiFileGenerator) { + OutFiles = Fn.MultiFileGenerator(FilenamePrefix, Records); + return false; + } + return true; } static void printLine(raw_ostream &OS, const Twine &Prefix, char Fill, diff --git a/llvm/lib/Target/AMDGPU/SIFoldOperands.cpp b/llvm/lib/Target/AMDGPU/SIFoldOperands.cpp index 2c00e23d113cb..a4faf9ae7376e 100644 --- a/llvm/lib/Target/AMDGPU/SIFoldOperands.cpp +++ b/llvm/lib/Target/AMDGPU/SIFoldOperands.cpp @@ -1358,7 +1358,7 @@ void SIFoldOperandsImpl::foldOperand( // Remove this if 16-bit SGPRs (i.e. SGPR_LO16) are added to the // VS_16RegClass // - // Excerpt from AMDGPUGenRegisterInfo.inc + // Excerpt from AMDGPUGenRegisterInfoEnums.inc // NoSubRegister, //0 // hi16, // 1 // lo16, // 2 diff --git a/llvm/test/TableGen/ArtificialSubregs.td b/llvm/test/TableGen/ArtificialSubregs.td index b8d5686dee51b..e1e83e504137e 100644 --- a/llvm/test/TableGen/ArtificialSubregs.td +++ b/llvm/test/TableGen/ArtificialSubregs.td @@ -1,4 +1,4 @@ -// RUN: llvm-tblgen -gen-register-info -register-info-debug -I %p/../../include %s -o /dev/null 2>&1 | FileCheck %s --check-prefix=CHECK +// RUN: llvm-tblgen -gen-register-info -register-info-debug -I %p/../../include %s -o - 2>&1 >/dev/null | FileCheck %s --check-prefix=CHECK include "llvm/Target/Target.td" // This file tests that when using `isArtificial` for subregisters in diff --git a/llvm/test/TableGen/ConcatenatedSubregs.td b/llvm/test/TableGen/ConcatenatedSubregs.td index ea4e7f01a2e2d..8b0bd2a691cc8 100644 --- a/llvm/test/TableGen/ConcatenatedSubregs.td +++ b/llvm/test/TableGen/ConcatenatedSubregs.td @@ -1,4 +1,4 @@ -// RUN: llvm-tblgen -gen-register-info -register-info-debug -I %p/../../include %s -o /dev/null 2>&1 | FileCheck %s +// RUN: llvm-tblgen -gen-register-info -register-info-debug -I %p/../../include %s -o - 2>&1 >/dev/null | FileCheck %s // Checks that tablegen correctly and completely infers subregister relations. include "llvm/Target/Target.td" diff --git a/llvm/test/TableGen/HwModeBitSet.td b/llvm/test/TableGen/HwModeBitSet.td index 869b09b3c6316..70cf789e4a9c7 100644 --- a/llvm/test/TableGen/HwModeBitSet.td +++ b/llvm/test/TableGen/HwModeBitSet.td @@ -1,5 +1,5 @@ // This is to test the scenario where different HwMode attributes coexist. -// RUN: llvm-tblgen -gen-register-info -register-info-debug -I %p/../../include %s -o /dev/null 2>&1 | FileCheck %s --check-prefix=CHECK-REG +// RUN: llvm-tblgen -gen-register-info -register-info-debug -I %p/../../include %s -o - 2>&1 >/dev/null | FileCheck %s --check-prefix=CHECK-REG // RUN: llvm-tblgen -gen-subtarget -I %p/../../include %s -o - 2>&1 | FileCheck %s --check-prefix=CHECK-SUBTARGET diff --git a/llvm/test/TableGen/HwModeSubRegs.td b/llvm/test/TableGen/HwModeSubRegs.td index 31a569fcdaad1..c71e963fca13b 100644 --- a/llvm/test/TableGen/HwModeSubRegs.td +++ b/llvm/test/TableGen/HwModeSubRegs.td @@ -1,4 +1,4 @@ -// RUN: llvm-tblgen -gen-register-info -register-info-debug -I %p/../../include %s -o /dev/null 2>&1 | FileCheck %s +// RUN: llvm-tblgen -gen-register-info -register-info-debug -I %p/../../include %s -o - 2>&1 >/dev/null | FileCheck %s include "llvm/Target/Target.td" def HasFeat : Predicate<"Subtarget->hasFeat()">; diff --git a/llvm/test/TableGen/SubRegsAndAliases.td b/llvm/test/TableGen/SubRegsAndAliases.td index ec450f8945b49..bd062a7ab6f53 100644 --- a/llvm/test/TableGen/SubRegsAndAliases.td +++ b/llvm/test/TableGen/SubRegsAndAliases.td @@ -1,4 +1,4 @@ -// RUN: llvm-tblgen -gen-register-info -register-info-debug -I %p/../../include %s -o /dev/null 2>&1 | FileCheck %s +// RUN: llvm-tblgen -gen-register-info -register-info-debug -I %p/../../include %s -o - 2>&1 >/dev/null | FileCheck %s include "llvm/Target/Target.td" def TestTarget : Target; diff --git a/llvm/utils/TableGen/Basic/TableGen.cpp b/llvm/utils/TableGen/Basic/TableGen.cpp index edb7791500699..b79ae93dab4f7 100644 --- a/llvm/utils/TableGen/Basic/TableGen.cpp +++ b/llvm/utils/TableGen/Basic/TableGen.cpp @@ -60,7 +60,9 @@ static TableGen::Emitter::Opt X[] = { true}, {"print-detailed-records", EmitDetailedRecords, "Print full details of all records to stdout"}, - {"null-backend", [](const RecordKeeper &Records, raw_ostream &OS) {}, + {"null-backend", + TableGen::Emitter::FnT( + [](const RecordKeeper &Records, raw_ostream &OS) {}), "Do nothing after parsing (useful for timing)"}, {"dump-json", EmitJSON, "Dump all records as machine-readable JSON"}, {"print-enums", printEnums, "Print enum values for a class"}, @@ -71,7 +73,8 @@ int tblgen_main(int argc, char **argv) { InitLLVM X(argc, argv); cl::ParseCommandLineOptions(argc, argv); - return TableGenMain(argv[0]); + std::function MainFn = nullptr; + return TableGenMain(argv[0], MainFn); } #ifndef __has_feature diff --git a/llvm/utils/TableGen/RegisterInfoEmitter.cpp b/llvm/utils/TableGen/RegisterInfoEmitter.cpp index eac908d9bc2bd..ef7b13e8940f8 100644 --- a/llvm/utils/TableGen/RegisterInfoEmitter.cpp +++ b/llvm/utils/TableGen/RegisterInfoEmitter.cpp @@ -68,19 +68,22 @@ class RegisterInfoEmitter { } // runEnums - Print out enum values for all of the registers. - void runEnums(raw_ostream &OS); + void runEnums(raw_ostream &OS, raw_ostream &MainOS, StringRef FilenamePrefix); // runMCDesc - Print out MC register descriptions. - void runMCDesc(raw_ostream &OS); + void runMCDesc(raw_ostream &OS, raw_ostream &MainOS, + StringRef FilenamePrefix); // runTargetHeader - Emit a header fragment for the register info emitter. - void runTargetHeader(raw_ostream &OS); + void runTargetHeader(raw_ostream &OS, raw_ostream &MainOS, + StringRef FilenamePrefix); // runTargetDesc - Output the target register and register file descriptions. - void runTargetDesc(raw_ostream &OS); + void runTargetDesc(raw_ostream &OS, raw_ostream &MainOS, + StringRef FilenamePrefix); // run - Output the register file description. - void run(raw_ostream &OS); + TableGenOutputFiles run(StringRef FilenamePrefix); void debugDump(raw_ostream &OS); @@ -97,8 +100,19 @@ class RegisterInfoEmitter { } // end anonymous namespace +static void emitInclude(StringRef FilenamePrefix, StringRef IncludeFile, + StringRef GuardMacro, raw_ostream &OS) { + OS << "#ifdef " << GuardMacro << '\n'; + OS << "#undef " << GuardMacro << '\n'; + OS << "#include \"" << FilenamePrefix << IncludeFile << "\"\n"; + OS << "#endif\n\n"; +} + // runEnums - Print out enum values for all of the registers. -void RegisterInfoEmitter::runEnums(raw_ostream &OS) { +void RegisterInfoEmitter::runEnums(raw_ostream &OS, raw_ostream &MainOS, + StringRef FilenamePrefix) { + emitInclude(FilenamePrefix, "Enums.inc", "GET_REGINFO_ENUM", MainOS); + const auto &Registers = RegBank.getRegisters(); // Register enums are stored as uint16_t in the tables. Make sure we'll fit. @@ -108,9 +122,6 @@ void RegisterInfoEmitter::runEnums(raw_ostream &OS) { emitSourceFileHeader("Target Register Enum Values", OS); - OS << "\n#ifdef GET_REGINFO_ENUM\n"; - OS << "#undef GET_REGINFO_ENUM\n\n"; - OS << "namespace llvm {\n\n"; OS << "class MCRegisterClass;\n" @@ -194,7 +205,6 @@ void RegisterInfoEmitter::runEnums(raw_ostream &OS) { OS << '\n'; OS << "} // end namespace llvm\n\n"; - OS << "#endif // GET_REGINFO_ENUM\n\n"; } static void printInt(raw_ostream &OS, int Val) { OS << Val; } @@ -902,11 +912,11 @@ void RegisterInfoEmitter::emitComposeSubRegIndexLaneMask(raw_ostream &OS, // // runMCDesc - Print out MC register descriptions. // -void RegisterInfoEmitter::runMCDesc(raw_ostream &OS) { - emitSourceFileHeader("MC Register Information", OS); +void RegisterInfoEmitter::runMCDesc(raw_ostream &OS, raw_ostream &MainOS, + StringRef FilenamePrefix) { + emitInclude(FilenamePrefix, "MCDesc.inc", "GET_REGINFO_MC_DESC", MainOS); - OS << "\n#ifdef GET_REGINFO_MC_DESC\n"; - OS << "#undef GET_REGINFO_MC_DESC\n\n"; + emitSourceFileHeader("MC Register Information", OS); const auto &Regs = RegBank.getRegisters(); @@ -1131,14 +1141,13 @@ void RegisterInfoEmitter::runMCDesc(raw_ostream &OS) { OS << "}\n\n"; OS << "} // end namespace llvm\n\n"; - OS << "#endif // GET_REGINFO_MC_DESC\n\n"; } -void RegisterInfoEmitter::runTargetHeader(raw_ostream &OS) { - emitSourceFileHeader("Register Information Header Fragment", OS); +void RegisterInfoEmitter::runTargetHeader(raw_ostream &OS, raw_ostream &MainOS, + StringRef FilenamePrefix) { + emitInclude(FilenamePrefix, "Header.inc", "GET_REGINFO_HEADER", MainOS); - OS << "\n#ifdef GET_REGINFO_HEADER\n"; - OS << "#undef GET_REGINFO_HEADER\n\n"; + emitSourceFileHeader("Register Information Header Fragment", OS); const std::string &TargetName = Target.getName().str(); std::string ClassName = TargetName + "GenRegisterInfo"; @@ -1215,17 +1224,17 @@ void RegisterInfoEmitter::runTargetHeader(raw_ostream &OS) { OS << "} // end namespace " << RegisterClasses.front().Namespace << "\n\n"; } OS << "} // end namespace llvm\n\n"; - OS << "#endif // GET_REGINFO_HEADER\n\n"; } // // runTargetDesc - Output the target register and register file descriptions. // -void RegisterInfoEmitter::runTargetDesc(raw_ostream &OS) { - emitSourceFileHeader("Target Register and Register Classes Information", OS); +void RegisterInfoEmitter::runTargetDesc(raw_ostream &OS, raw_ostream &MainOS, + StringRef FilenamePrefix) { + emitInclude(FilenamePrefix, "TargetDesc.inc", "GET_REGINFO_TARGET_DESC", + MainOS); - OS << "\n#ifdef GET_REGINFO_TARGET_DESC\n"; - OS << "#undef GET_REGINFO_TARGET_DESC\n\n"; + emitSourceFileHeader("Target Register and Register Classes Information", OS); OS << "namespace llvm {\n\n"; @@ -1840,25 +1849,40 @@ void RegisterInfoEmitter::runTargetDesc(raw_ostream &OS) { << "}\n\n"; OS << "} // end namespace llvm\n\n"; - OS << "#endif // GET_REGINFO_TARGET_DESC\n\n"; } -void RegisterInfoEmitter::run(raw_ostream &OS) { +TableGenOutputFiles RegisterInfoEmitter::run(StringRef FilenamePrefix) { TGTimer &Timer = Records.getTimer(); Timer.startTimer("Print enums"); - runEnums(OS); + std::string Main; + raw_string_ostream MainOS(Main); + std::string Enums; + raw_string_ostream EnumsOS(Enums); + runEnums(EnumsOS, MainOS, FilenamePrefix); Timer.startTimer("Print MC registers"); - runMCDesc(OS); + std::string MCDesc; + raw_string_ostream MCDescOS(MCDesc); + runMCDesc(MCDescOS, MainOS, FilenamePrefix); Timer.startTimer("Print header fragment"); - runTargetHeader(OS); + std::string Header; + raw_string_ostream HeaderOS(Header); + runTargetHeader(HeaderOS, MainOS, FilenamePrefix); Timer.startTimer("Print target registers"); - runTargetDesc(OS); + std::string TargetDesc; + raw_string_ostream TargetDescOS(TargetDesc); + runTargetDesc(TargetDescOS, MainOS, FilenamePrefix); if (RegisterInfoDebug) debugDump(errs()); + + return {Main, + {{"Enums.inc", Enums}, + {"MCDesc.inc", MCDesc}, + {"Header.inc", Header}, + {"TargetDesc.inc", TargetDesc}}}; } void RegisterInfoEmitter::debugDump(raw_ostream &OS) { @@ -1935,5 +1959,5 @@ void RegisterInfoEmitter::debugDump(raw_ostream &OS) { } } -static TableGen::Emitter::OptClass +static TableGen::Emitter::MultiFileOptClass X("gen-register-info", "Generate registers and register classes info"); diff --git a/mlir/lib/Tools/mlir-tblgen/MlirTblgenMain.cpp b/mlir/lib/Tools/mlir-tblgen/MlirTblgenMain.cpp index 685e79484e175..64e86f2a62073 100644 --- a/mlir/lib/Tools/mlir-tblgen/MlirTblgenMain.cpp +++ b/mlir/lib/Tools/mlir-tblgen/MlirTblgenMain.cpp @@ -153,5 +153,12 @@ int mlir::MlirTblgenMain(int argc, char **argv) { cl::ParseCommandLineOptions(argc, argv); - return TableGenMain(argv[0], &mlirTableGenMain); + return TableGenMain( + argv[0], [](TableGenOutputFiles &OutFiles, const RecordKeeper &RK) { + std::string S; + raw_string_ostream OS(S); + bool Res = mlirTableGenMain(OS, RK); + OutFiles = {S, {}}; + return Res; + }); }