summaryrefslogtreecommitdiffstats
path: root/lib/Driver/Driver.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'lib/Driver/Driver.cpp')
-rw-r--r--lib/Driver/Driver.cpp129
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);
OpenPOWER on IntegriCloud