From c4a134a5107c1926262ee887057036ca53aa7265 Mon Sep 17 00:00:00 2001 From: Nico Weber Date: Wed, 15 Jan 2020 10:45:02 -0500 Subject: [PATCH] Replace CLANG_SPAWN_CC1 env var with a driver mode flag Flags are clang's default UI is flags. We can have an env var in addition to that, but in D69825 nobody has yet mentioned why this needs an env var, so omit it for now. If someone needs to set the flag via env var, the existing CCC_OVERRIDE_OPTIONS mechanism works for it (set CCC_OVERRIDE_OPTIONS=+-fno-integrated-cc1 for example). Also mention the cc1-in-process change in the release notes. Also spruce up the test a bit so it actually tests something :) Differential Revision: https://reviews.llvm.org/D72769 (cherry picked from commit 8e5018e990b701391e6c33ba85b012343df67272) --- clang/docs/ReleaseNotes.rst | 5 +++ clang/include/clang/Driver/Options.td | 8 +++++ clang/lib/Driver/Driver.cpp | 4 +++ clang/test/Driver/cc1-spawnprocess.c | 26 ++++++++++++--- clang/tools/driver/driver.cpp | 47 +++++++++++++-------------- 5 files changed, 62 insertions(+), 28 deletions(-) diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst index e131e4f127803..881dcb78b6638 100644 --- a/clang/docs/ReleaseNotes.rst +++ b/clang/docs/ReleaseNotes.rst @@ -46,6 +46,11 @@ sections with improvements to Clang's support for those languages. Major New Features ------------------ +- clang used to run the actual compilation in a subprocess ("clang -cc1"). + Now compilations are done in-process by default. ``-fno-integrated-cc1`` + restores the former behavior. The ``-v`` and ``-###`` flags will print + "(in-process)" when compilations are done in-process. + - ... Improvements to Clang's diagnostics diff --git a/clang/include/clang/Driver/Options.td b/clang/include/clang/Driver/Options.td index 1218172fd5b69..abfa767afea8f 100644 --- a/clang/include/clang/Driver/Options.td +++ b/clang/include/clang/Driver/Options.td @@ -2855,6 +2855,14 @@ def fintegrated_as : Flag<["-"], "fintegrated-as">, Flags<[DriverOption]>, def fno_integrated_as : Flag<["-"], "fno-integrated-as">, Flags<[CC1Option, DriverOption]>, Group, HelpText<"Disable the integrated assembler">; + +def fintegrated_cc1 : Flag<["-"], "fintegrated-cc1">, + Flags<[CoreOption, DriverOption]>, Group, + HelpText<"Run cc1 in-process">; +def fno_integrated_cc1 : Flag<["-"], "fno-integrated-cc1">, + Flags<[CoreOption, DriverOption]>, Group, + HelpText<"Spawn a separate process for each cc1">; + def : Flag<["-"], "integrated-as">, Alias, Flags<[DriverOption]>; def : Flag<["-"], "no-integrated-as">, Alias, Flags<[CC1Option, DriverOption]>; diff --git a/clang/lib/Driver/Driver.cpp b/clang/lib/Driver/Driver.cpp index e718b8366df0e..7ee3caaa0bce0 100644 --- a/clang/lib/Driver/Driver.cpp +++ b/clang/lib/Driver/Driver.cpp @@ -1035,6 +1035,10 @@ Compilation *Driver::BuildCompilation(ArrayRef ArgList) { // -no-canonical-prefixes is used very early in main. Args.ClaimAllArgs(options::OPT_no_canonical_prefixes); + // f(no-)integated-cc1 is also used very early in main. + Args.ClaimAllArgs(options::OPT_fintegrated_cc1); + Args.ClaimAllArgs(options::OPT_fno_integrated_cc1); + // Ignore -pipe. Args.ClaimAllArgs(options::OPT_pipe); diff --git a/clang/test/Driver/cc1-spawnprocess.c b/clang/test/Driver/cc1-spawnprocess.c index c5c16ce8513fc..624593895961e 100644 --- a/clang/test/Driver/cc1-spawnprocess.c +++ b/clang/test/Driver/cc1-spawnprocess.c @@ -1,4 +1,22 @@ -// RUN: env CLANG_SPAWN_CC1= %clang -S %s -o /dev/null -// RUN: env CLANG_SPAWN_CC1=0 %clang -S %s -o /dev/null -// RUN: env CLANG_SPAWN_CC1=1 %clang -S %s -o /dev/null -// RUN: env CLANG_SPAWN_CC1=test not %clang -S %s -o /dev/null +// RUN: %clang -fintegrated-cc1 -### %s 2>&1 | FileCheck %s --check-prefix=YES +// RUN: %clang -fno-integrated-cc1 -### %s 2>&1 | FileCheck %s --check-prefix=NO + +// RUN: %clang -fintegrated-cc1 -fno-integrated-cc1 -### %s 2>&1 \ +// RUN: | FileCheck %s --check-prefix=NO +// RUN: %clang -fno-integrated-cc1 -fintegrated-cc1 -### %s 2>&1 \ +// RUN: | FileCheck %s --check-prefix=YES + +// RUN: %clang_cl -fintegrated-cc1 -### -- %s 2>&1 \ +// RUN: | FileCheck %s --check-prefix=YES +// RUN: %clang_cl -fno-integrated-cc1 -### -- %s 2>&1 \ +// RUN: | FileCheck %s --check-prefix=NO + +// RUN: env CCC_OVERRIDE_OPTIONS=+-fintegrated-cc1 \ +// RUN: %clang -fintegrated-cc1 -### %s 2>&1 \ +// RUN: | FileCheck %s --check-prefix=YES +// RUN: env CCC_OVERRIDE_OPTIONS=+-fno-integrated-cc1 \ +// RUN: %clang -fintegrated-cc1 -### %s 2>&1 \ +// RUN: | FileCheck %s --check-prefix=NO + +// YES: (in-process) +// NO-NOT: (in-process) diff --git a/clang/tools/driver/driver.cpp b/clang/tools/driver/driver.cpp index 4cdf8015b1bfc..39f6c7f62be41 100644 --- a/clang/tools/driver/driver.cpp +++ b/clang/tools/driver/driver.cpp @@ -258,27 +258,6 @@ static void SetBackdoorDriverOutputsFromEnvVars(Driver &TheDriver) { TheDriver.CCLogDiagnostics = !!::getenv("CC_LOG_DIAGNOSTICS"); if (TheDriver.CCLogDiagnostics) 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, @@ -294,7 +273,7 @@ static void FixupDiagPrefixExeName(TextDiagnosticPrinter *DiagClient, // This lets us create the DiagnosticsEngine with a properly-filled-out // DiagnosticOptions instance. static DiagnosticOptions * -CreateAndPopulateDiagOpts(ArrayRef argv) { +CreateAndPopulateDiagOpts(ArrayRef argv, bool &UseNewCC1Process) { auto *DiagOpts = new DiagnosticOptions; unsigned MissingArgIndex, MissingArgCount; InputArgList Args = getDriverOptTable().ParseArgs( @@ -303,6 +282,12 @@ CreateAndPopulateDiagOpts(ArrayRef argv) { // Any errors that would be diagnosed here will also be diagnosed later, // when the DiagnosticsEngine actually exists. (void)ParseDiagnosticArgs(*DiagOpts, Args); + + UseNewCC1Process = + Args.hasFlag(clang::driver::options::OPT_fno_integrated_cc1, + clang::driver::options::OPT_fintegrated_cc1, + /*Default=*/CLANG_SPAWN_CC1); + return DiagOpts; } @@ -330,7 +315,7 @@ static void SetInstallDir(SmallVectorImpl &argv, static int ExecuteCC1Tool(ArrayRef argv) { // If we call the cc1 tool from the clangDriver library (through - // Driver::CC1Main), we need to cleanup the options usage count. The options + // Driver::CC1Main), we need to clean up the options usage count. The options // are currently global, and they might have been used previously by the // driver. llvm::cl::ResetAllOptionOccurrences(); @@ -413,6 +398,8 @@ int main(int argc_, const char **argv_) { return ExecuteCC1Tool(argv); } + // Handle options that need handling before the real command line parsing in + // Driver::BuildCompilation() bool CanonicalPrefixes = true; for (int i = 1, size = argv.size(); i < size; ++i) { // Skip end-of-line response file markers @@ -457,8 +444,14 @@ int main(int argc_, const char **argv_) { std::string Path = GetExecutablePath(argv[0], CanonicalPrefixes); + // Whether the cc1 tool should be called inside the current process, or if we + // should spawn a new clang subprocess (old behavior). + // Not having an additional process saves some execution time of Windows, + // and makes debugging and profiling easier. + bool UseNewCC1Process; + IntrusiveRefCntPtr DiagOpts = - CreateAndPopulateDiagOpts(argv); + CreateAndPopulateDiagOpts(argv, UseNewCC1Process); TextDiagnosticPrinter *DiagClient = new TextDiagnosticPrinter(llvm::errs(), &*DiagOpts); @@ -486,6 +479,12 @@ int main(int argc_, const char **argv_) { SetBackdoorDriverOutputsFromEnvVars(TheDriver); + if (!UseNewCC1Process) { + TheDriver.CC1Main = &ExecuteCC1Tool; + // Ensure the CC1Command actually catches cc1 crashes + llvm::CrashRecoveryContext::Enable(); + } + std::unique_ptr C(TheDriver.BuildCompilation(argv)); int Res = 1; if (C && !C->containsError()) {