2323#include " llvm/Support/ErrorOr.h"
2424#include " llvm/Support/FileSystem.h"
2525#include " llvm/Support/MemoryBuffer.h"
26+ #include " llvm/Support/Path.h"
2627#include " llvm/Support/SMLoc.h"
2728#include " llvm/Support/SourceMgr.h"
2829#include " llvm/Support/ToolOutputFile.h"
@@ -104,8 +105,30 @@ static int createDependencyFile(const TGParser &Parser, const char *argv0) {
104105 return 0 ;
105106}
106107
108+ static int WriteOutput (const TGParser &Parser, const char *argv0,
109+ StringRef Filename, StringRef Content) {
110+ if (WriteIfChanged) {
111+ // Only updates the real output file if there are any differences.
112+ // This prevents recompilation of all the files depending on it if there
113+ // aren't any.
114+ if (auto ExistingOrErr = MemoryBuffer::getFile (Filename, /* IsText=*/ true ))
115+ if (std::move (ExistingOrErr.get ())->getBuffer () == Content)
116+ return 0 ;
117+ }
118+ std::error_code EC;
119+ ToolOutputFile OutFile (Filename, EC, sys::fs::OF_Text);
120+ if (EC)
121+ return reportError (argv0, " error opening " + Filename + " : " +
122+ EC.message () + " \n " );
123+ OutFile.os () << Content;
124+ if (ErrorsPrinted == 0 )
125+ OutFile.keep ();
126+
127+ return 0 ;
128+ }
129+
107130int llvm::TableGenMain (const char *argv0,
108- std::function<TableGenMainFn > MainFn) {
131+ std::function<MultiFileTableGenMainFn > MainFn) {
109132 RecordKeeper Records;
110133 TGTimer &Timer = Records.getTimer ();
111134
@@ -144,13 +167,14 @@ int llvm::TableGenMain(const char *argv0,
144167
145168 // Write output to memory.
146169 Timer.startBackendTimer (" Backend overall" );
147- std::string OutString;
148- raw_string_ostream Out (OutString);
170+ SmallString<128 > FilenamePrefix (OutputFilename);
171+ sys::path::replace_extension (FilenamePrefix, " " );
172+ TableGenOutputFiles OutFiles;
149173 unsigned status = 0 ;
150174 // ApplyCallback will return true if it did not apply any callback. In that
151175 // case, attempt to apply the MainFn.
152- if (TableGen::Emitter::ApplyCallback (Records, Out ))
153- status = MainFn ? MainFn (Out , Records) : 1 ;
176+ if (TableGen::Emitter::ApplyCallback (Records, OutFiles, FilenamePrefix ))
177+ status = MainFn ? MainFn (OutFiles , Records) : 1 ;
154178 Timer.stopBackendTimer ();
155179 if (status)
156180 return 1 ;
@@ -165,25 +189,17 @@ int llvm::TableGenMain(const char *argv0,
165189 }
166190
167191 Timer.startTimer (" Write output" );
168- bool WriteFile = true ;
169- if (WriteIfChanged) {
170- // Only updates the real output file if there are any differences.
171- // This prevents recompilation of all the files depending on it if there
172- // aren't any.
173- if (auto ExistingOrErr =
174- MemoryBuffer::getFile (OutputFilename, /* IsText=*/ true ))
175- if (std::move (ExistingOrErr.get ())->getBuffer () == OutString)
176- WriteFile = false ;
177- }
178- if (WriteFile) {
179- std::error_code EC;
180- ToolOutputFile OutFile (OutputFilename, EC, sys::fs::OF_Text);
181- if (EC)
182- return reportError (argv0, " error opening " + OutputFilename + " : " +
183- EC.message () + " \n " );
184- OutFile.os () << OutString;
185- if (ErrorsPrinted == 0 )
186- OutFile.keep ();
192+ if (int Ret = WriteOutput (Parser, argv0, OutputFilename, OutFiles.MainFile ))
193+ return Ret;
194+ for (auto [Suffix, Content] : OutFiles.AdditionalFiles ) {
195+ SmallString<128 > Filename (OutputFilename);
196+ // TODO: Format using the split-file convention when writing to stdout?
197+ if (Filename != " -" ) {
198+ Filename = FilenamePrefix;
199+ Filename.append (Suffix);
200+ }
201+ if (int Ret = WriteOutput (Parser, argv0, Filename, Content))
202+ return Ret;
187203 }
188204
189205 Timer.stopTimer ();
@@ -193,3 +209,15 @@ int llvm::TableGenMain(const char *argv0,
193209 return reportError (argv0, Twine (ErrorsPrinted) + " errors.\n " );
194210 return 0 ;
195211}
212+
213+ int llvm::TableGenMain (const char *argv0,
214+ std::function<TableGenMainFn> MainFn) {
215+ return TableGenMain (argv0, [&MainFn](TableGenOutputFiles &OutFiles,
216+ const RecordKeeper &Records) {
217+ std::string S;
218+ raw_string_ostream OS (S);
219+ int Res = MainFn (OS, Records);
220+ OutFiles = {S, {}};
221+ return Res;
222+ });
223+ }
0 commit comments