diff options
Diffstat (limited to 'lib/Driver/Driver.cpp')
-rw-r--r-- | lib/Driver/Driver.cpp | 129 |
1 files changed, 74 insertions, 55 deletions
diff --git a/lib/Driver/Driver.cpp b/lib/Driver/Driver.cpp index 1664d0d..65d0049 100644 --- a/lib/Driver/Driver.cpp +++ b/lib/Driver/Driver.cpp @@ -17,6 +17,7 @@ #include "clang/Driver/DriverDiagnostic.h" #include "clang/Driver/Job.h" #include "clang/Driver/Options.h" +#include "clang/Driver/SanitizerArgs.h" #include "clang/Driver/Tool.h" #include "clang/Driver/ToolChain.h" #include "llvm/ADT/ArrayRef.h" @@ -44,21 +45,19 @@ using namespace clang::driver; using namespace clang; using namespace llvm::opt; -Driver::Driver(StringRef ClangExecutable, - StringRef DefaultTargetTriple, +Driver::Driver(StringRef ClangExecutable, StringRef DefaultTargetTriple, DiagnosticsEngine &Diags) - : Opts(createDriverOptTable()), Diags(Diags), Mode(GCCMode), - ClangExecutable(ClangExecutable), SysRoot(DEFAULT_SYSROOT), - UseStdLib(true), DefaultTargetTriple(DefaultTargetTriple), - DriverTitle("clang LLVM compiler"), - CCPrintOptionsFilename(nullptr), CCPrintHeadersFilename(nullptr), - CCLogDiagnosticsFilename(nullptr), - CCCPrintBindings(false), - CCPrintHeaders(false), CCLogDiagnostics(false), - CCGenDiagnostics(false), CCCGenericGCCName(""), CheckInputsExist(true), - CCCUsePCH(true), SuppressMissingInputWarning(false) { - - Name = llvm::sys::path::stem(ClangExecutable); + : Opts(createDriverOptTable()), Diags(Diags), Mode(GCCMode), + SaveTemps(SaveTempsNone), ClangExecutable(ClangExecutable), + SysRoot(DEFAULT_SYSROOT), UseStdLib(true), + DefaultTargetTriple(DefaultTargetTriple), + DriverTitle("clang LLVM compiler"), CCPrintOptionsFilename(nullptr), + CCPrintHeadersFilename(nullptr), CCLogDiagnosticsFilename(nullptr), + CCCPrintBindings(false), CCPrintHeaders(false), CCLogDiagnostics(false), + CCGenDiagnostics(false), CCCGenericGCCName(""), CheckInputsExist(true), + CCCUsePCH(true), SuppressMissingInputWarning(false) { + + Name = llvm::sys::path::filename(ClangExecutable); Dir = llvm::sys::path::parent_path(ClangExecutable); // Compute the path to the resource directory. @@ -364,6 +363,13 @@ Compilation *Driver::BuildCompilation(ArrayRef<const char *> ArgList) { if (const Arg *A = Args->getLastArg(options::OPT_resource_dir)) ResourceDir = A->getValue(); + if (const Arg *A = Args->getLastArg(options::OPT_save_temps_EQ)) { + SaveTemps = llvm::StringSwitch<SaveTempsMode>(A->getValue()) + .Case("cwd", SaveTempsCwd) + .Case("obj", SaveTempsObj) + .Default(SaveTempsCwd); + } + // Perform the default argument translations. DerivedArgList *TranslatedArgs = TranslateInputArgs(*Args); @@ -504,7 +510,7 @@ void Driver::generateCompilationDiagnostics(Compilation &C, // If any of the preprocessing commands failed, clean up and exit. if (!FailingCommands.empty()) { - if (!C.getArgs().hasArg(options::OPT_save_temps)) + if (!isSaveTempsEnabled()) C.CleanupFileList(C.getTempFiles(), true); Diag(clang::diag::note_drv_command_failed_diag_msg) @@ -545,6 +551,9 @@ void Driver::generateCompilationDiagnostics(Compilation &C, Diag(clang::diag::note_drv_command_failed_diag_msg) << "Error generating run script: " + Script + " " + EC.message(); } else { + ScriptOS << "# Crash reproducer for " << getClangFullVersion() << "\n" + << "# Original command: "; + Cmd.Print(ScriptOS, "\n", /*Quote=*/true); Cmd.Print(ScriptOS, "\n", /*Quote=*/true, &CrashInfo); Diag(clang::diag::note_drv_command_failed_diag_msg) << Script; } @@ -612,7 +621,7 @@ int Driver::ExecuteCompilation(Compilation &C, const Command *FailingCommand = it->second; // Remove result files if we're not saving temps. - if (!C.getArgs().hasArg(options::OPT_save_temps)) { + if (!isSaveTempsEnabled()) { const JobAction *JA = cast<JobAction>(&FailingCommand->getSource()); C.CleanupFileMap(C.getResultFiles(), JA, true); @@ -970,7 +979,7 @@ static bool DiagnoseInputExistence(const Driver &D, const DerivedArgList &Args, SmallString<64> Path(Value); if (Arg *WorkDir = Args.getLastArg(options::OPT_working_directory)) { - if (!llvm::sys::path::is_absolute(Path.str())) { + if (!llvm::sys::path::is_absolute(Path)) { SmallString<64> Directory(WorkDir->getValue()); llvm::sys::path::append(Directory, Value); Path.assign(Directory); @@ -980,10 +989,11 @@ static bool DiagnoseInputExistence(const Driver &D, const DerivedArgList &Args, if (llvm::sys::fs::exists(Twine(Path))) return true; - if (D.IsCLMode() && llvm::sys::Process::FindInEnvPath("LIB", Value)) + if (D.IsCLMode() && !llvm::sys::path::is_absolute(Twine(Path)) && + llvm::sys::Process::FindInEnvPath("LIB", Value)) return true; - D.Diag(clang::diag::err_drv_no_such_file) << Path.str(); + D.Diag(clang::diag::err_drv_no_such_file) << Path; return false; } @@ -1264,7 +1274,7 @@ void Driver::BuildActions(const ToolChain &TC, DerivedArgList &Args, continue; // Otherwise construct the appropriate action. - Current = ConstructPhaseAction(Args, Phase, std::move(Current)); + Current = ConstructPhaseAction(TC, Args, Phase, std::move(Current)); if (Current->getType() == types::TY_Nothing) break; } @@ -1290,7 +1300,8 @@ void Driver::BuildActions(const ToolChain &TC, DerivedArgList &Args, } std::unique_ptr<Action> -Driver::ConstructPhaseAction(const ArgList &Args, phases::ID Phase, +Driver::ConstructPhaseAction(const ToolChain &TC, const ArgList &Args, + phases::ID Phase, std::unique_ptr<Action> Input) const { llvm::PrettyStackTraceString CrashInfo("Constructing phase actions"); // Build the appropriate action. @@ -1349,7 +1360,7 @@ Driver::ConstructPhaseAction(const ArgList &Args, phases::ID Phase, types::TY_LLVM_BC); } case phases::Backend: { - if (IsUsingLTO(Args)) { + if (IsUsingLTO(TC, Args)) { types::ID Output = Args.hasArg(options::OPT_S) ? types::TY_LTO_IR : types::TY_LTO_BC; return llvm::make_unique<BackendJobAction>(std::move(Input), Output); @@ -1370,7 +1381,10 @@ Driver::ConstructPhaseAction(const ArgList &Args, phases::ID Phase, llvm_unreachable("invalid phase in ConstructPhaseAction"); } -bool Driver::IsUsingLTO(const ArgList &Args) const { +bool Driver::IsUsingLTO(const ToolChain &TC, const ArgList &Args) const { + if (TC.getSanitizerArgs().needsLTO()) + return true; + if (Args.hasFlag(options::OPT_flto, options::OPT_fno_lto, false)) return true; @@ -1471,8 +1485,8 @@ void Driver::BuildJobs(Compilation &C) const { } } -static const Tool *SelectToolForJob(Compilation &C, const ToolChain *TC, - const JobAction *JA, +static const Tool *SelectToolForJob(Compilation &C, bool SaveTemps, + const ToolChain *TC, const JobAction *JA, const ActionList *&Inputs) { const Tool *ToolForJob = nullptr; @@ -1481,7 +1495,7 @@ static const Tool *SelectToolForJob(Compilation &C, const ToolChain *TC, // compiler input. if (TC->useIntegratedAs() && - !C.getArgs().hasArg(options::OPT_save_temps) && + !SaveTemps && !C.getArgs().hasArg(options::OPT_via_file_asm) && !C.getArgs().hasArg(options::OPT__SLASH_FA) && !C.getArgs().hasArg(options::OPT__SLASH_Fa) && @@ -1512,8 +1526,7 @@ static const Tool *SelectToolForJob(Compilation &C, const ToolChain *TC, const Tool *Compiler = TC->SelectTool(*CompileJA); if (!Compiler) return nullptr; - if (!Compiler->canEmitIR() || - !C.getArgs().hasArg(options::OPT_save_temps)) { + if (!Compiler->canEmitIR() || !SaveTemps) { Inputs = &(*Inputs)[0]->getInputs(); ToolForJob = Compiler; } @@ -1529,7 +1542,7 @@ static const Tool *SelectToolForJob(Compilation &C, const ToolChain *TC, if (Inputs->size() == 1 && isa<PreprocessJobAction>(*Inputs->begin()) && !C.getArgs().hasArg(options::OPT_no_integrated_cpp) && !C.getArgs().hasArg(options::OPT_traditional_cpp) && - !C.getArgs().hasArg(options::OPT_save_temps) && + !SaveTemps && !C.getArgs().hasArg(options::OPT_rewrite_objc) && ToolForJob->hasIntegratedCPP()) Inputs = &(*Inputs)[0]->getInputs(); @@ -1577,7 +1590,7 @@ void Driver::BuildJobsForAction(Compilation &C, const ActionList *Inputs = &A->getInputs(); const JobAction *JA = cast<JobAction>(A); - const Tool *T = SelectToolForJob(C, TC, JA, Inputs); + const Tool *T = SelectToolForJob(C, isSaveTempsEnabled(), TC, JA, Inputs); if (!T) return; @@ -1708,7 +1721,7 @@ const char *Driver::GetNamedOutputPath(Compilation &C, } // Output to a temporary file? - if ((!AtTopLevel && !C.getArgs().hasArg(options::OPT_save_temps) && + if ((!AtTopLevel && !isSaveTempsEnabled() && !C.getArgs().hasArg(options::OPT__SLASH_Fo)) || CCGenDiagnostics) { StringRef Name = llvm::sys::path::filename(BaseInput); @@ -1780,11 +1793,20 @@ const char *Driver::GetNamedOutputPath(Compilation &C, NamedOutput = C.getArgs().MakeArgString(Suffixed.c_str()); } + // Prepend object file path if -save-temps=obj + if (!AtTopLevel && isSaveTempsObj() && C.getArgs().hasArg(options::OPT_o) && + JA.getType() != types::TY_PCH) { + Arg *FinalOutput = C.getArgs().getLastArg(options::OPT_o); + SmallString<128> TempPath(FinalOutput->getValue()); + llvm::sys::path::remove_filename(TempPath); + StringRef OutputFileName = llvm::sys::path::filename(NamedOutput); + llvm::sys::path::append(TempPath, OutputFileName); + NamedOutput = C.getArgs().MakeArgString(TempPath.c_str()); + } + // If we're saving temps and the temp file conflicts with the input file, // then avoid overwriting input file. - if (!AtTopLevel && C.getArgs().hasArg(options::OPT_save_temps) && - NamedOutput == BaseName) { - + if (!AtTopLevel && isSaveTempsEnabled() && NamedOutput == BaseName) { bool SameFile = false; SmallString<256> Result; llvm::sys::fs::current_path(Result); @@ -2003,12 +2025,15 @@ static llvm::Triple computeTargetTriple(StringRef DefaultTargetTriple, const ToolChain &Driver::getToolChain(const ArgList &Args, StringRef DarwinArchName) const { - llvm::Triple Target = computeTargetTriple(DefaultTargetTriple, Args, - DarwinArchName); + llvm::Triple Target = + computeTargetTriple(DefaultTargetTriple, Args, DarwinArchName); ToolChain *&TC = ToolChains[Target.str()]; if (!TC) { switch (Target.getOS()) { + case llvm::Triple::CloudABI: + TC = new toolchains::CloudABI(*this, Target, Args); + break; case llvm::Triple::Darwin: case llvm::Triple::MacOSX: case llvm::Triple::IOS: @@ -2038,6 +2063,9 @@ const ToolChain &Driver::getToolChain(const ArgList &Args, else TC = new toolchains::Linux(*this, Target, Args); break; + case llvm::Triple::NaCl: + TC = new toolchains::NaCl_TC(*this, Target, Args); + break; case llvm::Triple::Solaris: TC = new toolchains::Solaris(*this, Target, Args); break; @@ -2069,29 +2097,20 @@ const ToolChain &Driver::getToolChain(const ArgList &Args, } break; default: - // TCE is an OSless target - if (Target.getArchName() == "tce") { + // Of these targets, Hexagon is the only one that might have + // an OS of Linux, in which case it got handled above already. + if (Target.getArchName() == "tce") TC = new toolchains::TCEToolChain(*this, Target, Args); - break; - } - // If Hexagon is configured as an OSless target - if (Target.getArch() == llvm::Triple::hexagon) { + else if (Target.getArch() == llvm::Triple::hexagon) TC = new toolchains::Hexagon_TC(*this, Target, Args); - break; - } - if (Target.getArch() == llvm::Triple::xcore) { + else if (Target.getArch() == llvm::Triple::xcore) TC = new toolchains::XCore(*this, Target, Args); - break; - } - if (Target.isOSBinFormatELF()) { + else if (Target.isOSBinFormatELF()) TC = new toolchains::Generic_ELF(*this, Target, Args); - break; - } - if (Target.isOSBinFormatMachO()) { + else if (Target.isOSBinFormatMachO()) TC = new toolchains::MachO(*this, Target, Args); - break; - } - TC = new toolchains::Generic_GCC(*this, Target, Args); + else + TC = new toolchains::Generic_GCC(*this, Target, Args); break; } } @@ -2125,7 +2144,7 @@ bool Driver::GetReleaseVersion(const char *Str, unsigned &Major, Major = Minor = Micro = 0; if (*Str == '\0') - return true; + return false; char *End; Major = (unsigned) strtol(Str, &End, 10); |