aboutsummaryrefslogtreecommitdiff
path: root/contrib/llvm-project/clang/lib/Driver/ToolChain.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'contrib/llvm-project/clang/lib/Driver/ToolChain.cpp')
-rw-r--r--contrib/llvm-project/clang/lib/Driver/ToolChain.cpp574
1 files changed, 477 insertions, 97 deletions
diff --git a/contrib/llvm-project/clang/lib/Driver/ToolChain.cpp b/contrib/llvm-project/clang/lib/Driver/ToolChain.cpp
index 6c1b88141c45..20a555afb809 100644
--- a/contrib/llvm-project/clang/lib/Driver/ToolChain.cpp
+++ b/contrib/llvm-project/clang/lib/Driver/ToolChain.cpp
@@ -7,10 +7,12 @@
//===----------------------------------------------------------------------===//
#include "clang/Driver/ToolChain.h"
+#include "ToolChains/Arch/AArch64.h"
#include "ToolChains/Arch/ARM.h"
#include "ToolChains/Clang.h"
-#include "ToolChains/InterfaceStubs.h"
+#include "ToolChains/CommonArgs.h"
#include "ToolChains/Flang.h"
+#include "ToolChains/InterfaceStubs.h"
#include "clang/Basic/ObjCRuntime.h"
#include "clang/Basic/Sanitizers.h"
#include "clang/Config/config.h"
@@ -24,22 +26,25 @@
#include "clang/Driver/XRayArgs.h"
#include "llvm/ADT/STLExtras.h"
#include "llvm/ADT/SmallString.h"
+#include "llvm/ADT/StringExtras.h"
#include "llvm/ADT/StringRef.h"
-#include "llvm/ADT/Triple.h"
#include "llvm/ADT/Twine.h"
#include "llvm/Config/llvm-config.h"
#include "llvm/MC/MCTargetOptions.h"
+#include "llvm/MC/TargetRegistry.h"
#include "llvm/Option/Arg.h"
#include "llvm/Option/ArgList.h"
#include "llvm/Option/OptTable.h"
#include "llvm/Option/Option.h"
#include "llvm/Support/ErrorHandling.h"
#include "llvm/Support/FileSystem.h"
+#include "llvm/Support/FileUtilities.h"
#include "llvm/Support/Path.h"
-#include "llvm/Support/TargetParser.h"
-#include "llvm/Support/TargetRegistry.h"
#include "llvm/Support/VersionTuple.h"
#include "llvm/Support/VirtualFileSystem.h"
+#include "llvm/TargetParser/AArch64TargetParser.h"
+#include "llvm/TargetParser/TargetParser.h"
+#include "llvm/TargetParser/Triple.h"
#include <cassert>
#include <cstddef>
#include <cstring>
@@ -67,25 +72,62 @@ static ToolChain::RTTIMode CalculateRTTIMode(const ArgList &Args,
return ToolChain::RM_Disabled;
}
- // -frtti is default, except for the PS4 CPU.
- return (Triple.isPS4CPU()) ? ToolChain::RM_Disabled : ToolChain::RM_Enabled;
+ // -frtti is default, except for the PS4/PS5 and DriverKit.
+ bool NoRTTI = Triple.isPS() || Triple.isDriverKit();
+ return NoRTTI ? ToolChain::RM_Disabled : ToolChain::RM_Enabled;
+}
+
+static ToolChain::ExceptionsMode CalculateExceptionsMode(const ArgList &Args) {
+ if (Args.hasFlag(options::OPT_fexceptions, options::OPT_fno_exceptions,
+ true)) {
+ return ToolChain::EM_Enabled;
+ }
+ return ToolChain::EM_Disabled;
}
ToolChain::ToolChain(const Driver &D, const llvm::Triple &T,
const ArgList &Args)
: D(D), Triple(T), Args(Args), CachedRTTIArg(GetRTTIArgument(Args)),
- CachedRTTIMode(CalculateRTTIMode(Args, Triple, CachedRTTIArg)) {
- std::string RuntimePath = getRuntimePath();
- if (getVFS().exists(RuntimePath))
- getLibraryPaths().push_back(RuntimePath);
+ CachedRTTIMode(CalculateRTTIMode(Args, Triple, CachedRTTIArg)),
+ CachedExceptionsMode(CalculateExceptionsMode(Args)) {
+ auto addIfExists = [this](path_list &List, const std::string &Path) {
+ if (getVFS().exists(Path))
+ List.push_back(Path);
+ };
+
+ if (std::optional<std::string> Path = getRuntimePath())
+ getLibraryPaths().push_back(*Path);
+ if (std::optional<std::string> Path = getStdlibPath())
+ getFilePaths().push_back(*Path);
+ for (const auto &Path : getArchSpecificLibPaths())
+ addIfExists(getFilePaths(), Path);
+}
+
+llvm::Expected<std::unique_ptr<llvm::MemoryBuffer>>
+ToolChain::executeToolChainProgram(StringRef Executable,
+ unsigned SecondsToWait) const {
+ llvm::SmallString<64> OutputFile;
+ llvm::sys::fs::createTemporaryFile("toolchain-program", "txt", OutputFile);
+ llvm::FileRemover OutputRemover(OutputFile.c_str());
+ std::optional<llvm::StringRef> Redirects[] = {
+ {""},
+ OutputFile.str(),
+ {""},
+ };
- std::string StdlibPath = getStdlibPath();
- if (getVFS().exists(StdlibPath))
- getFilePaths().push_back(StdlibPath);
+ std::string ErrorMessage;
+ if (llvm::sys::ExecuteAndWait(Executable, {}, {}, Redirects, SecondsToWait,
+ /*MemoryLimit=*/0, &ErrorMessage))
+ return llvm::createStringError(std::error_code(),
+ Executable + ": " + ErrorMessage);
- std::string CandidateLibPath = getArchSpecificLibPath();
- if (getVFS().exists(CandidateLibPath))
- getFilePaths().push_back(CandidateLibPath);
+ llvm::ErrorOr<std::unique_ptr<llvm::MemoryBuffer>> OutputBuf =
+ llvm::MemoryBuffer::getFile(OutputFile.c_str());
+ if (!OutputBuf)
+ return llvm::createStringError(OutputBuf.getError(),
+ "Failed to read stdout of " + Executable +
+ ": " + OutputBuf.getError().message());
+ return std::move(*OutputBuf);
}
void ToolChain::setTripleEnvironment(llvm::Triple::EnvironmentType Env) {
@@ -106,24 +148,169 @@ bool ToolChain::useIntegratedAs() const {
IsIntegratedAssemblerDefault());
}
+bool ToolChain::useIntegratedBackend() const {
+ assert(
+ ((IsIntegratedBackendDefault() && IsIntegratedBackendSupported()) ||
+ (!IsIntegratedBackendDefault() || IsNonIntegratedBackendSupported())) &&
+ "(Non-)integrated backend set incorrectly!");
+
+ bool IBackend = Args.hasFlag(options::OPT_fintegrated_objemitter,
+ options::OPT_fno_integrated_objemitter,
+ IsIntegratedBackendDefault());
+
+ // Diagnose when integrated-objemitter options are not supported by this
+ // toolchain.
+ unsigned DiagID;
+ if ((IBackend && !IsIntegratedBackendSupported()) ||
+ (!IBackend && !IsNonIntegratedBackendSupported()))
+ DiagID = clang::diag::err_drv_unsupported_opt_for_target;
+ else
+ DiagID = clang::diag::warn_drv_unsupported_opt_for_target;
+ Arg *A = Args.getLastArg(options::OPT_fno_integrated_objemitter);
+ if (A && !IsNonIntegratedBackendSupported())
+ D.Diag(DiagID) << A->getAsString(Args) << Triple.getTriple();
+ A = Args.getLastArg(options::OPT_fintegrated_objemitter);
+ if (A && !IsIntegratedBackendSupported())
+ D.Diag(DiagID) << A->getAsString(Args) << Triple.getTriple();
+
+ return IBackend;
+}
+
bool ToolChain::useRelaxRelocations() const {
return ENABLE_X86_RELAX_RELOCATIONS;
}
-bool ToolChain::isNoExecStackDefault() const {
- return false;
+bool ToolChain::defaultToIEEELongDouble() const {
+ return PPC_LINUX_DEFAULT_IEEELONGDOUBLE && getTriple().isOSLinux();
+}
+
+static void getAArch64MultilibFlags(const Driver &D,
+ const llvm::Triple &Triple,
+ const llvm::opt::ArgList &Args,
+ Multilib::flags_list &Result) {
+ std::vector<StringRef> Features;
+ tools::aarch64::getAArch64TargetFeatures(D, Triple, Args, Features, false);
+ const auto UnifiedFeatures = tools::unifyTargetFeatures(Features);
+ llvm::DenseSet<StringRef> FeatureSet(UnifiedFeatures.begin(),
+ UnifiedFeatures.end());
+ std::vector<std::string> MArch;
+ for (const auto &Ext : AArch64::Extensions)
+ if (!Ext.UserVisibleName.empty())
+ if (FeatureSet.contains(Ext.PosTargetFeature))
+ MArch.push_back(Ext.UserVisibleName.str());
+ for (const auto &Ext : AArch64::Extensions)
+ if (!Ext.UserVisibleName.empty())
+ if (FeatureSet.contains(Ext.NegTargetFeature))
+ MArch.push_back(("no" + Ext.UserVisibleName).str());
+ StringRef ArchName;
+ for (const auto &ArchInfo : AArch64::ArchInfos)
+ if (FeatureSet.contains(ArchInfo->ArchFeature))
+ ArchName = ArchInfo->Name;
+ assert(!ArchName.empty() && "at least one architecture should be found");
+ MArch.insert(MArch.begin(), ("-march=" + ArchName).str());
+ Result.push_back(llvm::join(MArch, "+"));
+}
+
+static void getARMMultilibFlags(const Driver &D,
+ const llvm::Triple &Triple,
+ const llvm::opt::ArgList &Args,
+ Multilib::flags_list &Result) {
+ std::vector<StringRef> Features;
+ llvm::ARM::FPUKind FPUKind = tools::arm::getARMTargetFeatures(
+ D, Triple, Args, Features, false /*ForAs*/, true /*ForMultilib*/);
+ const auto UnifiedFeatures = tools::unifyTargetFeatures(Features);
+ llvm::DenseSet<StringRef> FeatureSet(UnifiedFeatures.begin(),
+ UnifiedFeatures.end());
+ std::vector<std::string> MArch;
+ for (const auto &Ext : ARM::ARCHExtNames)
+ if (!Ext.Name.empty())
+ if (FeatureSet.contains(Ext.Feature))
+ MArch.push_back(Ext.Name.str());
+ for (const auto &Ext : ARM::ARCHExtNames)
+ if (!Ext.Name.empty())
+ if (FeatureSet.contains(Ext.NegFeature))
+ MArch.push_back(("no" + Ext.Name).str());
+ MArch.insert(MArch.begin(), ("-march=" + Triple.getArchName()).str());
+ Result.push_back(llvm::join(MArch, "+"));
+
+ switch (FPUKind) {
+#define ARM_FPU(NAME, KIND, VERSION, NEON_SUPPORT, RESTRICTION) \
+ case llvm::ARM::KIND: \
+ Result.push_back("-mfpu=" NAME); \
+ break;
+#include "llvm/TargetParser/ARMTargetParser.def"
+ default:
+ llvm_unreachable("Invalid FPUKind");
+ }
+
+ switch (arm::getARMFloatABI(D, Triple, Args)) {
+ case arm::FloatABI::Soft:
+ Result.push_back("-mfloat-abi=soft");
+ break;
+ case arm::FloatABI::SoftFP:
+ Result.push_back("-mfloat-abi=softfp");
+ break;
+ case arm::FloatABI::Hard:
+ Result.push_back("-mfloat-abi=hard");
+ break;
+ case arm::FloatABI::Invalid:
+ llvm_unreachable("Invalid float ABI");
+ }
}
-const SanitizerArgs& ToolChain::getSanitizerArgs() const {
- if (!SanitizerArguments.get())
- SanitizerArguments.reset(new SanitizerArgs(*this, Args));
- return *SanitizerArguments.get();
+Multilib::flags_list
+ToolChain::getMultilibFlags(const llvm::opt::ArgList &Args) const {
+ using namespace clang::driver::options;
+
+ std::vector<std::string> Result;
+ const llvm::Triple Triple(ComputeEffectiveClangTriple(Args));
+ Result.push_back("--target=" + Triple.str());
+
+ switch (Triple.getArch()) {
+ case llvm::Triple::aarch64:
+ case llvm::Triple::aarch64_32:
+ case llvm::Triple::aarch64_be:
+ getAArch64MultilibFlags(D, Triple, Args, Result);
+ break;
+ case llvm::Triple::arm:
+ case llvm::Triple::armeb:
+ case llvm::Triple::thumb:
+ case llvm::Triple::thumbeb:
+ getARMMultilibFlags(D, Triple, Args, Result);
+ break;
+ default:
+ break;
+ }
+
+ // Include fno-exceptions and fno-rtti
+ // to improve multilib selection
+ if (getRTTIMode() == ToolChain::RTTIMode::RM_Disabled)
+ Result.push_back("-fno-rtti");
+ else
+ Result.push_back("-frtti");
+
+ if (getExceptionsMode() == ToolChain::ExceptionsMode::EM_Disabled)
+ Result.push_back("-fno-exceptions");
+ else
+ Result.push_back("-fexceptions");
+
+ // Sort and remove duplicates.
+ std::sort(Result.begin(), Result.end());
+ Result.erase(std::unique(Result.begin(), Result.end()), Result.end());
+ return Result;
+}
+
+SanitizerArgs
+ToolChain::getSanitizerArgs(const llvm::opt::ArgList &JobArgs) const {
+ SanitizerArgs SanArgs(*this, JobArgs, !SanitizerArgsChecked);
+ SanitizerArgsChecked = true;
+ return SanArgs;
}
const XRayArgs& ToolChain::getXRayArgs() const {
- if (!XRayArguments.get())
+ if (!XRayArguments)
XRayArguments.reset(new XRayArgs(*this, Args));
- return *XRayArguments.get();
+ return *XRayArguments;
}
namespace {
@@ -153,13 +340,14 @@ static const DriverSuffix *FindDriverSuffix(StringRef ProgName, size_t &Pos) {
{"cl", "--driver-mode=cl"},
{"++", "--driver-mode=g++"},
{"flang", "--driver-mode=flang"},
+ {"clang-dxc", "--driver-mode=dxc"},
};
- for (size_t i = 0; i < llvm::array_lengthof(DriverSuffixes); ++i) {
- StringRef Suffix(DriverSuffixes[i].Suffix);
- if (ProgName.endswith(Suffix)) {
+ for (const auto &DS : DriverSuffixes) {
+ StringRef Suffix(DS.Suffix);
+ if (ProgName.ends_with(Suffix)) {
Pos = ProgName.size() - Suffix.size();
- return &DriverSuffixes[i];
+ return &DS;
}
}
return nullptr;
@@ -168,11 +356,12 @@ static const DriverSuffix *FindDriverSuffix(StringRef ProgName, size_t &Pos) {
/// Normalize the program name from argv[0] by stripping the file extension if
/// present and lower-casing the string on Windows.
static std::string normalizeProgramName(llvm::StringRef Argv0) {
- std::string ProgName = std::string(llvm::sys::path::stem(Argv0));
-#ifdef _WIN32
- // Transform to lowercase for case insensitive file systems.
- std::transform(ProgName.begin(), ProgName.end(), ProgName.begin(), ::tolower);
-#endif
+ std::string ProgName = std::string(llvm::sys::path::filename(Argv0));
+ if (is_style_windows(llvm::sys::path::Style::native)) {
+ // Transform to lowercase for case insensitive file systems.
+ std::transform(ProgName.begin(), ProgName.end(), ProgName.begin(),
+ ::tolower);
+ }
return ProgName;
}
@@ -186,6 +375,13 @@ static const DriverSuffix *parseDriverSuffix(StringRef ProgName, size_t &Pos) {
// added via -target as implicit first argument.
const DriverSuffix *DS = FindDriverSuffix(ProgName, Pos);
+ if (!DS && ProgName.ends_with(".exe")) {
+ // Try again after stripping the executable suffix:
+ // clang++.exe -> clang++
+ ProgName = ProgName.drop_back(StringRef(".exe").size());
+ DS = FindDriverSuffix(ProgName, Pos);
+ }
+
if (!DS) {
// Try again after stripping any trailing version number:
// clang++3.5 -> clang++
@@ -256,13 +452,14 @@ std::string ToolChain::getInputFilename(const InputInfo &Input) const {
return Input.getFilename();
}
-bool ToolChain::IsUnwindTablesDefault(const ArgList &Args) const {
- return false;
+ToolChain::UnwindTableLevel
+ToolChain::getDefaultUnwindTableLevel(const ArgList &Args) const {
+ return UnwindTableLevel::None;
}
Tool *ToolChain::getClang() const {
if (!Clang)
- Clang.reset(new tools::Clang(*this));
+ Clang.reset(new tools::Clang(*this, useIntegratedBackend()));
return Clang.get();
}
@@ -320,10 +517,16 @@ Tool *ToolChain::getOffloadBundler() const {
return OffloadBundler.get();
}
-Tool *ToolChain::getOffloadWrapper() const {
- if (!OffloadWrapper)
- OffloadWrapper.reset(new tools::OffloadWrapper(*this));
- return OffloadWrapper.get();
+Tool *ToolChain::getOffloadPackager() const {
+ if (!OffloadPackager)
+ OffloadPackager.reset(new tools::OffloadPackager(*this));
+ return OffloadPackager.get();
+}
+
+Tool *ToolChain::getLinkerWrapper() const {
+ if (!LinkerWrapper)
+ LinkerWrapper.reset(new tools::LinkerWrapper(*this, getLink()));
+ return LinkerWrapper.get();
}
Tool *ToolChain::getTool(Action::ActionClass AC) const {
@@ -346,12 +549,13 @@ Tool *ToolChain::getTool(Action::ActionClass AC) const {
case Action::LipoJobClass:
case Action::DsymutilJobClass:
case Action::VerifyDebugInfoJobClass:
+ case Action::BinaryAnalyzeJobClass:
llvm_unreachable("Invalid tool kind.");
case Action::CompileJobClass:
case Action::PrecompileJobClass:
- case Action::HeaderModulePrecompileJobClass:
case Action::PreprocessJobClass:
+ case Action::ExtractAPIJobClass:
case Action::AnalyzeJobClass:
case Action::MigrateJobClass:
case Action::VerifyPCHJobClass:
@@ -362,8 +566,10 @@ Tool *ToolChain::getTool(Action::ActionClass AC) const {
case Action::OffloadUnbundlingJobClass:
return getOffloadBundler();
- case Action::OffloadWrapperJobClass:
- return getOffloadWrapper();
+ case Action::OffloadPackagerJobClass:
+ return getOffloadPackager();
+ case Action::LinkerWrapperJobClass:
+ return getLinkerWrapper();
}
llvm_unreachable("Invalid tool kind.");
@@ -374,6 +580,9 @@ static StringRef getArchNameForCompilerRTLib(const ToolChain &TC,
const llvm::Triple &Triple = TC.getTriple();
bool IsWindows = Triple.isOSWindows();
+ if (TC.isBareMetal())
+ return Triple.getArchName();
+
if (TC.getArch() == llvm::Triple::arm || TC.getArch() == llvm::Triple::armeb)
return (arm::getARMFloatABI(TC, Args) == arm::FloatABI::Hard && !IsWindows)
? "armhf"
@@ -411,12 +620,17 @@ StringRef ToolChain::getOSLibName() const {
std::string ToolChain::getCompilerRTPath() const {
SmallString<128> Path(getDriver().ResourceDir);
- if (Triple.isOSUnknown()) {
+ if (isBareMetal()) {
+ llvm::sys::path::append(Path, "lib", getOSLibName());
+ if (!SelectedMultilibs.empty()) {
+ Path += SelectedMultilibs.back().gccSuffix();
+ }
+ } else if (Triple.isOSUnknown()) {
llvm::sys::path::append(Path, "lib");
} else {
llvm::sys::path::append(Path, "lib", getOSLibName());
}
- return std::string(Path.str());
+ return std::string(Path);
}
std::string ToolChain::getCompilerRTBasename(const ArgList &Args,
@@ -465,20 +679,30 @@ std::string ToolChain::getCompilerRT(const ArgList &Args, StringRef Component,
// Check for runtime files in the new layout without the architecture first.
std::string CRTBasename =
buildCompilerRTBasename(Args, Component, Type, /*AddArch=*/false);
+ SmallString<128> Path;
for (const auto &LibPath : getLibraryPaths()) {
SmallString<128> P(LibPath);
llvm::sys::path::append(P, CRTBasename);
if (getVFS().exists(P))
- return std::string(P.str());
+ return std::string(P);
+ if (Path.empty())
+ Path = P;
}
+ if (getTriple().isOSAIX())
+ Path.clear();
- // Fall back to the old expected compiler-rt name if the new one does not
- // exist.
+ // Check the filename for the old layout if the new one does not exist.
CRTBasename =
buildCompilerRTBasename(Args, Component, Type, /*AddArch=*/true);
- SmallString<128> Path(getCompilerRTPath());
- llvm::sys::path::append(Path, CRTBasename);
- return std::string(Path.str());
+ SmallString<128> OldPath(getCompilerRTPath());
+ llvm::sys::path::append(OldPath, CRTBasename);
+ if (Path.empty() || getVFS().exists(OldPath))
+ return std::string(OldPath);
+
+ // If none is found, use a file name from the new layout, which may get
+ // printed in an error message, aiding users in knowing what Clang is
+ // looking for.
+ return std::string(Path);
}
const char *ToolChain::getCompilerRTArgString(const llvm::opt::ArgList &Args,
@@ -487,23 +711,130 @@ const char *ToolChain::getCompilerRTArgString(const llvm::opt::ArgList &Args,
return Args.MakeArgString(getCompilerRT(Args, Component, Type));
}
-std::string ToolChain::getRuntimePath() const {
+// Android target triples contain a target version. If we don't have libraries
+// for the exact target version, we should fall back to the next newest version
+// or a versionless path, if any.
+std::optional<std::string>
+ToolChain::getFallbackAndroidTargetPath(StringRef BaseDir) const {
+ llvm::Triple TripleWithoutLevel(getTriple());
+ TripleWithoutLevel.setEnvironmentName("android"); // remove any version number
+ const std::string &TripleWithoutLevelStr = TripleWithoutLevel.str();
+ unsigned TripleVersion = getTriple().getEnvironmentVersion().getMajor();
+ unsigned BestVersion = 0;
+
+ SmallString<32> TripleDir;
+ bool UsingUnversionedDir = false;
+ std::error_code EC;
+ for (llvm::vfs::directory_iterator LI = getVFS().dir_begin(BaseDir, EC), LE;
+ !EC && LI != LE; LI = LI.increment(EC)) {
+ StringRef DirName = llvm::sys::path::filename(LI->path());
+ StringRef DirNameSuffix = DirName;
+ if (DirNameSuffix.consume_front(TripleWithoutLevelStr)) {
+ if (DirNameSuffix.empty() && TripleDir.empty()) {
+ TripleDir = DirName;
+ UsingUnversionedDir = true;
+ } else {
+ unsigned Version;
+ if (!DirNameSuffix.getAsInteger(10, Version) && Version > BestVersion &&
+ Version < TripleVersion) {
+ BestVersion = Version;
+ TripleDir = DirName;
+ UsingUnversionedDir = false;
+ }
+ }
+ }
+ }
+
+ if (TripleDir.empty())
+ return {};
+
+ SmallString<128> P(BaseDir);
+ llvm::sys::path::append(P, TripleDir);
+ if (UsingUnversionedDir)
+ D.Diag(diag::warn_android_unversioned_fallback) << P << getTripleString();
+ return std::string(P);
+}
+
+std::optional<std::string>
+ToolChain::getTargetSubDirPath(StringRef BaseDir) const {
+ auto getPathForTriple =
+ [&](const llvm::Triple &Triple) -> std::optional<std::string> {
+ SmallString<128> P(BaseDir);
+ llvm::sys::path::append(P, Triple.str());
+ if (getVFS().exists(P))
+ return std::string(P);
+ return {};
+ };
+
+ if (auto Path = getPathForTriple(getTriple()))
+ return *Path;
+
+ // When building with per target runtime directories, various ways of naming
+ // the Arm architecture may have been normalised to simply "arm".
+ // For example "armv8l" (Armv8 AArch32 little endian) is replaced with "arm".
+ // Since an armv8l system can use libraries built for earlier architecture
+ // versions assuming endian and float ABI match.
+ //
+ // Original triple: armv8l-unknown-linux-gnueabihf
+ // Runtime triple: arm-unknown-linux-gnueabihf
+ //
+ // We do not do this for armeb (big endian) because doing so could make us
+ // select little endian libraries. In addition, all known armeb triples only
+ // use the "armeb" architecture name.
+ //
+ // M profile Arm is bare metal and we know they will not be using the per
+ // target runtime directory layout.
+ if (getTriple().getArch() == Triple::arm && !getTriple().isArmMClass()) {
+ llvm::Triple ArmTriple = getTriple();
+ ArmTriple.setArch(Triple::arm);
+ if (auto Path = getPathForTriple(ArmTriple))
+ return *Path;
+ }
+
+ if (getTriple().isAndroid())
+ return getFallbackAndroidTargetPath(BaseDir);
+
+ return {};
+}
+
+std::optional<std::string> ToolChain::getRuntimePath() const {
SmallString<128> P(D.ResourceDir);
- llvm::sys::path::append(P, "lib", getTripleString());
- return std::string(P.str());
+ llvm::sys::path::append(P, "lib");
+ if (auto Ret = getTargetSubDirPath(P))
+ return Ret;
+ // Darwin does not use per-target runtime directory.
+ if (Triple.isOSDarwin())
+ return {};
+ llvm::sys::path::append(P, Triple.str());
+ return std::string(P);
}
-std::string ToolChain::getStdlibPath() const {
+std::optional<std::string> ToolChain::getStdlibPath() const {
SmallString<128> P(D.Dir);
- llvm::sys::path::append(P, "..", "lib", getTripleString());
- return std::string(P.str());
+ llvm::sys::path::append(P, "..", "lib");
+ return getTargetSubDirPath(P);
}
-std::string ToolChain::getArchSpecificLibPath() const {
- SmallString<128> Path(getDriver().ResourceDir);
- llvm::sys::path::append(Path, "lib", getOSLibName(),
- llvm::Triple::getArchTypeName(getArch()));
- return std::string(Path.str());
+std::optional<std::string> ToolChain::getStdlibIncludePath() const {
+ SmallString<128> P(D.Dir);
+ llvm::sys::path::append(P, "..", "include");
+ return getTargetSubDirPath(P);
+}
+
+ToolChain::path_list ToolChain::getArchSpecificLibPaths() const {
+ path_list Paths;
+
+ auto AddPath = [&](const ArrayRef<StringRef> &SS) {
+ SmallString<128> Path(getDriver().ResourceDir);
+ llvm::sys::path::append(Path, "lib");
+ for (auto &S : SS)
+ llvm::sys::path::append(Path, S);
+ Paths.push_back(std::string(Path));
+ };
+
+ AddPath({getTriple().str()});
+ AddPath({getOSLibName(), llvm::Triple::getArchTypeName(getArch())});
+ return Paths;
}
bool ToolChain::needsProfileRT(const ArgList &Args) {
@@ -530,7 +861,8 @@ Tool *ToolChain::SelectTool(const JobAction &JA) const {
if (D.IsFlangMode() && getDriver().ShouldUseFlangCompiler(JA)) return getFlang();
if (getDriver().ShouldUseClangCompiler(JA)) return getClang();
Action::ActionClass AC = JA.getKind();
- if (AC == Action::AssembleJobClass && useIntegratedAs())
+ if (AC == Action::AssembleJobClass && useIntegratedAs() &&
+ !getTriple().isOSAIX())
return getClangAs();
return getTool(AC);
}
@@ -543,12 +875,9 @@ std::string ToolChain::GetProgramPath(const char *Name) const {
return D.GetProgramPath(Name, *this);
}
-std::string ToolChain::GetLinkerPath(bool *LinkerIsLLD,
- bool *LinkerIsLLDDarwinNew) const {
+std::string ToolChain::GetLinkerPath(bool *LinkerIsLLD) const {
if (LinkerIsLLD)
*LinkerIsLLD = false;
- if (LinkerIsLLDDarwinNew)
- *LinkerIsLLDDarwinNew = false;
// Get -fuse-ld= first to prevent -Wunused-command-line-argument. -fuse-ld= is
// considered as the linker flavor, e.g. "bfd", "gold", or "lld".
@@ -558,13 +887,18 @@ std::string ToolChain::GetLinkerPath(bool *LinkerIsLLD,
// --ld-path= takes precedence over -fuse-ld= and specifies the executable
// name. -B, COMPILER_PATH and PATH and consulted if the value does not
// contain a path component separator.
+ // -fuse-ld=lld can be used with --ld-path= to inform clang that the binary
+ // that --ld-path= points to is lld.
if (const Arg *A = Args.getLastArg(options::OPT_ld_path_EQ)) {
std::string Path(A->getValue());
if (!Path.empty()) {
if (llvm::sys::path::parent_path(Path).empty())
Path = GetProgramPath(A->getValue());
- if (llvm::sys::fs::can_execute(Path))
+ if (llvm::sys::fs::can_execute(Path)) {
+ if (LinkerIsLLD)
+ *LinkerIsLLD = UseLinker == "lld";
return std::string(Path);
+ }
}
getDriver().Diag(diag::err_drv_invalid_linker_name) << A->getAsString(Args);
return GetProgramPath(getDefaultLinker());
@@ -583,7 +917,7 @@ std::string ToolChain::GetLinkerPath(bool *LinkerIsLLD,
// for the linker flavor is brittle. In addition, prepending "ld." or "ld64."
// to a relative path is surprising. This is more complex due to priorities
// among -B, COMPILER_PATH and PATH. --ld-path= should be used instead.
- if (UseLinker.find('/') != StringRef::npos)
+ if (UseLinker.contains('/'))
getDriver().Diag(diag::warn_drv_fuse_ld_path);
if (llvm::sys::path::is_absolute(UseLinker)) {
@@ -601,11 +935,8 @@ std::string ToolChain::GetLinkerPath(bool *LinkerIsLLD,
std::string LinkerPath(GetProgramPath(LinkerName.c_str()));
if (llvm::sys::fs::can_execute(LinkerPath)) {
- // FIXME: Remove LinkerIsLLDDarwinNew once there's only one MachO lld.
if (LinkerIsLLD)
- *LinkerIsLLD = UseLinker == "lld" || UseLinker == "lld.darwinold";
- if (LinkerIsLLDDarwinNew)
- *LinkerIsLLDDarwinNew = UseLinker == "lld";
+ *LinkerIsLLD = UseLinker == "lld";
return LinkerPath;
}
}
@@ -618,6 +949,8 @@ std::string ToolChain::GetLinkerPath(bool *LinkerIsLLD,
std::string ToolChain::GetStaticLibToolPath() const {
// TODO: Add support for static lib archiving on Windows
+ if (Triple.isOSDarwin())
+ return GetProgramPath("libtool");
return GetProgramPath("llvm-ar");
}
@@ -698,11 +1031,12 @@ std::string ToolChain::ComputeLLVMTriple(const ArgList &Args,
}
case llvm::Triple::aarch64: {
llvm::Triple Triple = getTriple();
+ tools::aarch64::setPAuthABIInTriple(getDriver(), Args, Triple);
if (!Triple.isOSBinFormatMachO())
- return getTripleString();
+ return Triple.getTriple();
if (Triple.isArm64e())
- return getTripleString();
+ return Triple.getTriple();
// FIXME: older versions of ld64 expect the "arm64" component in the actual
// triple string and query it to determine whether an LTO file can be
@@ -742,6 +1076,9 @@ void ToolChain::addClangTargetOptions(
const ArgList &DriverArgs, ArgStringList &CC1Args,
Action::OffloadKind DeviceOffloadKind) const {}
+void ToolChain::addClangCC1ASTargetOptions(const ArgList &Args,
+ ArgStringList &CC1ASArgs) const {}
+
void ToolChain::addClangWarningOptions(ArgStringList &CC1Args) const {}
void ToolChain::addProfileRTLibs(const llvm::opt::ArgList &Args,
@@ -879,6 +1216,14 @@ void ToolChain::addExternCSystemIncludeIfExists(const ArgList &DriverArgs,
}
}
+/*static*/ std::string ToolChain::concat(StringRef Path, const Twine &A,
+ const Twine &B, const Twine &C,
+ const Twine &D) {
+ SmallString<128> Result(Path);
+ llvm::sys::path::append(Result, llvm::sys::path::Style::posix, A, B, C, D);
+ return std::string(Result);
+}
+
std::string ToolChain::detectLibcxxVersion(StringRef IncludePath) const {
std::error_code EC;
int MaxVersion = 0;
@@ -920,8 +1265,15 @@ void ToolChain::AddClangCXXStdlibIsystemArgs(
const llvm::opt::ArgList &DriverArgs,
llvm::opt::ArgStringList &CC1Args) const {
DriverArgs.ClaimAllArgs(options::OPT_stdlibxx_isystem);
- if (!DriverArgs.hasArg(options::OPT_nostdinc, options::OPT_nostdincxx,
- options::OPT_nostdlibinc))
+ // This intentionally only looks at -nostdinc++, and not -nostdinc or
+ // -nostdlibinc. The purpose of -stdlib++-isystem is to support toolchain
+ // setups with non-standard search logic for the C++ headers, while still
+ // allowing users of the toolchain to bring their own C++ headers. Such a
+ // toolchain likely also has non-standard search logic for the C headers and
+ // uses -nostdinc to suppress the default logic, but -stdlib++-isystem should
+ // still work in that case and only be suppressed by an explicit -nostdinc++
+ // in a project using the toolchain.
+ if (!DriverArgs.hasArg(options::OPT_nostdincxx))
for (const auto &P :
DriverArgs.getAllArgValues(options::OPT_stdlibxx_isystem))
addSystemInclude(DriverArgs, CC1Args, P);
@@ -942,6 +1294,8 @@ void ToolChain::AddCXXStdlibLibArgs(const ArgList &Args,
switch (Type) {
case ToolChain::CST_Libcxx:
CmdArgs.push_back("-lc++");
+ if (Args.hasArg(options::OPT_fexperimental_library))
+ CmdArgs.push_back("-lc++experimental");
break;
case ToolChain::CST_Libstdcxx:
@@ -964,19 +1318,35 @@ void ToolChain::AddCCKextLibArgs(const ArgList &Args,
bool ToolChain::isFastMathRuntimeAvailable(const ArgList &Args,
std::string &Path) const {
+ // Don't implicitly link in mode-changing libraries in a shared library, since
+ // this can have very deleterious effects. See the various links from
+ // https://github.com/llvm/llvm-project/issues/57589 for more information.
+ bool Default = !Args.hasArgNoClaim(options::OPT_shared);
+
// Do not check for -fno-fast-math or -fno-unsafe-math when -Ofast passed
// (to keep the linker options consistent with gcc and clang itself).
- if (!isOptimizationLevelFast(Args)) {
+ if (Default && !isOptimizationLevelFast(Args)) {
// Check if -ffast-math or -funsafe-math.
- Arg *A =
- Args.getLastArg(options::OPT_ffast_math, options::OPT_fno_fast_math,
- options::OPT_funsafe_math_optimizations,
- options::OPT_fno_unsafe_math_optimizations);
+ Arg *A = Args.getLastArg(
+ options::OPT_ffast_math, options::OPT_fno_fast_math,
+ options::OPT_funsafe_math_optimizations,
+ options::OPT_fno_unsafe_math_optimizations, options::OPT_ffp_model_EQ);
if (!A || A->getOption().getID() == options::OPT_fno_fast_math ||
A->getOption().getID() == options::OPT_fno_unsafe_math_optimizations)
- return false;
+ Default = false;
+ if (A && A->getOption().getID() == options::OPT_ffp_model_EQ) {
+ StringRef Model = A->getValue();
+ if (Model != "fast")
+ Default = false;
+ }
}
+
+ // Whatever decision came as a result of the above implicit settings, either
+ // -mdaz-ftz or -mno-daz-ftz is capable of overriding it.
+ if (!Args.hasFlag(options::OPT_mdaz_ftz, options::OPT_mno_daz_ftz, Default))
+ return false;
+
// If crtfastmath.o exists add it to the arguments.
Path = GetFilePath("crtfastmath.o");
return (Path != "crtfastmath.o"); // Not found.
@@ -993,22 +1363,27 @@ bool ToolChain::addFastMathRuntimeIfAvailable(const ArgList &Args,
return false;
}
+Expected<SmallVector<std::string>>
+ToolChain::getSystemGPUArchs(const llvm::opt::ArgList &Args) const {
+ return SmallVector<std::string>();
+}
+
SanitizerMask ToolChain::getSupportedSanitizers() const {
// Return sanitizers which don't require runtime support and are not
// platform dependent.
SanitizerMask Res =
- (SanitizerKind::Undefined & ~SanitizerKind::Vptr &
- ~SanitizerKind::Function) |
+ (SanitizerKind::Undefined & ~SanitizerKind::Vptr) |
(SanitizerKind::CFI & ~SanitizerKind::CFIICall) |
SanitizerKind::CFICastStrict | SanitizerKind::FloatDivideByZero |
- SanitizerKind::UnsignedIntegerOverflow |
+ SanitizerKind::KCFI | SanitizerKind::UnsignedIntegerOverflow |
SanitizerKind::UnsignedShiftBase | SanitizerKind::ImplicitConversion |
SanitizerKind::Nullability | SanitizerKind::LocalBounds;
if (getTriple().getArch() == llvm::Triple::x86 ||
getTriple().getArch() == llvm::Triple::x86_64 ||
getTriple().getArch() == llvm::Triple::arm || getTriple().isWasm() ||
- getTriple().isAArch64())
+ getTriple().isAArch64() || getTriple().isRISCV() ||
+ getTriple().isLoongArch64())
Res |= SanitizerKind::CFIICall;
if (getTriple().getArch() == llvm::Triple::x86_64 ||
getTriple().isAArch64(64) || getTriple().isRISCV())
@@ -1024,8 +1399,8 @@ void ToolChain::AddCudaIncludeArgs(const ArgList &DriverArgs,
void ToolChain::AddHIPIncludeArgs(const ArgList &DriverArgs,
ArgStringList &CC1Args) const {}
-llvm::SmallVector<std::string, 12>
-ToolChain::getHIPDeviceLibs(const ArgList &DriverArgs) const {
+llvm::SmallVector<ToolChain::BitCodeLibraryInfo, 12>
+ToolChain::getDeviceLibs(const ArgList &DriverArgs) const {
return {};
}
@@ -1100,7 +1475,10 @@ llvm::opt::DerivedArgList *ToolChain::TranslateOpenMPTargetArgs(
// matches the current toolchain triple. If it is not present
// at all, target and host share a toolchain.
if (A->getOption().matches(options::OPT_m_Group)) {
- if (SameTripleAsHost)
+ // Pass code object version to device toolchain
+ // to correctly set metadata in intermediate files.
+ if (SameTripleAsHost ||
+ A->getOption().matches(options::OPT_mcode_object_version_EQ))
DAL->append(A);
else
Modified = true;
@@ -1113,8 +1491,10 @@ llvm::opt::DerivedArgList *ToolChain::TranslateOpenMPTargetArgs(
A->getOption().matches(options::OPT_Xopenmp_target);
if (A->getOption().matches(options::OPT_Xopenmp_target_EQ)) {
+ llvm::Triple TT(getOpenMPTriple(A->getValue(0)));
+
// Passing device args: -Xopenmp-target=<triple> -opt=val.
- if (A->getValue(0) == getTripleString())
+ if (TT.getTriple() == getTripleString())
Index = Args.getBaseArgs().MakeIndex(A->getValue(1));
else
continue;
@@ -1205,17 +1585,17 @@ llvm::opt::DerivedArgList *ToolChain::TranslateXarchArgs(
DerivedArgList *DAL = new DerivedArgList(Args.getBaseArgs());
bool Modified = false;
- bool IsGPU = OFK == Action::OFK_Cuda || OFK == Action::OFK_HIP;
+ bool IsDevice = OFK != Action::OFK_None && OFK != Action::OFK_Host;
for (Arg *A : Args) {
bool NeedTrans = false;
bool Skip = false;
if (A->getOption().matches(options::OPT_Xarch_device)) {
- NeedTrans = IsGPU;
- Skip = !IsGPU;
+ NeedTrans = IsDevice;
+ Skip = !IsDevice;
} else if (A->getOption().matches(options::OPT_Xarch_host)) {
- NeedTrans = !IsGPU;
- Skip = IsGPU;
- } else if (A->getOption().matches(options::OPT_Xarch__) && IsGPU) {
+ NeedTrans = !IsDevice;
+ Skip = IsDevice;
+ } else if (A->getOption().matches(options::OPT_Xarch__) && IsDevice) {
// Do not translate -Xarch_ options for non CUDA/HIP toolchain since
// they may need special translation.
// Skip this argument unless the architecture matches BoundArch