diff options
Diffstat (limited to 'clang/tools')
-rw-r--r-- | clang/tools/driver/cc1_main.cpp | 10 | ||||
-rw-r--r-- | clang/tools/driver/cc1as_main.cpp | 44 | ||||
-rw-r--r-- | clang/tools/driver/cc1gen_reproducer_main.cpp | 1 | ||||
-rw-r--r-- | clang/tools/driver/driver.cpp | 106 |
4 files changed, 94 insertions, 67 deletions
diff --git a/clang/tools/driver/cc1_main.cpp b/clang/tools/driver/cc1_main.cpp index b551e9f4cf829..0872015e0ab05 100644 --- a/clang/tools/driver/cc1_main.cpp +++ b/clang/tools/driver/cc1_main.cpp @@ -36,6 +36,7 @@ #include "llvm/Support/ErrorHandling.h" #include "llvm/Support/ManagedStatic.h" #include "llvm/Support/Path.h" +#include "llvm/Support/Process.h" #include "llvm/Support/Signals.h" #include "llvm/Support/TargetRegistry.h" #include "llvm/Support/TargetSelect.h" @@ -69,7 +70,7 @@ static void LLVMErrorHandler(void *UserData, const std::string &Message, // We cannot recover from llvm errors. When reporting a fatal error, exit // with status 70 to generate crash diagnostics. For BSD systems this is // defined as an internal software error. Otherwise, exit with status 1. - exit(GenCrashDiag ? 70 : 1); + llvm::sys::Process::Exit(GenCrashDiag ? 70 : 1); } #ifdef CLANG_HAVE_RLIMITS @@ -176,7 +177,7 @@ static int PrintSupportedCPUs(std::string TargetStr) { // the target machine will handle the mcpu printing llvm::TargetOptions Options; std::unique_ptr<llvm::TargetMachine> TheTargetMachine( - TheTarget->createTargetMachine(TargetStr, "", "+cpuHelp", Options, None)); + TheTarget->createTargetMachine(TargetStr, "", "+cpuhelp", Options, None)); return 0; } @@ -202,8 +203,8 @@ int cc1_main(ArrayRef<const char *> Argv, const char *Argv0, void *MainAddr) { IntrusiveRefCntPtr<DiagnosticOptions> DiagOpts = new DiagnosticOptions(); TextDiagnosticBuffer *DiagsBuffer = new TextDiagnosticBuffer; DiagnosticsEngine Diags(DiagID, &*DiagOpts, DiagsBuffer); - bool Success = - CompilerInvocation::CreateFromArgs(Clang->getInvocation(), Argv, Diags); + bool Success = CompilerInvocation::CreateFromArgs(Clang->getInvocation(), + Argv, Diags, Argv0); if (Clang->getFrontendOpts().TimeTrace) { llvm::timeTraceProfilerInitialize( @@ -258,6 +259,7 @@ int cc1_main(ArrayRef<const char *> Argv, const char *Argv0, void *MainAddr) { // FIXME(ibiryukov): make profilerOutput flush in destructor instead. profilerOutput->flush(); llvm::timeTraceProfilerCleanup(); + Clang->clearOutputFiles(false); } } diff --git a/clang/tools/driver/cc1as_main.cpp b/clang/tools/driver/cc1as_main.cpp index 53c8a9d642dc0..77b99b2013640 100644 --- a/clang/tools/driver/cc1as_main.cpp +++ b/clang/tools/driver/cc1as_main.cpp @@ -46,6 +46,7 @@ #include "llvm/Support/Host.h" #include "llvm/Support/MemoryBuffer.h" #include "llvm/Support/Path.h" +#include "llvm/Support/Process.h" #include "llvm/Support/Signals.h" #include "llvm/Support/SourceMgr.h" #include "llvm/Support/TargetRegistry.h" @@ -206,7 +207,7 @@ bool AssemblerInvocation::CreateFromArgs(AssemblerInvocation &Opts, // Target Options Opts.Triple = llvm::Triple::normalize(Args.getLastArgValue(OPT_triple)); - Opts.CPU = Args.getLastArgValue(OPT_target_cpu); + Opts.CPU = std::string(Args.getLastArgValue(OPT_target_cpu)); Opts.Features = Args.getAllArgValues(OPT_target_feature); // Use the default target triple if unspecified. @@ -237,13 +238,19 @@ bool AssemblerInvocation::CreateFromArgs(AssemblerInvocation &Opts, Opts.RelaxELFRelocations = Args.hasArg(OPT_mrelax_relocations); Opts.DwarfVersion = getLastArgIntValue(Args, OPT_dwarf_version_EQ, 2, Diags); - Opts.DwarfDebugFlags = Args.getLastArgValue(OPT_dwarf_debug_flags); - Opts.DwarfDebugProducer = Args.getLastArgValue(OPT_dwarf_debug_producer); - Opts.DebugCompilationDir = Args.getLastArgValue(OPT_fdebug_compilation_dir); - Opts.MainFileName = Args.getLastArgValue(OPT_main_file_name); - - for (const auto &Arg : Args.getAllArgValues(OPT_fdebug_prefix_map_EQ)) - Opts.DebugPrefixMap.insert(StringRef(Arg).split('=')); + Opts.DwarfDebugFlags = + std::string(Args.getLastArgValue(OPT_dwarf_debug_flags)); + Opts.DwarfDebugProducer = + std::string(Args.getLastArgValue(OPT_dwarf_debug_producer)); + Opts.DebugCompilationDir = + std::string(Args.getLastArgValue(OPT_fdebug_compilation_dir)); + Opts.MainFileName = std::string(Args.getLastArgValue(OPT_main_file_name)); + + for (const auto &Arg : Args.getAllArgValues(OPT_fdebug_prefix_map_EQ)) { + auto Split = StringRef(Arg).split('='); + Opts.DebugPrefixMap.insert( + {std::string(Split.first), std::string(Split.second)}); + } // Frontend Options if (Args.hasArg(OPT_INPUT)) { @@ -259,8 +266,9 @@ bool AssemblerInvocation::CreateFromArgs(AssemblerInvocation &Opts, } } Opts.LLVMArgs = Args.getAllArgValues(OPT_mllvm); - Opts.OutputPath = Args.getLastArgValue(OPT_o); - Opts.SplitDwarfOutput = Args.getLastArgValue(OPT_split_dwarf_output); + Opts.OutputPath = std::string(Args.getLastArgValue(OPT_o)); + Opts.SplitDwarfOutput = + std::string(Args.getLastArgValue(OPT_split_dwarf_output)); if (Arg *A = Args.getLastArg(OPT_filetype)) { StringRef Name = A->getValue(); unsigned OutputType = StringSwitch<unsigned>(Name) @@ -288,8 +296,9 @@ bool AssemblerInvocation::CreateFromArgs(AssemblerInvocation &Opts, Opts.NoExecStack = Args.hasArg(OPT_mno_exec_stack); Opts.FatalWarnings = Args.hasArg(OPT_massembler_fatal_warnings); Opts.NoWarn = Args.hasArg(OPT_massembler_no_warn); - Opts.RelocationModel = Args.getLastArgValue(OPT_mrelocation_model, "pic"); - Opts.TargetABI = Args.getLastArgValue(OPT_target_abi); + Opts.RelocationModel = + std::string(Args.getLastArgValue(OPT_mrelocation_model, "pic")); + Opts.TargetABI = std::string(Args.getLastArgValue(OPT_target_abi)); Opts.IncrementalLinkerCompatible = Args.hasArg(OPT_mincremental_linker_compatible); Opts.SymbolDefs = Args.getAllArgValues(OPT_defsym); @@ -420,12 +429,7 @@ static bool ExecuteAssembler(AssemblerInvocation &Opts, SrcMgr.getMemoryBuffer(BufferIndex)->getBuffer()); // Build up the feature string from the target feature list. - std::string FS; - if (!Opts.Features.empty()) { - FS = Opts.Features[0]; - for (unsigned i = 1, e = Opts.Features.size(); i != e; ++i) - FS += "," + Opts.Features[i]; - } + std::string FS = llvm::join(Opts.Features, ","); std::unique_ptr<MCStreamer> Str; @@ -489,7 +493,7 @@ static bool ExecuteAssembler(AssemblerInvocation &Opts, MCSection *AsmLabel = Ctx.getMachOSection( "__LLVM", "__asm", MachO::S_REGULAR, 4, SectionKind::getReadOnly()); Str.get()->SwitchSection(AsmLabel); - Str.get()->EmitZeros(1); + Str.get()->emitZeros(1); } // Assembly to object compilation should leverage assembly info. @@ -547,7 +551,7 @@ static void LLVMErrorHandler(void *UserData, const std::string &Message, Diags.Report(diag::err_fe_error_backend) << Message; // We cannot recover from llvm errors. - exit(1); + sys::Process::Exit(1); } int cc1as_main(ArrayRef<const char *> Argv, const char *Argv0, void *MainAddr) { diff --git a/clang/tools/driver/cc1gen_reproducer_main.cpp b/clang/tools/driver/cc1gen_reproducer_main.cpp index 4aadab7301bc9..472055ee21708 100644 --- a/clang/tools/driver/cc1gen_reproducer_main.cpp +++ b/clang/tools/driver/cc1gen_reproducer_main.cpp @@ -18,6 +18,7 @@ #include "llvm/ADT/ArrayRef.h" #include "llvm/ADT/STLExtras.h" #include "llvm/Support/FileSystem.h" +#include "llvm/Support/Host.h" #include "llvm/Support/TargetSelect.h" #include "llvm/Support/VirtualFileSystem.h" #include "llvm/Support/YAMLTraits.h" diff --git a/clang/tools/driver/driver.cpp b/clang/tools/driver/driver.cpp index 4cdf8015b1bfc..f24fd61e61a54 100644 --- a/clang/tools/driver/driver.cpp +++ b/clang/tools/driver/driver.cpp @@ -30,6 +30,7 @@ #include "llvm/Option/ArgList.h" #include "llvm/Option/OptTable.h" #include "llvm/Option/Option.h" +#include "llvm/Support/BuryPointer.h" #include "llvm/Support/CommandLine.h" #include "llvm/Support/CrashRecoveryContext.h" #include "llvm/Support/ErrorHandling.h" @@ -37,6 +38,7 @@ #include "llvm/Support/Host.h" #include "llvm/Support/InitLLVM.h" #include "llvm/Support/Path.h" +#include "llvm/Support/PrettyStackTrace.h" #include "llvm/Support/Process.h" #include "llvm/Support/Program.h" #include "llvm/Support/Regex.h" @@ -60,7 +62,7 @@ std::string GetExecutablePath(const char *Argv0, bool CanonicalPrefixes) { if (llvm::ErrorOr<std::string> P = llvm::sys::findProgramByName(ExecutablePath)) ExecutablePath = *P; - return ExecutablePath.str(); + return std::string(ExecutablePath.str()); } // This just needs to be some symbol in the binary; C++ doesn't @@ -71,7 +73,7 @@ std::string GetExecutablePath(const char *Argv0, bool CanonicalPrefixes) { static const char *GetStableCStr(std::set<std::string> &SavedStrings, StringRef S) { - return SavedStrings.insert(S).first->c_str(); + return SavedStrings.insert(std::string(S)).first->c_str(); } /// ApplyQAOverride - Apply a list of edits to the input argument lists. @@ -241,8 +243,6 @@ static void getCLEnvVarOptions(std::string &EnvValue, llvm::StringSaver &Saver, *NumberSignPtr = '='; } -static int ExecuteCC1Tool(ArrayRef<const char *> argv); - static void SetBackdoorDriverOutputsFromEnvVars(Driver &TheDriver) { // Handle CC_PRINT_OPTIONS and CC_PRINT_OPTIONS_FILE. TheDriver.CCPrintOptions = !!::getenv("CC_PRINT_OPTIONS"); @@ -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, @@ -288,13 +267,13 @@ static void FixupDiagPrefixExeName(TextDiagnosticPrinter *DiagClient, StringRef ExeBasename(llvm::sys::path::stem(Path)); if (ExeBasename.equals_lower("cl")) ExeBasename = "clang-cl"; - DiagClient->setPrefix(ExeBasename); + DiagClient->setPrefix(std::string(ExeBasename)); } // This lets us create the DiagnosticsEngine with a properly-filled-out // DiagnosticOptions instance. static DiagnosticOptions * -CreateAndPopulateDiagOpts(ArrayRef<const char *> argv) { +CreateAndPopulateDiagOpts(ArrayRef<const char *> argv, bool &UseNewCC1Process) { auto *DiagOpts = new DiagnosticOptions; unsigned MissingArgIndex, MissingArgCount; InputArgList Args = getDriverOptTable().ParseArgs( @@ -303,6 +282,12 @@ CreateAndPopulateDiagOpts(ArrayRef<const char *> 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; } @@ -328,21 +313,27 @@ static void SetInstallDir(SmallVectorImpl<const char *> &argv, TheDriver.setInstalledDir(InstalledPathParent); } -static int ExecuteCC1Tool(ArrayRef<const char *> argv) { +static int ExecuteCC1Tool(SmallVectorImpl<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 + // 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(); - StringRef Tool = argv[1]; - void *GetExecutablePathVP = (void *)(intptr_t) GetExecutablePath; + + llvm::BumpPtrAllocator A; + llvm::StringSaver Saver(A); + llvm::cl::ExpandResponseFiles(Saver, &llvm::cl::TokenizeGNUCommandLine, ArgV, + /*MarkEOLs=*/false); + StringRef Tool = ArgV[1]; + void *GetExecutablePathVP = (void *)(intptr_t)GetExecutablePath; if (Tool == "-cc1") - return cc1_main(argv.slice(2), argv[0], GetExecutablePathVP); + return cc1_main(makeArrayRef(ArgV).slice(1), ArgV[0], GetExecutablePathVP); if (Tool == "-cc1as") - return cc1as_main(argv.slice(2), argv[0], GetExecutablePathVP); + return cc1as_main(makeArrayRef(ArgV).slice(2), ArgV[0], + GetExecutablePathVP); if (Tool == "-cc1gen-reproducer") - return cc1gen_reproducer_main(argv.slice(2), argv[0], GetExecutablePathVP); - + return cc1gen_reproducer_main(makeArrayRef(ArgV).slice(2), ArgV[0], + GetExecutablePathVP); // Reject unknown tools. llvm::errs() << "error: unknown integrated tool '" << Tool << "'. " << "Valid tools include '-cc1' and '-cc1as'.\n"; @@ -352,6 +343,9 @@ static int ExecuteCC1Tool(ArrayRef<const char *> argv) { int main(int argc_, const char **argv_) { noteBottomOfStack(); llvm::InitLLVM X(argc_, argv_); + llvm::setBugReportMsg("PLEASE submit a bug report to " BUG_REPORT_URL + " and include the crash backtrace, preprocessed " + "source, and associated run script.\n"); SmallVector<const char *, 256> argv(argv_, argv_ + argc_); if (llvm::sys::Process::FixupStandardFileDescriptors()) @@ -413,6 +407,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 +453,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<DiagnosticOptions> DiagOpts = - CreateAndPopulateDiagOpts(argv); + CreateAndPopulateDiagOpts(argv, UseNewCC1Process); TextDiagnosticPrinter *DiagClient = new TextDiagnosticPrinter(llvm::errs(), &*DiagOpts); @@ -486,8 +488,15 @@ 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<Compilation> C(TheDriver.BuildCompilation(argv)); int Res = 1; + bool IsCrash = false; if (C && !C->containsError()) { SmallVector<std::pair<int, const Command *>, 4> FailingCommands; Res = TheDriver.ExecuteCompilation(*C, FailingCommands); @@ -502,6 +511,11 @@ int main(int argc_, const char **argv_) { for (const auto &J : C->getJobs()) if (const Command *C = dyn_cast<Command>(&J)) FailingCommands.push_back(std::make_pair(-1, C)); + + // Print the bug report message that would be printed if we did actually + // crash, but only if we're crashing due to FORCE_CLANG_DIAGNOSTICS_CRASH. + if (::getenv("FORCE_CLANG_DIAGNOSTICS_CRASH")) + llvm::dbgs() << llvm::getBugReportMsg(); } for (const auto &P : FailingCommands) { @@ -514,11 +528,11 @@ int main(int argc_, const char **argv_) { // If result status is 70, then the driver command reported a fatal error. // On Windows, abort will return an exit code of 3. In these cases, // generate additional diagnostic information if possible. - bool DiagnoseCrash = CommandRes < 0 || CommandRes == 70; + IsCrash = CommandRes < 0 || CommandRes == 70; #ifdef _WIN32 - DiagnoseCrash |= CommandRes == 3; + IsCrash |= CommandRes == 3; #endif - if (DiagnoseCrash) { + if (IsCrash) { TheDriver.generateCompilationDiagnostics(*C, *FailingCommand); break; } @@ -527,10 +541,16 @@ int main(int argc_, const char **argv_) { Diags.getClient()->finish(); - // If any timers were active but haven't been destroyed yet, print their - // results now. This happens in -disable-free mode. - llvm::TimerGroup::printAll(llvm::errs()); - llvm::TimerGroup::clearAll(); + if (!UseNewCC1Process && IsCrash) { + // When crashing in -fintegrated-cc1 mode, bury the timer pointers, because + // the internal linked list might point to already released stack frames. + llvm::BuryPointer(llvm::TimerGroup::aquireDefaultGroup()); + } else { + // If any timers were active but haven't been destroyed yet, print their + // results now. This happens in -disable-free mode. + llvm::TimerGroup::printAll(llvm::errs()); + llvm::TimerGroup::clearAll(); + } #ifdef _WIN32 // Exit status should not be negative on Win32, unless abnormal termination. |