aganea updated this revision to Diff 244172. aganea marked 7 inline comments as done. aganea added a comment.
Address @hans' comments. While it'd be good to have a bot running without `-disable-free`, I concur with @thakis. This patch will probably introduce too much (untested) variability for release 10.0, if merged. Let's enable `integrate-cc1` just for one TU for the 10.0, and then we'll see if we want to land this patch or not in the trunk for the 11.0. I'll open another review. CHANGES SINCE LAST ACTION https://reviews.llvm.org/D74447/new/ https://reviews.llvm.org/D74447 Files: clang/include/clang/Driver/Job.h clang/lib/Driver/Driver.cpp clang/lib/Driver/Job.cpp clang/lib/Driver/ToolChains/Clang.cpp clang/test/Driver/cc1-spawnprocess.c clang/tools/driver/cc1_main.cpp
Index: clang/tools/driver/cc1_main.cpp =================================================================== --- clang/tools/driver/cc1_main.cpp +++ clang/tools/driver/cc1_main.cpp @@ -259,6 +259,7 @@ // FIXME(ibiryukov): make profilerOutput flush in destructor instead. profilerOutput->flush(); llvm::timeTraceProfilerCleanup(); + Clang->clearOutputFiles(false); } } Index: clang/test/Driver/cc1-spawnprocess.c =================================================================== --- clang/test/Driver/cc1-spawnprocess.c +++ clang/test/Driver/cc1-spawnprocess.c @@ -20,3 +20,48 @@ // YES: (in-process) // NO-NOT: (in-process) + +// The following tests ensure that only the last integrated-cc1 has -disable-free + +// RUN: echo 'int main() { return f() + g(); }' > %t1.cpp +// RUN: echo 'int f() { return 1; }' > %t2.cpp +// RUN: echo 'int g() { return 2; }' > %t3.cpp + +// Only one TU, one job, thus no cleanup is needed. +// RUN: %clang -fintegrated-cc1 -c %t1.cpp -### 2>&1 | FileCheck %s --check-prefix=CLEAN +// CLEAN: cc1 +// CLEAN-SAME: -disable-free + +// Three jobs, only the last invocation will skip clean up. +// RUN: %clang -fintegrated-cc1 -c %t1.cpp %t2.cpp %t3.cpp -### 2>&1 | FileCheck %s --check-prefix=NOCLEAN-LAST +// NOCLEAN-LAST: cc1 +// NOCLEAN-LAST-NOT: -disable-free +// NOCLEAN-LAST-SAME: {{.*}}1.cpp +// NOCLEAN-LAST: cc1 +// NOCLEAN-LAST-NOT: -disable-free +// NOCLEAN-LAST-SAME: {{.*}}2.cpp +// NOCLEAN-LAST: cc1 +// NOCLEAN-LAST-SAME: -disable-free +// NOCLEAN-LAST-SAME: {{.*}}3.cpp + +// Four jobs, no invocation will skip clean up because the last job is linking. +// RUN: %clang -fintegrated-cc1 %t1.cpp %t2.cpp %t3.cpp -### 2>&1 | FileCheck %s --check-prefix=ALL +// ALL-NOT: -disable-free + +// In no-integrated-cc1 mode, no cleanup is needed, because we're running the +// CC1 tool in a secondary process and the process' heap will be released +// anyway when the process ends. +// RUN: %clang -fno-integrated-cc1 -c %t1.cpp -### 2>&1 | FileCheck %s --check-prefix=CLEAN + +// RUN: %clang -fno-integrated-cc1 -c %t1.cpp %t2.cpp %t3.cpp -### 2>&1 | FileCheck %s --check-prefix=CLEANALL +// CLEANALL: cc1 +// CLEANALL-SAME: -disable-free +// CLEANALL-SAME: {{.*}}1.cpp +// CLEANALL: cc1 +// CLEANALL-SAME: -disable-free +// CLEANALL-SAME: {{.*}}2.cpp +// CLEANALL: cc1 +// CLEANALL-SAME: -disable-free +// CLEANALL-SAME: {{.*}}3.cpp + +// RUN: %clang -fno-integrated-cc1 %t1.cpp %t2.cpp %t3.cpp -### 2>&1 | FileCheck %s --check-prefix=CLEANALL Index: clang/lib/Driver/ToolChains/Clang.cpp =================================================================== --- clang/lib/Driver/ToolChains/Clang.cpp +++ clang/lib/Driver/ToolChains/Clang.cpp @@ -6148,7 +6148,7 @@ if (Output.getType() == types::TY_Object && Args.hasFlag(options::OPT__SLASH_showFilenames, options::OPT__SLASH_showFilenames_, false)) { - C.getJobs().getJobs().back()->setPrintInputFilenames(true); + C.getJobs().getJobs().back()->PrintInputFilenames = true; } if (Arg *A = Args.getLastArg(options::OPT_pg)) Index: clang/lib/Driver/Job.cpp =================================================================== --- clang/lib/Driver/Job.cpp +++ clang/lib/Driver/Job.cpp @@ -40,7 +40,7 @@ const llvm::opt::ArgStringList &Arguments, ArrayRef<InputInfo> Inputs) : Source(Source), Creator(Creator), Executable(Executable), - Arguments(Arguments) { + Arguments(Arguments), PrintInputFilenames(false), InProcess(false) { for (const auto &II : Inputs) if (II.isFilename()) InputFilenames.push_back(II.getFilename()); @@ -315,6 +315,15 @@ Environment.push_back(nullptr); } +// In some cases when running the calling process, we need to clean up if there +// are other Commands being executed after us, to prevent bloating the heap. +void Command::enableFree() { + auto RemoveDisableFree = [](const char *A) { + return StringRef(A).equals("-disable-free"); + }; + llvm::erase_if(Arguments, RemoveDisableFree); +} + void Command::PrintFileNames() const { if (PrintInputFilenames) { for (const char *Arg : InputFilenames) @@ -371,6 +380,14 @@ /*memoryLimit*/ 0, ErrMsg, ExecutionFailed); } +CC1Command::CC1Command(const Action &Source, const Tool &Creator, + const char *Executable, + const llvm::opt::ArgStringList &Arguments, + ArrayRef<InputInfo> Inputs) + : Command(Source, Creator, Executable, Arguments, Inputs) { + InProcess = true; +} + void CC1Command::Print(raw_ostream &OS, const char *Terminator, bool Quote, CrashReportInfo *CrashInfo) const { OS << " (in-process)\n"; Index: clang/lib/Driver/Driver.cpp =================================================================== --- clang/lib/Driver/Driver.cpp +++ clang/lib/Driver/Driver.cpp @@ -3753,6 +3753,13 @@ /*TargetDeviceOffloadKind*/ Action::OFK_None); } + // Make sure we clean up after in-process jobs. + for (size_t I = 0, E = C.getJobs().size(); I + 1 < E; I++) { + auto &Job = *C.getJobs().getJobs()[I]; + if (Job.InProcess) + Job.enableFree(); + } + // If the user passed -Qunused-arguments or there were errors, don't warn // about any unused arguments. if (Diags.hasErrorOccurred() || Index: clang/include/clang/Driver/Job.h =================================================================== --- clang/include/clang/Driver/Job.h +++ clang/include/clang/Driver/Job.h @@ -55,9 +55,6 @@ /// The list of program arguments which are inputs. llvm::opt::ArgStringList InputFilenames; - /// Whether to print the input filenames when executing. - bool PrintInputFilenames = false; - /// Response file name, if this command is set to use one, or nullptr /// otherwise const char *ResponseFile = nullptr; @@ -86,6 +83,12 @@ void writeResponseFile(raw_ostream &OS) const; public: + /// Whether to print the input filenames when executing. + bool PrintInputFilenames; + + /// Whether the command will be executed in this process or not. + bool InProcess; + Command(const Action &Source, const Tool &Creator, const char *Executable, const llvm::opt::ArgStringList &Arguments, ArrayRef<InputInfo> Inputs); @@ -128,8 +131,8 @@ /// Print a command argument, and optionally quote it. static void printArg(llvm::raw_ostream &OS, StringRef Arg, bool Quote); - /// Set whether to print the input filenames when executing. - void setPrintInputFilenames(bool P) { PrintInputFilenames = P; } + /// Ensure the memory allocated by the job is freed after execution. + void enableFree(); protected: /// Optionally print the filenames to be compiled @@ -139,7 +142,9 @@ /// Use the CC1 tool callback when available, to avoid creating a new process class CC1Command : public Command { public: - using Command::Command; + CC1Command(const Action &Source, const Tool &Creator, const char *Executable, + const llvm::opt::ArgStringList &Arguments, + ArrayRef<InputInfo> Inputs); void Print(llvm::raw_ostream &OS, const char *Terminator, bool Quote, CrashReportInfo *CrashInfo = nullptr) const override;
_______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits