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
@@ -2041,12 +2043,17 @@ void Driver::generateCompilationDiagnostics(
20412043 InputList Inputs;
20422044 BuildInputs (C.getDefaultToolChain (), C.getArgs (), Inputs);
20432045
2046+ ArgStringList IRInputs;
20442047 for (InputList::iterator it = Inputs.begin (), ie = Inputs.end (); it != ie;) {
20452048 bool IgnoreInput = false ;
20462049
2047- // Ignore input from stdin or any inputs that cannot be preprocessed.
2048- // Check type first as not all linker inputs have a value.
2049- if (types::getPreprocessedType (it->first ) == types::TY_INVALID) {
2050+ // Save IR inputs separately, ignore input from stdin or any other inputs
2051+ // that cannot be preprocessed. Check type first as not all linker inputs
2052+ // have a value.
2053+ if (types::isLLVMIR (it->first )) {
2054+ IRInputs.push_back (it->second ->getValue ());
2055+ IgnoreInput = true ;
2056+ } else if (types::getPreprocessedType (it->first ) == types::TY_INVALID) {
20502057 IgnoreInput = true ;
20512058 } else if (!strcmp (it->second ->getValue (), " -" )) {
20522059 Diag (clang::diag::note_drv_command_failed_diag_msg)
@@ -2063,7 +2070,7 @@ void Driver::generateCompilationDiagnostics(
20632070 }
20642071 }
20652072
2066- if (Inputs.empty ()) {
2073+ if (Inputs.empty () && IRInputs. empty () ) {
20672074 Diag (clang::diag::note_drv_command_failed_diag_msg)
20682075 << " Error generating preprocessed source(s) - "
20692076 " no preprocessable inputs." ;
@@ -2086,46 +2093,77 @@ void Driver::generateCompilationDiagnostics(
20862093 return ;
20872094 }
20882095
2089- // Construct the list of abstract actions to perform for this compilation. On
2090- // Darwin OSes this uses the driver-driver and builds universal actions.
2091- const ToolChain &TC = C.getDefaultToolChain ();
2092- if (TC.getTriple ().isOSBinFormatMachO ())
2093- BuildUniversalActions (C, TC, Inputs);
2094- else
2095- BuildActions (C, C.getArgs (), Inputs, C.getActions ());
2096+ // If we only have IR inputs there's no need for preprocessing.
2097+ if (!Inputs.empty ()) {
2098+ // Construct the list of abstract actions to perform for this compilation.
2099+ // On
2100+ // Darwin OSes this uses the driver-driver and builds universal actions.
2101+ const ToolChain &TC = C.getDefaultToolChain ();
2102+ if (TC.getTriple ().isOSBinFormatMachO ())
2103+ BuildUniversalActions (C, TC, Inputs);
2104+ else
2105+ BuildActions (C, C.getArgs (), Inputs, C.getActions ());
20962106
2097- BuildJobs (C);
2107+ BuildJobs (C);
20982108
2099- // If there were errors building the compilation, quit now.
2100- if (Trap.hasErrorOccurred ()) {
2101- Diag (clang::diag::note_drv_command_failed_diag_msg)
2102- << " Error generating preprocessed source(s)." ;
2103- return ;
2104- }
2109+ // If there were errors building the compilation, quit now.
2110+ if (Trap.hasErrorOccurred ()) {
2111+ Diag (clang::diag::note_drv_command_failed_diag_msg)
2112+ << " Error generating preprocessed source(s)." ;
2113+ return ;
2114+ }
2115+ // Generate preprocessed output.
2116+ SmallVector<std::pair<int , const Command *>, 4 > FailingCommands;
2117+ C.ExecuteJobs (C.getJobs (), FailingCommands);
21052118
2106- // Generate preprocessed output.
2107- SmallVector<std::pair<int , const Command *>, 4 > FailingCommands;
2108- C.ExecuteJobs (C.getJobs (), FailingCommands);
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 ;
2124+ }
21092125
2110- // If any of the preprocessing commands failed, clean up and exit.
2111- if (!FailingCommands.empty ()) {
2112- Diag (clang::diag::note_drv_command_failed_diag_msg)
2113- << " Error generating preprocessed source(s)." ;
2114- return ;
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 ;
2131+ }
21152132 }
21162133
2117- const ArgStringList &TempFiles = C.getTempFiles ();
2118- if (TempFiles.empty ()) {
2119- Diag (clang::diag::note_drv_command_failed_diag_msg)
2120- << " Error generating preprocessed source(s)." ;
2121- return ;
2134+ // Copying filenames due to ownership.
2135+ const ArgStringList &Files = C.getTempFiles ();
2136+ SmallVector<std::string> TempFiles (Files.begin (), Files.end ());
2137+
2138+ // We'd like to copy the IR input file into our own temp file
2139+ // because the build system might try to clean-up after itself.
2140+ for (auto const *Input : IRInputs) {
2141+ int FD;
2142+ llvm::SmallVector<char , 64 > Path;
2143+
2144+ StringRef extension = llvm::sys::path::extension (Input);
2145+ if (!extension.empty ())
2146+ extension = extension.drop_front ();
2147+
2148+ std::error_code EC = llvm::sys::fs::createTemporaryFile (
2149+ llvm::sys::path::stem (Input), extension, FD, Path);
2150+
2151+ if (EC) {
2152+ Diag (clang::diag::note_drv_command_failed_diag_msg)
2153+ << " Error generating run script: " << " Failed copying IR input files"
2154+ << " " << EC.message ();
2155+ return ;
2156+ }
2157+ llvm::sys::fs::copy_file (Input, FD);
2158+
2159+ TempFiles.push_back (std::string (Path.begin (), Path.end ()));
21222160 }
21232161
21242162 Diag (clang::diag::note_drv_command_failed_diag_msg) << BugReporMsg;
21252163
21262164 SmallString<128 > VFS;
21272165 SmallString<128 > ReproCrashFilename;
2128- for (const char * TempFile : TempFiles) {
2166+ for (std::string & TempFile : TempFiles) {
21292167 Diag (clang::diag::note_drv_command_failed_diag_msg) << TempFile;
21302168 if (Report)
21312169 Report->TemporaryFiles .push_back (TempFile);
@@ -2142,7 +2180,7 @@ void Driver::generateCompilationDiagnostics(
21422180 }
21432181
21442182 for (const char *TempFile : SavedTemps)
2145- C. addTempFile (TempFile);
2183+ TempFiles. push_back (TempFile);
21462184
21472185 // Assume associated files are based off of the first temporary file.
21482186 CrashReportInfo CrashInfo (TempFiles[0 ], VFS);
0 commit comments