Update aosp/master clang for rebase to r230699.
Change-Id: I6a546ab3d4ae37119eebb735e102cca4f80ab520
diff --git a/lib/Driver/Action.cpp b/lib/Driver/Action.cpp
index d4f339d..360dbee 100644
--- a/lib/Driver/Action.cpp
+++ b/lib/Driver/Action.cpp
@@ -29,6 +29,7 @@
case AnalyzeJobClass: return "analyzer";
case MigrateJobClass: return "migrator";
case CompileJobClass: return "compiler";
+ case BackendJobClass: return "backend";
case AssembleJobClass: return "assembler";
case LinkJobClass: return "linker";
case LipoJobClass: return "lipo";
@@ -92,6 +93,12 @@
types::ID OutputType)
: JobAction(CompileJobClass, std::move(Input), OutputType) {}
+void BackendJobAction::anchor() {}
+
+BackendJobAction::BackendJobAction(std::unique_ptr<Action> Input,
+ types::ID OutputType)
+ : JobAction(BackendJobClass, std::move(Input), OutputType) {}
+
void AssembleJobAction::anchor() {}
AssembleJobAction::AssembleJobAction(std::unique_ptr<Action> Input,
diff --git a/lib/Driver/Driver.cpp b/lib/Driver/Driver.cpp
index d459e4b..61aaa97 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,20 +45,17 @@
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),
- DefaultImageName("a.out"),
- 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) {
+ : 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::stem(ClangExecutable);
Dir = llvm::sys::path::parent_path(ClangExecutable);
@@ -65,10 +63,13 @@
// Compute the path to the resource directory.
StringRef ClangResourceDir(CLANG_RESOURCE_DIR);
SmallString<128> P(Dir);
- if (ClangResourceDir != "")
+ if (ClangResourceDir != "") {
llvm::sys::path::append(P, ClangResourceDir);
- else
- llvm::sys::path::append(P, "..", "lib", "clang", CLANG_VERSION_STRING);
+ } else {
+ StringRef ClangLibdirSuffix(CLANG_LIBDIR_SUFFIX);
+ llvm::sys::path::append(P, "..", Twine("lib") + ClangLibdirSuffix, "clang",
+ CLANG_VERSION_STRING);
+ }
ResourceDir = P.str();
}
@@ -125,9 +126,7 @@
<< Args->getArgString(MissingArgIndex) << MissingArgCount;
// Check for unsupported options.
- for (ArgList::const_iterator it = Args->begin(), ie = Args->end();
- it != ie; ++it) {
- Arg *A = *it;
+ for (const Arg *A : *Args) {
if (A->getOption().hasFlag(options::Unsupported)) {
Diag(clang::diag::err_drv_unsupported_opt) << A->getAsString(*Args);
continue;
@@ -165,7 +164,7 @@
(PhaseArg = DAL.getLastArg(options::OPT__SLASH_P))) {
FinalPhase = phases::Preprocess;
- // -{fsyntax-only,-analyze,emit-ast,S} only run up to the compiler.
+ // -{fsyntax-only,-analyze,emit-ast} only run up to the compiler.
} else if ((PhaseArg = DAL.getLastArg(options::OPT_fsyntax_only)) ||
(PhaseArg = DAL.getLastArg(options::OPT_module_file_info)) ||
(PhaseArg = DAL.getLastArg(options::OPT_verify_pch)) ||
@@ -174,10 +173,13 @@
(PhaseArg = DAL.getLastArg(options::OPT__migrate)) ||
(PhaseArg = DAL.getLastArg(options::OPT__analyze,
options::OPT__analyze_auto)) ||
- (PhaseArg = DAL.getLastArg(options::OPT_emit_ast)) ||
- (PhaseArg = DAL.getLastArg(options::OPT_S))) {
+ (PhaseArg = DAL.getLastArg(options::OPT_emit_ast))) {
FinalPhase = phases::Compile;
+ // -S only runs up to the backend.
+ } else if ((PhaseArg = DAL.getLastArg(options::OPT_S))) {
+ FinalPhase = phases::Backend;
+
// -c only runs up to the assembler.
} else if ((PhaseArg = DAL.getLastArg(options::OPT_c))) {
FinalPhase = phases::Assemble;
@@ -205,10 +207,7 @@
DerivedArgList *DAL = new DerivedArgList(Args);
bool HasNostdlib = Args.hasArg(options::OPT_nostdlib);
- for (ArgList::const_iterator it = Args.begin(),
- ie = Args.end(); it != ie; ++it) {
- const Arg *A = *it;
-
+ for (Arg *A : Args) {
// Unfortunately, we have to parse some forwarding options (-Xassembler,
// -Xlinker, -Xpreprocessor) because we either integrate their functionality
// (assembler and preprocessor), or bypass a previous driver ('collect2').
@@ -274,7 +273,7 @@
continue;
}
- DAL->append(*it);
+ DAL->append(A);
}
// Add a default value of -mlinker-version=, if one was given and the user
@@ -364,6 +363,13 @@
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);
@@ -468,9 +474,7 @@
// Don't attempt to generate preprocessed files if multiple -arch options are
// used, unless they're all duplicates.
llvm::StringSet<> ArchNames;
- for (ArgList::const_iterator it = C.getArgs().begin(), ie = C.getArgs().end();
- it != ie; ++it) {
- Arg *A = *it;
+ for (const Arg *A : C.getArgs()) {
if (A->getOption().matches(options::OPT_arch)) {
StringRef ArchName = A->getValue();
ArchNames.insert(ArchName);
@@ -506,7 +510,7 @@
// 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)
@@ -550,6 +554,11 @@
Cmd.Print(ScriptOS, "\n", /*Quote=*/true, &CrashInfo);
Diag(clang::diag::note_drv_command_failed_diag_msg) << Script;
}
+
+ for (const auto &A : C.getArgs().filtered(options::OPT_frewrite_map_file,
+ options::OPT_frewrite_map_file_EQ))
+ Diag(clang::diag::note_drv_command_failed_diag_msg) << A->getValue();
+
Diag(clang::diag::note_drv_command_failed_diag_msg)
<< "\n\n********************";
}
@@ -609,7 +618,7 @@
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);
@@ -849,7 +858,9 @@
/// \brief Check whether the given input tree contains any compilation or
/// assembly actions.
static bool ContainsCompileOrAssembleAction(const Action *A) {
- if (isa<CompileJobAction>(A) || isa<AssembleJobAction>(A))
+ if (isa<CompileJobAction>(A) ||
+ isa<BackendJobAction>(A) ||
+ isa<AssembleJobAction>(A))
return true;
for (Action::const_iterator it = A->begin(), ie = A->end(); it != ie; ++it)
@@ -868,10 +879,7 @@
// be handled once (in the order seen).
llvm::StringSet<> ArchNames;
SmallVector<const char *, 4> Archs;
- for (ArgList::const_iterator it = Args.begin(), ie = Args.end();
- it != ie; ++it) {
- Arg *A = *it;
-
+ for (Arg *A : Args) {
if (A->getOption().matches(options::OPT_arch)) {
// Validate the option here; we don't save the type here because its
// particular spelling may participate in other driver choices.
@@ -1019,10 +1027,7 @@
assert(!Args.hasArg(options::OPT_x) && "-x and /TC or /TP is not allowed");
}
- for (ArgList::const_iterator it = Args.begin(), ie = Args.end();
- it != ie; ++it) {
- Arg *A = *it;
-
+ for (Arg *A : Args) {
if (A->getOption().getKind() == Option::InputClass) {
const char *Value = A->getValue();
types::ID Ty = types::TY_INVALID;
@@ -1265,7 +1270,7 @@
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;
}
@@ -1291,7 +1296,8 @@
}
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.
@@ -1346,17 +1352,21 @@
if (Args.hasArg(options::OPT_verify_pch))
return llvm::make_unique<VerifyPCHJobAction>(std::move(Input),
types::TY_Nothing);
- if (IsUsingLTO(Args)) {
+ return llvm::make_unique<CompileJobAction>(std::move(Input),
+ types::TY_LLVM_BC);
+ }
+ case phases::Backend: {
+ if (IsUsingLTO(TC, Args)) {
types::ID Output =
Args.hasArg(options::OPT_S) ? types::TY_LTO_IR : types::TY_LTO_BC;
- return llvm::make_unique<CompileJobAction>(std::move(Input), Output);
+ return llvm::make_unique<BackendJobAction>(std::move(Input), Output);
}
if (Args.hasArg(options::OPT_emit_llvm)) {
types::ID Output =
Args.hasArg(options::OPT_S) ? types::TY_LLVM_IR : types::TY_LLVM_BC;
- return llvm::make_unique<CompileJobAction>(std::move(Input), Output);
+ return llvm::make_unique<BackendJobAction>(std::move(Input), Output);
}
- return llvm::make_unique<CompileJobAction>(std::move(Input),
+ return llvm::make_unique<BackendJobAction>(std::move(Input),
types::TY_PP_Asm);
}
case phases::Assemble:
@@ -1367,7 +1377,10 @@
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;
@@ -1383,9 +1396,8 @@
// files.
if (FinalOutput) {
unsigned NumOutputs = 0;
- for (ActionList::const_iterator it = C.getActions().begin(),
- ie = C.getActions().end(); it != ie; ++it)
- if ((*it)->getType() != types::TY_Nothing)
+ for (const Action *A : C.getActions())
+ if (A->getType() != types::TY_Nothing)
++NumOutputs;
if (NumOutputs > 1) {
@@ -1396,19 +1408,12 @@
// Collect the list of architectures.
llvm::StringSet<> ArchNames;
- if (C.getDefaultToolChain().getTriple().isOSBinFormatMachO()) {
- for (ArgList::const_iterator it = C.getArgs().begin(), ie = C.getArgs().end();
- it != ie; ++it) {
- Arg *A = *it;
+ if (C.getDefaultToolChain().getTriple().isOSBinFormatMachO())
+ for (const Arg *A : C.getArgs())
if (A->getOption().matches(options::OPT_arch))
ArchNames.insert(A->getValue());
- }
- }
- for (ActionList::const_iterator it = C.getActions().begin(),
- ie = C.getActions().end(); it != ie; ++it) {
- Action *A = *it;
-
+ for (Action *A : C.getActions()) {
// If we are linking an image for multiple archs then the linker wants
// -arch_multiple and -final_output <final image name>. Unfortunately, this
// doesn't fit in cleanly because we have to pass this information down.
@@ -1420,7 +1425,7 @@
if (FinalOutput)
LinkingOutput = FinalOutput->getValue();
else
- LinkingOutput = DefaultImageName.c_str();
+ LinkingOutput = getDefaultImageName();
}
InputInfo II;
@@ -1444,10 +1449,7 @@
// Claim --driver-mode, it was handled earlier.
(void) C.getArgs().hasArg(options::OPT_driver_mode);
- for (ArgList::const_iterator it = C.getArgs().begin(), ie = C.getArgs().end();
- it != ie; ++it) {
- Arg *A = *it;
-
+ for (Arg *A : C.getArgs()) {
// FIXME: It would be nice to be able to send the argument to the
// DiagnosticsEngine, so that extra values, position, and so on could be
// printed.
@@ -1479,8 +1481,8 @@
}
}
-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;
@@ -1489,17 +1491,38 @@
// 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) &&
isa<AssembleJobAction>(JA) &&
- Inputs->size() == 1 && isa<CompileJobAction>(*Inputs->begin())) {
- const Tool *Compiler =
- TC->SelectTool(cast<JobAction>(**Inputs->begin()));
+ Inputs->size() == 1 && isa<BackendJobAction>(*Inputs->begin())) {
+ // A BackendJob is always preceded by a CompileJob, and without
+ // -save-temps they will always get combined together, so instead of
+ // checking the backend tool, check if the tool for the CompileJob
+ // has an integrated assembler.
+ const ActionList *BackendInputs = &(*Inputs)[0]->getInputs();
+ JobAction *CompileJA = cast<CompileJobAction>(*BackendInputs->begin());
+ const Tool *Compiler = TC->SelectTool(*CompileJA);
if (!Compiler)
return nullptr;
if (Compiler->hasIntegratedAssembler()) {
+ Inputs = &(*BackendInputs)[0]->getInputs();
+ ToolForJob = Compiler;
+ }
+ }
+
+ // A backend job should always be combined with the preceding compile job
+ // unless OPT_save_temps is enabled and the compiler is capable of emitting
+ // LLVM IR as an intermediate output.
+ if (isa<BackendJobAction>(JA)) {
+ // Check if the compiler supports emitting LLVM IR.
+ assert(Inputs->size() == 1);
+ JobAction *CompileJA = cast<CompileJobAction>(*Inputs->begin());
+ const Tool *Compiler = TC->SelectTool(*CompileJA);
+ if (!Compiler)
+ return nullptr;
+ if (!Compiler->canEmitIR() || !SaveTemps) {
Inputs = &(*Inputs)[0]->getInputs();
ToolForJob = Compiler;
}
@@ -1515,7 +1538,7 @@
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();
@@ -1563,14 +1586,13 @@
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;
// Only use pipes when there is exactly one input.
InputInfoList InputInfos;
- for (ActionList::const_iterator it = Inputs->begin(), ie = Inputs->end();
- it != ie; ++it) {
+ for (const Action *Input : *Inputs) {
// Treat dsymutil and verify sub-jobs as being at the top-level too, they
// shouldn't get temporary output names.
// FIXME: Clean this up.
@@ -1579,7 +1601,7 @@
SubJobAtTopLevel = true;
InputInfo II;
- BuildJobsForAction(C, *it, TC, BoundArch, SubJobAtTopLevel, MultipleArchs,
+ BuildJobsForAction(C, Input, TC, BoundArch, SubJobAtTopLevel, MultipleArchs,
LinkingOutput, II);
InputInfos.push_back(II);
}
@@ -1615,6 +1637,11 @@
}
}
+const char *Driver::getDefaultImageName() const {
+ llvm::Triple Target(llvm::Triple::normalize(DefaultTargetTriple));
+ return Target.isOSWindows() ? "a.exe" : "a.out";
+}
+
/// \brief Create output filename based on ArgValue, which could either be a
/// full filename, filename without extension, or a directory. If ArgValue
/// does not provide a filename, then use BaseName, and use the extension
@@ -1690,7 +1717,7 @@
}
// 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);
@@ -1733,12 +1760,12 @@
NamedOutput = MakeCLOutputFilename(C.getArgs(), "", BaseName,
types::TY_Image);
} else if (MultipleArchs && BoundArch) {
- SmallString<128> Output(DefaultImageName.c_str());
+ SmallString<128> Output(getDefaultImageName());
Output += "-";
Output.append(BoundArch);
NamedOutput = C.getArgs().MakeArgString(Output.c_str());
} else
- NamedOutput = DefaultImageName.c_str();
+ NamedOutput = getDefaultImageName();
} else {
const char *Suffix = types::getTypeTempSuffix(JA.getType(), IsCLMode());
assert(Suffix && "All types used for output should have a suffix.");
@@ -1751,16 +1778,31 @@
Suffixed += "-";
Suffixed.append(BoundArch);
}
+ // When using both -save-temps and -emit-llvm, use a ".tmp.bc" suffix for
+ // the unoptimized bitcode so that it does not get overwritten by the ".bc"
+ // optimized bitcode output.
+ if (!AtTopLevel && C.getArgs().hasArg(options::OPT_emit_llvm) &&
+ JA.getType() == types::TY_LLVM_BC)
+ Suffixed += ".tmp";
Suffixed += '.';
Suffixed += Suffix;
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);
@@ -2063,7 +2105,7 @@
TC = new toolchains::Generic_ELF(*this, Target, Args);
break;
}
- if (Target.getObjectFormat() == llvm::Triple::MachO) {
+ if (Target.isOSBinFormatMachO()) {
TC = new toolchains::MachO(*this, Target, Args);
break;
}
@@ -2083,7 +2125,7 @@
// Otherwise make sure this is an action clang understands.
if (!isa<PreprocessJobAction>(JA) && !isa<PrecompileJobAction>(JA) &&
- !isa<CompileJobAction>(JA))
+ !isa<CompileJobAction>(JA) && !isa<BackendJobAction>(JA))
return false;
return true;
diff --git a/lib/Driver/Job.cpp b/lib/Driver/Job.cpp
index c5b3f5a..66434cf 100644
--- a/lib/Driver/Job.cpp
+++ b/lib/Driver/Job.cpp
@@ -217,8 +217,7 @@
if (ResponseFile == nullptr) {
Argv.push_back(Executable);
- for (size_t i = 0, e = Arguments.size(); i != e; ++i)
- Argv.push_back(Arguments[i]);
+ Argv.append(Arguments.begin(), Arguments.end());
Argv.push_back(nullptr);
return llvm::sys::ExecuteAndWait(Executable, Argv.data(), /*env*/ nullptr,
diff --git a/lib/Driver/MSVCToolChain.cpp b/lib/Driver/MSVCToolChain.cpp
index 692d01d5..874e540 100644
--- a/lib/Driver/MSVCToolChain.cpp
+++ b/lib/Driver/MSVCToolChain.cpp
@@ -21,6 +21,7 @@
#include "llvm/Support/ErrorHandling.h"
#include "llvm/Support/FileSystem.h"
#include "llvm/Support/Process.h"
+#include <cstdio>
// Include the necessary headers to interface with the Windows registry and
// environment.
@@ -31,7 +32,9 @@
#ifdef USE_WIN32
#define WIN32_LEAN_AND_MEAN
#define NOGDI
- #define NOMINMAX
+ #ifndef NOMINMAX
+ #define NOMINMAX
+ #endif
#include <windows.h>
#endif
@@ -43,6 +46,9 @@
MSVCToolChain::MSVCToolChain(const Driver &D, const llvm::Triple& Triple,
const ArgList &Args)
: ToolChain(D, Triple, Args) {
+ getProgramPaths().push_back(getDriver().getInstalledDir());
+ if (getDriver().getInstalledDir() != getDriver().Dir)
+ getProgramPaths().push_back(getDriver().Dir);
}
Tool *MSVCToolChain::buildLinker() const {
@@ -207,7 +213,7 @@
"SOFTWARE\\Microsoft\\Microsoft SDKs\\Windows\\$VERSION",
"InstallationFolder", path, &sdkVersion);
if (!sdkVersion.empty())
- ::sscanf(sdkVersion.c_str(), "v%d.%d", &major, &minor);
+ std::sscanf(sdkVersion.c_str(), "v%d.%d", &major, &minor);
return hasSDKDir && !path.empty();
}
diff --git a/lib/Driver/Phases.cpp b/lib/Driver/Phases.cpp
index 155e53b..7ae2708 100644
--- a/lib/Driver/Phases.cpp
+++ b/lib/Driver/Phases.cpp
@@ -18,6 +18,7 @@
case Preprocess: return "preprocessor";
case Precompile: return "precompiler";
case Compile: return "compiler";
+ case Backend: return "backend";
case Assemble: return "assembler";
case Link: return "linker";
}
diff --git a/lib/Driver/SanitizerArgs.cpp b/lib/Driver/SanitizerArgs.cpp
index 4460f9f..11b9288 100644
--- a/lib/Driver/SanitizerArgs.cpp
+++ b/lib/Driver/SanitizerArgs.cpp
@@ -42,8 +42,13 @@
#include "clang/Basic/Sanitizers.def"
NeedsUbsanRt = Undefined | Integer,
NotAllowedWithTrap = Vptr,
- HasZeroBaseShadow = Thread | Memory | DataFlow,
- NeedsUnwindTables = Address | Thread | Memory | DataFlow
+ RequiresPIE = Memory | DataFlow,
+ NeedsUnwindTables = Address | Thread | Memory | DataFlow,
+ SupportsCoverage = Address | Memory | Leak | Undefined | Integer,
+ RecoverableByDefault = Undefined | Integer,
+ Unrecoverable = Address | Unreachable | Return,
+ LegacyFsanitizeRecoverMask = Undefined | Integer,
+ NeedsLTO = CFIVptr,
};
}
@@ -83,12 +88,6 @@
static unsigned parseArgValues(const Driver &D, const llvm::opt::Arg *A,
bool DiagnoseErrors);
-/// Parse a single flag of the form -f[no]sanitize=.
-/// Sets the masks defining required change of the set of sanitizers.
-/// Returns true if the flag was parsed successfully.
-static bool parseArgument(const Driver &D, const llvm::opt::Arg *A,
- unsigned &Add, unsigned &Remove, bool DiagnoseErrors);
-
/// Produce an argument string from ArgList \p Args, which shows how it
/// provides some sanitizer kind from \p Mask. For example, the argument list
/// "-fsanitize=thread,vptr -fsanitize=address" with mask \c NeedsUbsanRt
@@ -122,12 +121,14 @@
bool IsLinux = TC.getTriple().getOS() == llvm::Triple::Linux;
bool IsX86 = TC.getTriple().getArch() == llvm::Triple::x86;
bool IsX86_64 = TC.getTriple().getArch() == llvm::Triple::x86_64;
+ bool IsMIPS64 = TC.getTriple().getArch() == llvm::Triple::mips64 ||
+ TC.getTriple().getArch() == llvm::Triple::mips64el;
unsigned Unsupported = 0;
- if (!(IsLinux && IsX86_64)) {
+ if (!(IsLinux && (IsX86_64 || IsMIPS64))) {
Unsupported |= Memory | DataFlow;
}
- if (!((IsLinux || IsFreeBSD) && IsX86_64)) {
+ if (!((IsLinux || IsFreeBSD) && (IsX86_64 || IsMIPS64))) {
Unsupported |= Thread;
}
if (!(IsLinux && (IsX86 || IsX86_64))) {
@@ -140,18 +141,22 @@
return !UbsanTrapOnError && hasOneOf(Sanitizers, NeedsUbsanRt);
}
-bool SanitizerArgs::hasZeroBaseShadow() const {
- return AsanZeroBaseShadow || hasOneOf(Sanitizers, HasZeroBaseShadow);
+bool SanitizerArgs::requiresPIE() const {
+ return AsanZeroBaseShadow || hasOneOf(Sanitizers, RequiresPIE);
}
bool SanitizerArgs::needsUnwindTables() const {
return hasOneOf(Sanitizers, NeedsUnwindTables);
}
+bool SanitizerArgs::needsLTO() const {
+ return hasOneOf(Sanitizers, CFIVptr);
+}
+
void SanitizerArgs::clear() {
Sanitizers.clear();
- SanitizeRecover = false;
- BlacklistFile = "";
+ RecoverableSanitizers.clear();
+ BlacklistFiles.clear();
SanitizeCoverage = 0;
MsanTrackOrigins = 0;
AsanFieldPadding = 0;
@@ -171,43 +176,111 @@
// Used to deduplicate diagnostics.
unsigned Kinds = 0;
unsigned NotSupported = getToolchainUnsupportedKinds(TC);
+ ToolChain::RTTIMode RTTIMode = TC.getRTTIMode();
+
const Driver &D = TC.getDriver();
for (ArgList::const_reverse_iterator I = Args.rbegin(), E = Args.rend();
I != E; ++I) {
- unsigned Add, Remove;
- if (!parseArgument(D, *I, Add, Remove, true))
- continue;
- (*I)->claim();
+ const auto *Arg = *I;
+ if (Arg->getOption().matches(options::OPT_fsanitize_EQ)) {
+ Arg->claim();
+ unsigned Add = parseArgValues(D, Arg, true);
- AllRemove |= expandGroups(Remove);
+ // Avoid diagnosing any sanitizer which is disabled later.
+ Add &= ~AllRemove;
+ // At this point we have not expanded groups, so any unsupported
+ // sanitizers in Add are those which have been explicitly enabled.
+ // Diagnose them.
+ if (unsigned KindsToDiagnose = Add & NotSupported & ~DiagnosedKinds) {
+ // Only diagnose the new kinds.
+ std::string Desc = describeSanitizeArg(*I, KindsToDiagnose);
+ D.Diag(diag::err_drv_unsupported_opt_for_target)
+ << Desc << TC.getTriple().str();
+ DiagnosedKinds |= KindsToDiagnose;
+ }
+ Add &= ~NotSupported;
- // Avoid diagnosing any sanitizer which is disabled later.
- Add &= ~AllRemove;
+ // Test for -fno-rtti + explicit -fsanitizer=vptr before expanding groups
+ // so we don't error out if -fno-rtti and -fsanitize=undefined were
+ // passed.
+ if (Add & SanitizeKind::Vptr &&
+ (RTTIMode == ToolChain::RM_DisabledImplicitly ||
+ RTTIMode == ToolChain::RM_DisabledExplicitly)) {
+ if (RTTIMode == ToolChain::RM_DisabledImplicitly)
+ // Warn about not having rtti enabled if the vptr sanitizer is
+ // explicitly enabled
+ D.Diag(diag::warn_drv_disabling_vptr_no_rtti_default);
+ else {
+ const llvm::opt::Arg *NoRTTIArg = TC.getRTTIArg();
+ assert(NoRTTIArg &&
+ "RTTI disabled explicitly but we have no argument!");
+ D.Diag(diag::err_drv_argument_not_allowed_with)
+ << "-fsanitize=vptr" << NoRTTIArg->getAsString(Args);
+ }
- // At this point we have not expanded groups, so any unsupported sanitizers
- // in Add are those which have been explicitly enabled. Diagnose them.
- if (unsigned KindsToDiagnose = Add & NotSupported & ~DiagnosedKinds) {
- // Only diagnose the new kinds.
- std::string Desc = describeSanitizeArg(*I, KindsToDiagnose);
- D.Diag(diag::err_drv_unsupported_opt_for_target) << Desc
- << TC.getTriple().str();
- DiagnosedKinds |= KindsToDiagnose;
+ // Take out the Vptr sanitizer from the enabled sanitizers
+ AllRemove |= SanitizeKind::Vptr;
+ }
+
+ Add = expandGroups(Add);
+ // Group expansion may have enabled a sanitizer which is disabled later.
+ Add &= ~AllRemove;
+ // Silently discard any unsupported sanitizers implicitly enabled through
+ // group expansion.
+ Add &= ~NotSupported;
+
+ Kinds |= Add;
+ } else if (Arg->getOption().matches(options::OPT_fno_sanitize_EQ)) {
+ Arg->claim();
+ unsigned Remove = parseArgValues(D, Arg, true);
+ AllRemove |= expandGroups(Remove);
}
- Add &= ~NotSupported;
-
- Add = expandGroups(Add);
- // Group expansion may have enabled a sanitizer which is disabled later.
- Add &= ~AllRemove;
- // Silently discard any unsupported sanitizers implicitly enabled through
- // group expansion.
- Add &= ~NotSupported;
-
- Kinds |= Add;
}
addAllOf(Sanitizers, Kinds);
- SanitizeRecover = Args.hasFlag(options::OPT_fsanitize_recover,
- options::OPT_fno_sanitize_recover, true);
+ // We disable the vptr sanitizer if it was enabled by group expansion but RTTI
+ // is disabled.
+ if (Sanitizers.has(SanitizerKind::Vptr) &&
+ (RTTIMode == ToolChain::RM_DisabledImplicitly ||
+ RTTIMode == ToolChain::RM_DisabledExplicitly)) {
+ Kinds &= ~SanitizeKind::Vptr;
+ Sanitizers.set(SanitizerKind::Vptr, 0);
+ }
+
+ // Parse -f(no-)?sanitize-recover flags.
+ unsigned RecoverableKinds = RecoverableByDefault;
+ unsigned DiagnosedUnrecoverableKinds = 0;
+ for (const auto *Arg : Args) {
+ if (Arg->getOption().matches(options::OPT_fsanitize_recover)) {
+ // FIXME: Add deprecation notice, and then remove this flag.
+ RecoverableKinds |= expandGroups(LegacyFsanitizeRecoverMask);
+ Arg->claim();
+ } else if (Arg->getOption().matches(options::OPT_fno_sanitize_recover)) {
+ // FIXME: Add deprecation notice, and then remove this flag.
+ RecoverableKinds &= ~expandGroups(LegacyFsanitizeRecoverMask);
+ Arg->claim();
+ } else if (Arg->getOption().matches(options::OPT_fsanitize_recover_EQ)) {
+ unsigned Add = parseArgValues(D, Arg, true);
+ // Report error if user explicitly tries to recover from unrecoverable
+ // sanitizer.
+ if (unsigned KindsToDiagnose =
+ Add & Unrecoverable & ~DiagnosedUnrecoverableKinds) {
+ SanitizerSet SetToDiagnose;
+ addAllOf(SetToDiagnose, KindsToDiagnose);
+ D.Diag(diag::err_drv_unsupported_option_argument)
+ << Arg->getOption().getName() << toString(SetToDiagnose);
+ DiagnosedUnrecoverableKinds |= KindsToDiagnose;
+ }
+ RecoverableKinds |= expandGroups(Add);
+ Arg->claim();
+ } else if (Arg->getOption().matches(options::OPT_fno_sanitize_recover_EQ)) {
+ RecoverableKinds &= ~expandGroups(parseArgValues(D, Arg, true));
+ Arg->claim();
+ }
+ }
+ RecoverableKinds &= Kinds;
+ RecoverableKinds &= ~Unrecoverable;
+ addAllOf(RecoverableSanitizers, RecoverableKinds);
UbsanTrapOnError =
Args.hasFlag(options::OPT_fsanitize_undefined_trap_on_error,
@@ -250,30 +323,34 @@
// -f(-no)sanitize=leak should change whether leak detection is enabled by
// default in ASan?
- // Parse -f(no-)sanitize-blacklist options.
- if (Arg *BLArg = Args.getLastArg(options::OPT_fsanitize_blacklist,
- options::OPT_fno_sanitize_blacklist)) {
- if (BLArg->getOption().matches(options::OPT_fsanitize_blacklist)) {
- std::string BLPath = BLArg->getValue();
- if (llvm::sys::fs::exists(BLPath)) {
- // Validate the blacklist format.
- std::string BLError;
- std::unique_ptr<llvm::SpecialCaseList> SCL(
- llvm::SpecialCaseList::create(BLPath, BLError));
- if (!SCL.get())
- D.Diag(clang::diag::err_drv_malformed_sanitizer_blacklist) << BLError;
- else
- BlacklistFile = BLPath;
- } else {
- D.Diag(clang::diag::err_drv_no_such_file) << BLPath;
- }
- }
- } else {
- // If no -fsanitize-blacklist option is specified, try to look up for
- // blacklist in the resource directory.
+ // Setup blacklist files.
+ // Add default blacklist from resource directory.
+ {
std::string BLPath;
if (getDefaultBlacklist(D, BLPath) && llvm::sys::fs::exists(BLPath))
- BlacklistFile = BLPath;
+ BlacklistFiles.push_back(BLPath);
+ }
+ // Parse -f(no-)sanitize-blacklist options.
+ for (const auto *Arg : Args) {
+ if (Arg->getOption().matches(options::OPT_fsanitize_blacklist)) {
+ Arg->claim();
+ std::string BLPath = Arg->getValue();
+ if (llvm::sys::fs::exists(BLPath))
+ BlacklistFiles.push_back(BLPath);
+ else
+ D.Diag(clang::diag::err_drv_no_such_file) << BLPath;
+ } else if (Arg->getOption().matches(options::OPT_fno_sanitize_blacklist)) {
+ Arg->claim();
+ BlacklistFiles.clear();
+ }
+ }
+ // Validate blacklists format.
+ {
+ std::string BLError;
+ std::unique_ptr<llvm::SpecialCaseList> SCL(
+ llvm::SpecialCaseList::create(BlacklistFiles, BLError));
+ if (!SCL.get())
+ D.Diag(clang::diag::err_drv_malformed_sanitizer_blacklist) << BLError;
}
// Parse -f[no-]sanitize-memory-track-origins[=level] options.
@@ -283,7 +360,7 @@
options::OPT_fsanitize_memory_track_origins,
options::OPT_fno_sanitize_memory_track_origins)) {
if (A->getOption().matches(options::OPT_fsanitize_memory_track_origins)) {
- MsanTrackOrigins = 1;
+ MsanTrackOrigins = 2;
} else if (A->getOption().matches(
options::OPT_fno_sanitize_memory_track_origins)) {
MsanTrackOrigins = 0;
@@ -297,8 +374,8 @@
}
}
- // Parse -fsanitize-coverage=N
- if (NeedsAsan) { // Currently asan is required.
+ // Parse -fsanitize-coverage=N. Currently one of asan/msan/lsan is required.
+ if (hasOneOf(Sanitizers, SupportsCoverage)) {
if (Arg *A = Args.getLastArg(options::OPT_fsanitize_coverage)) {
StringRef S = A->getValue();
// Legal values are 0..4.
@@ -363,15 +440,16 @@
return;
CmdArgs.push_back(Args.MakeArgString("-fsanitize=" + toString(Sanitizers)));
- if (!SanitizeRecover)
- CmdArgs.push_back("-fno-sanitize-recover");
+ if (!RecoverableSanitizers.empty())
+ CmdArgs.push_back(Args.MakeArgString("-fsanitize-recover=" +
+ toString(RecoverableSanitizers)));
if (UbsanTrapOnError)
CmdArgs.push_back("-fsanitize-undefined-trap-on-error");
- if (!BlacklistFile.empty()) {
+ for (const auto &BLPath : BlacklistFiles) {
SmallString<64> BlacklistOpt("-fsanitize-blacklist=");
- BlacklistOpt += BlacklistFile;
+ BlacklistOpt += BLPath;
CmdArgs.push_back(Args.MakeArgString(BlacklistOpt));
}
@@ -384,8 +462,13 @@
if (SanitizeCoverage)
CmdArgs.push_back(Args.MakeArgString("-fsanitize-coverage=" +
llvm::utostr(SanitizeCoverage)));
- // Workaround for PR16386.
- if (Sanitizers.has(SanitizerKind::Memory))
+ // MSan: Workaround for PR16386.
+ // ASan: This is mainly to help LSan with cases such as
+ // https://code.google.com/p/address-sanitizer/issues/detail?id=373
+ // We can't make this conditional on -fsanitize=leak, as that flag shouldn't
+ // affect compilation.
+ if (Sanitizers.has(SanitizerKind::Memory) ||
+ Sanitizers.has(SanitizerKind::Address))
CmdArgs.push_back(Args.MakeArgString("-fno-assume-sane-operator-new"));
}
@@ -427,30 +510,29 @@
unsigned parseArgValues(const Driver &D, const llvm::opt::Arg *A,
bool DiagnoseErrors) {
- unsigned Kind = 0;
+ assert((A->getOption().matches(options::OPT_fsanitize_EQ) ||
+ A->getOption().matches(options::OPT_fno_sanitize_EQ) ||
+ A->getOption().matches(options::OPT_fsanitize_recover_EQ) ||
+ A->getOption().matches(options::OPT_fno_sanitize_recover_EQ)) &&
+ "Invalid argument in parseArgValues!");
+ unsigned Kinds = 0;
for (unsigned I = 0, N = A->getNumValues(); I != N; ++I) {
- if (unsigned K = parseValue(A->getValue(I)))
- Kind |= K;
+ const char *Value = A->getValue(I);
+ unsigned Kind;
+ // Special case: don't accept -fsanitize=all.
+ if (A->getOption().matches(options::OPT_fsanitize_EQ) &&
+ 0 == strcmp("all", Value))
+ Kind = 0;
+ else
+ Kind = parseValue(Value);
+
+ if (Kind)
+ Kinds |= Kind;
else if (DiagnoseErrors)
D.Diag(clang::diag::err_drv_unsupported_option_argument)
- << A->getOption().getName() << A->getValue(I);
+ << A->getOption().getName() << Value;
}
- return Kind;
-}
-
-bool parseArgument(const Driver &D, const llvm::opt::Arg *A, unsigned &Add,
- unsigned &Remove, bool DiagnoseErrors) {
- Add = 0;
- Remove = 0;
- if (A->getOption().matches(options::OPT_fsanitize_EQ)) {
- Add = parseArgValues(D, A, DiagnoseErrors);
- return true;
- }
- if (A->getOption().matches(options::OPT_fno_sanitize_EQ)) {
- Remove = parseArgValues(D, A, DiagnoseErrors);
- return true;
- }
- return false;
+ return Kinds;
}
std::string lastArgumentForMask(const Driver &D, const llvm::opt::ArgList &Args,
@@ -458,11 +540,15 @@
for (llvm::opt::ArgList::const_reverse_iterator I = Args.rbegin(),
E = Args.rend();
I != E; ++I) {
- unsigned Add, Remove;
- if (parseArgument(D, *I, Add, Remove, false) &&
- (expandGroups(Add) & Mask))
- return describeSanitizeArg(*I, Mask);
- Mask &= ~Remove;
+ const auto *Arg = *I;
+ if (Arg->getOption().matches(options::OPT_fsanitize_EQ)) {
+ unsigned AddKinds = expandGroups(parseArgValues(D, Arg, false));
+ if (AddKinds & Mask)
+ return describeSanitizeArg(Arg, Mask);
+ } else if (Arg->getOption().matches(options::OPT_fno_sanitize_EQ)) {
+ unsigned RemoveKinds = expandGroups(parseArgValues(D, Arg, false));
+ Mask &= ~RemoveKinds;
+ }
}
llvm_unreachable("arg list didn't provide expected value");
}
diff --git a/lib/Driver/ToolChain.cpp b/lib/Driver/ToolChain.cpp
index 6734ce7..5feeda4 100644
--- a/lib/Driver/ToolChain.cpp
+++ b/lib/Driver/ToolChain.cpp
@@ -26,14 +26,47 @@
using namespace clang;
using namespace llvm::opt;
+static llvm::opt::Arg *GetRTTIArgument(const ArgList &Args) {
+ return Args.getLastArg(options::OPT_mkernel, options::OPT_fapple_kext,
+ options::OPT_fno_rtti, options::OPT_frtti);
+}
+
+static ToolChain::RTTIMode CalculateRTTIMode(const ArgList &Args,
+ const llvm::Triple &Triple,
+ const Arg *CachedRTTIArg) {
+ // Explicit rtti/no-rtti args
+ if (CachedRTTIArg) {
+ if (CachedRTTIArg->getOption().matches(options::OPT_frtti))
+ return ToolChain::RM_EnabledExplicitly;
+ else
+ return ToolChain::RM_DisabledExplicitly;
+ }
+
+ // -frtti is default, except for the PS4 CPU.
+ if (!Triple.isPS4CPU())
+ return ToolChain::RM_EnabledImplicitly;
+
+ // On the PS4, turning on c++ exceptions turns on rtti.
+ // We're assuming that, if we see -fexceptions, rtti gets turned on.
+ Arg *Exceptions = Args.getLastArg(
+ options::OPT_fcxx_exceptions, options::OPT_fno_cxx_exceptions,
+ options::OPT_fexceptions, options::OPT_fno_exceptions);
+ if (Exceptions &&
+ (Exceptions->getOption().matches(options::OPT_fexceptions) ||
+ Exceptions->getOption().matches(options::OPT_fcxx_exceptions)))
+ return ToolChain::RM_EnabledImplicitly;
+
+ return ToolChain::RM_DisabledImplicitly;
+}
+
ToolChain::ToolChain(const Driver &D, const llvm::Triple &T,
const ArgList &Args)
- : D(D), Triple(T), Args(Args) {
+ : D(D), Triple(T), Args(Args), CachedRTTIArg(GetRTTIArgument(Args)),
+ CachedRTTIMode(CalculateRTTIMode(Args, Triple, CachedRTTIArg)) {
if (Arg *A = Args.getLastArg(options::OPT_mthread_model))
if (!isThreadModelSupported(A->getValue()))
D.Diag(diag::err_drv_invalid_thread_model_for_target)
- << A->getValue()
- << A->getAsString(Args);
+ << A->getValue() << A->getAsString(Args);
}
ToolChain::~ToolChain() {
@@ -129,6 +162,7 @@
case Action::AnalyzeJobClass:
case Action::MigrateJobClass:
case Action::VerifyPCHJobClass:
+ case Action::BackendJobClass:
return getClang();
}
diff --git a/lib/Driver/ToolChains.cpp b/lib/Driver/ToolChains.cpp
index 17ef107..93e6db8 100644
--- a/lib/Driver/ToolChains.cpp
+++ b/lib/Driver/ToolChains.cpp
@@ -132,11 +132,11 @@
.Cases("arm1020t", "arm1020e", "arm1022e", "arm1026ej-s", "armv5")
.Case("xscale", "xscale")
.Cases("arm1136j-s", "arm1136jf-s", "arm1176jz-s", "arm1176jzf-s", "armv6")
- .Case("cortex-m0", "armv6m")
+ .Cases("sc000", "cortex-m0", "cortex-m0plus", "cortex-m1", "armv6m")
.Cases("cortex-a5", "cortex-a7", "cortex-a8", "armv7")
.Cases("cortex-a9", "cortex-a12", "cortex-a15", "cortex-a17", "krait", "armv7")
- .Cases("cortex-r4", "cortex-r5", "armv7r")
- .Case("cortex-m3", "armv7m")
+ .Cases("cortex-r4", "cortex-r5", "cortex-r7", "armv7r")
+ .Cases("sc300", "cortex-m3", "armv7m")
.Cases("cortex-m4", "cortex-m7", "armv7em")
.Case("swift", "armv7s")
.Default(nullptr);
@@ -902,8 +902,7 @@
// FIXME: It would be far better to avoid inserting those -static arguments,
// but we can't check the deployment target in the translation code until
// it is set here.
- if (isTargetIOSBased() && !isIPhoneOSVersionLT(6, 0) &&
- getTriple().getArch() != llvm::Triple::aarch64) {
+ if (isTargetIOSBased() && !isIPhoneOSVersionLT(6, 0)) {
for (ArgList::iterator it = DAL->begin(), ie = DAL->end(); it != ie; ) {
Arg *A = *it;
++it;
@@ -1725,6 +1724,7 @@
MultilibSet AndroidMipsMultilibs = MultilibSet()
.Maybe(Multilib("/mips-r2").flag("+march=mips32r2"))
+ .Maybe(Multilib("/mips-r6").flag("+march=mips32r6"))
.FilterOut(NonExistent);
MultilibSet DebianMipsMultilibs;
@@ -1783,9 +1783,13 @@
addMultilibFlag(isMips64(TargetArch), "m64", Flags);
addMultilibFlag(isMips16(Args), "mips16", Flags);
addMultilibFlag(CPUName == "mips32", "march=mips32", Flags);
- addMultilibFlag(CPUName == "mips32r2", "march=mips32r2", Flags);
+ addMultilibFlag(CPUName == "mips32r2" || CPUName == "mips32r3" ||
+ CPUName == "mips32r5",
+ "march=mips32r2", Flags);
+ addMultilibFlag(CPUName == "mips32r6", "march=mips32r6", Flags);
addMultilibFlag(CPUName == "mips64", "march=mips64", Flags);
- addMultilibFlag(CPUName == "mips64r2" || CPUName == "octeon",
+ addMultilibFlag(CPUName == "mips64r2" || CPUName == "mips64r3" ||
+ CPUName == "mips64r5" || CPUName == "octeon",
"march=mips64r2", Flags);
addMultilibFlag(isMicroMips(Args), "mmicromips", Flags);
addMultilibFlag(tools::mips::isUCLibc(Args), "muclibc", Flags);
@@ -2068,8 +2072,11 @@
getTriple().getArch() == llvm::Triple::armeb ||
getTriple().getArch() == llvm::Triple::thumb ||
getTriple().getArch() == llvm::Triple::thumbeb ||
+ getTriple().getArch() == llvm::Triple::ppc ||
getTriple().getArch() == llvm::Triple::ppc64 ||
getTriple().getArch() == llvm::Triple::ppc64le ||
+ getTriple().getArch() == llvm::Triple::sparc ||
+ getTriple().getArch() == llvm::Triple::sparcv9 ||
getTriple().getArch() == llvm::Triple::systemz;
}
@@ -2507,7 +2514,7 @@
}
bool FreeBSD::isPIEDefault() const {
- return getSanitizerArgs().hasZeroBaseShadow();
+ return getSanitizerArgs().requiresPIE();
}
/// NetBSD - NetBSD tool chain which can call as(1) and ld(1) directly.
@@ -3152,7 +3159,8 @@
SmallVector<StringRef, 5> dirs;
CIncludeDirs.split(dirs, ":");
for (StringRef dir : dirs) {
- StringRef Prefix = llvm::sys::path::is_absolute(dir) ? SysRoot : "";
+ StringRef Prefix =
+ llvm::sys::path::is_absolute(dir) ? StringRef(SysRoot) : "";
addExternCSystemInclude(DriverArgs, CC1Args, Prefix + dir);
}
return;
@@ -3383,7 +3391,7 @@
}
bool Linux::isPIEDefault() const {
- return getSanitizerArgs().hasZeroBaseShadow();
+ return getSanitizerArgs().requiresPIE();
}
/// DragonFly - DragonFly tool chain which can call as(1) and ld(1) directly.
diff --git a/lib/Driver/ToolChains.h b/lib/Driver/ToolChains.h
index 876bb01..90893c3 100644
--- a/lib/Driver/ToolChains.h
+++ b/lib/Driver/ToolChains.h
@@ -256,7 +256,7 @@
bool IsBlocksDefault() const override {
// Always allow blocks on Apple; users interested in versioning are
- // expected to use /usr/include/Blocks.h.
+ // expected to use /usr/include/Block.h.
return true;
}
bool IsIntegratedAssemblerDefault() const override {
@@ -362,8 +362,7 @@
llvm::opt::ArgStringList &CmdArgs) const override;
bool isKernelStatic() const override {
- return !isTargetIPhoneOS() || isIPhoneOSVersionLT(6, 0) ||
- getTriple().getArch() == llvm::Triple::aarch64;
+ return !isTargetIPhoneOS() || isIPhoneOSVersionLT(6, 0);
}
protected:
@@ -534,17 +533,6 @@
return 2;
}
- virtual bool IsIntegratedAssemblerDefault() const override {
- switch (getTriple().getArch()) {
- case llvm::Triple::ppc:
- case llvm::Triple::sparc:
- case llvm::Triple::sparcv9:
- return true;
- default:
- return Generic_ELF::IsIntegratedAssemblerDefault();
- }
- }
-
protected:
Tool *buildAssembler() const override;
Tool *buildLinker() const override;
@@ -586,14 +574,6 @@
void
AddClangCXXStdlibIncludeArgs(const llvm::opt::ArgList &DriverArgs,
llvm::opt::ArgStringList &CC1Args) const override;
- bool IsIntegratedAssemblerDefault() const override {
- switch (getTriple().getArch()) {
- case llvm::Triple::ppc:
- return true;
- default:
- return Generic_ELF::IsIntegratedAssemblerDefault();
- }
- }
bool UseSjLjExceptions() const override;
bool isPIEDefault() const override;
@@ -618,14 +598,6 @@
bool IsUnwindTablesDefault() const override {
return true;
}
- bool IsIntegratedAssemblerDefault() const override {
- switch (getTriple().getArch()) {
- case llvm::Triple::ppc:
- return true;
- default:
- return Generic_ELF::IsIntegratedAssemblerDefault();
- }
- }
protected:
Tool *buildAssembler() const override;
diff --git a/lib/Driver/Tools.cpp b/lib/Driver/Tools.cpp
index 28b9068..b0e581b 100644
--- a/lib/Driver/Tools.cpp
+++ b/lib/Driver/Tools.cpp
@@ -10,9 +10,11 @@
#include "Tools.h"
#include "InputInfo.h"
#include "ToolChains.h"
+#include "clang/Basic/CharInfo.h"
#include "clang/Basic/LangOptions.h"
#include "clang/Basic/ObjCRuntime.h"
#include "clang/Basic/Version.h"
+#include "clang/Config/config.h"
#include "clang/Driver/Action.h"
#include "clang/Driver/Compilation.h"
#include "clang/Driver/Driver.h"
@@ -32,13 +34,16 @@
#include "llvm/Support/Compression.h"
#include "llvm/Support/ErrorHandling.h"
#include "llvm/Support/FileSystem.h"
-#include "llvm/Support/Format.h"
#include "llvm/Support/Host.h"
#include "llvm/Support/Path.h"
#include "llvm/Support/Process.h"
#include "llvm/Support/Program.h"
#include "llvm/Support/raw_ostream.h"
+#ifdef LLVM_ON_UNIX
+#include <unistd.h> // For getuid().
+#endif
+
using namespace clang::driver;
using namespace clang::driver::tools;
using namespace clang;
@@ -589,6 +594,12 @@
Features.push_back("+crypto");
} else if (FPU == "neon") {
Features.push_back("+neon");
+ } else if (FPU == "neon-vfpv3") {
+ Features.push_back("+vfp3");
+ Features.push_back("+neon");
+ } else if (FPU == "neon-vfpv4") {
+ Features.push_back("+neon");
+ Features.push_back("+vfp4");
} else if (FPU == "none") {
Features.push_back("-vfp2");
Features.push_back("-vfp3");
@@ -759,6 +770,7 @@
// Select the ABI to use.
//
// FIXME: Support -meabi.
+ // FIXME: Parts of this are duplicated in the backend, unify this somehow.
const char *ABIName = nullptr;
if (Arg *A = Args.getLastArg(options::OPT_mabi_EQ)) {
ABIName = A->getValue();
@@ -766,8 +778,7 @@
// The backend is hardwired to assume AAPCS for M-class processors, ensure
// the frontend matches that.
if (Triple.getEnvironment() == llvm::Triple::EABI ||
- (Triple.getOS() == llvm::Triple::UnknownOS &&
- Triple.getObjectFormat() == llvm::Triple::MachO) ||
+ Triple.getOS() == llvm::Triple::UnknownOS ||
StringRef(CPUName).startswith("cortex-m")) {
ABIName = "aapcs";
} else {
@@ -932,6 +943,19 @@
CmdArgs.push_back("-aarch64-no-strict-align");
}
+ if (Arg *A = Args.getLastArg(options::OPT_mfix_cortex_a53_835769,
+ options::OPT_mno_fix_cortex_a53_835769)) {
+ CmdArgs.push_back("-backend-option");
+ if (A->getOption().matches(options::OPT_mfix_cortex_a53_835769))
+ CmdArgs.push_back("-aarch64-fix-cortex-a53-835769=1");
+ else
+ CmdArgs.push_back("-aarch64-fix-cortex-a53-835769=0");
+ } else if (Triple.getEnvironment() == llvm::Triple::Android) {
+ // Enabled A53 errata (835769) workaround by default on android
+ CmdArgs.push_back("-backend-option");
+ CmdArgs.push_back("-aarch64-fix-cortex-a53-835769=1");
+ }
+
// Setting -mno-global-merge disables the codegen global merge pass. Setting
// -mglobal-merge has no effect as the pass is enabled by default.
if (Arg *A = Args.getLastArg(options::OPT_mglobal_merge,
@@ -939,6 +963,11 @@
if (A->getOption().matches(options::OPT_mno_global_merge))
CmdArgs.push_back("-mno-global-merge");
}
+
+ if (Args.hasArg(options::OPT_ffixed_x18)) {
+ CmdArgs.push_back("-backend-option");
+ CmdArgs.push_back("-aarch64-reserve-x18");
+ }
}
// Get CPU and ABI names. They are not independent
@@ -958,6 +987,10 @@
DefMips64CPU = "mips64r6";
}
+ // MIPS3 is the default for mips64*-unknown-openbsd.
+ if (Triple.getOS() == llvm::Triple::OpenBSD)
+ DefMips64CPU = "mips3";
+
if (Arg *A = Args.getLastArg(options::OPT_march_EQ,
options::OPT_mcpu_EQ))
CPUName = A->getValue();
@@ -1067,17 +1100,6 @@
mips::getMipsCPUAndABI(Args, Triple, CPUName, ABIName);
ABIName = getGnuCompatibleMipsABIName(ABIName);
- // Always override the backend's default ABI.
- std::string ABIFeature = llvm::StringSwitch<StringRef>(ABIName)
- .Case("32", "+o32")
- .Case("n32", "+n32")
- .Case("64", "+n64")
- .Case("eabi", "+eabi")
- .Default(("+" + ABIName).str());
- Features.push_back("-o32");
- Features.push_back("-n64");
- Features.push_back(Args.MakeArgString(ABIFeature));
-
AddTargetFeature(Args, Features, options::OPT_mno_abicalls,
options::OPT_mabicalls, "noabicalls");
@@ -1416,6 +1438,10 @@
return Is64Bit ? "core2" : "yonah";
}
+ // Set up default CPU name for PS4 compilers.
+ if (Triple.isPS4CPU())
+ return "btver2";
+
// On Android use targets compatible with gcc
if (Triple.getEnvironment() == llvm::Triple::Android)
return Is64Bit ? "x86-64" : "i686";
@@ -1499,6 +1525,7 @@
return getSystemZTargetCPU(Args);
case llvm::Triple::r600:
+ case llvm::Triple::amdgcn:
return getR600TargetGPU(Args);
}
}
@@ -1509,7 +1536,7 @@
// as gold requires -plugin to come before any -plugin-opt that -Wl might
// forward.
CmdArgs.push_back("-plugin");
- std::string Plugin = ToolChain.getDriver().Dir + "/../lib/LLVMgold.so";
+ std::string Plugin = ToolChain.getDriver().Dir + "/../lib" CLANG_LIBDIR_SUFFIX "/LLVMgold.so";
CmdArgs.push_back(Args.MakeArgString(Plugin));
// Try to pass driver level flags relevant to LTO code generation down to
@@ -1704,7 +1731,7 @@
std::vector<const char *> &Features) {
std::pair<StringRef, StringRef> Split = Mcpu.split("+");
CPU = Split.first;
- if (CPU == "cyclone" || CPU == "cortex-a53" || CPU == "cortex-a57") {
+ if (CPU == "cyclone" || CPU == "cortex-a53" || CPU == "cortex-a57" || CPU == "cortex-a72") {
Features.push_back("+neon");
Features.push_back("+crc");
Features.push_back("+crypto");
@@ -1893,55 +1920,28 @@
Triple.getArch() == llvm::Triple::arm));
}
-namespace {
- struct ExceptionSettings {
- bool ExceptionsEnabled;
- bool ShouldUseExceptionTables;
- ExceptionSettings() : ExceptionsEnabled(false),
- ShouldUseExceptionTables(false) {}
- };
-} // end anonymous namespace.
-
// exceptionSettings() exists to share the logic between -cc1 and linker
// invocations.
-static ExceptionSettings exceptionSettings(const ArgList &Args,
- const llvm::Triple &Triple) {
- ExceptionSettings ES;
-
- // Are exceptions enabled by default?
- ES.ExceptionsEnabled = (Triple.getArch() != llvm::Triple::xcore);
-
- // This keeps track of whether exceptions were explicitly turned on or off.
- bool DidHaveExplicitExceptionFlag = false;
-
+static bool exceptionSettings(const ArgList &Args, const llvm::Triple &Triple) {
if (Arg *A = Args.getLastArg(options::OPT_fexceptions,
- options::OPT_fno_exceptions)) {
+ options::OPT_fno_exceptions))
if (A->getOption().matches(options::OPT_fexceptions))
- ES.ExceptionsEnabled = true;
- else
- ES.ExceptionsEnabled = false;
+ return true;
- DidHaveExplicitExceptionFlag = true;
- }
-
- // Exception tables and cleanups can be enabled with -fexceptions even if the
- // language itself doesn't support exceptions.
- if (ES.ExceptionsEnabled && DidHaveExplicitExceptionFlag)
- ES.ShouldUseExceptionTables = true;
-
- return ES;
+ return false;
}
-/// addExceptionArgs - Adds exception related arguments to the driver command
-/// arguments. There's a master flag, -fexceptions and also language specific
-/// flags to enable/disable C++ and Objective-C exceptions.
-/// This makes it possible to for example disable C++ exceptions but enable
-/// Objective-C exceptions.
+/// Adds exception related arguments to the driver command arguments. There's a
+/// master flag, -fexceptions and also language specific flags to enable/disable
+/// C++ and Objective-C exceptions. This makes it possible to for example
+/// disable C++ exceptions but enable Objective-C exceptions.
static void addExceptionArgs(const ArgList &Args, types::ID InputType,
- const llvm::Triple &Triple,
- bool KernelOrKext,
+ const ToolChain &TC, bool KernelOrKext,
const ObjCRuntime &objcRuntime,
ArgStringList &CmdArgs) {
+ const Driver &D = TC.getDriver();
+ const llvm::Triple &Triple = TC.getTriple();
+
if (KernelOrKext) {
// -mkernel and -fapple-kext imply no exceptions, so claim exception related
// arguments now to avoid warnings about unused arguments.
@@ -1954,8 +1954,8 @@
return;
}
- // Gather the exception settings from the command line arguments.
- ExceptionSettings ES = exceptionSettings(Args, Triple);
+ // Gather the exception settings from the command line arguments.
+ bool EH = exceptionSettings(Args, Triple);
// Obj-C exceptions are enabled by default, regardless of -fexceptions. This
// is not necessarily sensible, but follows GCC.
@@ -1965,31 +1965,43 @@
true)) {
CmdArgs.push_back("-fobjc-exceptions");
- ES.ShouldUseExceptionTables |=
- shouldUseExceptionTablesForObjCExceptions(objcRuntime, Triple);
+ EH |= shouldUseExceptionTablesForObjCExceptions(objcRuntime, Triple);
}
if (types::isCXX(InputType)) {
- bool CXXExceptionsEnabled = ES.ExceptionsEnabled;
-
- if (Arg *A = Args.getLastArg(options::OPT_fcxx_exceptions,
- options::OPT_fno_cxx_exceptions,
- options::OPT_fexceptions,
- options::OPT_fno_exceptions)) {
- if (A->getOption().matches(options::OPT_fcxx_exceptions))
- CXXExceptionsEnabled = true;
- else if (A->getOption().matches(options::OPT_fno_cxx_exceptions))
- CXXExceptionsEnabled = false;
- }
+ bool CXXExceptionsEnabled =
+ Triple.getArch() != llvm::Triple::xcore && !Triple.isPS4CPU();
+ Arg *ExceptionArg = Args.getLastArg(
+ options::OPT_fcxx_exceptions, options::OPT_fno_cxx_exceptions,
+ options::OPT_fexceptions, options::OPT_fno_exceptions);
+ if (ExceptionArg)
+ CXXExceptionsEnabled =
+ ExceptionArg->getOption().matches(options::OPT_fcxx_exceptions) ||
+ ExceptionArg->getOption().matches(options::OPT_fexceptions);
if (CXXExceptionsEnabled) {
+ if (Triple.isPS4CPU()) {
+ ToolChain::RTTIMode RTTIMode = TC.getRTTIMode();
+ assert(ExceptionArg &&
+ "On the PS4 exceptions should only be enabled if passing "
+ "an argument");
+ if (RTTIMode == ToolChain::RM_DisabledExplicitly) {
+ const Arg *RTTIArg = TC.getRTTIArg();
+ assert(RTTIArg && "RTTI disabled explicitly but no RTTIArg!");
+ D.Diag(diag::err_drv_argument_not_allowed_with)
+ << RTTIArg->getAsString(Args) << ExceptionArg->getAsString(Args);
+ } else if (RTTIMode == ToolChain::RM_EnabledImplicitly)
+ D.Diag(diag::warn_drv_enabling_rtti_with_exceptions);
+ } else
+ assert(TC.getRTTIMode() != ToolChain::RM_DisabledImplicitly);
+
CmdArgs.push_back("-fcxx-exceptions");
- ES.ShouldUseExceptionTables = true;
+ EH = true;
}
}
- if (ES.ShouldUseExceptionTables)
+ if (EH)
CmdArgs.push_back("-fexceptions");
}
@@ -2015,7 +2027,7 @@
/// \brief Check whether the given input tree contains any compilation actions.
static bool ContainsCompileAction(const Action *A) {
- if (isa<CompileJobAction>(A))
+ if (isa<CompileJobAction>(A) || isa<BackendJobAction>(A))
return true;
for (const auto &Act : *A)
@@ -2116,11 +2128,13 @@
// Until ARM libraries are build separately, we have them all in one library
static StringRef getArchNameForCompilerRTLib(const ToolChain &TC) {
- if (TC.getArch() == llvm::Triple::arm ||
- TC.getArch() == llvm::Triple::armeb)
+ // FIXME: handle 64-bit
+ if (TC.getTriple().isOSWindows() &&
+ !TC.getTriple().isWindowsItaniumEnvironment())
+ return "i386";
+ if (TC.getArch() == llvm::Triple::arm || TC.getArch() == llvm::Triple::armeb)
return "arm";
- else
- return TC.getArchName();
+ return TC.getArchName();
}
static SmallString<128> getCompilerRTLibDir(const ToolChain &TC) {
@@ -2128,38 +2142,48 @@
SmallString<128> Res(TC.getDriver().ResourceDir);
const llvm::Triple &Triple = TC.getTriple();
// TC.getOS() yield "freebsd10.0" whereas "freebsd" is expected.
- StringRef OSLibName = (Triple.getOS() == llvm::Triple::FreeBSD) ?
- "freebsd" : TC.getOS();
+ StringRef OSLibName =
+ (Triple.getOS() == llvm::Triple::FreeBSD) ? "freebsd" : TC.getOS();
llvm::sys::path::append(Res, "lib", OSLibName);
return Res;
}
+static SmallString<128> getCompilerRT(const ToolChain &TC, StringRef Component,
+ bool Shared = false) {
+ const char *Env = TC.getTriple().getEnvironment() == llvm::Triple::Android
+ ? "-android"
+ : "";
+
+ bool IsOSWindows = TC.getTriple().isOSWindows();
+ StringRef Arch = getArchNameForCompilerRTLib(TC);
+ const char *Prefix = IsOSWindows ? "" : "lib";
+ const char *Suffix =
+ Shared ? (IsOSWindows ? ".dll" : ".so") : (IsOSWindows ? ".lib" : ".a");
+
+ SmallString<128> Path = getCompilerRTLibDir(TC);
+ llvm::sys::path::append(Path, Prefix + Twine("clang_rt.") + Component + "-" +
+ Arch + Env + Suffix);
+
+ return Path;
+}
+
// This adds the static libclang_rt.builtins-arch.a directly to the command line
// FIXME: Make sure we can also emit shared objects if they're requested
// and available, check for possible errors, etc.
-static void addClangRTLinux(
- const ToolChain &TC, const ArgList &Args, ArgStringList &CmdArgs) {
- SmallString<128> LibClangRT = getCompilerRTLibDir(TC);
- llvm::sys::path::append(LibClangRT, Twine("libclang_rt.builtins-") +
- getArchNameForCompilerRTLib(TC) +
- ".a");
+static void addClangRT(const ToolChain &TC, const ArgList &Args,
+ ArgStringList &CmdArgs) {
+ CmdArgs.push_back(Args.MakeArgString(getCompilerRT(TC, "builtins")));
- CmdArgs.push_back(Args.MakeArgString(LibClangRT));
- CmdArgs.push_back("-lgcc_s");
- if (TC.getDriver().CCCIsCXX())
- CmdArgs.push_back("-lgcc_eh");
+ if (!TC.getTriple().isOSWindows()) {
+ // FIXME: why do we link against gcc when we are using compiler-rt?
+ CmdArgs.push_back("-lgcc_s");
+ if (TC.getDriver().CCCIsCXX())
+ CmdArgs.push_back("-lgcc_eh");
+ }
}
-static void addClangRTWindows(const ToolChain &TC, const ArgList &Args,
- ArgStringList &CmdArgs) {
- SmallString<128> LibClangRT = getCompilerRTLibDir(TC);
- llvm::sys::path::append(LibClangRT, Twine("libclang_rt.builtins-") +
- getArchNameForCompilerRTLib(TC) + ".lib");
- CmdArgs.push_back(Args.MakeArgString(LibClangRT));
-}
-
-static void addProfileRT(
- const ToolChain &TC, const ArgList &Args, ArgStringList &CmdArgs) {
+static void addProfileRT(const ToolChain &TC, const ArgList &Args,
+ ArgStringList &CmdArgs) {
if (!(Args.hasFlag(options::OPT_fprofile_arcs, options::OPT_fno_profile_arcs,
false) ||
Args.hasArg(options::OPT_fprofile_generate) ||
@@ -2168,38 +2192,17 @@
Args.hasArg(options::OPT_coverage)))
return;
- SmallString<128> LibProfile = getCompilerRTLibDir(TC);
- llvm::sys::path::append(LibProfile, Twine("libclang_rt.profile-") +
- getArchNameForCompilerRTLib(TC) +
- ".a");
-
- CmdArgs.push_back(Args.MakeArgString(LibProfile));
-}
-
-static SmallString<128> getSanitizerRTLibName(const ToolChain &TC,
- StringRef Sanitizer,
- bool Shared) {
- // Sanitizer runtime has name "libclang_rt.<Sanitizer>-<ArchName>.{a,so}"
- // (or "libclang_rt.<Sanitizer>-<ArchName>-android.so for Android)
- const char *EnvSuffix =
- TC.getTriple().getEnvironment() == llvm::Triple::Android ? "-android" : "";
- SmallString<128> LibSanitizer = getCompilerRTLibDir(TC);
- llvm::sys::path::append(LibSanitizer,
- Twine("libclang_rt.") + Sanitizer + "-" +
- getArchNameForCompilerRTLib(TC) + EnvSuffix +
- (Shared ? ".so" : ".a"));
- return LibSanitizer;
+ CmdArgs.push_back(Args.MakeArgString(getCompilerRT(TC, "profile")));
}
static void addSanitizerRuntime(const ToolChain &TC, const ArgList &Args,
ArgStringList &CmdArgs, StringRef Sanitizer,
bool IsShared) {
- SmallString<128> LibSanitizer = getSanitizerRTLibName(TC, Sanitizer, IsShared);
// Static runtimes must be forced into executable, so we wrap them in
// whole-archive.
if (!IsShared)
CmdArgs.push_back("-whole-archive");
- CmdArgs.push_back(Args.MakeArgString(LibSanitizer));
+ CmdArgs.push_back(Args.MakeArgString(getCompilerRT(TC, Sanitizer, IsShared)));
if (!IsShared)
CmdArgs.push_back("-no-whole-archive");
}
@@ -2209,10 +2212,9 @@
static bool addSanitizerDynamicList(const ToolChain &TC, const ArgList &Args,
ArgStringList &CmdArgs,
StringRef Sanitizer) {
- SmallString<128> LibSanitizer = getSanitizerRTLibName(TC, Sanitizer, false);
- if (llvm::sys::fs::exists(LibSanitizer + ".syms")) {
- CmdArgs.push_back(
- Args.MakeArgString("--dynamic-list=" + LibSanitizer + ".syms"));
+ SmallString<128> SanRT = getCompilerRT(TC, Sanitizer);
+ if (llvm::sys::fs::exists(SanRT + ".syms")) {
+ CmdArgs.push_back(Args.MakeArgString("--dynamic-list=" + SanRT + ".syms"));
return true;
}
return false;
@@ -2301,27 +2303,49 @@
return !StaticRuntimes.empty();
}
+static bool areOptimizationsEnabled(const ArgList &Args) {
+ // Find the last -O arg and see if it is non-zero.
+ if (Arg *A = Args.getLastArg(options::OPT_O_Group))
+ return !A->getOption().matches(options::OPT_O0);
+ // Defaults to -O0.
+ return false;
+}
+
static bool shouldUseFramePointerForTarget(const ArgList &Args,
const llvm::Triple &Triple) {
- switch (Triple.getArch()) {
- // Don't use a frame pointer on linux if optimizing for certain targets.
- case llvm::Triple::mips64:
- case llvm::Triple::mips64el:
- case llvm::Triple::mips:
- case llvm::Triple::mipsel:
- case llvm::Triple::systemz:
- case llvm::Triple::x86:
- case llvm::Triple::x86_64:
- if (Triple.isOSLinux())
- if (Arg *A = Args.getLastArg(options::OPT_O_Group))
- if (!A->getOption().matches(options::OPT_O0))
- return false;
- return true;
- case llvm::Triple::xcore:
+ // XCore never wants frame pointers, regardless of OS.
+ if (Triple.getArch() == llvm::Triple::xcore) {
return false;
- default:
- return true;
}
+
+ if (Triple.isOSLinux()) {
+ switch (Triple.getArch()) {
+ // Don't use a frame pointer on linux if optimizing for certain targets.
+ case llvm::Triple::mips64:
+ case llvm::Triple::mips64el:
+ case llvm::Triple::mips:
+ case llvm::Triple::mipsel:
+ case llvm::Triple::systemz:
+ case llvm::Triple::x86:
+ case llvm::Triple::x86_64:
+ return !areOptimizationsEnabled(Args);
+ default:
+ return true;
+ }
+ }
+
+ if (Triple.isOSWindows()) {
+ switch (Triple.getArch()) {
+ case llvm::Triple::x86:
+ return !areOptimizationsEnabled(Args);
+ default:
+ // All other supported Windows ISAs use xdata unwind information, so frame
+ // pointers are not generally useful.
+ return false;
+ }
+ }
+
+ return true;
}
static bool shouldUseFramePointer(const ArgList &Args,
@@ -2339,6 +2363,9 @@
options::OPT_momit_leaf_frame_pointer))
return A->getOption().matches(options::OPT_mno_omit_leaf_frame_pointer);
+ if (Triple.isPS4CPU())
+ return false;
+
return shouldUseFramePointerForTarget(Args, Triple);
}
@@ -2461,6 +2488,48 @@
llvm::utostr_32(Build);
}
+// Claim options we don't want to warn if they are unused. We do this for
+// options that build systems might add but are unused when assembling or only
+// running the preprocessor for example.
+static void claimNoWarnArgs(const ArgList &Args) {
+ // Don't warn about unused -f(no-)?lto. This can happen when we're
+ // preprocessing, precompiling or assembling.
+ Args.ClaimAllArgs(options::OPT_flto);
+ Args.ClaimAllArgs(options::OPT_fno_lto);
+}
+
+static void appendUserToPath(SmallVectorImpl<char> &Result) {
+#ifdef LLVM_ON_UNIX
+ const char *Username = getenv("LOGNAME");
+#else
+ const char *Username = getenv("USERNAME");
+#endif
+ if (Username) {
+ // Validate that LoginName can be used in a path, and get its length.
+ size_t Len = 0;
+ for (const char *P = Username; *P; ++P, ++Len) {
+ if (!isAlphanumeric(*P) && *P != '_') {
+ Username = nullptr;
+ break;
+ }
+ }
+
+ if (Username && Len > 0) {
+ Result.append(Username, Username + Len);
+ return;
+ }
+ }
+
+ // Fallback to user id.
+#ifdef LLVM_ON_UNIX
+ std::string UID = llvm::utostr(getuid());
+#else
+ // FIXME: Windows seems to have an 'SID' that might work.
+ std::string UID = "9999";
+#endif
+ Result.append(UID.begin(), UID.end());
+}
+
void Clang::ConstructJob(Compilation &C, const JobAction &JA,
const InputInfo &Output,
const InputInfoList &Inputs,
@@ -2541,7 +2610,8 @@
} else if (isa<VerifyPCHJobAction>(JA)) {
CmdArgs.push_back("-verify-pch");
} else {
- assert(isa<CompileJobAction>(JA) && "Invalid action for clang tool.");
+ assert((isa<CompileJobAction>(JA) || isa<BackendJobAction>(JA)) &&
+ "Invalid action for clang tool.");
if (JA.getType() == types::TY_Nothing) {
CmdArgs.push_back("-fsyntax-only");
@@ -2734,8 +2804,7 @@
// Note that these flags are trump-cards. Regardless of the order w.r.t. the
// PIC or PIE options above, if these show up, PIC is disabled.
llvm::Triple Triple(TripleStr);
- if (KernelOrKext && (!Triple.isiOS() || Triple.isOSVersionLT(6) ||
- Triple.getArch() == llvm::Triple::aarch64))
+ if (KernelOrKext && (!Triple.isiOS() || Triple.isOSVersionLT(6)))
PIC = PIE = false;
if (Args.hasArg(options::OPT_static))
PIC = PIE = false;
@@ -2787,6 +2856,19 @@
// LLVM Code Generator Options.
+ if (Args.hasArg(options::OPT_frewrite_map_file) ||
+ Args.hasArg(options::OPT_frewrite_map_file_EQ)) {
+ for (arg_iterator
+ MFI = Args.filtered_begin(options::OPT_frewrite_map_file,
+ options::OPT_frewrite_map_file_EQ),
+ MFE = Args.filtered_end();
+ MFI != MFE; ++MFI) {
+ CmdArgs.push_back("-frewrite-map-file");
+ CmdArgs.push_back((*MFI)->getValue());
+ (*MFI)->claim();
+ }
+ }
+
if (Arg *A = Args.getLastArg(options::OPT_Wframe_larger_than_EQ)) {
StringRef v = A->getValue();
CmdArgs.push_back("-mllvm");
@@ -2948,6 +3030,8 @@
!TrappingMath)
CmdArgs.push_back("-menable-unsafe-fp-math");
+ if (!SignedZeros)
+ CmdArgs.push_back("-fno-signed-zeros");
// Validate and pass through -fp-contract option.
if (Arg *A = Args.getLastArg(options::OPT_ffast_math, FastMathAliasOption,
@@ -3232,6 +3316,10 @@
CmdArgs.push_back("-fdata-sections");
}
+ if (!Args.hasFlag(options::OPT_funique_section_names,
+ options::OPT_fno_unique_section_names, true))
+ CmdArgs.push_back("-fno-unique-section-names");
+
Args.AddAllArgs(CmdArgs, options::OPT_finstrument_functions);
if (Args.hasArg(options::OPT_fprofile_instr_generate) &&
@@ -3400,9 +3488,7 @@
D.Diag(diag::warn_ignored_gcc_optimization) << (*it)->getAsString(Args);
}
- // Don't warn about unused -flto. This can happen when we're preprocessing or
- // precompiling.
- Args.ClaimAllArgs(options::OPT_flto);
+ claimNoWarnArgs(Args);
Args.AddAllArgs(CmdArgs, options::OPT_R_Group);
Args.AddAllArgs(CmdArgs, options::OPT_W_Group);
@@ -3425,8 +3511,10 @@
else
Std->render(Args, CmdArgs);
+ // If -f(no-)trigraphs appears after the language standard flag, honor it.
if (Arg *A = Args.getLastArg(options::OPT_std_EQ, options::OPT_ansi,
- options::OPT_trigraphs))
+ options::OPT_ftrigraphs,
+ options::OPT_fno_trigraphs))
if (A != Std)
A->render(Args, CmdArgs);
} else {
@@ -3442,7 +3530,8 @@
else if (IsWindowsMSVC)
CmdArgs.push_back("-std=c++11");
- Args.AddLastArg(CmdArgs, options::OPT_trigraphs);
+ Args.AddLastArg(CmdArgs, options::OPT_ftrigraphs,
+ options::OPT_fno_trigraphs);
}
// GCC's behavior for -Wwrite-strings is a bit strange:
@@ -3561,6 +3650,11 @@
CmdArgs.push_back(A->getValue());
}
+ if (Arg *A = Args.getLastArg(options::OPT_fspell_checking_limit_EQ)) {
+ CmdArgs.push_back("-fspell-checking-limit");
+ CmdArgs.push_back(A->getValue());
+ }
+
// Pass -fmessage-length=.
CmdArgs.push_back("-fmessage-length");
if (Arg *A = Args.getLastArg(options::OPT_fmessage_length_EQ)) {
@@ -3720,6 +3814,15 @@
CmdArgs.push_back(Args.MakeArgString("-mstack-alignment=" + alignment));
}
+ if (Args.hasArg(options::OPT_mstack_probe_size)) {
+ StringRef Size = Args.getLastArgValue(options::OPT_mstack_probe_size);
+
+ if (!Size.empty())
+ CmdArgs.push_back(Args.MakeArgString("-mstack-probe-size=" + Size));
+ else
+ CmdArgs.push_back("-mstack-probe-size=0");
+ }
+
if (getToolChain().getTriple().getArch() == llvm::Triple::aarch64 ||
getToolChain().getTriple().getArch() == llvm::Triple::aarch64_be)
CmdArgs.push_back("-fallow-half-arguments-and-returns");
@@ -3826,6 +3929,12 @@
CmdArgs.push_back("-fmodules-strict-decluse");
}
+ // -fno-implicit-modules turns off implicitly compiling modules on demand.
+ if (!Args.hasFlag(options::OPT_fimplicit_modules,
+ options::OPT_fno_implicit_modules)) {
+ CmdArgs.push_back("-fno-implicit-modules");
+ }
+
// -fmodule-name specifies the module that is currently being built (or
// used for header checking by -fmodule-maps).
Args.AddLastArg(CmdArgs, options::OPT_fmodule_name);
@@ -3853,7 +3962,8 @@
// No module path was provided: use the default.
llvm::sys::path::system_temp_directory(/*erasedOnReboot=*/false,
ModuleCachePath);
- llvm::sys::path::append(ModuleCachePath, "org.llvm.clang");
+ llvm::sys::path::append(ModuleCachePath, "org.llvm.clang.");
+ appendUserToPath(ModuleCachePath);
llvm::sys::path::append(ModuleCachePath, "ModuleCache");
}
const char Arg[] = "-fmodules-cache-path=";
@@ -3892,10 +4002,9 @@
llvm::sys::fs::file_status Status;
if (llvm::sys::fs::status(A->getValue(), Status))
D.Diag(diag::err_drv_no_such_file) << A->getValue();
- char TimeStamp[48];
- snprintf(TimeStamp, sizeof(TimeStamp), "-fbuild-session-timestamp=%" PRIu64,
- (uint64_t)Status.getLastModificationTime().toEpochTime());
- CmdArgs.push_back(Args.MakeArgString(TimeStamp));
+ CmdArgs.push_back(Args.MakeArgString(
+ "-fbuild-session-timestamp=" +
+ Twine((uint64_t)Status.getLastModificationTime().toEpochTime())));
}
if (Args.getLastArg(options::OPT_fmodules_validate_once_per_build_session)) {
@@ -3921,21 +4030,11 @@
false))
CmdArgs.push_back("-fno-elide-constructors");
- // -frtti is default.
- if (!Args.hasFlag(options::OPT_frtti, options::OPT_fno_rtti) ||
- KernelOrKext) {
- CmdArgs.push_back("-fno-rtti");
+ ToolChain::RTTIMode RTTIMode = getToolChain().getRTTIMode();
- // -fno-rtti cannot usefully be combined with -fsanitize=vptr.
- if (Sanitize.sanitizesVptr()) {
- std::string NoRttiArg =
- Args.getLastArg(options::OPT_mkernel,
- options::OPT_fapple_kext,
- options::OPT_fno_rtti)->getAsString(Args);
- D.Diag(diag::err_drv_argument_not_allowed_with)
- << "-fsanitize=vptr" << NoRttiArg;
- }
- }
+ if (RTTIMode == ToolChain::RM_DisabledExplicitly ||
+ RTTIMode == ToolChain::RM_DisabledImplicitly)
+ CmdArgs.push_back("-fno-rtti");
// -fshort-enums=0 is default for all architectures except Hexagon.
if (Args.hasFlag(options::OPT_fshort_enums,
@@ -3968,6 +4067,11 @@
IsWindowsMSVC))
CmdArgs.push_back("-fms-extensions");
+ // -fno-use-line-directives is default.
+ if (Args.hasFlag(options::OPT_fuse_line_directives,
+ options::OPT_fno_use_line_directives, false))
+ CmdArgs.push_back("-fuse-line-directives");
+
// -fms-compatibility=0 is default.
if (Args.hasFlag(options::OPT_fms_compatibility,
options::OPT_fno_ms_compatibility,
@@ -3996,7 +4100,7 @@
Ver = getMSCompatibilityVersion(MSCVersion->getValue());
if (Ver.empty())
- CmdArgs.push_back("-fms-compatibility-version=17.00");
+ CmdArgs.push_back("-fms-compatibility-version=18.00");
else
CmdArgs.push_back(Args.MakeArgString("-fms-compatibility-version=" + Ver));
}
@@ -4113,7 +4217,7 @@
// Handle GCC-style exception args.
if (!C.getDriver().IsCLMode())
- addExceptionArgs(Args, InputType, getToolChain().getTriple(), KernelOrKext,
+ addExceptionArgs(Args, InputType, getToolChain(), KernelOrKext,
objcRuntime, CmdArgs);
if (getToolChain().UseSjLjExceptions())
@@ -4307,6 +4411,11 @@
false))
CmdArgs.push_back("-fasm-blocks");
+ // -fgnu-inline-asm is default.
+ if (!Args.hasFlag(options::OPT_fgnu_inline_asm,
+ options::OPT_fno_gnu_inline_asm, true))
+ CmdArgs.push_back("-fno-gnu-inline-asm");
+
// Enable vectorization per default according to the optimization level
// selected. For optimization levels that want vectorization we use the alias
// option to simplify the hasFlag logic.
@@ -4414,18 +4523,27 @@
// Forward -Xclang arguments to -cc1, and -mllvm arguments to the LLVM option
// parser.
Args.AddAllArgValues(CmdArgs, options::OPT_Xclang);
+ bool OptDisabled = false;
for (arg_iterator it = Args.filtered_begin(options::OPT_mllvm),
ie = Args.filtered_end(); it != ie; ++it) {
(*it)->claim();
// We translate this by hand to the -cc1 argument, since nightly test uses
// it and developers have been trained to spell it with -mllvm.
- if (StringRef((*it)->getValue(0)) == "-disable-llvm-optzns")
+ if (StringRef((*it)->getValue(0)) == "-disable-llvm-optzns") {
CmdArgs.push_back("-disable-llvm-optzns");
- else
+ OptDisabled = true;
+ } else
(*it)->render(Args, CmdArgs);
}
+ // With -save-temps, we want to save the unoptimized bitcode output from the
+ // CompileJobAction, so disable optimizations if they are not already
+ // disabled.
+ if (C.getDriver().isSaveTempsEnabled() && !OptDisabled &&
+ isa<CompileJobAction>(JA))
+ CmdArgs.push_back("-disable-llvm-optzns");
+
if (Output.getType() == types::TY_Dependencies) {
// Handled with other dependency code.
} else if (Output.isFilename()) {
@@ -4471,7 +4589,8 @@
// can propagate it to the backend.
bool SplitDwarf = Args.hasArg(options::OPT_gsplit_dwarf) &&
getToolChain().getTriple().isOSLinux() &&
- (isa<AssembleJobAction>(JA) || isa<CompileJobAction>(JA));
+ (isa<AssembleJobAction>(JA) || isa<CompileJobAction>(JA) ||
+ isa<BackendJobAction>(JA));
const char *SplitDwarfOut;
if (SplitDwarf) {
CmdArgs.push_back("-split-dwarf-file");
@@ -4495,7 +4614,7 @@
// Handle the debug info splitting at object creation time if we're
// creating an object.
// TODO: Currently only works on linux with newer objcopy.
- if (SplitDwarf && !isa<CompileJobAction>(JA))
+ if (SplitDwarf && !isa<CompileJobAction>(JA) && !isa<BackendJobAction>(JA))
SplitDebugInfo(getToolChain(), C, *this, JA, Args, Output, SplitDwarfOut);
if (Arg *A = Args.getLastArg(options::OPT_pg))
@@ -4743,8 +4862,8 @@
EHFlags EH = parseClangCLEHFlags(D, Args);
// FIXME: Do something with NoExceptC.
if (EH.Synch || EH.Asynch) {
- CmdArgs.push_back("-fexceptions");
CmdArgs.push_back("-fcxx-exceptions");
+ CmdArgs.push_back("-fexceptions");
}
// /EP should expand to -E -P.
@@ -4753,6 +4872,19 @@
CmdArgs.push_back("-P");
}
+ unsigned VolatileOptionID;
+ if (getToolChain().getTriple().getArch() == llvm::Triple::x86_64 ||
+ getToolChain().getTriple().getArch() == llvm::Triple::x86)
+ VolatileOptionID = options::OPT__SLASH_volatile_ms;
+ else
+ VolatileOptionID = options::OPT__SLASH_volatile_iso;
+
+ if (Arg *A = Args.getLastArg(options::OPT__SLASH_volatile_Group))
+ VolatileOptionID = A->getOption().getID();
+
+ if (VolatileOptionID == options::OPT__SLASH_volatile_ms)
+ CmdArgs.push_back("-fms-volatile");
+
Arg *MostGeneralArg = Args.getLastArg(options::OPT__SLASH_vmg);
Arg *BestCaseArg = Args.getLastArg(options::OPT__SLASH_vmb);
if (MostGeneralArg && BestCaseArg)
@@ -4797,6 +4929,17 @@
return CLFallback.get();
}
+void ClangAs::AddMIPSTargetArgs(const ArgList &Args,
+ ArgStringList &CmdArgs) const {
+ StringRef CPUName;
+ StringRef ABIName;
+ const llvm::Triple &Triple = getToolChain().getTriple();
+ mips::getMipsCPUAndABI(Args, Triple, CPUName, ABIName);
+
+ CmdArgs.push_back("-target-abi");
+ CmdArgs.push_back(ABIName.data());
+}
+
void ClangAs::ConstructJob(Compilation &C, const JobAction &JA,
const InputInfo &Output,
const InputInfoList &Inputs,
@@ -4812,6 +4955,8 @@
// and "clang -emit-llvm -c foo.s"
Args.ClaimAllArgs(options::OPT_emit_llvm);
+ claimNoWarnArgs(Args);
+
// Invoke ourselves in -cc1as mode.
//
// FIXME: Implement custom jobs for internal actions.
@@ -4902,6 +5047,19 @@
// FIXME: Add -static support, once we have it.
+ // Add target specific flags.
+ switch(getToolChain().getArch()) {
+ default:
+ break;
+
+ case llvm::Triple::mips:
+ case llvm::Triple::mipsel:
+ case llvm::Triple::mips64:
+ case llvm::Triple::mips64el:
+ AddMIPSTargetArgs(Args, CmdArgs);
+ break;
+ }
+
// Consume all the warning flags. Usually this would be handled more
// gracefully by -cc1 (warning about unknown warning flags, etc) but -cc1as
// doesn't handle that so rather than warning about unused flags that are
@@ -5064,16 +5222,22 @@
ArgStringList &CmdArgs) const {
const Driver &D = getToolChain().getDriver();
+ switch (JA.getType()) {
// If -flto, etc. are present then make sure not to force assembly output.
- if (JA.getType() == types::TY_LLVM_IR || JA.getType() == types::TY_LTO_IR ||
- JA.getType() == types::TY_LLVM_BC || JA.getType() == types::TY_LTO_BC)
+ case types::TY_LLVM_IR:
+ case types::TY_LTO_IR:
+ case types::TY_LLVM_BC:
+ case types::TY_LTO_BC:
CmdArgs.push_back("-c");
- else {
- if (JA.getType() != types::TY_PP_Asm)
- D.Diag(diag::err_drv_invalid_gcc_output_type)
- << getTypeName(JA.getType());
-
+ break;
+ case types::TY_PP_Asm:
CmdArgs.push_back("-S");
+ break;
+ case types::TY_Nothing:
+ CmdArgs.push_back("-fsyntax-only");
+ break;
+ default:
+ D.Diag(diag::err_drv_invalid_gcc_output_type) << getTypeName(JA.getType());
}
}
@@ -5092,6 +5256,7 @@
const InputInfoList &Inputs,
const ArgList &Args,
const char *LinkingOutput) const {
+ claimNoWarnArgs(Args);
const Driver &D = getToolChain().getDriver();
ArgStringList CmdArgs;
@@ -5382,16 +5547,30 @@
.Cases("arm1156t2-s", "arm1156t2f-s", "v6t2")
.Cases("cortex-a5", "cortex-a7", "cortex-a8", "v7")
.Cases("cortex-a9", "cortex-a12", "cortex-a15", "cortex-a17", "krait", "v7")
- .Cases("cortex-r4", "cortex-r5", "v7r")
- .Case("cortex-m0", "v6m")
- .Case("cortex-m3", "v7m")
+ .Cases("cortex-r4", "cortex-r5", "cortex-r7", "v7r")
+ .Cases("sc000", "cortex-m0", "cortex-m0plus", "cortex-m1", "v6m")
+ .Cases("sc300", "cortex-m3", "v7m")
.Cases("cortex-m4", "cortex-m7", "v7em")
.Case("swift", "v7s")
.Case("cyclone", "v8")
- .Cases("cortex-a53", "cortex-a57", "v8")
+ .Cases("cortex-a53", "cortex-a57", "cortex-a72", "v8")
.Default("");
}
+void arm::appendEBLinkFlags(const ArgList &Args, ArgStringList &CmdArgs, const llvm::Triple &Triple) {
+ if (Args.hasArg(options::OPT_r))
+ return;
+
+ StringRef Suffix = getLLVMArchSuffixForARM(getARMCPUForMArch(Args, Triple));
+ const char *LinkFlag = llvm::StringSwitch<const char *>(Suffix)
+ .Cases("v4", "v4t", "v5", "v5e", nullptr)
+ .Cases("v6", "v6t2", nullptr)
+ .Default("--be8");
+
+ if (LinkFlag)
+ CmdArgs.push_back(LinkFlag);
+}
+
bool mips::hasMipsAbiArg(const ArgList &Args, const char *Value) {
Arg *A = Args.getLastArg(options::OPT_mabi_EQ);
return A && (A->getValue() == StringRef(Value));
@@ -5428,8 +5607,8 @@
return llvm::StringSwitch<bool>(CPUName)
.Cases("mips2", "mips3", "mips4", "mips5", true)
- .Cases("mips32", "mips32r2", true)
- .Cases("mips64", "mips64r2", true)
+ .Cases("mips32", "mips32r2", "mips32r3", "mips32r5", true)
+ .Cases("mips64", "mips64r2", "mips64r3", "mips64r5", true)
.Default(false);
}
@@ -5460,6 +5639,7 @@
.Cases("armv7s", "xscale", llvm::Triple::arm)
.Case("arm64", llvm::Triple::aarch64)
.Case("r600", llvm::Triple::r600)
+ .Case("amdgcn", llvm::Triple::amdgcn)
.Case("nvptx", llvm::Triple::nvptx)
.Case("nvptx64", llvm::Triple::nvptx64)
.Case("amdil", llvm::Triple::amdil)
@@ -5633,7 +5813,8 @@
// If we are using LTO, then automatically create a temporary file path for
// the linker to use, so that it's lifetime will extend past a possible
// dsymutil step.
- if (Version[0] >= 116 && D.IsUsingLTO(Args) && NeedsTempPath(Inputs)) {
+ if (Version[0] >= 116 && D.IsUsingLTO(getToolChain(), Args) &&
+ NeedsTempPath(Inputs)) {
const char *TmpPath = C.getArgs().MakeArgString(
D.GetTemporaryPath("cc", types::getTypeTempSuffix(types::TY_Object)));
C.addTempFile(TmpPath);
@@ -5923,6 +6104,12 @@
Args.AddAllArgs(CmdArgs, options::OPT_T_Group);
Args.AddAllArgs(CmdArgs, options::OPT_F);
+ // -iframework should be forwarded as -F.
+ for (auto it = Args.filtered_begin(options::OPT_iframework),
+ ie = Args.filtered_end(); it != ie; ++it)
+ CmdArgs.push_back(Args.MakeArgString(std::string("-F") +
+ (*it)->getValue()));
+
const char *Exec =
Args.MakeArgString(getToolChain().GetLinkerPath());
std::unique_ptr<Command> Cmd =
@@ -6001,6 +6188,7 @@
const InputInfoList &Inputs,
const ArgList &Args,
const char *LinkingOutput) const {
+ claimNoWarnArgs(Args);
ArgStringList CmdArgs;
Args.AddAllArgValues(CmdArgs, options::OPT_Wa_COMMA,
@@ -6126,6 +6314,7 @@
const InputInfoList &Inputs,
const ArgList &Args,
const char *LinkingOutput) const {
+ claimNoWarnArgs(Args);
ArgStringList CmdArgs;
bool NeedsKPIC = false;
@@ -6328,6 +6517,7 @@
const InputInfoList &Inputs,
const ArgList &Args,
const char *LinkingOutput) const {
+ claimNoWarnArgs(Args);
ArgStringList CmdArgs;
Args.AddAllArgValues(CmdArgs, options::OPT_Wa_COMMA,
@@ -6464,6 +6654,7 @@
const InputInfoList &Inputs,
const ArgList &Args,
const char *LinkingOutput) const {
+ claimNoWarnArgs(Args);
ArgStringList CmdArgs;
// When building 32-bit code on FreeBSD/amd64, we have to explicitly
@@ -6646,7 +6837,7 @@
Args.AddAllArgs(CmdArgs, options::OPT_Z_Flag);
Args.AddAllArgs(CmdArgs, options::OPT_r);
- if (D.IsUsingLTO(Args))
+ if (D.IsUsingLTO(getToolChain(), Args))
AddGoldPlugin(ToolChain, Args, CmdArgs);
bool NeedsSanitizerDeps = addSanitizerRuntimes(ToolChain, Args, CmdArgs);
@@ -6729,6 +6920,7 @@
const InputInfoList &Inputs,
const ArgList &Args,
const char *LinkingOutput) const {
+ claimNoWarnArgs(Args);
ArgStringList CmdArgs;
// GNU as needs different flags for creating the correct output format
@@ -6849,6 +7041,7 @@
break;
case llvm::Triple::armeb:
case llvm::Triple::thumbeb:
+ arm::appendEBLinkFlags(Args, CmdArgs, getToolChain().getTriple());
CmdArgs.push_back("-m");
switch (getToolChain().getTriple().getEnvironment()) {
case llvm::Triple::EABI:
@@ -7011,6 +7204,8 @@
const InputInfoList &Inputs,
const ArgList &Args,
const char *LinkingOutput) const {
+ claimNoWarnArgs(Args);
+
ArgStringList CmdArgs;
bool NeedsKPIC = false;
@@ -7289,19 +7484,17 @@
}
static void AddRunTimeLibs(const ToolChain &TC, const Driver &D,
- ArgStringList &CmdArgs, const ArgList &Args) {
+ ArgStringList &CmdArgs, const ArgList &Args) {
// Make use of compiler-rt if --rtlib option is used
ToolChain::RuntimeLibType RLT = TC.GetRuntimeLibType(Args);
- switch(RLT) {
+ switch (RLT) {
case ToolChain::RLT_CompilerRT:
switch (TC.getTriple().getOS()) {
default: llvm_unreachable("unsupported OS");
case llvm::Triple::Win32:
- addClangRTWindows(TC, Args, CmdArgs);
- break;
case llvm::Triple::Linux:
- addClangRTLinux(TC, Args, CmdArgs);
+ addClangRT(TC, Args, CmdArgs);
break;
}
break;
@@ -7399,6 +7592,10 @@
if (Args.hasArg(options::OPT_s))
CmdArgs.push_back("-s");
+ if (ToolChain.getArch() == llvm::Triple::armeb ||
+ ToolChain.getArch() == llvm::Triple::thumbeb)
+ arm::appendEBLinkFlags(Args, CmdArgs, getToolChain().getTriple());
+
for (const auto &Opt : ToolChain.ExtraOpts)
CmdArgs.push_back(Opt.c_str());
@@ -7476,7 +7673,7 @@
for (const auto &Path : Paths)
CmdArgs.push_back(Args.MakeArgString(StringRef("-L") + Path));
- if (D.IsUsingLTO(Args))
+ if (D.IsUsingLTO(getToolChain(), Args))
AddGoldPlugin(ToolChain, Args, CmdArgs);
if (Args.hasArg(options::OPT_Z_Xlinker__no_demangle))
@@ -7573,6 +7770,7 @@
const InputInfoList &Inputs,
const ArgList &Args,
const char *LinkingOutput) const {
+ claimNoWarnArgs(Args);
ArgStringList CmdArgs;
Args.AddAllArgValues(CmdArgs, options::OPT_Wa_COMMA, options::OPT_Xassembler);
@@ -7650,6 +7848,7 @@
const InputInfoList &Inputs,
const ArgList &Args,
const char *LinkingOutput) const {
+ claimNoWarnArgs(Args);
ArgStringList CmdArgs;
// When building 32-bit code on DragonFly/pc64, we have to explicitly
@@ -7816,15 +8015,6 @@
C.addCommand(llvm::make_unique<Command>(JA, *this, Exec, CmdArgs));
}
-static void addSanitizerRTWindows(const ToolChain &TC, const ArgList &Args,
- ArgStringList &CmdArgs,
- StringRef RTName) {
- SmallString<128> LibSanitizer(getCompilerRTLibDir(TC));
- llvm::sys::path::append(LibSanitizer,
- Twine("clang_rt.") + RTName + ".lib");
- CmdArgs.push_back(Args.MakeArgString(LibSanitizer));
-}
-
// Try to find Exe from a Visual Studio distribution. This first tries to find
// an installed copy of Visual Studio and, failing that, looks in the PATH,
// making sure that whatever executable that's found is not a same-named exe
@@ -7851,19 +8041,16 @@
const ArgList &Args,
const char *LinkingOutput) const {
ArgStringList CmdArgs;
+ const ToolChain &TC = getToolChain();
- if (Output.isFilename()) {
+ assert((Output.isFilename() || Output.isNothing()) && "invalid output");
+ if (Output.isFilename())
CmdArgs.push_back(Args.MakeArgString(std::string("-out:") +
Output.getFilename()));
- } else {
- assert(Output.isNothing() && "Invalid output.");
- }
if (!Args.hasArg(options::OPT_nostdlib) &&
- !Args.hasArg(options::OPT_nostartfiles) &&
- !C.getDriver().IsCLMode()) {
+ !Args.hasArg(options::OPT_nostartfiles) && !C.getDriver().IsCLMode())
CmdArgs.push_back("-defaultlib:libcmt");
- }
if (!llvm::sys::Process::GetEnv("LIB")) {
// If the VC environment hasn't been configured (perhaps because the user
@@ -7871,7 +8058,7 @@
// the environment variable is set however, assume the user knows what he's
// doing.
std::string VisualStudioDir;
- const auto &MSVC = static_cast<const toolchains::MSVCToolChain &>(getToolChain());
+ const auto &MSVC = static_cast<const toolchains::MSVCToolChain &>(TC);
if (MSVC.getVisualStudioInstallDir(VisualStudioDir)) {
SmallString<128> LibDir(VisualStudioDir);
llvm::sys::path::append(LibDir, "VC", "lib");
@@ -7900,12 +8087,10 @@
CmdArgs.push_back("-nologo");
- if (Args.hasArg(options::OPT_g_Group)) {
+ if (Args.hasArg(options::OPT_g_Group))
CmdArgs.push_back("-debug");
- }
bool DLL = Args.hasArg(options::OPT__SLASH_LD, options::OPT__SLASH_LDd);
-
if (DLL) {
CmdArgs.push_back(Args.MakeArgString("-dll"));
@@ -7915,23 +8100,28 @@
ImplibName.str()));
}
- if (getToolChain().getSanitizerArgs().needsAsanRt()) {
+ if (TC.getSanitizerArgs().needsAsanRt()) {
CmdArgs.push_back(Args.MakeArgString("-debug"));
CmdArgs.push_back(Args.MakeArgString("-incremental:no"));
- // FIXME: Handle 64-bit.
if (Args.hasArg(options::OPT__SLASH_MD, options::OPT__SLASH_MDd)) {
- addSanitizerRTWindows(getToolChain(), Args, CmdArgs, "asan_dynamic-i386");
- addSanitizerRTWindows(getToolChain(), Args, CmdArgs,
- "asan_dynamic_runtime_thunk-i386");
+ static const char *CompilerRTComponents[] = {
+ "asan_dynamic",
+ "asan_dynamic_runtime_thunk",
+ };
+ for (const auto &Component : CompilerRTComponents)
+ CmdArgs.push_back(Args.MakeArgString(getCompilerRT(TC, Component)));
// Make sure the dynamic runtime thunk is not optimized out at link time
// to ensure proper SEH handling.
CmdArgs.push_back(Args.MakeArgString("-include:___asan_seh_interceptor"));
} else if (DLL) {
- addSanitizerRTWindows(getToolChain(), Args, CmdArgs,
- "asan_dll_thunk-i386");
+ CmdArgs.push_back(Args.MakeArgString(getCompilerRT(TC, "asan_dll_thunk")));
} else {
- addSanitizerRTWindows(getToolChain(), Args, CmdArgs, "asan-i386");
- addSanitizerRTWindows(getToolChain(), Args, CmdArgs, "asan_cxx-i386");
+ static const char *CompilerRTComponents[] = {
+ "asan",
+ "asan_cxx",
+ };
+ for (const auto &Component : CompilerRTComponents)
+ CmdArgs.push_back(Args.MakeArgString(getCompilerRT(TC, Component)));
}
}
@@ -7963,10 +8153,26 @@
A.renderAsInput(Args, CmdArgs);
}
- // It's not sufficient to just use link from the program PATH, because other
- // environments like GnuWin32 install their own link.exe which may come first.
- llvm::SmallString<128> linkPath(FindVisualStudioExecutable(
- getToolChain(), "link.exe", C.getDriver().getClangProgramPath()));
+ // We need to special case some linker paths. In the case of lld, we need to
+ // translate 'lld' into 'lld-link', and in the case of the regular msvc
+ // linker, we need to use a special search algorithm.
+ llvm::SmallString<128> linkPath;
+ StringRef Linker = Args.getLastArgValue(options::OPT_fuse_ld_EQ, "link");
+ if (Linker.equals_lower("lld"))
+ Linker = "lld-link";
+
+ if (Linker.equals_lower("link")) {
+ // If we're using the MSVC linker, it's not sufficient to just use link
+ // from the program PATH, because other environments like GnuWin32 install
+ // their own link.exe which may come first.
+ linkPath = FindVisualStudioExecutable(TC, "link.exe",
+ C.getDriver().getClangProgramPath());
+ } else {
+ linkPath = Linker;
+ llvm::sys::path::replace_extension(linkPath, "exe");
+ linkPath = TC.GetProgramPath(linkPath.c_str());
+ }
+
const char *Exec = Args.MakeArgString(linkPath);
C.addCommand(llvm::make_unique<Command>(JA, *this, Exec, CmdArgs));
}
@@ -8075,6 +8281,7 @@
const InputInfoList &Inputs,
const ArgList &Args,
const char *LinkingOutput) const {
+ claimNoWarnArgs(Args);
ArgStringList CmdArgs;
CmdArgs.push_back("-o");
@@ -8120,8 +8327,7 @@
if (Args.hasArg(options::OPT_v))
CmdArgs.push_back("-v");
- ExceptionSettings EH = exceptionSettings(Args, getToolChain().getTriple());
- if (EH.ShouldUseExceptionTables)
+ if (exceptionSettings(Args, getToolChain().getTriple()))
CmdArgs.push_back("-fexceptions");
AddLinkerInputs(getToolChain(), Inputs, Args, CmdArgs);
@@ -8135,6 +8341,7 @@
const InputInfoList &Inputs,
const ArgList &Args,
const char *LinkingOutput) const {
+ claimNoWarnArgs(Args);
const auto &TC =
static_cast<const toolchains::CrossWindowsToolChain &>(getToolChain());
ArgStringList CmdArgs;
@@ -8306,4 +8513,3 @@
C.addCommand(llvm::make_unique<Command>(JA, *this, Exec, CmdArgs));
}
-
diff --git a/lib/Driver/Tools.h b/lib/Driver/Tools.h
index 59af8a0..93a19fb 100644
--- a/lib/Driver/Tools.h
+++ b/lib/Driver/Tools.h
@@ -95,6 +95,7 @@
bool hasGoodDiagnostics() const override { return true; }
bool hasIntegratedAssembler() const override { return true; }
bool hasIntegratedCPP() const override { return true; }
+ bool canEmitIR() const override { return true; }
void ConstructJob(Compilation &C, const JobAction &JA,
const InputInfo &Output, const InputInfoList &Inputs,
@@ -108,7 +109,8 @@
ClangAs(const ToolChain &TC) : Tool("clang::as",
"clang integrated assembler", TC,
RF_Full) {}
-
+ void AddMIPSTargetArgs(const llvm::opt::ArgList &Args,
+ llvm::opt::ArgStringList &CmdArgs) const;
bool hasGoodDiagnostics() const override { return true; }
bool hasIntegratedAssembler() const override { return false; }
bool hasIntegratedCPP() const override { return false; }
@@ -227,6 +229,8 @@
const char* getARMCPUForMArch(const llvm::opt::ArgList &Args,
const llvm::Triple &Triple);
const char* getLLVMArchSuffixForARM(StringRef CPU);
+
+ void appendEBLinkFlags(const llvm::opt::ArgList &Args, ArgStringList &CmdArgs, const llvm::Triple &Triple);
}
namespace mips {
diff --git a/lib/Driver/Types.cpp b/lib/Driver/Types.cpp
index 4a22dcf..6ee764c 100644
--- a/lib/Driver/Types.cpp
+++ b/lib/Driver/Types.cpp
@@ -203,6 +203,7 @@
} else {
if (!onlyAssembleType(Id)) {
P.push_back(phases::Compile);
+ P.push_back(phases::Backend);
}
P.push_back(phases::Assemble);
}