summaryrefslogtreecommitdiffstats
path: root/lib/Driver
diff options
context:
space:
mode:
Diffstat (limited to 'lib/Driver')
-rw-r--r--lib/Driver/Driver.cpp34
-rw-r--r--lib/Driver/MSVCToolChain.cpp9
-rw-r--r--lib/Driver/SanitizerArgs.cpp138
-rw-r--r--lib/Driver/ToolChain.cpp9
-rw-r--r--lib/Driver/ToolChains.cpp186
-rw-r--r--lib/Driver/ToolChains.h39
-rw-r--r--lib/Driver/Tools.cpp359
-rw-r--r--lib/Driver/Tools.h35
-rw-r--r--lib/Driver/Types.cpp2
9 files changed, 606 insertions, 205 deletions
diff --git a/lib/Driver/Driver.cpp b/lib/Driver/Driver.cpp
index 8cca1de..0f3ebef 100644
--- a/lib/Driver/Driver.cpp
+++ b/lib/Driver/Driver.cpp
@@ -277,7 +277,8 @@ DerivedArgList *Driver::TranslateInputArgs(const InputArgList &Args) const {
// Add a default value of -mlinker-version=, if one was given and the user
// didn't specify one.
#if defined(HOST_LINK_VERSION)
- if (!Args.hasArg(options::OPT_mlinker_version_EQ)) {
+ if (!Args.hasArg(options::OPT_mlinker_version_EQ) &&
+ strlen(HOST_LINK_VERSION) > 0) {
DAL->AddJoinedArg(0, Opts->getOption(options::OPT_mlinker_version_EQ),
HOST_LINK_VERSION);
DAL->getLastArg(options::OPT_mlinker_version_EQ)->claim();
@@ -814,9 +815,12 @@ bool Driver::HandleImmediateArgs(const Compilation &C) {
return true;
}
+// Display an action graph human-readably. Action A is the "sink" node
+// and latest-occuring action. Traversal is in pre-order, visiting the
+// inputs to each action before printing the action itself.
static unsigned PrintActions1(const Compilation &C, Action *A,
std::map<Action*, unsigned> &Ids) {
- if (Ids.count(A))
+ if (Ids.count(A)) // A was already visited.
return Ids[A];
std::string str;
@@ -847,6 +851,8 @@ static unsigned PrintActions1(const Compilation &C, Action *A,
return Id;
}
+// Print the action graphs in a compilation C.
+// For example "clang -c file1.c file2.c" is composed of two subgraphs.
void Driver::PrintActions(const Compilation &C) const {
std::map<Action*, unsigned> Ids;
for (ActionList::const_iterator it = C.getActions().begin(),
@@ -1356,7 +1362,7 @@ Driver::ConstructPhaseAction(const ToolChain &TC, const ArgList &Args,
types::TY_LLVM_BC);
}
case phases::Backend: {
- if (IsUsingLTO(TC, Args)) {
+ if (IsUsingLTO(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);
@@ -1377,14 +1383,8 @@ Driver::ConstructPhaseAction(const ToolChain &TC, const ArgList &Args,
llvm_unreachable("invalid phase in ConstructPhaseAction");
}
-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;
-
- return false;
+bool Driver::IsUsingLTO(const ArgList &Args) const {
+ return Args.hasFlag(options::OPT_flto, options::OPT_fno_lto, false);
}
void Driver::BuildJobs(Compilation &C) const {
@@ -1563,8 +1563,9 @@ void Driver::BuildJobsForAction(Compilation &C,
if (Input.getOption().matches(options::OPT_INPUT)) {
const char *Name = Input.getValue();
Result = InputInfo(Name, A->getType(), Name);
- } else
+ } else {
Result = InputInfo(&Input, A->getType(), "");
+ }
return;
}
@@ -1738,7 +1739,7 @@ const char *Driver::GetNamedOutputPath(Compilation &C,
// Determine what the derived output name should be.
const char *NamedOutput;
- if ((JA.getType() == types::TY_Object || JA.getType() == types::TY_LTO_BC) &&
+ if (JA.getType() == types::TY_Object &&
C.getArgs().hasArg(options::OPT__SLASH_Fo, options::OPT__SLASH_o)) {
// The /Fo or /o flag decides the object filename.
StringRef Val = C.getArgs().getLastArg(options::OPT__SLASH_Fo,
@@ -2099,6 +2100,8 @@ const ToolChain &Driver::getToolChain(const ArgList &Args,
TC = new toolchains::Hexagon_TC(*this, Target, Args);
else if (Target.getArch() == llvm::Triple::xcore)
TC = new toolchains::XCore(*this, Target, Args);
+ else if (Target.getArch() == llvm::Triple::shave)
+ TC = new toolchains::SHAVEToolChain(*this, Target, Args);
else if (Target.isOSBinFormatELF())
TC = new toolchains::Generic_ELF(*this, Target, Args);
else if (Target.isOSBinFormatMachO())
@@ -2112,13 +2115,12 @@ const ToolChain &Driver::getToolChain(const ArgList &Args,
}
bool Driver::ShouldUseClangCompiler(const JobAction &JA) const {
- // Check if user requested no clang, or clang doesn't understand this type (we
- // only handle single inputs for now).
+ // Say "no" if there is not exactly one input of a type clang understands.
if (JA.size() != 1 ||
!types::isAcceptedByClang((*JA.begin())->getType()))
return false;
- // Otherwise make sure this is an action clang understands.
+ // And say "no" if this is not a kind of action clang understands.
if (!isa<PreprocessJobAction>(JA) && !isa<PrecompileJobAction>(JA) &&
!isa<CompileJobAction>(JA) && !isa<BackendJobAction>(JA))
return false;
diff --git a/lib/Driver/MSVCToolChain.cpp b/lib/Driver/MSVCToolChain.cpp
index d824fe4..7216121 100644
--- a/lib/Driver/MSVCToolChain.cpp
+++ b/lib/Driver/MSVCToolChain.cpp
@@ -522,3 +522,12 @@ MSVCToolChain::ComputeEffectiveClangTriple(const ArgList &Args,
}
return Triple.getTriple();
}
+
+SanitizerMask MSVCToolChain::getSupportedSanitizers() const {
+ SanitizerMask Res = ToolChain::getSupportedSanitizers();
+ Res |= SanitizerKind::Address;
+ // CFI checks are not implemented for MSVC ABI for now.
+ Res &= ~SanitizerKind::CFI;
+ Res &= ~SanitizerKind::CFICastStrict;
+ return Res;
+}
diff --git a/lib/Driver/SanitizerArgs.cpp b/lib/Driver/SanitizerArgs.cpp
index 72530b4..14c3702 100644
--- a/lib/Driver/SanitizerArgs.cpp
+++ b/lib/Driver/SanitizerArgs.cpp
@@ -25,7 +25,7 @@ using namespace clang::driver;
using namespace llvm::opt;
enum : SanitizerMask {
- NeedsUbsanRt = Undefined | Integer,
+ NeedsUbsanRt = Undefined | Integer | CFI,
NotAllowedWithTrap = Vptr,
RequiresPIE = Memory | DataFlow,
NeedsUnwindTables = Address | Thread | Memory | DataFlow,
@@ -34,6 +34,9 @@ enum : SanitizerMask {
Unrecoverable = Address | Unreachable | Return,
LegacyFsanitizeRecoverMask = Undefined | Integer,
NeedsLTO = CFI,
+ TrappingSupported =
+ (Undefined & ~Vptr) | UnsignedIntegerOverflow | LocalBounds | CFI,
+ TrappingDefault = CFI,
};
enum CoverageFeature {
@@ -74,27 +77,6 @@ static std::string describeSanitizeArg(const llvm::opt::Arg *A,
/// Sanitizers set.
static std::string toString(const clang::SanitizerSet &Sanitizers);
-static SanitizerMask getToolchainUnsupportedKinds(const ToolChain &TC) {
- bool IsFreeBSD = TC.getTriple().getOS() == llvm::Triple::FreeBSD;
- 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;
-
- SanitizerMask Unsupported = 0;
- if (!(IsLinux && (IsX86_64 || IsMIPS64))) {
- Unsupported |= Memory | DataFlow;
- }
- if (!((IsLinux || IsFreeBSD) && (IsX86_64 || IsMIPS64))) {
- Unsupported |= Thread;
- }
- if (!(IsLinux && (IsX86 || IsX86_64))) {
- Unsupported |= Function;
- }
- return Unsupported;
-}
-
static bool getDefaultBlacklist(const Driver &D, SanitizerMask Kinds,
std::string &BLPath) {
const char *BlacklistFile = nullptr;
@@ -116,8 +98,62 @@ static bool getDefaultBlacklist(const Driver &D, SanitizerMask Kinds,
return false;
}
+/// Sets group bits for every group that has at least one representative already
+/// enabled in \p Kinds.
+static SanitizerMask setGroupBits(SanitizerMask Kinds) {
+#define SANITIZER(NAME, ID)
+#define SANITIZER_GROUP(NAME, ID, ALIAS) \
+ if (Kinds & SanitizerKind::ID) \
+ Kinds |= SanitizerKind::ID##Group;
+#include "clang/Basic/Sanitizers.def"
+ return Kinds;
+}
+
+static SanitizerMask parseSanitizeTrapArgs(const Driver &D,
+ const llvm::opt::ArgList &Args) {
+ SanitizerMask TrapRemove = 0; // During the loop below, the accumulated set of
+ // sanitizers disabled by the current sanitizer
+ // argument or any argument after it.
+ SanitizerMask TrappingKinds = 0;
+ SanitizerMask TrappingSupportedWithGroups = setGroupBits(TrappingSupported);
+
+ for (ArgList::const_reverse_iterator I = Args.rbegin(), E = Args.rend();
+ I != E; ++I) {
+ const auto *Arg = *I;
+ if (Arg->getOption().matches(options::OPT_fsanitize_trap_EQ)) {
+ Arg->claim();
+ SanitizerMask Add = parseArgValues(D, Arg, true);
+ Add &= ~TrapRemove;
+ if (SanitizerMask InvalidValues = Add & ~TrappingSupportedWithGroups) {
+ SanitizerSet S;
+ S.Mask = InvalidValues;
+ D.Diag(diag::err_drv_unsupported_option_argument) << "-fsanitize-trap"
+ << toString(S);
+ }
+ TrappingKinds |= expandSanitizerGroups(Add) & ~TrapRemove;
+ } else if (Arg->getOption().matches(options::OPT_fno_sanitize_trap_EQ)) {
+ Arg->claim();
+ TrapRemove |= expandSanitizerGroups(parseArgValues(D, Arg, true));
+ } else if (Arg->getOption().matches(
+ options::OPT_fsanitize_undefined_trap_on_error)) {
+ Arg->claim();
+ TrappingKinds |=
+ expandSanitizerGroups(UndefinedGroup & ~TrapRemove) & ~TrapRemove;
+ } else if (Arg->getOption().matches(
+ options::OPT_fno_sanitize_undefined_trap_on_error)) {
+ Arg->claim();
+ TrapRemove |= expandSanitizerGroups(UndefinedGroup);
+ }
+ }
+
+ // Apply default trapping behavior.
+ TrappingKinds |= TrappingDefault & ~TrapRemove;
+
+ return TrappingKinds;
+}
+
bool SanitizerArgs::needsUbsanRt() const {
- return !UbsanTrapOnError && (Sanitizers.Mask & NeedsUbsanRt) &&
+ return (Sanitizers.Mask & NeedsUbsanRt & ~TrapSanitizers.Mask) &&
!Sanitizers.has(Address) &&
!Sanitizers.has(Memory) &&
!Sanitizers.has(Thread);
@@ -131,19 +167,15 @@ bool SanitizerArgs::needsUnwindTables() const {
return Sanitizers.Mask & NeedsUnwindTables;
}
-bool SanitizerArgs::needsLTO() const {
- return Sanitizers.Mask & NeedsLTO;
-}
-
void SanitizerArgs::clear() {
Sanitizers.clear();
RecoverableSanitizers.clear();
+ TrapSanitizers.clear();
BlacklistFiles.clear();
CoverageFeatures = 0;
MsanTrackOrigins = 0;
AsanFieldPadding = 0;
AsanZeroBaseShadow = false;
- UbsanTrapOnError = false;
AsanSharedRuntime = false;
LinkCXXRuntimes = false;
}
@@ -162,10 +194,13 @@ SanitizerArgs::SanitizerArgs(const ToolChain &TC,
SanitizerMask DiagnosedKinds = 0; // All Kinds we have diagnosed up to now.
// Used to deduplicate diagnostics.
SanitizerMask Kinds = 0;
- SanitizerMask NotSupported = getToolchainUnsupportedKinds(TC);
+ SanitizerMask Supported = setGroupBits(TC.getSupportedSanitizers());
ToolChain::RTTIMode RTTIMode = TC.getRTTIMode();
const Driver &D = TC.getDriver();
+ SanitizerMask TrappingKinds = parseSanitizeTrapArgs(D, Args);
+ SanitizerMask InvalidTrappingKinds = TrappingKinds & NotAllowedWithTrap;
+
for (ArgList::const_reverse_iterator I = Args.rbegin(), E = Args.rend();
I != E; ++I) {
const auto *Arg = *I;
@@ -180,14 +215,20 @@ SanitizerArgs::SanitizerArgs(const ToolChain &TC,
// sanitizers in Add are those which have been explicitly enabled.
// Diagnose them.
if (SanitizerMask KindsToDiagnose =
- Add & NotSupported & ~DiagnosedKinds) {
- // Only diagnose the new kinds.
+ Add & InvalidTrappingKinds & ~DiagnosedKinds) {
+ std::string Desc = describeSanitizeArg(*I, KindsToDiagnose);
+ D.Diag(diag::err_drv_argument_not_allowed_with)
+ << Desc << "-fsanitize-trap=undefined";
+ DiagnosedKinds |= KindsToDiagnose;
+ }
+ Add &= ~InvalidTrappingKinds;
+ if (SanitizerMask KindsToDiagnose = Add & ~Supported & ~DiagnosedKinds) {
std::string Desc = describeSanitizeArg(*I, KindsToDiagnose);
D.Diag(diag::err_drv_unsupported_opt_for_target)
<< Desc << TC.getTriple().str();
DiagnosedKinds |= KindsToDiagnose;
}
- Add &= ~NotSupported;
+ Add &= Supported;
// Test for -fno-rtti + explicit -fsanitizer=vptr before expanding groups
// so we don't error out if -fno-rtti and -fsanitize=undefined were
@@ -216,7 +257,8 @@ SanitizerArgs::SanitizerArgs(const ToolChain &TC,
Add &= ~AllRemove;
// Silently discard any unsupported sanitizers implicitly enabled through
// group expansion.
- Add &= ~NotSupported;
+ Add &= ~InvalidTrappingKinds;
+ Add &= Supported;
Kinds |= Add;
} else if (Arg->getOption().matches(options::OPT_fno_sanitize_EQ)) {
@@ -234,22 +276,20 @@ SanitizerArgs::SanitizerArgs(const ToolChain &TC,
Kinds &= ~Vptr;
}
- // Warn about undefined sanitizer options that require runtime support.
- UbsanTrapOnError =
- Args.hasFlag(options::OPT_fsanitize_undefined_trap_on_error,
- options::OPT_fno_sanitize_undefined_trap_on_error, false);
- if (UbsanTrapOnError && (Kinds & NotAllowedWithTrap)) {
- D.Diag(clang::diag::err_drv_argument_not_allowed_with)
- << lastArgumentForMask(D, Args, NotAllowedWithTrap)
- << "-fsanitize-undefined-trap-on-error";
- Kinds &= ~NotAllowedWithTrap;
+ // Check that LTO is enabled if we need it.
+ if ((Kinds & NeedsLTO) && !D.IsUsingLTO(Args)) {
+ D.Diag(diag::err_drv_argument_only_allowed_with)
+ << lastArgumentForMask(D, Args, Kinds & NeedsLTO) << "-flto";
}
// Warn about incompatible groups of sanitizers.
std::pair<SanitizerMask, SanitizerMask> IncompatibleGroups[] = {
std::make_pair(Address, Thread), std::make_pair(Address, Memory),
std::make_pair(Thread, Memory), std::make_pair(Leak, Thread),
- std::make_pair(Leak, Memory)};
+ std::make_pair(Leak, Memory), std::make_pair(KernelAddress, Address),
+ std::make_pair(KernelAddress, Leak),
+ std::make_pair(KernelAddress, Thread),
+ std::make_pair(KernelAddress, Memory)};
for (auto G : IncompatibleGroups) {
SanitizerMask Group = G.first;
if (Kinds & Group) {
@@ -305,6 +345,8 @@ SanitizerArgs::SanitizerArgs(const ToolChain &TC,
RecoverableKinds &= Kinds;
RecoverableKinds &= ~Unrecoverable;
+ TrappingKinds &= Kinds;
+
// Setup blacklist files.
// Add default blacklist from resource directory.
{
@@ -460,6 +502,7 @@ SanitizerArgs::SanitizerArgs(const ToolChain &TC,
// Finally, initialize the set of available and recoverable sanitizers.
Sanitizers.Mask |= Kinds;
RecoverableSanitizers.Mask |= RecoverableKinds;
+ TrapSanitizers.Mask |= TrappingKinds;
}
static std::string toString(const clang::SanitizerSet &Sanitizers) {
@@ -484,8 +527,9 @@ void SanitizerArgs::addArgs(const llvm::opt::ArgList &Args,
CmdArgs.push_back(Args.MakeArgString("-fsanitize-recover=" +
toString(RecoverableSanitizers)));
- if (UbsanTrapOnError)
- CmdArgs.push_back("-fsanitize-undefined-trap-on-error");
+ if (!TrapSanitizers.empty())
+ CmdArgs.push_back(
+ Args.MakeArgString("-fsanitize-trap=" + toString(TrapSanitizers)));
for (const auto &BLPath : BlacklistFiles) {
SmallString<64> BlacklistOpt("-fsanitize-blacklist=");
@@ -528,7 +572,9 @@ SanitizerMask parseArgValues(const Driver &D, const llvm::opt::Arg *A,
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)) &&
+ A->getOption().matches(options::OPT_fno_sanitize_recover_EQ) ||
+ A->getOption().matches(options::OPT_fsanitize_trap_EQ) ||
+ A->getOption().matches(options::OPT_fno_sanitize_trap_EQ)) &&
"Invalid argument in parseArgValues!");
SanitizerMask Kinds = 0;
for (int i = 0, n = A->getNumValues(); i != n; ++i) {
diff --git a/lib/Driver/ToolChain.cpp b/lib/Driver/ToolChain.cpp
index 82eb854..da020a2 100644
--- a/lib/Driver/ToolChain.cpp
+++ b/lib/Driver/ToolChain.cpp
@@ -481,3 +481,12 @@ bool ToolChain::AddFastMathRuntimeIfAvailable(const ArgList &Args,
CmdArgs.push_back(Args.MakeArgString(Path));
return true;
}
+
+SanitizerMask ToolChain::getSupportedSanitizers() const {
+ // Return sanitizers which don't require runtime support and are not
+ // platform or architecture-dependent.
+ using namespace SanitizerKind;
+ return (Undefined & ~Vptr & ~Function) | CFI | CFICastStrict |
+ UnsignedIntegerOverflow | LocalBounds;
+}
+
diff --git a/lib/Driver/ToolChains.cpp b/lib/Driver/ToolChains.cpp
index 115a16f..987e063 100644
--- a/lib/Driver/ToolChains.cpp
+++ b/lib/Driver/ToolChains.cpp
@@ -42,10 +42,6 @@ using namespace llvm::opt;
MachO::MachO(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);
-
// We expect 'as', 'ld', etc. to be adjacent to our install dir.
getProgramPaths().push_back(getDriver().getInstalledDir());
if (getDriver().getInstalledDir() != getDriver().Dir)
@@ -53,28 +49,8 @@ MachO::MachO(const Driver &D, const llvm::Triple &Triple,
}
/// Darwin - Darwin tool chain for i386 and x86_64.
-Darwin::Darwin(const Driver & D, const llvm::Triple & Triple,
- const ArgList & Args)
- : MachO(D, Triple, Args), TargetInitialized(false) {
- // Compute the initial Darwin version from the triple
- unsigned Major, Minor, Micro;
- if (!Triple.getMacOSXVersion(Major, Minor, Micro))
- getDriver().Diag(diag::err_drv_invalid_darwin_version) <<
- Triple.getOSName();
- llvm::raw_string_ostream(MacosxVersionMin)
- << Major << '.' << Minor << '.' << Micro;
-
- // FIXME: DarwinVersion is only used to find GCC's libexec directory.
- // It should be removed when we stop supporting that.
- DarwinVersion[0] = Minor + 4;
- DarwinVersion[1] = Micro;
- DarwinVersion[2] = 0;
-
- // Compute the initial iOS version from the triple
- Triple.getiOSVersion(Major, Minor, Micro);
- llvm::raw_string_ostream(iOSVersionMin)
- << Major << '.' << Minor << '.' << Micro;
-}
+Darwin::Darwin(const Driver &D, const llvm::Triple &Triple, const ArgList &Args)
+ : MachO(D, Triple, Args), TargetInitialized(false) {}
types::ID MachO::LookupTypeForExtension(const char *Ext) const {
types::ID Ty = types::lookupTypeForExtension(Ext);
@@ -403,26 +379,10 @@ void DarwinClang::AddLinkRuntimeLibArgs(const ArgList &Args,
const SanitizerArgs &Sanitize = getSanitizerArgs();
-
- if (Sanitize.needsAsanRt()) {
- if (!isTargetMacOS() && !isTargetIOSSimulator()) {
- // FIXME: Move this check to SanitizerArgs::filterUnsupportedKinds.
- getDriver().Diag(diag::err_drv_clang_unsupported_per_platform)
- << "-fsanitize=address";
- } else {
- AddLinkSanitizerLibArgs(Args, CmdArgs, "asan");
- }
- }
-
- if (Sanitize.needsUbsanRt()) {
- if (!isTargetMacOS() && !isTargetIOSSimulator()) {
- // FIXME: Move this check to SanitizerArgs::filterUnsupportedKinds.
- getDriver().Diag(diag::err_drv_clang_unsupported_per_platform)
- << "-fsanitize=undefined";
- } else {
- AddLinkSanitizerLibArgs(Args, CmdArgs, "ubsan");
- }
- }
+ if (Sanitize.needsAsanRt())
+ AddLinkSanitizerLibArgs(Args, CmdArgs, "asan");
+ if (Sanitize.needsUbsanRt())
+ AddLinkSanitizerLibArgs(Args, CmdArgs, "ubsan");
// Otherwise link libSystem, then the dynamic runtime library, and finally any
// target specific static runtime library.
@@ -499,8 +459,8 @@ void Darwin::AddDeploymentTarget(DerivedArgList &Args) const {
} else if (!OSXVersion && !iOSVersion) {
// If no deployment target was specified on the command line, check for
// environment defines.
- StringRef OSXTarget;
- StringRef iOSTarget;
+ std::string OSXTarget;
+ std::string iOSTarget;
if (char *env = ::getenv("MACOSX_DEPLOYMENT_TARGET"))
OSXTarget = env;
if (char *env = ::getenv("IPHONEOS_DEPLOYMENT_TARGET"))
@@ -519,13 +479,26 @@ void Darwin::AddDeploymentTarget(DerivedArgList &Args) const {
}
}
- // If no OSX or iOS target has been specified and we're compiling for armv7,
- // go ahead as assume we're targeting iOS.
- StringRef MachOArchName = getMachOArchName(Args);
- if (OSXTarget.empty() && iOSTarget.empty() &&
- (MachOArchName == "armv7" || MachOArchName == "armv7s" ||
- MachOArchName == "arm64"))
- iOSTarget = iOSVersionMin;
+ // If no OSX or iOS target has been specified, try to guess platform
+ // from arch name and compute the version from the triple.
+ if (OSXTarget.empty() && iOSTarget.empty()) {
+ StringRef MachOArchName = getMachOArchName(Args);
+ unsigned Major, Minor, Micro;
+ if (MachOArchName == "armv7" || MachOArchName == "armv7s" ||
+ MachOArchName == "arm64") {
+ getTriple().getiOSVersion(Major, Minor, Micro);
+ llvm::raw_string_ostream(iOSTarget) << Major << '.' << Minor << '.'
+ << Micro;
+ } else if (MachOArchName != "armv6m" && MachOArchName != "armv7m" &&
+ MachOArchName != "armv7em") {
+ if (!getTriple().getMacOSXVersion(Major, Minor, Micro)) {
+ getDriver().Diag(diag::err_drv_invalid_darwin_version)
+ << getTriple().getOSName();
+ }
+ llvm::raw_string_ostream(OSXTarget) << Major << '.' << Minor << '.'
+ << Micro;
+ }
+ }
// Allow conflicts among OSX and iOS for historical reasons, but choose the
// default platform.
@@ -546,12 +519,6 @@ void Darwin::AddDeploymentTarget(DerivedArgList &Args) const {
const Option O = Opts.getOption(options::OPT_miphoneos_version_min_EQ);
iOSVersion = Args.MakeJoinedArg(nullptr, O, iOSTarget);
Args.append(iOSVersion);
- } else if (MachOArchName != "armv6m" && MachOArchName != "armv7m" &&
- MachOArchName != "armv7em") {
- // Otherwise, assume we are targeting OS X.
- const Option O = Opts.getOption(options::OPT_mmacosx_version_min_EQ);
- OSXVersion = Args.MakeJoinedArg(nullptr, O, MacosxVersionMin);
- Args.append(OSXVersion);
}
}
@@ -1101,6 +1068,18 @@ void Darwin::CheckObjCARC() const {
getDriver().Diag(diag::err_arc_unsupported_on_toolchain);
}
+SanitizerMask Darwin::getSupportedSanitizers() const {
+ SanitizerMask Res = ToolChain::getSupportedSanitizers();
+ if (isTargetMacOS() || isTargetIOSSimulator()) {
+ // ASan and UBSan are available on Mac OS and on iOS simulator.
+ Res |= SanitizerKind::Address;
+ Res |= SanitizerKind::Vptr;
+ }
+ if (isTargetMacOS())
+ Res |= SanitizerKind::SafeStack;
+ return Res;
+}
+
/// Generic_GCC - A tool chain using the 'gcc' command to perform
/// all subcommands; this relies on gcc translating the majority of
/// command line options.
@@ -2084,6 +2063,8 @@ bool Generic_GCC::IsIntegratedAssemblerDefault() const {
case llvm::Triple::aarch64_be:
case llvm::Triple::arm:
case llvm::Triple::armeb:
+ case llvm::Triple::bpfel:
+ case llvm::Triple::bpfeb:
case llvm::Triple::thumb:
case llvm::Triple::thumbeb:
case llvm::Triple::ppc:
@@ -2739,6 +2720,24 @@ bool FreeBSD::isPIEDefault() const {
return getSanitizerArgs().requiresPIE();
}
+SanitizerMask FreeBSD::getSupportedSanitizers() const {
+ const bool IsX86 = getTriple().getArch() == llvm::Triple::x86;
+ const bool IsX86_64 = getTriple().getArch() == llvm::Triple::x86_64;
+ const bool IsMIPS64 = getTriple().getArch() == llvm::Triple::mips64 ||
+ getTriple().getArch() == llvm::Triple::mips64el;
+ SanitizerMask Res = ToolChain::getSupportedSanitizers();
+ Res |= SanitizerKind::Address;
+ Res |= SanitizerKind::Vptr;
+ if (IsX86_64 || IsMIPS64) {
+ Res |= SanitizerKind::Leak;
+ Res |= SanitizerKind::Thread;
+ }
+ if (IsX86 || IsX86_64) {
+ Res |= SanitizerKind::SafeStack;
+ }
+ return Res;
+}
+
/// NetBSD - NetBSD tool chain which can call as(1) and ld(1) directly.
NetBSD::NetBSD(const Driver &D, const llvm::Triple& Triple, const ArgList &Args)
@@ -3643,6 +3642,28 @@ bool Linux::isPIEDefault() const {
return getSanitizerArgs().requiresPIE();
}
+SanitizerMask Linux::getSupportedSanitizers() const {
+ const bool IsX86 = getTriple().getArch() == llvm::Triple::x86;
+ const bool IsX86_64 = getTriple().getArch() == llvm::Triple::x86_64;
+ const bool IsMIPS64 = getTriple().getArch() == llvm::Triple::mips64 ||
+ getTriple().getArch() == llvm::Triple::mips64el;
+ SanitizerMask Res = ToolChain::getSupportedSanitizers();
+ Res |= SanitizerKind::Address;
+ Res |= SanitizerKind::KernelAddress;
+ Res |= SanitizerKind::Vptr;
+ if (IsX86_64 || IsMIPS64) {
+ Res |= SanitizerKind::DataFlow;
+ Res |= SanitizerKind::Leak;
+ Res |= SanitizerKind::Memory;
+ Res |= SanitizerKind::Thread;
+ }
+ if (IsX86 || IsX86_64) {
+ Res |= SanitizerKind::Function;
+ Res |= SanitizerKind::SafeStack;
+ }
+ return Res;
+}
+
/// DragonFly - DragonFly tool chain which can call as(1) and ld(1) directly.
DragonFly::DragonFly(const Driver &D, const llvm::Triple& Triple, const ArgList &Args)
@@ -3742,3 +3763,46 @@ void XCore::AddCXXStdlibLibArgs(const ArgList &Args,
ArgStringList &CmdArgs) const {
// We don't output any lib args. This is handled by xcc.
}
+
+// SHAVEToolChain does not call Clang's C compiler.
+// We override SelectTool to avoid testing ShouldUseClangCompiler().
+Tool *SHAVEToolChain::SelectTool(const JobAction &JA) const {
+ switch (JA.getKind()) {
+ case Action::CompileJobClass:
+ if (!Compiler)
+ Compiler.reset(new tools::SHAVE::Compile(*this));
+ return Compiler.get();
+ case Action::AssembleJobClass:
+ if (!Assembler)
+ Assembler.reset(new tools::SHAVE::Assemble(*this));
+ return Assembler.get();
+ default:
+ return ToolChain::getTool(JA.getKind());
+ }
+}
+
+SHAVEToolChain::SHAVEToolChain(const Driver &D, const llvm::Triple &Triple,
+ const ArgList &Args)
+ : Generic_GCC(D, Triple, Args) {}
+
+SHAVEToolChain::~SHAVEToolChain() {}
+
+/// Following are methods necessary to avoid having moviClang be an abstract
+/// class.
+
+Tool *SHAVEToolChain::getTool(Action::ActionClass AC) const {
+ // SelectTool() must find a tool using the method in the superclass.
+ // There's nothing we can do if that fails.
+ llvm_unreachable("SHAVEToolChain can't getTool");
+}
+
+Tool *SHAVEToolChain::buildLinker() const {
+ // SHAVEToolChain executables can not be linked except by the vendor tools.
+ llvm_unreachable("SHAVEToolChain can't buildLinker");
+}
+
+Tool *SHAVEToolChain::buildAssembler() const {
+ // This one you'd think should be reachable since we expose an
+ // assembler to the driver, except not the way it expects.
+ llvm_unreachable("SHAVEToolChain can't buildAssembler");
+}
diff --git a/lib/Driver/ToolChains.h b/lib/Driver/ToolChains.h
index 0b7073f..a48bb5f 100644
--- a/lib/Driver/ToolChains.h
+++ b/lib/Driver/ToolChains.h
@@ -316,9 +316,6 @@ public:
/// Darwin - The base Darwin tool chain.
class LLVM_LIBRARY_VISIBILITY Darwin : public MachO {
public:
- /// The host version.
- unsigned DarwinVersion[3];
-
/// Whether the information on the target has been initialized.
//
// FIXME: This should be eliminated. What we want to do is make this part of
@@ -338,15 +335,6 @@ public:
mutable VersionTuple TargetVersion;
private:
- /// The default macosx-version-min of this tool chain; empty until
- /// initialized.
- std::string MacosxVersionMin;
-
- /// The default ios-version-min of this tool chain; empty until
- /// initialized.
- std::string iOSVersionMin;
-
-private:
void AddDeploymentTarget(llvm::opt::DerivedArgList &Args) const;
public:
@@ -412,6 +400,7 @@ protected:
}
bool isTargetMacOS() const {
+ assert(TargetInitialized && "Target not initialized!");
return TargetPlatform == MacOS;
}
@@ -474,6 +463,8 @@ public:
void CheckObjCARC() const override;
bool UseSjLjExceptions() const override;
+
+ SanitizerMask getSupportedSanitizers() const override;
};
/// DarwinClang - The Darwin toolchain used by Clang.
@@ -616,6 +607,7 @@ public:
bool UseSjLjExceptions() const override;
bool isPIEDefault() const override;
+ SanitizerMask getSupportedSanitizers() const override;
protected:
Tool *buildAssembler() const override;
Tool *buildLinker() const override;
@@ -679,6 +671,7 @@ public:
AddClangCXXStdlibIncludeArgs(const llvm::opt::ArgList &DriverArgs,
llvm::opt::ArgStringList &CC1Args) const override;
bool isPIEDefault() const override;
+ SanitizerMask getSupportedSanitizers() const override;
std::string Linker;
std::vector<std::string> ExtraOpts;
@@ -809,6 +802,7 @@ public:
std::string ComputeEffectiveClangTriple(const llvm::opt::ArgList &Args,
types::ID InputType) const override;
+ SanitizerMask getSupportedSanitizers() const override;
protected:
void AddSystemIncludeWithSubfolder(const llvm::opt::ArgList &DriverArgs,
@@ -872,6 +866,27 @@ public:
llvm::opt::ArgStringList &CmdArgs) const override;
};
+/// SHAVEToolChain - A tool chain using the compiler installed by the the
+// Movidius SDK into MV_TOOLS_DIR (which we assume will be copied to llvm's
+// installation dir) to perform all subcommands.
+class LLVM_LIBRARY_VISIBILITY SHAVEToolChain : public Generic_GCC {
+public:
+ SHAVEToolChain(const Driver &D, const llvm::Triple &Triple,
+ const llvm::opt::ArgList &Args);
+ ~SHAVEToolChain() override;
+
+ virtual Tool *SelectTool(const JobAction &JA) const override;
+
+protected:
+ Tool *getTool(Action::ActionClass AC) const override;
+ Tool *buildAssembler() const override;
+ Tool *buildLinker() const override;
+
+private:
+ mutable std::unique_ptr<Tool> Compiler;
+ mutable std::unique_ptr<Tool> Assembler;
+};
+
} // end namespace toolchains
} // end namespace driver
} // end namespace clang
diff --git a/lib/Driver/Tools.cpp b/lib/Driver/Tools.cpp
index 711dee2..2367914 100644
--- a/lib/Driver/Tools.cpp
+++ b/lib/Driver/Tools.cpp
@@ -679,7 +679,7 @@ static void getARMTargetFeatures(const Driver &D, const llvm::Triple &Triple,
// getARMArch is used here instead of just checking the -march value in order
// to handle -march=native correctly.
if (const Arg *A = Args.getLastArg(options::OPT_march_EQ)) {
- StringRef Arch = arm::getARMArch(Args, Triple);
+ std::string Arch = arm::getARMArch(Args, Triple);
if (llvm::ARMTargetParser::parseArch(Arch) == llvm::ARM::AK_INVALID)
D.Diag(diag::err_drv_clang_unsupported) << A->getAsString(Args);
}
@@ -689,7 +689,7 @@ static void getARMTargetFeatures(const Driver &D, const llvm::Triple &Triple,
// getLLVMArchSuffixForARM which also needs an architecture.
if (const Arg *A = Args.getLastArg(options::OPT_mcpu_EQ)) {
std::string CPU = arm::getARMTargetCPU(Args, Triple);
- StringRef Arch = arm::getARMArch(Args, Triple);
+ std::string Arch = arm::getARMArch(Args, Triple);
if (strcmp(arm::getLLVMArchSuffixForARM(CPU, Arch), "") == 0)
D.Diag(diag::err_drv_clang_unsupported) << A->getAsString(Args);
}
@@ -850,7 +850,7 @@ static std::string getAArch64TargetCPU(const ArgList &Args) {
CPU = A->getValue();
} else if ((A = Args.getLastArg(options::OPT_mcpu_EQ))) {
StringRef Mcpu = A->getValue();
- CPU = Mcpu.split("+").first;
+ CPU = Mcpu.split("+").first.lower();
}
// Handle CPU name is 'native'.
@@ -1116,7 +1116,7 @@ static void getMIPSTargetFeatures(const Driver &D, const llvm::Triple &Triple,
Features.push_back(Args.MakeArgString("+nooddspreg"));
} else
Features.push_back(Args.MakeArgString("+fp64"));
- } else if (mips::isFPXXDefault(Triple, CPUName, ABIName)) {
+ } else if (mips::shouldUseFPXX(Args, Triple, CPUName, ABIName, FloatABI)) {
Features.push_back(Args.MakeArgString("+fpxx"));
Features.push_back(Args.MakeArgString("+nooddspreg"));
}
@@ -1334,47 +1334,26 @@ static std::string getR600TargetGPU(const ArgList &Args) {
return "";
}
-static void getSparcTargetFeatures(const ArgList &Args,
- std::vector<const char *> &Features) {
- bool SoftFloatABI = true;
- if (Arg *A =
- Args.getLastArg(options::OPT_msoft_float, options::OPT_mhard_float)) {
- if (A->getOption().matches(options::OPT_mhard_float))
- SoftFloatABI = false;
- }
- if (SoftFloatABI)
- Features.push_back("+soft-float");
-}
-
void Clang::AddSparcTargetArgs(const ArgList &Args,
ArgStringList &CmdArgs) const {
const Driver &D = getToolChain().getDriver();
+ std::string Triple = getToolChain().ComputeEffectiveClangTriple(Args);
- // Select the float ABI as determined by -msoft-float and -mhard-float.
- StringRef FloatABI;
- if (Arg *A = Args.getLastArg(options::OPT_msoft_float,
- options::OPT_mhard_float)) {
+ bool SoftFloatABI = false;
+ if (Arg *A =
+ Args.getLastArg(options::OPT_msoft_float, options::OPT_mhard_float)) {
if (A->getOption().matches(options::OPT_msoft_float))
- FloatABI = "soft";
- else if (A->getOption().matches(options::OPT_mhard_float))
- FloatABI = "hard";
+ SoftFloatABI = true;
}
- // If unspecified, choose the default based on the platform.
- if (FloatABI.empty()) {
- // Assume "soft", but warn the user we are guessing.
- FloatABI = "soft";
- D.Diag(diag::warn_drv_assuming_mfloat_abi_is) << "soft";
- }
-
- if (FloatABI == "soft") {
- // Floating point operations and argument passing are soft.
- //
- // FIXME: This changes CPP defines, we need -target-soft-float.
- CmdArgs.push_back("-msoft-float");
- } else {
- assert(FloatABI == "hard" && "Invalid float abi!");
- CmdArgs.push_back("-mhard-float");
+ // Only the hard-float ABI on Sparc is standardized, and it is the
+ // default. GCC also supports a nonstandard soft-float ABI mode, and
+ // perhaps LLVM should implement that, too. However, since llvm
+ // currently does not support Sparc soft-float, at all, display an
+ // error if it's requested.
+ if (SoftFloatABI) {
+ D.Diag(diag::err_drv_unsupported_opt_for_target)
+ << "-msoft-float" << Triple;
}
}
@@ -1550,6 +1529,137 @@ static void AddGoldPlugin(const ToolChain &ToolChain, const ArgList &Args,
CmdArgs.push_back(Args.MakeArgString(Twine("-plugin-opt=mcpu=") + CPU));
}
+/// This is a helper function for validating the optional refinement step
+/// parameter in reciprocal argument strings. Return false if there is an error
+/// parsing the refinement step. Otherwise, return true and set the Position
+/// of the refinement step in the input string.
+static bool getRefinementStep(const StringRef &In, const Driver &D,
+ const Arg &A, size_t &Position) {
+ const char RefinementStepToken = ':';
+ Position = In.find(RefinementStepToken);
+ if (Position != StringRef::npos) {
+ StringRef Option = A.getOption().getName();
+ StringRef RefStep = In.substr(Position + 1);
+ // Allow exactly one numeric character for the additional refinement
+ // step parameter. This is reasonable for all currently-supported
+ // operations and architectures because we would expect that a larger value
+ // of refinement steps would cause the estimate "optimization" to
+ // under-perform the native operation. Also, if the estimate does not
+ // converge quickly, it probably will not ever converge, so further
+ // refinement steps will not produce a better answer.
+ if (RefStep.size() != 1) {
+ D.Diag(diag::err_drv_invalid_value) << Option << RefStep;
+ return false;
+ }
+ char RefStepChar = RefStep[0];
+ if (RefStepChar < '0' || RefStepChar > '9') {
+ D.Diag(diag::err_drv_invalid_value) << Option << RefStep;
+ return false;
+ }
+ }
+ return true;
+}
+
+/// The -mrecip flag requires processing of many optional parameters.
+static void ParseMRecip(const Driver &D, const ArgList &Args,
+ ArgStringList &OutStrings) {
+ StringRef DisabledPrefixIn = "!";
+ StringRef DisabledPrefixOut = "!";
+ StringRef EnabledPrefixOut = "";
+ StringRef Out = "-mrecip=";
+
+ Arg *A = Args.getLastArg(options::OPT_mrecip, options::OPT_mrecip_EQ);
+ if (!A)
+ return;
+
+ unsigned NumOptions = A->getNumValues();
+ if (NumOptions == 0) {
+ // No option is the same as "all".
+ OutStrings.push_back(Args.MakeArgString(Out + "all"));
+ return;
+ }
+
+ // Pass through "all", "none", or "default" with an optional refinement step.
+ if (NumOptions == 1) {
+ StringRef Val = A->getValue(0);
+ size_t RefStepLoc;
+ if (!getRefinementStep(Val, D, *A, RefStepLoc))
+ return;
+ StringRef ValBase = Val.slice(0, RefStepLoc);
+ if (ValBase == "all" || ValBase == "none" || ValBase == "default") {
+ OutStrings.push_back(Args.MakeArgString(Out + Val));
+ return;
+ }
+ }
+
+ // Each reciprocal type may be enabled or disabled individually.
+ // Check each input value for validity, concatenate them all back together,
+ // and pass through.
+
+ llvm::StringMap<bool> OptionStrings;
+ OptionStrings.insert(std::make_pair("divd", false));
+ OptionStrings.insert(std::make_pair("divf", false));
+ OptionStrings.insert(std::make_pair("vec-divd", false));
+ OptionStrings.insert(std::make_pair("vec-divf", false));
+ OptionStrings.insert(std::make_pair("sqrtd", false));
+ OptionStrings.insert(std::make_pair("sqrtf", false));
+ OptionStrings.insert(std::make_pair("vec-sqrtd", false));
+ OptionStrings.insert(std::make_pair("vec-sqrtf", false));
+
+ for (unsigned i = 0; i != NumOptions; ++i) {
+ StringRef Val = A->getValue(i);
+
+ bool IsDisabled = Val.startswith(DisabledPrefixIn);
+ // Ignore the disablement token for string matching.
+ if (IsDisabled)
+ Val = Val.substr(1);
+
+ size_t RefStep;
+ if (!getRefinementStep(Val, D, *A, RefStep))
+ return;
+
+ StringRef ValBase = Val.slice(0, RefStep);
+ llvm::StringMap<bool>::iterator OptionIter = OptionStrings.find(ValBase);
+ if (OptionIter == OptionStrings.end()) {
+ // Try again specifying float suffix.
+ OptionIter = OptionStrings.find(ValBase.str() + 'f');
+ if (OptionIter == OptionStrings.end()) {
+ // The input name did not match any known option string.
+ D.Diag(diag::err_drv_unknown_argument) << Val;
+ return;
+ }
+ // The option was specified without a float or double suffix.
+ // Make sure that the double entry was not already specified.
+ // The float entry will be checked below.
+ if (OptionStrings[ValBase.str() + 'd']) {
+ D.Diag(diag::err_drv_invalid_value) << A->getOption().getName() << Val;
+ return;
+ }
+ }
+
+ if (OptionIter->second == true) {
+ // Duplicate option specified.
+ D.Diag(diag::err_drv_invalid_value) << A->getOption().getName() << Val;
+ return;
+ }
+
+ // Mark the matched option as found. Do not allow duplicate specifiers.
+ OptionIter->second = true;
+
+ // If the precision was not specified, also mark the double entry as found.
+ if (ValBase.back() != 'f' && ValBase.back() != 'd')
+ OptionStrings[ValBase.str() + 'd'] = true;
+
+ // Build the output string.
+ StringRef Prefix = IsDisabled ? DisabledPrefixOut : EnabledPrefixOut;
+ Out = Args.MakeArgString(Out + Prefix + Val);
+ if (i != NumOptions - 1)
+ Out = Args.MakeArgString(Out + ",");
+ }
+
+ OutStrings.push_back(Args.MakeArgString(Out));
+}
+
static void getX86TargetFeatures(const Driver &D, const llvm::Triple &Triple,
const ArgList &Args,
std::vector<const char *> &Features) {
@@ -1738,7 +1848,8 @@ static bool
getAArch64ArchFeaturesFromMarch(const Driver &D, StringRef March,
const ArgList &Args,
std::vector<const char *> &Features) {
- std::pair<StringRef, StringRef> Split = March.split("+");
+ std::string MarchLowerCase = March.lower();
+ std::pair<StringRef, StringRef> Split = StringRef(MarchLowerCase).split("+");
if (Split.first == "armv8-a" ||
Split.first == "armv8a") {
@@ -1762,7 +1873,8 @@ getAArch64ArchFeaturesFromMcpu(const Driver &D, StringRef Mcpu,
const ArgList &Args,
std::vector<const char *> &Features) {
StringRef CPU;
- if (!DecodeAArch64Mcpu(D, Mcpu, CPU, Features))
+ std::string McpuLowerCase = Mcpu.lower();
+ if (!DecodeAArch64Mcpu(D, McpuLowerCase, CPU, Features))
return false;
return true;
@@ -1788,7 +1900,8 @@ getAArch64MicroArchFeaturesFromMcpu(const Driver &D, StringRef Mcpu,
std::vector<const char *> &Features) {
StringRef CPU;
std::vector<const char *> DecodedFeature;
- if (!DecodeAArch64Mcpu(D, Mcpu, CPU, DecodedFeature))
+ std::string McpuLowerCase = Mcpu.lower();
+ if (!DecodeAArch64Mcpu(D, McpuLowerCase, CPU, DecodedFeature))
return false;
return getAArch64MicroArchFeaturesFromMtune(D, CPU, Args, Features);
@@ -1863,11 +1976,6 @@ static void getTargetFeatures(const Driver &D, const llvm::Triple &Triple,
case llvm::Triple::ppc64le:
getPPCTargetFeatures(Args, Features);
break;
- case llvm::Triple::sparc:
- case llvm::Triple::sparcel:
- case llvm::Triple::sparcv9:
- getSparcTargetFeatures(Args, Features);
- break;
case llvm::Triple::systemz:
getSystemZTargetFeatures(Args, Features);
break;
@@ -2326,6 +2434,8 @@ collectSanitizerRuntimes(const ToolChain &TC, const ArgList &Args,
if (SanArgs.linkCXXRuntimes())
StaticRuntimes.push_back("ubsan_standalone_cxx");
}
+ if (SanArgs.needsSafeStackRt())
+ StaticRuntimes.push_back("safestack");
}
// Should be called before we add system libraries (C++ ABI, libstdc++/libc++,
@@ -3151,6 +3261,8 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,
CmdArgs.push_back(Args.MakeArgString("-ffp-contract=fast"));
}
}
+
+ ParseMRecip(getToolChain().getDriver(), Args, CmdArgs);
// We separately look for the '-ffast-math' and '-ffinite-math-only' flags,
// and if we find them, tell the frontend to provide the appropriate
@@ -3892,7 +4004,12 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,
// -stack-protector=0 is default.
unsigned StackProtectorLevel = 0;
- if (Arg *A = Args.getLastArg(options::OPT_fno_stack_protector,
+ if (getToolChain().getSanitizerArgs().needsSafeStackRt()) {
+ Args.ClaimAllArgs(options::OPT_fno_stack_protector);
+ Args.ClaimAllArgs(options::OPT_fstack_protector_all);
+ Args.ClaimAllArgs(options::OPT_fstack_protector_strong);
+ Args.ClaimAllArgs(options::OPT_fstack_protector);
+ } else if (Arg *A = Args.getLastArg(options::OPT_fno_stack_protector,
options::OPT_fstack_protector_all,
options::OPT_fstack_protector_strong,
options::OPT_fstack_protector)) {
@@ -4019,9 +4136,9 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,
CmdArgs.push_back("-fblocks-runtime-optional");
}
- // -fmodules enables modules (off by default).
+ // -fmodules enables the use of precompiled modules (off by default).
// Users can pass -fno-cxx-modules to turn off modules support for
- // C++/Objective-C++ programs, which is a little less mature.
+ // C++/Objective-C++ programs.
bool HaveModules = false;
if (Args.hasFlag(options::OPT_fmodules, options::OPT_fno_modules, false)) {
bool AllowedInCXX = Args.hasFlag(options::OPT_fcxx_modules,
@@ -4033,11 +4150,11 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,
}
}
- // -fmodule-maps enables module map processing (off by default) for header
- // checking. It is implied by -fmodules.
- if (Args.hasFlag(options::OPT_fmodule_maps, options::OPT_fno_module_maps,
- false)) {
- CmdArgs.push_back("-fmodule-maps");
+ // -fmodule-maps enables implicit reading of module map files. By default,
+ // this is enabled if we are using precompiled modules.
+ if (Args.hasFlag(options::OPT_fimplicit_module_maps,
+ options::OPT_fno_implicit_module_maps, HaveModules)) {
+ CmdArgs.push_back("-fimplicit-module-maps");
}
// -fmodules-decluse checks that modules used are declared so (off by
@@ -5627,9 +5744,9 @@ void hexagon::Link::ConstructJob(Compilation &C, const JobAction &JA,
}
// Hexagon tools end.
-const StringRef arm::getARMArch(const ArgList &Args,
- const llvm::Triple &Triple) {
- StringRef MArch;
+const std::string arm::getARMArch(const ArgList &Args,
+ const llvm::Triple &Triple) {
+ std::string MArch;
if (Arg *A = Args.getLastArg(options::OPT_march_EQ)) {
// Otherwise, if we have -march= choose the base CPU for that arch.
MArch = A->getValue();
@@ -5637,6 +5754,7 @@ const StringRef arm::getARMArch(const ArgList &Args,
// Otherwise, use the Arch from the triple.
MArch = Triple.getArchName();
}
+ MArch = StringRef(MArch).lower();
// Handle -march=native.
if (MArch == "native") {
@@ -5658,7 +5776,7 @@ const StringRef arm::getARMArch(const ArgList &Args,
/// Get the (LLVM) name of the minimum ARM CPU for the arch we are targeting.
const char *arm::getARMCPUForMArch(const ArgList &Args,
const llvm::Triple &Triple) {
- StringRef MArch = getARMArch(Args, Triple);
+ std::string MArch = getARMArch(Args, Triple);
// getARMCPUForArch defaults to the triple if MArch is empty, but empty MArch
// here means an -march=native that we can't handle, so instead return no CPU.
if (MArch.empty())
@@ -5761,7 +5879,7 @@ bool mips::isNaN2008(const ArgList &Args, const llvm::Triple &Triple) {
}
bool mips::isFPXXDefault(const llvm::Triple &Triple, StringRef CPUName,
- StringRef ABIName) {
+ StringRef ABIName, StringRef FloatABI) {
if (Triple.getVendor() != llvm::Triple::ImaginationTechnologies &&
Triple.getVendor() != llvm::Triple::MipsTechnologies)
return false;
@@ -5769,6 +5887,11 @@ bool mips::isFPXXDefault(const llvm::Triple &Triple, StringRef CPUName,
if (ABIName != "32")
return false;
+ // FPXX shouldn't be used if either -msoft-float or -mfloat-abi=soft is
+ // present.
+ if (FloatABI == "soft")
+ return false;
+
return llvm::StringSwitch<bool>(CPUName)
.Cases("mips2", "mips3", "mips4", "mips5", true)
.Cases("mips32", "mips32r2", "mips32r3", "mips32r5", true)
@@ -5776,6 +5899,20 @@ bool mips::isFPXXDefault(const llvm::Triple &Triple, StringRef CPUName,
.Default(false);
}
+bool mips::shouldUseFPXX(const ArgList &Args, const llvm::Triple &Triple,
+ StringRef CPUName, StringRef ABIName,
+ StringRef FloatABI) {
+ bool UseFPXX = isFPXXDefault(Triple, CPUName, ABIName, FloatABI);
+
+ // FPXX shouldn't be used if -msingle-float is present.
+ if (Arg *A = Args.getLastArg(options::OPT_msingle_float,
+ options::OPT_mdouble_float))
+ if (A->getOption().matches(options::OPT_msingle_float))
+ UseFPXX = false;
+
+ return UseFPXX;
+}
+
llvm::Triple::ArchType darwin::getArchTypeForMachOArchName(StringRef Str) {
// See arch(3) and llvm-gcc's driver-driver.c. We don't implement support for
// archs which Darwin doesn't use.
@@ -5901,7 +6038,7 @@ void cloudabi::Link::ConstructJob(Compilation &C, const JobAction &JA,
Args.AddAllArgs(CmdArgs, options::OPT_Z_Flag);
Args.AddAllArgs(CmdArgs, options::OPT_r);
- if (D.IsUsingLTO(ToolChain, Args))
+ if (D.IsUsingLTO(Args))
AddGoldPlugin(ToolChain, Args, CmdArgs);
AddLinkerInputs(ToolChain, Inputs, Args, CmdArgs);
@@ -6052,8 +6189,7 @@ void darwin::Link::AddLinkArgs(Compilation &C,
// 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(getToolChain(), Args) &&
- NeedsTempPath(Inputs)) {
+ if (Version[0] >= 116 && D.IsUsingLTO(Args) && NeedsTempPath(Inputs)) {
const char *TmpPath = C.getArgs().MakeArgString(
D.GetTemporaryPath("cc", types::getTypeTempSuffix(types::TY_Object)));
C.addTempFile(TmpPath);
@@ -6254,6 +6390,15 @@ void darwin::Link::ConstructJob(Compilation &C, const JobAction &JA,
!Args.hasArg(options::OPT_nostartfiles))
getMachOToolChain().addStartObjectFileArgs(Args, CmdArgs);
+ // SafeStack requires its own runtime libraries
+ // These libraries should be linked first, to make sure the
+ // __safestack_init constructor executes before everything else
+ if (getToolChain().getSanitizerArgs().needsSafeStackRt()) {
+ getMachOToolChain().AddLinkRuntimeLib(Args, CmdArgs,
+ "libclang_rt.safestack_osx.a",
+ /*AlwaysLink=*/true);
+ }
+
Args.AddAllArgs(CmdArgs, options::OPT_L);
if (Args.hasFlag(options::OPT_fopenmp, options::OPT_fopenmp_EQ,
@@ -7080,7 +7225,7 @@ void freebsd::Link::ConstructJob(Compilation &C, const JobAction &JA,
Args.AddAllArgs(CmdArgs, options::OPT_Z_Flag);
Args.AddAllArgs(CmdArgs, options::OPT_r);
- if (D.IsUsingLTO(getToolChain(), Args))
+ if (D.IsUsingLTO(Args))
AddGoldPlugin(ToolChain, Args, CmdArgs);
bool NeedsSanitizerDeps = addSanitizerRuntimes(ToolChain, Args, CmdArgs);
@@ -7577,12 +7722,13 @@ void gnutools::Assemble::ConstructJob(Compilation &C, const JobAction &JA,
}
// Add the last -mfp32/-mfpxx/-mfp64 or -mfpxx if it is enabled by default.
+ StringRef MIPSFloatABI = getMipsFloatABI(getToolChain().getDriver(), Args);
if (Arg *A = Args.getLastArg(options::OPT_mfp32, options::OPT_mfpxx,
options::OPT_mfp64)) {
A->claim();
A->render(Args, CmdArgs);
- } else if (mips::isFPXXDefault(getToolChain().getTriple(), CPUName,
- ABIName))
+ } else if (mips::shouldUseFPXX(Args, getToolChain().getTriple(), CPUName,
+ ABIName, MIPSFloatABI))
CmdArgs.push_back("-mfpxx");
// Pass on -mmips16 or -mno-mips16. However, the assembler equivalent of
@@ -7613,6 +7759,9 @@ void gnutools::Assemble::ConstructJob(Compilation &C, const JobAction &JA,
Args.AddLastArg(CmdArgs, options::OPT_mhard_float,
options::OPT_msoft_float);
+ Args.AddLastArg(CmdArgs, options::OPT_mdouble_float,
+ options::OPT_msingle_float);
+
Args.AddLastArg(CmdArgs, options::OPT_modd_spreg,
options::OPT_mno_odd_spreg);
@@ -7936,7 +8085,7 @@ void gnutools::Link::ConstructJob(Compilation &C, const JobAction &JA,
for (const auto &Path : Paths)
CmdArgs.push_back(Args.MakeArgString(StringRef("-L") + Path));
- if (D.IsUsingLTO(getToolChain(), Args))
+ if (D.IsUsingLTO(Args))
AddGoldPlugin(ToolChain, Args, CmdArgs);
if (Args.hasArg(options::OPT_Z_Xlinker__no_demangle))
@@ -8948,3 +9097,81 @@ void CrossWindows::Link::ConstructJob(Compilation &C, const JobAction &JA,
C.addCommand(llvm::make_unique<Command>(JA, *this, Exec, CmdArgs));
}
+
+void tools::SHAVE::Compile::ConstructJob(Compilation &C, const JobAction &JA,
+ const InputInfo &Output,
+ const InputInfoList &Inputs,
+ const ArgList &Args,
+ const char *LinkingOutput) const {
+
+ ArgStringList CmdArgs;
+
+ assert(Inputs.size() == 1);
+ const InputInfo &II = Inputs[0];
+ assert(II.getType() == types::TY_C || II.getType() == types::TY_CXX);
+ assert(Output.getType() == types::TY_PP_Asm); // Require preprocessed asm.
+
+ // Append all -I, -iquote, -isystem paths.
+ Args.AddAllArgs(CmdArgs, options::OPT_clang_i_Group);
+ // These are spelled the same way in clang and moviCompile.
+ Args.AddAllArgs(CmdArgs, options::OPT_D, options::OPT_U);
+
+ CmdArgs.push_back("-DMYRIAD2");
+ CmdArgs.push_back("-mcpu=myriad2");
+ CmdArgs.push_back("-S");
+
+ // Any -O option passes through without translation. What about -Ofast ?
+ if (Arg *A = Args.getLastArg(options::OPT_O_Group))
+ A->render(Args, CmdArgs);
+
+ if (Args.hasFlag(options::OPT_ffunction_sections,
+ options::OPT_fno_function_sections)) {
+ CmdArgs.push_back("-ffunction-sections");
+ }
+ if (Args.hasArg(options::OPT_fno_inline_functions))
+ CmdArgs.push_back("-fno-inline-functions");
+
+ CmdArgs.push_back("-fno-exceptions"); // Always do this even if unspecified.
+
+ CmdArgs.push_back(II.getFilename());
+ CmdArgs.push_back("-o");
+ CmdArgs.push_back(Output.getFilename());
+
+ std::string Exec =
+ Args.MakeArgString(getToolChain().GetProgramPath("moviCompile"));
+ C.addCommand(
+ llvm::make_unique<Command>(JA, *this, Args.MakeArgString(Exec), CmdArgs));
+}
+
+void tools::SHAVE::Assemble::ConstructJob(Compilation &C,
+ const JobAction &JA,
+ const InputInfo &Output,
+ const InputInfoList &Inputs,
+ const ArgList &Args,
+ const char *LinkingOutput) const {
+ ArgStringList CmdArgs;
+
+ assert(Inputs.size() == 1);
+ const InputInfo &II = Inputs[0];
+ assert(II.getType() == types::TY_PP_Asm); // Require preprocessed asm input.
+ assert(Output.getType() == types::TY_Object);
+
+ CmdArgs.push_back("-no6thSlotCompression");
+ CmdArgs.push_back("-cv:myriad2"); // Chip Version ?
+ CmdArgs.push_back("-noSPrefixing");
+ CmdArgs.push_back("-a"); // Mystery option.
+ for (auto Arg : Args.filtered(options::OPT_I)) {
+ Arg->claim();
+ CmdArgs.push_back(
+ Args.MakeArgString(std::string("-i:") + Arg->getValue(0)));
+ }
+ CmdArgs.push_back("-elf"); // Output format.
+ CmdArgs.push_back(II.getFilename());
+ CmdArgs.push_back(
+ Args.MakeArgString(std::string("-o:") + Output.getFilename()));
+
+ std::string Exec =
+ Args.MakeArgString(getToolChain().GetProgramPath("moviAsm"));
+ C.addCommand(
+ llvm::make_unique<Command>(JA, *this, Args.MakeArgString(Exec), CmdArgs));
+}
diff --git a/lib/Driver/Tools.h b/lib/Driver/Tools.h
index 133a389..753f542 100644
--- a/lib/Driver/Tools.h
+++ b/lib/Driver/Tools.h
@@ -227,8 +227,8 @@ namespace hexagon {
namespace arm {
std::string getARMTargetCPU(const llvm::opt::ArgList &Args,
const llvm::Triple &Triple);
- const StringRef getARMArch(const llvm::opt::ArgList &Args,
- const llvm::Triple &Triple);
+ const std::string getARMArch(const llvm::opt::ArgList &Args,
+ const llvm::Triple &Triple);
const char* getARMCPUForMArch(const llvm::opt::ArgList &Args,
const llvm::Triple &Triple);
const char* getLLVMArchSuffixForARM(StringRef CPU, StringRef Arch);
@@ -249,7 +249,9 @@ namespace mips {
bool isUCLibc(const llvm::opt::ArgList &Args);
bool isNaN2008(const llvm::opt::ArgList &Args, const llvm::Triple &Triple);
bool isFPXXDefault(const llvm::Triple &Triple, StringRef CPUName,
- StringRef ABIName);
+ StringRef ABIName, StringRef FloatABI);
+ bool shouldUseFPXX(const llvm::opt::ArgList &Args, const llvm::Triple &Triple,
+ StringRef CPUName, StringRef ABIName, StringRef FloatABI);
}
namespace ppc {
@@ -731,6 +733,33 @@ public:
};
}
+/// SHAVE tools -- Directly call moviCompile and moviAsm
+namespace SHAVE {
+class LLVM_LIBRARY_VISIBILITY Compile : public Tool {
+public:
+ Compile(const ToolChain &TC) : Tool("moviCompile", "movicompile", TC) {}
+
+ bool hasIntegratedCPP() const override { return true; }
+
+ void ConstructJob(Compilation &C, const JobAction &JA,
+ const InputInfo &Output, const InputInfoList &Inputs,
+ const llvm::opt::ArgList &TCArgs,
+ const char *LinkingOutput) const override;
+};
+
+class LLVM_LIBRARY_VISIBILITY Assemble : public Tool {
+public:
+ Assemble(const ToolChain &TC) : Tool("moviAsm", "moviAsm", TC) {}
+
+ bool hasIntegratedCPP() const override { return false; } // not sure.
+
+ void ConstructJob(Compilation &C, const JobAction &JA,
+ const InputInfo &Output, const InputInfoList &Inputs,
+ const llvm::opt::ArgList &TCArgs,
+ const char *LinkingOutput) const override;
+};
+} // end namespace SHAVE
+
} // end namespace tools
} // end namespace driver
} // end namespace clang
diff --git a/lib/Driver/Types.cpp b/lib/Driver/Types.cpp
index 0b0878f..7b28145 100644
--- a/lib/Driver/Types.cpp
+++ b/lib/Driver/Types.cpp
@@ -45,7 +45,7 @@ types::ID types::getPreprocessedType(ID Id) {
}
const char *types::getTypeTempSuffix(ID Id, bool CLMode) {
- if ((Id == TY_Object || Id == TY_LTO_BC) && CLMode)
+ if (Id == TY_Object && CLMode)
return "obj";
if (Id == TY_Image && CLMode)
return "exe";
OpenPOWER on IntegriCloud