7070#include " llvm/ADT/ArrayRef.h"
7171#include " llvm/ADT/STLExtras.h"
7272#include " llvm/ADT/SmallSet.h"
73+ #include " llvm/ADT/SmallVector.h"
7374#include " llvm/ADT/StringExtras.h"
7475#include " llvm/ADT/StringRef.h"
7576#include " llvm/ADT/StringSet.h"
103104#include < memory>
104105#include < optional>
105106#include < set>
107+ #include < string>
106108#include < utility>
107109#if LLVM_ON_UNIX
108110#include < unistd.h> // getpid
@@ -2050,12 +2052,17 @@ void Driver::generateCompilationDiagnostics(
20502052 InputList Inputs;
20512053 BuildInputs (C.getDefaultToolChain (), C.getArgs (), Inputs);
20522054
2055+ ArgStringList IRInputs;
20532056 for (InputList::iterator it = Inputs.begin (), ie = Inputs.end (); it != ie;) {
20542057 bool IgnoreInput = false ;
20552058
2056- // Ignore input from stdin or any inputs that cannot be preprocessed.
2057- // Check type first as not all linker inputs have a value.
2058- if (types::getPreprocessedType (it->first ) == types::TY_INVALID) {
2059+ // Save IR inputs separately, ignore input from stdin or any other inputs
2060+ // that cannot be preprocessed. Check type first as not all linker inputs
2061+ // have a value.
2062+ if (types::isLLVMIR (it->first )) {
2063+ IRInputs.push_back (it->second ->getValue ());
2064+ IgnoreInput = true ;
2065+ } else if (types::getPreprocessedType (it->first ) == types::TY_INVALID) {
20592066 IgnoreInput = true ;
20602067 } else if (!strcmp (it->second ->getValue (), " -" )) {
20612068 Diag (clang::diag::note_drv_command_failed_diag_msg)
@@ -2072,7 +2079,7 @@ void Driver::generateCompilationDiagnostics(
20722079 }
20732080 }
20742081
2075- if (Inputs.empty ()) {
2082+ if (Inputs.empty () && IRInputs. empty () ) {
20762083 Diag (clang::diag::note_drv_command_failed_diag_msg)
20772084 << " Error generating preprocessed source(s) - "
20782085 " no preprocessable inputs." ;
@@ -2095,46 +2102,82 @@ void Driver::generateCompilationDiagnostics(
20952102 return ;
20962103 }
20972104
2098- // Construct the list of abstract actions to perform for this compilation. On
2099- // Darwin OSes this uses the driver-driver and builds universal actions.
2100- const ToolChain &TC = C.getDefaultToolChain ();
2101- if (TC.getTriple ().isOSBinFormatMachO ())
2102- BuildUniversalActions (C, TC, Inputs);
2103- else
2104- BuildActions (C, C.getArgs (), Inputs, C.getActions ());
2105+ // If we only have IR inputs there's no need for preprocessing.
2106+ if (!Inputs.empty ()) {
2107+ // Construct the list of abstract actions to perform for this compilation.
2108+ // On Darwin OSes this uses the driver-driver and builds universal actions.
2109+ const ToolChain &TC = C.getDefaultToolChain ();
2110+ if (TC.getTriple ().isOSBinFormatMachO ())
2111+ BuildUniversalActions (C, TC, Inputs);
2112+ else
2113+ BuildActions (C, C.getArgs (), Inputs, C.getActions ());
21052114
2106- BuildJobs (C);
2115+ BuildJobs (C);
21072116
2108- // If there were errors building the compilation, quit now.
2109- if (Trap.hasErrorOccurred ()) {
2110- Diag (clang::diag::note_drv_command_failed_diag_msg)
2111- << " Error generating preprocessed source(s)." ;
2112- return ;
2113- }
2117+ // If there were errors building the compilation, quit now.
2118+ if (Trap.hasErrorOccurred ()) {
2119+ Diag (clang::diag::note_drv_command_failed_diag_msg)
2120+ << " Error generating preprocessed source(s)." ;
2121+ return ;
2122+ }
2123+ // Generate preprocessed output.
2124+ SmallVector<std::pair<int , const Command *>, 4 > FailingCommands;
2125+ C.ExecuteJobs (C.getJobs (), FailingCommands);
21142126
2115- // Generate preprocessed output.
2116- SmallVector<std::pair<int , const Command *>, 4 > FailingCommands;
2117- C.ExecuteJobs (C.getJobs (), FailingCommands);
2127+ // If any of the preprocessing commands failed, clean up and exit.
2128+ if (!FailingCommands.empty ()) {
2129+ Diag (clang::diag::note_drv_command_failed_diag_msg)
2130+ << " Error generating preprocessed source(s)." ;
2131+ return ;
2132+ }
21182133
2119- // If any of the preprocessing commands failed, clean up and exit.
2120- if (!FailingCommands.empty ()) {
2121- Diag (clang::diag::note_drv_command_failed_diag_msg)
2122- << " Error generating preprocessed source(s)." ;
2123- return ;
2134+ const ArgStringList &TempFiles = C.getTempFiles ();
2135+ if (TempFiles.empty ()) {
2136+ Diag (clang::diag::note_drv_command_failed_diag_msg)
2137+ << " Error generating preprocessed source(s)." ;
2138+ return ;
2139+ }
21242140 }
21252141
2126- const ArgStringList &TempFiles = C.getTempFiles ();
2127- if (TempFiles.empty ()) {
2128- Diag (clang::diag::note_drv_command_failed_diag_msg)
2129- << " Error generating preprocessed source(s)." ;
2130- return ;
2142+ // Copying filenames due to ownership.
2143+ const ArgStringList &Files = C.getTempFiles ();
2144+ SmallVector<std::string> TempFiles (Files.begin (), Files.end ());
2145+
2146+ // We'd like to copy the IR input file into our own temp file
2147+ // because the build system might try to clean-up after itself.
2148+ for (auto const *Input : IRInputs) {
2149+ int FD;
2150+ llvm::SmallVector<char , 64 > Path;
2151+
2152+ StringRef extension = llvm::sys::path::extension (Input);
2153+ if (!extension.empty ())
2154+ extension = extension.drop_front ();
2155+
2156+ std::error_code EC = llvm::sys::fs::createTemporaryFile (
2157+ llvm::sys::path::stem (Input), extension, FD, Path);
2158+ if (EC) {
2159+ Diag (clang::diag::note_drv_command_failed_diag_msg)
2160+ << " Error generating run script: " << " Failed copying IR input files"
2161+ << " " << EC.message ();
2162+ return ;
2163+ }
2164+
2165+ EC = llvm::sys::fs::copy_file (Input, FD);
2166+ if (EC) {
2167+ Diag (clang::diag::note_drv_command_failed_diag_msg)
2168+ << " Error generating run script: " << " Failed copying IR input files"
2169+ << " " << EC.message ();
2170+ return ;
2171+ }
2172+
2173+ TempFiles.push_back (std::string (Path.begin (), Path.end ()));
21312174 }
21322175
21332176 Diag (clang::diag::note_drv_command_failed_diag_msg) << BugReporMsg;
21342177
21352178 SmallString<128 > VFS;
21362179 SmallString<128 > ReproCrashFilename;
2137- for (const char * TempFile : TempFiles) {
2180+ for (std::string & TempFile : TempFiles) {
21382181 Diag (clang::diag::note_drv_command_failed_diag_msg) << TempFile;
21392182 if (Report)
21402183 Report->TemporaryFiles .push_back (TempFile);
@@ -2151,7 +2194,7 @@ void Driver::generateCompilationDiagnostics(
21512194 }
21522195
21532196 for (const char *TempFile : SavedTemps)
2154- C. addTempFile (TempFile);
2197+ TempFiles. push_back (TempFile);
21552198
21562199 // Assume associated files are based off of the first temporary file.
21572200 CrashReportInfo CrashInfo (TempFiles[0 ], VFS);
0 commit comments