mirror of
https://github.com/Gericom/teak-llvm.git
synced 2025-06-19 11:35:51 -04:00
[Clang][Driver] Re-use the calling process instead of creating a new process for the cc1 invocation
With this patch, the clang tool will now call the -cc1 invocation directly inside the same process. Previously, the -cc1 invocation was creating, and waiting for, a new process. This patch therefore reduces the number of created processes during a build, thus it reduces build times on platforms where process creation can be costly (Windows) and/or impacted by a antivirus. It also makes debugging a bit easier, as there's no need to attach to the secondary -cc1 process anymore, breakpoints will be hit inside the same process. Crashes or signaling inside the -cc1 invocation will have the same side-effect as before, and will be reported through the same means. This behavior can be controlled at compile-time through the CLANG_SPAWN_CC1 cmake flag, which defaults to OFF. Setting it to ON will revert to the previous behavior, where any -cc1 invocation will create/fork a secondary process. At run-time, it is also possible to tweak the CLANG_SPAWN_CC1 environment variable. Setting it and will override the compile-time setting. A value of 0 calls -cc1 inside the calling process; a value of 1 will create a secondary process, as before. Differential Revision: https://reviews.llvm.org/D69825
This commit is contained in:
parent
043c5eafa8
commit
b4a99a061f
@ -237,6 +237,9 @@ set(ENABLE_X86_RELAX_RELOCATIONS OFF CACHE BOOL
|
|||||||
set(ENABLE_EXPERIMENTAL_NEW_PASS_MANAGER FALSE CACHE BOOL
|
set(ENABLE_EXPERIMENTAL_NEW_PASS_MANAGER FALSE CACHE BOOL
|
||||||
"Enable the experimental new pass manager by default.")
|
"Enable the experimental new pass manager by default.")
|
||||||
|
|
||||||
|
set(CLANG_SPAWN_CC1 OFF CACHE BOOL
|
||||||
|
"Whether clang should use a new process for the CC1 invocation")
|
||||||
|
|
||||||
# TODO: verify the values against LangStandards.def?
|
# TODO: verify the values against LangStandards.def?
|
||||||
set(CLANG_DEFAULT_STD_C "" CACHE STRING
|
set(CLANG_DEFAULT_STD_C "" CACHE STRING
|
||||||
"Default standard to use for C/ObjC code (IDENT from LangStandards.def, empty for platform default)")
|
"Default standard to use for C/ObjC code (IDENT from LangStandards.def, empty for platform default)")
|
||||||
|
@ -80,4 +80,7 @@
|
|||||||
#cmakedefine01 CLANG_ENABLE_OBJC_REWRITER
|
#cmakedefine01 CLANG_ENABLE_OBJC_REWRITER
|
||||||
#cmakedefine01 CLANG_ENABLE_STATIC_ANALYZER
|
#cmakedefine01 CLANG_ENABLE_STATIC_ANALYZER
|
||||||
|
|
||||||
|
/* Spawn a new process clang.exe for the CC1 tool invocation, when necessary */
|
||||||
|
#cmakedefine01 CLANG_SPAWN_CC1
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
@ -204,6 +204,13 @@ public:
|
|||||||
/// Whether the driver is generating diagnostics for debugging purposes.
|
/// Whether the driver is generating diagnostics for debugging purposes.
|
||||||
unsigned CCGenDiagnostics : 1;
|
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 = nullptr;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
/// Raw target triple.
|
/// Raw target triple.
|
||||||
std::string TargetTriple;
|
std::string TargetTriple;
|
||||||
|
@ -119,7 +119,7 @@ public:
|
|||||||
/// \param NewEnvironment An array of environment variables.
|
/// \param NewEnvironment An array of environment variables.
|
||||||
/// \remark If the environment remains unset, then the environment
|
/// \remark If the environment remains unset, then the environment
|
||||||
/// from the parent process will be used.
|
/// 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; }
|
const char *getExecutable() const { return Executable; }
|
||||||
|
|
||||||
@ -130,6 +130,24 @@ public:
|
|||||||
|
|
||||||
/// Set whether to print the input filenames when executing.
|
/// Set whether to print the input filenames when executing.
|
||||||
void setPrintInputFilenames(bool P) { PrintInputFilenames = P; }
|
void setPrintInputFilenames(bool P) { PrintInputFilenames = P; }
|
||||||
|
|
||||||
|
protected:
|
||||||
|
/// Optionally print the filenames to be compiled
|
||||||
|
void PrintFileNames() 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 setEnvironment(llvm::ArrayRef<const char *> NewEnvironment) override;
|
||||||
};
|
};
|
||||||
|
|
||||||
/// Like Command, but with a fallback which is executed in case
|
/// Like Command, but with a fallback which is executed in case
|
||||||
|
@ -19,8 +19,10 @@
|
|||||||
#include "llvm/ADT/StringRef.h"
|
#include "llvm/ADT/StringRef.h"
|
||||||
#include "llvm/ADT/StringSet.h"
|
#include "llvm/ADT/StringSet.h"
|
||||||
#include "llvm/ADT/StringSwitch.h"
|
#include "llvm/ADT/StringSwitch.h"
|
||||||
|
#include "llvm/Support/CrashRecoveryContext.h"
|
||||||
#include "llvm/Support/FileSystem.h"
|
#include "llvm/Support/FileSystem.h"
|
||||||
#include "llvm/Support/Path.h"
|
#include "llvm/Support/Path.h"
|
||||||
|
#include "llvm/Support/PrettyStackTrace.h"
|
||||||
#include "llvm/Support/Program.h"
|
#include "llvm/Support/Program.h"
|
||||||
#include "llvm/Support/raw_ostream.h"
|
#include "llvm/Support/raw_ostream.h"
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
@ -313,15 +315,46 @@ void Command::setEnvironment(llvm::ArrayRef<const char *> NewEnvironment) {
|
|||||||
Environment.push_back(nullptr);
|
Environment.push_back(nullptr);
|
||||||
}
|
}
|
||||||
|
|
||||||
int Command::Execute(ArrayRef<llvm::Optional<StringRef>> Redirects,
|
void Command::PrintFileNames() const {
|
||||||
std::string *ErrMsg, bool *ExecutionFailed) const {
|
|
||||||
if (PrintInputFilenames) {
|
if (PrintInputFilenames) {
|
||||||
for (const char *Arg : InputFilenames)
|
for (const char *Arg : InputFilenames)
|
||||||
llvm::outs() << llvm::sys::path::filename(Arg) << "\n";
|
llvm::outs() << llvm::sys::path::filename(Arg) << "\n";
|
||||||
llvm::outs().flush();
|
llvm::outs().flush();
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
SmallVector<const char*, 128> Argv;
|
int Command::Execute(ArrayRef<llvm::Optional<StringRef>> Redirects,
|
||||||
|
std::string *ErrMsg, bool *ExecutionFailed) const {
|
||||||
|
PrintFileNames();
|
||||||
|
|
||||||
|
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 by convention (see llvm/include/llvm/Support/Program.h) to
|
||||||
|
// indicate the requested executable cannot be started.
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
Optional<ArrayRef<StringRef>> Env;
|
Optional<ArrayRef<StringRef>> Env;
|
||||||
std::vector<StringRef> ArgvVectorStorage;
|
std::vector<StringRef> ArgvVectorStorage;
|
||||||
@ -332,44 +365,53 @@ int Command::Execute(ArrayRef<llvm::Optional<StringRef>> Redirects,
|
|||||||
Env = makeArrayRef(ArgvVectorStorage);
|
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());
|
auto Args = llvm::toStringRefArray(Argv.data());
|
||||||
return llvm::sys::ExecuteAndWait(Executable, Args, Env, Redirects,
|
return llvm::sys::ExecuteAndWait(Executable, Args, Env, Redirects,
|
||||||
/*secondsToWait*/ 0,
|
/*secondsToWait*/ 0,
|
||||||
/*memoryLimit*/ 0, ErrMsg, ExecutionFailed);
|
/*memoryLimit*/ 0, ErrMsg, ExecutionFailed);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void CC1Command::Print(raw_ostream &OS, const char *Terminator, bool Quote,
|
||||||
|
CrashReportInfo *CrashInfo) const {
|
||||||
|
OS << " (in-process)";
|
||||||
|
Command::Print(OS, Terminator, Quote, CrashInfo);
|
||||||
|
}
|
||||||
|
|
||||||
|
int CC1Command::Execute(ArrayRef<llvm::Optional<StringRef>> /*Redirects*/,
|
||||||
|
std::string *ErrMsg, bool *ExecutionFailed) const {
|
||||||
|
PrintFileNames();
|
||||||
|
|
||||||
|
SmallVector<const char *, 128> Argv;
|
||||||
|
Argv.push_back(getExecutable());
|
||||||
|
Argv.append(getArguments().begin(), getArguments().end());
|
||||||
|
Argv.push_back(nullptr);
|
||||||
|
|
||||||
|
// This flag simply indicates that the program couldn't start, which isn't
|
||||||
|
// applicable here.
|
||||||
|
if (ExecutionFailed)
|
||||||
|
*ExecutionFailed = false;
|
||||||
|
|
||||||
|
llvm::CrashRecoveryContext CRC;
|
||||||
|
CRC.DumpStackAndCleanupOnFailure = true;
|
||||||
|
|
||||||
|
const void *PrettyState = llvm::SavePrettyStackState();
|
||||||
|
const Driver &D = getCreator().getToolChain().getDriver();
|
||||||
|
|
||||||
|
int R = 0;
|
||||||
|
// 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::setEnvironment(llvm::ArrayRef<const char *> NewEnvironment) {
|
||||||
|
// We don't support set a new environment when calling into ExecuteCC1Tool()
|
||||||
|
llvm_unreachable(
|
||||||
|
"The CC1Command doesn't support changing the environment vars!");
|
||||||
|
}
|
||||||
|
|
||||||
FallbackCommand::FallbackCommand(const Action &Source_, const Tool &Creator_,
|
FallbackCommand::FallbackCommand(const Action &Source_, const Tool &Creator_,
|
||||||
const char *Executable_,
|
const char *Executable_,
|
||||||
const llvm::opt::ArgStringList &Arguments_,
|
const llvm::opt::ArgStringList &Arguments_,
|
||||||
|
@ -5979,6 +5979,10 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,
|
|||||||
// fails, so that the main compilation's fallback to cl.exe runs.
|
// fails, so that the main compilation's fallback to cl.exe runs.
|
||||||
C.addCommand(std::make_unique<ForceSuccessCommand>(JA, *this, Exec,
|
C.addCommand(std::make_unique<ForceSuccessCommand>(JA, *this, Exec,
|
||||||
CmdArgs, Inputs));
|
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 {
|
} else {
|
||||||
C.addCommand(std::make_unique<Command>(JA, *this, Exec, CmdArgs, Inputs));
|
C.addCommand(std::make_unique<Command>(JA, *this, Exec, CmdArgs, Inputs));
|
||||||
}
|
}
|
||||||
|
@ -13,6 +13,7 @@ llvm_canonicalize_cmake_booleans(
|
|||||||
CLANG_BUILD_EXAMPLES
|
CLANG_BUILD_EXAMPLES
|
||||||
CLANG_ENABLE_ARCMT
|
CLANG_ENABLE_ARCMT
|
||||||
CLANG_ENABLE_STATIC_ANALYZER
|
CLANG_ENABLE_STATIC_ANALYZER
|
||||||
|
CLANG_SPAWN_CC1
|
||||||
ENABLE_BACKTRACES
|
ENABLE_BACKTRACES
|
||||||
ENABLE_EXPERIMENTAL_NEW_PASS_MANAGER
|
ENABLE_EXPERIMENTAL_NEW_PASS_MANAGER
|
||||||
LLVM_ENABLE_ZLIB
|
LLVM_ENABLE_ZLIB
|
||||||
|
4
clang/test/Driver/cc1-spawnprocess.c
Normal file
4
clang/test/Driver/cc1-spawnprocess.c
Normal file
@ -0,0 +1,4 @@
|
|||||||
|
// RUN: env -u CLANG_SPAWN_CC1 %clang -c %s -o /dev/null
|
||||||
|
// RUN: env CLANG_SPAWN_CC1=0 %clang -c %s -o /dev/null
|
||||||
|
// RUN: env CLANG_SPAWN_CC1=1 %clang -c %s -o /dev/null
|
||||||
|
// RUN: env CLANG_SPAWN_CC1=test not %clang -c %s -o /dev/null
|
@ -493,7 +493,7 @@
|
|||||||
// RUN: %clang -target x86_64-unknown-none-none -### -fno-short-wchar -fshort-wchar %s 2>&1 | FileCheck -check-prefix=CHECK-WCHAR2 -check-prefix=DELIMITERS %s
|
// RUN: %clang -target x86_64-unknown-none-none -### -fno-short-wchar -fshort-wchar %s 2>&1 | FileCheck -check-prefix=CHECK-WCHAR2 -check-prefix=DELIMITERS %s
|
||||||
// Make sure we don't match the -NOT lines with the linker invocation.
|
// Make sure we don't match the -NOT lines with the linker invocation.
|
||||||
// Delimiters match the start of the cc1 and the start of the linker lines
|
// Delimiters match the start of the cc1 and the start of the linker lines
|
||||||
// DELIMITERS: {{^ *"}}
|
// DELIMITERS: {{^ (\(in-process\)|")}}
|
||||||
// CHECK-WCHAR1: -fwchar-type=int
|
// CHECK-WCHAR1: -fwchar-type=int
|
||||||
// CHECK-WCHAR1-NOT: -fwchar-type=short
|
// CHECK-WCHAR1-NOT: -fwchar-type=short
|
||||||
// CHECK-WCHAR2: -fwchar-type=short
|
// CHECK-WCHAR2: -fwchar-type=short
|
||||||
|
@ -6,7 +6,7 @@
|
|||||||
// Make sure we don't match the -NOT lines with the linker invocation.
|
// Make sure we don't match the -NOT lines with the linker invocation.
|
||||||
// Delimiters match the start of the cc1 and the start of the linker lines
|
// Delimiters match the start of the cc1 and the start of the linker lines
|
||||||
// for fragile tests.
|
// for fragile tests.
|
||||||
// DELIMITERS: {{^ *"}}
|
// DELIMITERS: {{^ (\(in-process\)|")}}
|
||||||
|
|
||||||
// RUN: echo "fun:foo" > %t.good
|
// RUN: echo "fun:foo" > %t.good
|
||||||
// RUN: echo "fun:bar" > %t.second
|
// RUN: echo "fun:bar" > %t.second
|
||||||
|
@ -54,7 +54,7 @@
|
|||||||
// SILENT-NOT: warning:
|
// SILENT-NOT: warning:
|
||||||
// CC1AS-DID-YOU-MEAN: error: unknown argument '-hell'; did you mean '-help'?
|
// CC1AS-DID-YOU-MEAN: error: unknown argument '-hell'; did you mean '-help'?
|
||||||
// CC1AS-DID-YOU-MEAN: error: unknown argument '--version'; did you mean '-version'?
|
// CC1AS-DID-YOU-MEAN: error: unknown argument '--version'; did you mean '-version'?
|
||||||
// UNKNOWN-INTEGRATED: error: unknown integrated tool 'asphalt'. Valid tools include '-cc1' and '-cc1as'.
|
// UNKNOWN-INTEGRATED: error: unknown integrated tool '-cc1asphalt'. Valid tools include '-cc1' and '-cc1as'.
|
||||||
|
|
||||||
// RUN: %clang -S %s -o %t.s -Wunknown-to-clang-option 2>&1 | FileCheck --check-prefix=IGNORED %s
|
// RUN: %clang -S %s -o %t.s -Wunknown-to-clang-option 2>&1 | FileCheck --check-prefix=IGNORED %s
|
||||||
|
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
// Make sure we don't match the -NOT lines with the linker invocation.
|
// Make sure we don't match the -NOT lines with the linker invocation.
|
||||||
// Delimiters match the start of the cc1 and the start of the linker lines
|
// Delimiters match the start of the cc1 and the start of the linker lines
|
||||||
// DELIMITERS: {{^ *"}}
|
// DELIMITERS: {{^ (\(in-process\)|")}}
|
||||||
|
|
||||||
// RUN: %clang -### -pedantic -no-pedantic %s 2>&1 | FileCheck -check-prefix=NO_PEDANTIC -check-prefix=DELIMITERS %s
|
// RUN: %clang -### -pedantic -no-pedantic %s 2>&1 | FileCheck -check-prefix=NO_PEDANTIC -check-prefix=DELIMITERS %s
|
||||||
// RUN: %clang -### -pedantic -Wno-pedantic %s 2>&1 | FileCheck -check-prefix=PEDANTIC -check-prefix=DELIMITERS %s
|
// RUN: %clang -### -pedantic -Wno-pedantic %s 2>&1 | FileCheck -check-prefix=PEDANTIC -check-prefix=DELIMITERS %s
|
||||||
|
@ -14,6 +14,7 @@
|
|||||||
#include "clang/Driver/Driver.h"
|
#include "clang/Driver/Driver.h"
|
||||||
#include "clang/Basic/DiagnosticOptions.h"
|
#include "clang/Basic/DiagnosticOptions.h"
|
||||||
#include "clang/Basic/Stack.h"
|
#include "clang/Basic/Stack.h"
|
||||||
|
#include "clang/Config/config.h"
|
||||||
#include "clang/Driver/Compilation.h"
|
#include "clang/Driver/Compilation.h"
|
||||||
#include "clang/Driver/DriverDiagnostic.h"
|
#include "clang/Driver/DriverDiagnostic.h"
|
||||||
#include "clang/Driver/Options.h"
|
#include "clang/Driver/Options.h"
|
||||||
@ -30,6 +31,7 @@
|
|||||||
#include "llvm/Option/OptTable.h"
|
#include "llvm/Option/OptTable.h"
|
||||||
#include "llvm/Option/Option.h"
|
#include "llvm/Option/Option.h"
|
||||||
#include "llvm/Support/CommandLine.h"
|
#include "llvm/Support/CommandLine.h"
|
||||||
|
#include "llvm/Support/CrashRecoveryContext.h"
|
||||||
#include "llvm/Support/ErrorHandling.h"
|
#include "llvm/Support/ErrorHandling.h"
|
||||||
#include "llvm/Support/FileSystem.h"
|
#include "llvm/Support/FileSystem.h"
|
||||||
#include "llvm/Support/Host.h"
|
#include "llvm/Support/Host.h"
|
||||||
@ -239,6 +241,8 @@ static void getCLEnvVarOptions(std::string &EnvValue, llvm::StringSaver &Saver,
|
|||||||
*NumberSignPtr = '=';
|
*NumberSignPtr = '=';
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int ExecuteCC1Tool(ArrayRef<const char *> argv);
|
||||||
|
|
||||||
static void SetBackdoorDriverOutputsFromEnvVars(Driver &TheDriver) {
|
static void SetBackdoorDriverOutputsFromEnvVars(Driver &TheDriver) {
|
||||||
// Handle CC_PRINT_OPTIONS and CC_PRINT_OPTIONS_FILE.
|
// Handle CC_PRINT_OPTIONS and CC_PRINT_OPTIONS_FILE.
|
||||||
TheDriver.CCPrintOptions = !!::getenv("CC_PRINT_OPTIONS");
|
TheDriver.CCPrintOptions = !!::getenv("CC_PRINT_OPTIONS");
|
||||||
@ -254,6 +258,27 @@ static void SetBackdoorDriverOutputsFromEnvVars(Driver &TheDriver) {
|
|||||||
TheDriver.CCLogDiagnostics = !!::getenv("CC_LOG_DIAGNOSTICS");
|
TheDriver.CCLogDiagnostics = !!::getenv("CC_LOG_DIAGNOSTICS");
|
||||||
if (TheDriver.CCLogDiagnostics)
|
if (TheDriver.CCLogDiagnostics)
|
||||||
TheDriver.CCLogDiagnosticsFilename = ::getenv("CC_LOG_DIAGNOSTICS_FILE");
|
TheDriver.CCLogDiagnosticsFilename = ::getenv("CC_LOG_DIAGNOSTICS_FILE");
|
||||||
|
|
||||||
|
// Whether the cc1 tool should be called inside the current process, or if we
|
||||||
|
// should spawn a new clang process (old behavior).
|
||||||
|
// Not having an additional process saves some execution time of Windows,
|
||||||
|
// and makes debugging easier.
|
||||||
|
bool UseNewCC1Process = CLANG_SPAWN_CC1;
|
||||||
|
|
||||||
|
StringRef SpawnCC1Str = ::getenv("CLANG_SPAWN_CC1");
|
||||||
|
if (!SpawnCC1Str.empty()) {
|
||||||
|
if (SpawnCC1Str != "0" && SpawnCC1Str != "1") {
|
||||||
|
llvm::errs() << "error: the value of the environment variable "
|
||||||
|
"CLANG_SPAWN_CC1 must be either 0 or 1.\n";
|
||||||
|
::exit(1);
|
||||||
|
}
|
||||||
|
UseNewCC1Process = SpawnCC1Str[0] - '0';
|
||||||
|
}
|
||||||
|
if (!UseNewCC1Process) {
|
||||||
|
TheDriver.CC1Main = &ExecuteCC1Tool;
|
||||||
|
// Ensure the CC1Command actually catches cc1 crashes
|
||||||
|
llvm::CrashRecoveryContext::Enable();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void FixupDiagPrefixExeName(TextDiagnosticPrinter *DiagClient,
|
static void FixupDiagPrefixExeName(TextDiagnosticPrinter *DiagClient,
|
||||||
@ -303,13 +328,19 @@ static void SetInstallDir(SmallVectorImpl<const char *> &argv,
|
|||||||
TheDriver.setInstalledDir(InstalledPathParent);
|
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];
|
||||||
void *GetExecutablePathVP = (void *)(intptr_t) GetExecutablePath;
|
void *GetExecutablePathVP = (void *)(intptr_t) GetExecutablePath;
|
||||||
if (Tool == "")
|
if (Tool == "-cc1")
|
||||||
return cc1_main(argv.slice(2), argv[0], GetExecutablePathVP);
|
return cc1_main(argv.slice(2), argv[0], GetExecutablePathVP);
|
||||||
if (Tool == "as")
|
if (Tool == "-cc1as")
|
||||||
return cc1as_main(argv.slice(2), argv[0], GetExecutablePathVP);
|
return cc1as_main(argv.slice(2), argv[0], GetExecutablePathVP);
|
||||||
if (Tool == "gen-reproducer")
|
if (Tool == "-cc1gen-reproducer")
|
||||||
return cc1gen_reproducer_main(argv.slice(2), argv[0], GetExecutablePathVP);
|
return cc1gen_reproducer_main(argv.slice(2), argv[0], GetExecutablePathVP);
|
||||||
|
|
||||||
// Reject unknown tools.
|
// Reject unknown tools.
|
||||||
@ -379,7 +410,7 @@ int main(int argc_, const char **argv_) {
|
|||||||
auto newEnd = std::remove(argv.begin(), argv.end(), nullptr);
|
auto newEnd = std::remove(argv.begin(), argv.end(), nullptr);
|
||||||
argv.resize(newEnd - argv.begin());
|
argv.resize(newEnd - argv.begin());
|
||||||
}
|
}
|
||||||
return ExecuteCC1Tool(argv, argv[1] + 4);
|
return ExecuteCC1Tool(argv);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool CanonicalPrefixes = true;
|
bool CanonicalPrefixes = true;
|
||||||
@ -503,7 +534,7 @@ int main(int argc_, const char **argv_) {
|
|||||||
|
|
||||||
#ifdef _WIN32
|
#ifdef _WIN32
|
||||||
// Exit status should not be negative on Win32, unless abnormal termination.
|
// 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.
|
// propagated.
|
||||||
if (Res < 0)
|
if (Res < 0)
|
||||||
Res = 1;
|
Res = 1;
|
||||||
|
Loading…
Reference in New Issue
Block a user