Index: clang/include/clang/Driver/Options.td =================================================================== --- clang/include/clang/Driver/Options.td +++ clang/include/clang/Driver/Options.td @@ -2855,6 +2855,13 @@ def fno_integrated_as : Flag<["-"], "fno-integrated-as">, Flags<[CC1Option, DriverOption]>, Group, HelpText<"Disable the integrated assembler">; + +def fintegrated_cc1 : Flag<["-"], "fintegrated-cc1">, Flags<[DriverOption]>, + Group, HelpText<"Run cc1 in-process">; +def fno_integrated_cc1 : Flag<["-"], "fno-integrated-cc1">, + Flags<[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]>; Index: clang/lib/Driver/Driver.cpp =================================================================== --- clang/lib/Driver/Driver.cpp +++ clang/lib/Driver/Driver.cpp @@ -1035,6 +1035,10 @@ // -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); Index: clang/test/Driver/cc1-spawnprocess.c =================================================================== --- clang/test/Driver/cc1-spawnprocess.c +++ clang/test/Driver/cc1-spawnprocess.c @@ -1,4 +1,5 @@ -// 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 + +// YES: (in-process) +// NO-NOT: (in-process) Index: clang/tools/driver/driver.cpp =================================================================== --- clang/tools/driver/driver.cpp +++ clang/tools/driver/driver.cpp @@ -258,27 +258,6 @@ 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, @@ -330,7 +309,7 @@ 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,14 +392,26 @@ return ExecuteCC1Tool(argv); } + // Handle options that need handling before the real command line parsing in + // Driver::BuildCompilation() bool CanonicalPrefixes = true; + + // 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 = CLANG_SPAWN_CC1; + for (int i = 1, size = argv.size(); i < size; ++i) { // Skip end-of-line response file markers if (argv[i] == nullptr) continue; if (StringRef(argv[i]) == "-no-canonical-prefixes") { CanonicalPrefixes = false; - break; + } else if (StringRef(argv[i]) == "-fno-integrated-cc1") { + UseNewCC1Process = true; + } else if (StringRef(argv[i]) == "-fintegrated-cc1") { + UseNewCC1Process = false; } } @@ -486,6 +477,12 @@ 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()) {