aganea updated this revision to Diff 230527.
aganea marked 3 inline comments as done.
CHANGES SINCE LAST ACTION
https://reviews.llvm.org/D69825/new/
https://reviews.llvm.org/D69825
Files:
clang/include/clang/Driver/Driver.h
clang/include/clang/Driver/Job.h
clang/lib/Driver/Job.cpp
clang/lib/Driver/ToolChains/Clang.cpp
clang/tools/driver/driver.cpp
Index: clang/tools/driver/driver.cpp
===================================================================
--- clang/tools/driver/driver.cpp
+++ clang/tools/driver/driver.cpp
@@ -30,6 +30,7 @@
#include "llvm/Option/OptTable.h"
#include "llvm/Option/Option.h"
#include "llvm/Support/CommandLine.h"
+#include "llvm/Support/CrashRecoveryContext.h"
#include "llvm/Support/ErrorHandling.h"
#include "llvm/Support/FileSystem.h"
#include "llvm/Support/Host.h"
@@ -303,7 +304,13 @@
TheDriver.setInstalledDir(InstalledPathParent);
}
-static int ExecuteCC1Tool(ArrayRef<const char *> argv, StringRef Tool) {
+static int ExecuteCC1Tool(ArrayRef<const char *> argv) {
+ // If we call the cc1 tool from the clangDriver library (through
+ // Driver::CC1Main), we need to cleanup the options usage count. The options
+ // are currently global, and they might have been used previously by the
+ // driver.
+ llvm::cl::ResetAllOptionOccurrences();
+ StringRef Tool = argv[1] + 4;
void *GetExecutablePathVP = (void *)(intptr_t) GetExecutablePath;
if (Tool == "")
return cc1_main(argv.slice(2), argv[0], GetExecutablePathVP);
@@ -379,7 +386,7 @@
auto newEnd = std::remove(argv.begin(), argv.end(), nullptr);
argv.resize(newEnd - argv.begin());
}
- return ExecuteCC1Tool(argv, argv[1] + 4);
+ return ExecuteCC1Tool(argv);
}
bool CanonicalPrefixes = true;
@@ -455,6 +462,11 @@
SetBackdoorDriverOutputsFromEnvVars(TheDriver);
+ // Here we provide a shortcut for calling the -cc1 cmd-line within the same
+ // process, instead of starting a new process. This saves a huge amount of
+ // time of Windows, as process creation can be expensive on that platform.
+ TheDriver.CC1Main = &ExecuteCC1Tool;
+
std::unique_ptr<Compilation> C(TheDriver.BuildCompilation(argv));
int Res = 1;
if (C && !C->containsError()) {
@@ -503,7 +515,7 @@
#ifdef _WIN32
// Exit status should not be negative on Win32, unless abnormal termination.
- // Once abnormal termiation was caught, negative status should not be
+ // Once abnormal termination was caught, negative status should not be
// propagated.
if (Res < 0)
Res = 1;
Index: clang/lib/Driver/ToolChains/Clang.cpp
===================================================================
--- clang/lib/Driver/ToolChains/Clang.cpp
+++ clang/lib/Driver/ToolChains/Clang.cpp
@@ -5656,6 +5656,10 @@
// fails, so that the main compilation's fallback to cl.exe runs.
C.addCommand(std::make_unique<ForceSuccessCommand>(JA, *this, Exec,
CmdArgs, Inputs));
+ } else if (D.CC1Main && !D.CCGenDiagnostics) {
+ // Invoke the CC1 directly in this process
+ C.addCommand(
+ std::make_unique<CC1Command>(JA, *this, Exec, CmdArgs, Inputs));
} else {
C.addCommand(std::make_unique<Command>(JA, *this, Exec, CmdArgs, Inputs));
}
Index: clang/lib/Driver/Job.cpp
===================================================================
--- clang/lib/Driver/Job.cpp
+++ clang/lib/Driver/Job.cpp
@@ -19,8 +19,10 @@
#include "llvm/ADT/StringRef.h"
#include "llvm/ADT/StringSet.h"
#include "llvm/ADT/StringSwitch.h"
+#include "llvm/Support/CrashRecoveryContext.h"
#include "llvm/Support/FileSystem.h"
#include "llvm/Support/Path.h"
+#include "llvm/Support/PrettyStackTrace.h"
#include "llvm/Support/Program.h"
#include "llvm/Support/raw_ostream.h"
#include <algorithm>
@@ -313,15 +315,49 @@
Environment.push_back(nullptr);
}
-int Command::Execute(ArrayRef<llvm::Optional<StringRef>> Redirects,
- std::string *ErrMsg, bool *ExecutionFailed) const {
+int Command::PrepareExecution(SmallVectorImpl<const char *> &Argv,
+ std::string *ErrMsg,
+ bool *ExecutionFailed) const {
if (PrintInputFilenames) {
for (const char *Arg : InputFilenames)
llvm::outs() << llvm::sys::path::filename(Arg) << "\n";
llvm::outs().flush();
}
- SmallVector<const char*, 128> Argv;
+ if (ResponseFile == nullptr) {
+ Argv.push_back(Executable);
+ Argv.append(Arguments.begin(), Arguments.end());
+ Argv.push_back(nullptr);
+ } else {
+ // If the command is too large, we need to put arguments in a response file.
+ std::string RespContents;
+ llvm::raw_string_ostream SS(RespContents);
+
+ // Write file contents and build the Argv vector
+ writeResponseFile(SS);
+ buildArgvForResponseFile(Argv);
+ Argv.push_back(nullptr);
+ SS.flush();
+
+ // Save the response file in the appropriate encoding
+ if (std::error_code EC = writeFileWithEncoding(
+ ResponseFile, RespContents, Creator.getResponseFileEncoding())) {
+ if (ErrMsg)
+ *ErrMsg = EC.message();
+ if (ExecutionFailed)
+ *ExecutionFailed = true;
+ return -1;
+ }
+ }
+ return 0;
+}
+
+int Command::Execute(ArrayRef<llvm::Optional<StringRef>> Redirects,
+ std::string *ErrMsg, bool *ExecutionFailed) const {
+ SmallVector<const char *, 128> Argv;
+ int R = PrepareExecution(Argv, ErrMsg, ExecutionFailed);
+ if (R)
+ return R;
Optional<ArrayRef<StringRef>> Env;
std::vector<StringRef> ArgvVectorStorage;
@@ -332,44 +368,53 @@
Env = makeArrayRef(ArgvVectorStorage);
}
- if (ResponseFile == nullptr) {
- Argv.push_back(Executable);
- Argv.append(Arguments.begin(), Arguments.end());
- Argv.push_back(nullptr);
-
- auto Args = llvm::toStringRefArray(Argv.data());
- return llvm::sys::ExecuteAndWait(
- Executable, Args, Env, Redirects, /*secondsToWait*/ 0,
- /*memoryLimit*/ 0, ErrMsg, ExecutionFailed);
- }
-
- // We need to put arguments in a response file (command is too large)
- // Open stream to store the response file contents
- std::string RespContents;
- llvm::raw_string_ostream SS(RespContents);
-
- // Write file contents and build the Argv vector
- writeResponseFile(SS);
- buildArgvForResponseFile(Argv);
- Argv.push_back(nullptr);
- SS.flush();
-
- // Save the response file in the appropriate encoding
- if (std::error_code EC = writeFileWithEncoding(
- ResponseFile, RespContents, Creator.getResponseFileEncoding())) {
- if (ErrMsg)
- *ErrMsg = EC.message();
- if (ExecutionFailed)
- *ExecutionFailed = true;
- return -1;
- }
-
auto Args = llvm::toStringRefArray(Argv.data());
return llvm::sys::ExecuteAndWait(Executable, Args, Env, Redirects,
/*secondsToWait*/ 0,
/*memoryLimit*/ 0, ErrMsg, ExecutionFailed);
}
+void CC1Command::Print(raw_ostream &OS, const char *Terminator, bool Quote,
+ CrashReportInfo *CrashInfo) const {
+ OS << " Running the following cmd-line in ExecuteCC1Tool():\n";
+ Command::Print(OS, Terminator, Quote, CrashInfo);
+}
+
+int CC1Command::Execute(ArrayRef<llvm::Optional<StringRef>> /*Redirects*/,
+ std::string *ErrMsg, bool *ExecutionFailed) const {
+ SmallVector<const char *, 128> Argv;
+ int R = PrepareExecution(Argv, ErrMsg, ExecutionFailed);
+ if (R)
+ return R;
+
+ // This flag simply indicates that the program couldn't start, which isn't
+ // applicable here.
+ if (ExecutionFailed)
+ *ExecutionFailed = false;
+
+ llvm::CrashRecoveryContext CRC;
+ CRC.EnableExceptionHandler = true;
+
+ const void *PrettyState = llvm::SavePrettyStackState();
+ const Driver &D = getCreator().getToolChain().getDriver();
+
+ // Enter ExecuteCC1Tool() instead of starting up a new process
+ if (!CRC.RunSafely([&]() { R = D.CC1Main(Argv); })) {
+ llvm::RestorePrettyStackState(PrettyState);
+ return CRC.RetCode;
+ }
+ return R;
+}
+
+void CC1Command::setResponseFile(const char *FileName) {
+ // We don't need response files when calling into ExecuteCC1Tool()
+}
+
+void CC1Command::setEnvironment(llvm::ArrayRef<const char *> NewEnvironment) {
+ // We don't support set a new environment when calling into ExecuteCC1Tool()
+ assert(0 && "The CC1Command doesn't support changing the environment vars!");
+}
+
FallbackCommand::FallbackCommand(const Action &Source_, const Tool &Creator_,
const char *Executable_,
const llvm::opt::ArgStringList &Arguments_,
Index: clang/include/clang/Driver/Job.h
===================================================================
--- clang/include/clang/Driver/Job.h
+++ clang/include/clang/Driver/Job.h
@@ -107,7 +107,7 @@
const Tool &getCreator() const { return Creator; }
/// Set to pass arguments via a response file when launching the command
- void setResponseFile(const char *FileName);
+ virtual void setResponseFile(const char *FileName);
/// Set an input file list, necessary if we need to use a response file but
/// the tool being called only supports input files lists.
@@ -119,7 +119,7 @@
/// \param NewEnvironment An array of environment variables.
/// \remark If the environment remains unset, then the environment
/// from the parent process will be used.
- void setEnvironment(llvm::ArrayRef<const char *> NewEnvironment);
+ virtual void setEnvironment(llvm::ArrayRef<const char *> NewEnvironment);
const char *getExecutable() const { return Executable; }
@@ -130,6 +130,27 @@
/// Set whether to print the input filenames when executing.
void setPrintInputFilenames(bool P) { PrintInputFilenames = P; }
+
+protected:
+ /// Lay out the arguments just before the call, or create a response file
+ int PrepareExecution(SmallVectorImpl<const char *> &Argv, std::string *ErrMsg,
+ bool *ExecutionFailed) const;
+};
+
+/// Use the CC1 tool callback when available, to avoid creating a new process
+class CC1Command : public Command {
+public:
+ using Command::Command;
+
+ void Print(llvm::raw_ostream &OS, const char *Terminator, bool Quote,
+ CrashReportInfo *CrashInfo = nullptr) const override;
+
+ int Execute(ArrayRef<Optional<StringRef>> Redirects, std::string *ErrMsg,
+ bool *ExecutionFailed) const override;
+
+ void setResponseFile(const char *FileName) override;
+
+ void setEnvironment(llvm::ArrayRef<const char *> NewEnvironment) override;
};
/// Like Command, but with a fallback which is executed in case
Index: clang/include/clang/Driver/Driver.h
===================================================================
--- clang/include/clang/Driver/Driver.h
+++ clang/include/clang/Driver/Driver.h
@@ -204,6 +204,13 @@
/// Whether the driver is generating diagnostics for debugging purposes.
unsigned CCGenDiagnostics : 1;
+ /// Pointer to the ExecuteCC1Tool function, if available.
+ /// When the clangDriver lib is used through clang.exe, this provides a
+ /// shortcut for executing the -cc1 command-line directly, in the same
+ /// process.
+ typedef int (*CC1ToolFunc)(ArrayRef<const char *> argv);
+ CC1ToolFunc CC1Main;
+
private:
/// Raw target triple.
std::string TargetTriple;
_______________________________________________
cfe-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits