Path: blob/main/contrib/llvm-project/clang/lib/Driver/ToolChain.cpp
35234 views
//===- ToolChain.cpp - Collections of tools for one platform --------------===//1//2// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.3// See https://llvm.org/LICENSE.txt for license information.4// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception5//6//===----------------------------------------------------------------------===//78#include "clang/Driver/ToolChain.h"9#include "ToolChains/Arch/AArch64.h"10#include "ToolChains/Arch/ARM.h"11#include "ToolChains/Clang.h"12#include "ToolChains/CommonArgs.h"13#include "ToolChains/Flang.h"14#include "ToolChains/InterfaceStubs.h"15#include "clang/Basic/ObjCRuntime.h"16#include "clang/Basic/Sanitizers.h"17#include "clang/Config/config.h"18#include "clang/Driver/Action.h"19#include "clang/Driver/Driver.h"20#include "clang/Driver/DriverDiagnostic.h"21#include "clang/Driver/InputInfo.h"22#include "clang/Driver/Job.h"23#include "clang/Driver/Options.h"24#include "clang/Driver/SanitizerArgs.h"25#include "clang/Driver/XRayArgs.h"26#include "llvm/ADT/STLExtras.h"27#include "llvm/ADT/SmallString.h"28#include "llvm/ADT/StringExtras.h"29#include "llvm/ADT/StringRef.h"30#include "llvm/ADT/Twine.h"31#include "llvm/Config/llvm-config.h"32#include "llvm/MC/MCTargetOptions.h"33#include "llvm/MC/TargetRegistry.h"34#include "llvm/Option/Arg.h"35#include "llvm/Option/ArgList.h"36#include "llvm/Option/OptTable.h"37#include "llvm/Option/Option.h"38#include "llvm/Support/ErrorHandling.h"39#include "llvm/Support/FileSystem.h"40#include "llvm/Support/FileUtilities.h"41#include "llvm/Support/Path.h"42#include "llvm/Support/VersionTuple.h"43#include "llvm/Support/VirtualFileSystem.h"44#include "llvm/TargetParser/AArch64TargetParser.h"45#include "llvm/TargetParser/TargetParser.h"46#include "llvm/TargetParser/Triple.h"47#include <cassert>48#include <cstddef>49#include <cstring>50#include <string>5152using namespace clang;53using namespace driver;54using namespace tools;55using namespace llvm;56using namespace llvm::opt;5758static llvm::opt::Arg *GetRTTIArgument(const ArgList &Args) {59return Args.getLastArg(options::OPT_mkernel, options::OPT_fapple_kext,60options::OPT_fno_rtti, options::OPT_frtti);61}6263static ToolChain::RTTIMode CalculateRTTIMode(const ArgList &Args,64const llvm::Triple &Triple,65const Arg *CachedRTTIArg) {66// Explicit rtti/no-rtti args67if (CachedRTTIArg) {68if (CachedRTTIArg->getOption().matches(options::OPT_frtti))69return ToolChain::RM_Enabled;70else71return ToolChain::RM_Disabled;72}7374// -frtti is default, except for the PS4/PS5 and DriverKit.75bool NoRTTI = Triple.isPS() || Triple.isDriverKit();76return NoRTTI ? ToolChain::RM_Disabled : ToolChain::RM_Enabled;77}7879static ToolChain::ExceptionsMode CalculateExceptionsMode(const ArgList &Args) {80if (Args.hasFlag(options::OPT_fexceptions, options::OPT_fno_exceptions,81true)) {82return ToolChain::EM_Enabled;83}84return ToolChain::EM_Disabled;85}8687ToolChain::ToolChain(const Driver &D, const llvm::Triple &T,88const ArgList &Args)89: D(D), Triple(T), Args(Args), CachedRTTIArg(GetRTTIArgument(Args)),90CachedRTTIMode(CalculateRTTIMode(Args, Triple, CachedRTTIArg)),91CachedExceptionsMode(CalculateExceptionsMode(Args)) {92auto addIfExists = [this](path_list &List, const std::string &Path) {93if (getVFS().exists(Path))94List.push_back(Path);95};9697if (std::optional<std::string> Path = getRuntimePath())98getLibraryPaths().push_back(*Path);99if (std::optional<std::string> Path = getStdlibPath())100getFilePaths().push_back(*Path);101for (const auto &Path : getArchSpecificLibPaths())102addIfExists(getFilePaths(), Path);103}104105llvm::Expected<std::unique_ptr<llvm::MemoryBuffer>>106ToolChain::executeToolChainProgram(StringRef Executable,107unsigned SecondsToWait) const {108llvm::SmallString<64> OutputFile;109llvm::sys::fs::createTemporaryFile("toolchain-program", "txt", OutputFile);110llvm::FileRemover OutputRemover(OutputFile.c_str());111std::optional<llvm::StringRef> Redirects[] = {112{""},113OutputFile.str(),114{""},115};116117std::string ErrorMessage;118if (llvm::sys::ExecuteAndWait(Executable, {}, {}, Redirects, SecondsToWait,119/*MemoryLimit=*/0, &ErrorMessage))120return llvm::createStringError(std::error_code(),121Executable + ": " + ErrorMessage);122123llvm::ErrorOr<std::unique_ptr<llvm::MemoryBuffer>> OutputBuf =124llvm::MemoryBuffer::getFile(OutputFile.c_str());125if (!OutputBuf)126return llvm::createStringError(OutputBuf.getError(),127"Failed to read stdout of " + Executable +128": " + OutputBuf.getError().message());129return std::move(*OutputBuf);130}131132void ToolChain::setTripleEnvironment(llvm::Triple::EnvironmentType Env) {133Triple.setEnvironment(Env);134if (EffectiveTriple != llvm::Triple())135EffectiveTriple.setEnvironment(Env);136}137138ToolChain::~ToolChain() = default;139140llvm::vfs::FileSystem &ToolChain::getVFS() const {141return getDriver().getVFS();142}143144bool ToolChain::useIntegratedAs() const {145return Args.hasFlag(options::OPT_fintegrated_as,146options::OPT_fno_integrated_as,147IsIntegratedAssemblerDefault());148}149150bool ToolChain::useIntegratedBackend() const {151assert(152((IsIntegratedBackendDefault() && IsIntegratedBackendSupported()) ||153(!IsIntegratedBackendDefault() || IsNonIntegratedBackendSupported())) &&154"(Non-)integrated backend set incorrectly!");155156bool IBackend = Args.hasFlag(options::OPT_fintegrated_objemitter,157options::OPT_fno_integrated_objemitter,158IsIntegratedBackendDefault());159160// Diagnose when integrated-objemitter options are not supported by this161// toolchain.162unsigned DiagID;163if ((IBackend && !IsIntegratedBackendSupported()) ||164(!IBackend && !IsNonIntegratedBackendSupported()))165DiagID = clang::diag::err_drv_unsupported_opt_for_target;166else167DiagID = clang::diag::warn_drv_unsupported_opt_for_target;168Arg *A = Args.getLastArg(options::OPT_fno_integrated_objemitter);169if (A && !IsNonIntegratedBackendSupported())170D.Diag(DiagID) << A->getAsString(Args) << Triple.getTriple();171A = Args.getLastArg(options::OPT_fintegrated_objemitter);172if (A && !IsIntegratedBackendSupported())173D.Diag(DiagID) << A->getAsString(Args) << Triple.getTriple();174175return IBackend;176}177178bool ToolChain::useRelaxRelocations() const {179return ENABLE_X86_RELAX_RELOCATIONS;180}181182bool ToolChain::defaultToIEEELongDouble() const {183return PPC_LINUX_DEFAULT_IEEELONGDOUBLE && getTriple().isOSLinux();184}185186static void getAArch64MultilibFlags(const Driver &D,187const llvm::Triple &Triple,188const llvm::opt::ArgList &Args,189Multilib::flags_list &Result) {190std::vector<StringRef> Features;191tools::aarch64::getAArch64TargetFeatures(D, Triple, Args, Features, false);192const auto UnifiedFeatures = tools::unifyTargetFeatures(Features);193llvm::DenseSet<StringRef> FeatureSet(UnifiedFeatures.begin(),194UnifiedFeatures.end());195std::vector<std::string> MArch;196for (const auto &Ext : AArch64::Extensions)197if (!Ext.UserVisibleName.empty())198if (FeatureSet.contains(Ext.PosTargetFeature))199MArch.push_back(Ext.UserVisibleName.str());200for (const auto &Ext : AArch64::Extensions)201if (!Ext.UserVisibleName.empty())202if (FeatureSet.contains(Ext.NegTargetFeature))203MArch.push_back(("no" + Ext.UserVisibleName).str());204StringRef ArchName;205for (const auto &ArchInfo : AArch64::ArchInfos)206if (FeatureSet.contains(ArchInfo->ArchFeature))207ArchName = ArchInfo->Name;208assert(!ArchName.empty() && "at least one architecture should be found");209MArch.insert(MArch.begin(), ("-march=" + ArchName).str());210Result.push_back(llvm::join(MArch, "+"));211}212213static void getARMMultilibFlags(const Driver &D,214const llvm::Triple &Triple,215const llvm::opt::ArgList &Args,216Multilib::flags_list &Result) {217std::vector<StringRef> Features;218llvm::ARM::FPUKind FPUKind = tools::arm::getARMTargetFeatures(219D, Triple, Args, Features, false /*ForAs*/, true /*ForMultilib*/);220const auto UnifiedFeatures = tools::unifyTargetFeatures(Features);221llvm::DenseSet<StringRef> FeatureSet(UnifiedFeatures.begin(),222UnifiedFeatures.end());223std::vector<std::string> MArch;224for (const auto &Ext : ARM::ARCHExtNames)225if (!Ext.Name.empty())226if (FeatureSet.contains(Ext.Feature))227MArch.push_back(Ext.Name.str());228for (const auto &Ext : ARM::ARCHExtNames)229if (!Ext.Name.empty())230if (FeatureSet.contains(Ext.NegFeature))231MArch.push_back(("no" + Ext.Name).str());232MArch.insert(MArch.begin(), ("-march=" + Triple.getArchName()).str());233Result.push_back(llvm::join(MArch, "+"));234235switch (FPUKind) {236#define ARM_FPU(NAME, KIND, VERSION, NEON_SUPPORT, RESTRICTION) \237case llvm::ARM::KIND: \238Result.push_back("-mfpu=" NAME); \239break;240#include "llvm/TargetParser/ARMTargetParser.def"241default:242llvm_unreachable("Invalid FPUKind");243}244245switch (arm::getARMFloatABI(D, Triple, Args)) {246case arm::FloatABI::Soft:247Result.push_back("-mfloat-abi=soft");248break;249case arm::FloatABI::SoftFP:250Result.push_back("-mfloat-abi=softfp");251break;252case arm::FloatABI::Hard:253Result.push_back("-mfloat-abi=hard");254break;255case arm::FloatABI::Invalid:256llvm_unreachable("Invalid float ABI");257}258}259260Multilib::flags_list261ToolChain::getMultilibFlags(const llvm::opt::ArgList &Args) const {262using namespace clang::driver::options;263264std::vector<std::string> Result;265const llvm::Triple Triple(ComputeEffectiveClangTriple(Args));266Result.push_back("--target=" + Triple.str());267268switch (Triple.getArch()) {269case llvm::Triple::aarch64:270case llvm::Triple::aarch64_32:271case llvm::Triple::aarch64_be:272getAArch64MultilibFlags(D, Triple, Args, Result);273break;274case llvm::Triple::arm:275case llvm::Triple::armeb:276case llvm::Triple::thumb:277case llvm::Triple::thumbeb:278getARMMultilibFlags(D, Triple, Args, Result);279break;280default:281break;282}283284// Include fno-exceptions and fno-rtti285// to improve multilib selection286if (getRTTIMode() == ToolChain::RTTIMode::RM_Disabled)287Result.push_back("-fno-rtti");288else289Result.push_back("-frtti");290291if (getExceptionsMode() == ToolChain::ExceptionsMode::EM_Disabled)292Result.push_back("-fno-exceptions");293else294Result.push_back("-fexceptions");295296// Sort and remove duplicates.297std::sort(Result.begin(), Result.end());298Result.erase(std::unique(Result.begin(), Result.end()), Result.end());299return Result;300}301302SanitizerArgs303ToolChain::getSanitizerArgs(const llvm::opt::ArgList &JobArgs) const {304SanitizerArgs SanArgs(*this, JobArgs, !SanitizerArgsChecked);305SanitizerArgsChecked = true;306return SanArgs;307}308309const XRayArgs& ToolChain::getXRayArgs() const {310if (!XRayArguments)311XRayArguments.reset(new XRayArgs(*this, Args));312return *XRayArguments;313}314315namespace {316317struct DriverSuffix {318const char *Suffix;319const char *ModeFlag;320};321322} // namespace323324static const DriverSuffix *FindDriverSuffix(StringRef ProgName, size_t &Pos) {325// A list of known driver suffixes. Suffixes are compared against the326// program name in order. If there is a match, the frontend type is updated as327// necessary by applying the ModeFlag.328static const DriverSuffix DriverSuffixes[] = {329{"clang", nullptr},330{"clang++", "--driver-mode=g++"},331{"clang-c++", "--driver-mode=g++"},332{"clang-cc", nullptr},333{"clang-cpp", "--driver-mode=cpp"},334{"clang-g++", "--driver-mode=g++"},335{"clang-gcc", nullptr},336{"clang-cl", "--driver-mode=cl"},337{"cc", nullptr},338{"cpp", "--driver-mode=cpp"},339{"cl", "--driver-mode=cl"},340{"++", "--driver-mode=g++"},341{"flang", "--driver-mode=flang"},342{"clang-dxc", "--driver-mode=dxc"},343};344345for (const auto &DS : DriverSuffixes) {346StringRef Suffix(DS.Suffix);347if (ProgName.ends_with(Suffix)) {348Pos = ProgName.size() - Suffix.size();349return &DS;350}351}352return nullptr;353}354355/// Normalize the program name from argv[0] by stripping the file extension if356/// present and lower-casing the string on Windows.357static std::string normalizeProgramName(llvm::StringRef Argv0) {358std::string ProgName = std::string(llvm::sys::path::filename(Argv0));359if (is_style_windows(llvm::sys::path::Style::native)) {360// Transform to lowercase for case insensitive file systems.361std::transform(ProgName.begin(), ProgName.end(), ProgName.begin(),362::tolower);363}364return ProgName;365}366367static const DriverSuffix *parseDriverSuffix(StringRef ProgName, size_t &Pos) {368// Try to infer frontend type and default target from the program name by369// comparing it against DriverSuffixes in order.370371// If there is a match, the function tries to identify a target as prefix.372// E.g. "x86_64-linux-clang" as interpreted as suffix "clang" with target373// prefix "x86_64-linux". If such a target prefix is found, it may be374// added via -target as implicit first argument.375const DriverSuffix *DS = FindDriverSuffix(ProgName, Pos);376377if (!DS && ProgName.ends_with(".exe")) {378// Try again after stripping the executable suffix:379// clang++.exe -> clang++380ProgName = ProgName.drop_back(StringRef(".exe").size());381DS = FindDriverSuffix(ProgName, Pos);382}383384if (!DS) {385// Try again after stripping any trailing version number:386// clang++3.5 -> clang++387ProgName = ProgName.rtrim("0123456789.");388DS = FindDriverSuffix(ProgName, Pos);389}390391if (!DS) {392// Try again after stripping trailing -component.393// clang++-tot -> clang++394ProgName = ProgName.slice(0, ProgName.rfind('-'));395DS = FindDriverSuffix(ProgName, Pos);396}397return DS;398}399400ParsedClangName401ToolChain::getTargetAndModeFromProgramName(StringRef PN) {402std::string ProgName = normalizeProgramName(PN);403size_t SuffixPos;404const DriverSuffix *DS = parseDriverSuffix(ProgName, SuffixPos);405if (!DS)406return {};407size_t SuffixEnd = SuffixPos + strlen(DS->Suffix);408409size_t LastComponent = ProgName.rfind('-', SuffixPos);410if (LastComponent == std::string::npos)411return ParsedClangName(ProgName.substr(0, SuffixEnd), DS->ModeFlag);412std::string ModeSuffix = ProgName.substr(LastComponent + 1,413SuffixEnd - LastComponent - 1);414415// Infer target from the prefix.416StringRef Prefix(ProgName);417Prefix = Prefix.slice(0, LastComponent);418std::string IgnoredError;419bool IsRegistered =420llvm::TargetRegistry::lookupTarget(std::string(Prefix), IgnoredError);421return ParsedClangName{std::string(Prefix), ModeSuffix, DS->ModeFlag,422IsRegistered};423}424425StringRef ToolChain::getDefaultUniversalArchName() const {426// In universal driver terms, the arch name accepted by -arch isn't exactly427// the same as the ones that appear in the triple. Roughly speaking, this is428// an inverse of the darwin::getArchTypeForDarwinArchName() function.429switch (Triple.getArch()) {430case llvm::Triple::aarch64: {431if (getTriple().isArm64e())432return "arm64e";433return "arm64";434}435case llvm::Triple::aarch64_32:436return "arm64_32";437case llvm::Triple::ppc:438return "ppc";439case llvm::Triple::ppcle:440return "ppcle";441case llvm::Triple::ppc64:442return "ppc64";443case llvm::Triple::ppc64le:444return "ppc64le";445default:446return Triple.getArchName();447}448}449450std::string ToolChain::getInputFilename(const InputInfo &Input) const {451return Input.getFilename();452}453454ToolChain::UnwindTableLevel455ToolChain::getDefaultUnwindTableLevel(const ArgList &Args) const {456return UnwindTableLevel::None;457}458459Tool *ToolChain::getClang() const {460if (!Clang)461Clang.reset(new tools::Clang(*this, useIntegratedBackend()));462return Clang.get();463}464465Tool *ToolChain::getFlang() const {466if (!Flang)467Flang.reset(new tools::Flang(*this));468return Flang.get();469}470471Tool *ToolChain::buildAssembler() const {472return new tools::ClangAs(*this);473}474475Tool *ToolChain::buildLinker() const {476llvm_unreachable("Linking is not supported by this toolchain");477}478479Tool *ToolChain::buildStaticLibTool() const {480llvm_unreachable("Creating static lib is not supported by this toolchain");481}482483Tool *ToolChain::getAssemble() const {484if (!Assemble)485Assemble.reset(buildAssembler());486return Assemble.get();487}488489Tool *ToolChain::getClangAs() const {490if (!Assemble)491Assemble.reset(new tools::ClangAs(*this));492return Assemble.get();493}494495Tool *ToolChain::getLink() const {496if (!Link)497Link.reset(buildLinker());498return Link.get();499}500501Tool *ToolChain::getStaticLibTool() const {502if (!StaticLibTool)503StaticLibTool.reset(buildStaticLibTool());504return StaticLibTool.get();505}506507Tool *ToolChain::getIfsMerge() const {508if (!IfsMerge)509IfsMerge.reset(new tools::ifstool::Merger(*this));510return IfsMerge.get();511}512513Tool *ToolChain::getOffloadBundler() const {514if (!OffloadBundler)515OffloadBundler.reset(new tools::OffloadBundler(*this));516return OffloadBundler.get();517}518519Tool *ToolChain::getOffloadPackager() const {520if (!OffloadPackager)521OffloadPackager.reset(new tools::OffloadPackager(*this));522return OffloadPackager.get();523}524525Tool *ToolChain::getLinkerWrapper() const {526if (!LinkerWrapper)527LinkerWrapper.reset(new tools::LinkerWrapper(*this, getLink()));528return LinkerWrapper.get();529}530531Tool *ToolChain::getTool(Action::ActionClass AC) const {532switch (AC) {533case Action::AssembleJobClass:534return getAssemble();535536case Action::IfsMergeJobClass:537return getIfsMerge();538539case Action::LinkJobClass:540return getLink();541542case Action::StaticLibJobClass:543return getStaticLibTool();544545case Action::InputClass:546case Action::BindArchClass:547case Action::OffloadClass:548case Action::LipoJobClass:549case Action::DsymutilJobClass:550case Action::VerifyDebugInfoJobClass:551case Action::BinaryAnalyzeJobClass:552llvm_unreachable("Invalid tool kind.");553554case Action::CompileJobClass:555case Action::PrecompileJobClass:556case Action::PreprocessJobClass:557case Action::ExtractAPIJobClass:558case Action::AnalyzeJobClass:559case Action::MigrateJobClass:560case Action::VerifyPCHJobClass:561case Action::BackendJobClass:562return getClang();563564case Action::OffloadBundlingJobClass:565case Action::OffloadUnbundlingJobClass:566return getOffloadBundler();567568case Action::OffloadPackagerJobClass:569return getOffloadPackager();570case Action::LinkerWrapperJobClass:571return getLinkerWrapper();572}573574llvm_unreachable("Invalid tool kind.");575}576577static StringRef getArchNameForCompilerRTLib(const ToolChain &TC,578const ArgList &Args) {579const llvm::Triple &Triple = TC.getTriple();580bool IsWindows = Triple.isOSWindows();581582if (TC.isBareMetal())583return Triple.getArchName();584585if (TC.getArch() == llvm::Triple::arm || TC.getArch() == llvm::Triple::armeb)586return (arm::getARMFloatABI(TC, Args) == arm::FloatABI::Hard && !IsWindows)587? "armhf"588: "arm";589590// For historic reasons, Android library is using i686 instead of i386.591if (TC.getArch() == llvm::Triple::x86 && Triple.isAndroid())592return "i686";593594if (TC.getArch() == llvm::Triple::x86_64 && Triple.isX32())595return "x32";596597return llvm::Triple::getArchTypeName(TC.getArch());598}599600StringRef ToolChain::getOSLibName() const {601if (Triple.isOSDarwin())602return "darwin";603604switch (Triple.getOS()) {605case llvm::Triple::FreeBSD:606return "freebsd";607case llvm::Triple::NetBSD:608return "netbsd";609case llvm::Triple::OpenBSD:610return "openbsd";611case llvm::Triple::Solaris:612return "sunos";613case llvm::Triple::AIX:614return "aix";615default:616return getOS();617}618}619620std::string ToolChain::getCompilerRTPath() const {621SmallString<128> Path(getDriver().ResourceDir);622if (isBareMetal()) {623llvm::sys::path::append(Path, "lib", getOSLibName());624if (!SelectedMultilibs.empty()) {625Path += SelectedMultilibs.back().gccSuffix();626}627} else if (Triple.isOSUnknown()) {628llvm::sys::path::append(Path, "lib");629} else {630llvm::sys::path::append(Path, "lib", getOSLibName());631}632return std::string(Path);633}634635std::string ToolChain::getCompilerRTBasename(const ArgList &Args,636StringRef Component,637FileType Type) const {638std::string CRTAbsolutePath = getCompilerRT(Args, Component, Type);639return llvm::sys::path::filename(CRTAbsolutePath).str();640}641642std::string ToolChain::buildCompilerRTBasename(const llvm::opt::ArgList &Args,643StringRef Component,644FileType Type,645bool AddArch) const {646const llvm::Triple &TT = getTriple();647bool IsITANMSVCWindows =648TT.isWindowsMSVCEnvironment() || TT.isWindowsItaniumEnvironment();649650const char *Prefix =651IsITANMSVCWindows || Type == ToolChain::FT_Object ? "" : "lib";652const char *Suffix;653switch (Type) {654case ToolChain::FT_Object:655Suffix = IsITANMSVCWindows ? ".obj" : ".o";656break;657case ToolChain::FT_Static:658Suffix = IsITANMSVCWindows ? ".lib" : ".a";659break;660case ToolChain::FT_Shared:661Suffix = TT.isOSWindows()662? (TT.isWindowsGNUEnvironment() ? ".dll.a" : ".lib")663: ".so";664break;665}666667std::string ArchAndEnv;668if (AddArch) {669StringRef Arch = getArchNameForCompilerRTLib(*this, Args);670const char *Env = TT.isAndroid() ? "-android" : "";671ArchAndEnv = ("-" + Arch + Env).str();672}673return (Prefix + Twine("clang_rt.") + Component + ArchAndEnv + Suffix).str();674}675676std::string ToolChain::getCompilerRT(const ArgList &Args, StringRef Component,677FileType Type) const {678// Check for runtime files in the new layout without the architecture first.679std::string CRTBasename =680buildCompilerRTBasename(Args, Component, Type, /*AddArch=*/false);681SmallString<128> Path;682for (const auto &LibPath : getLibraryPaths()) {683SmallString<128> P(LibPath);684llvm::sys::path::append(P, CRTBasename);685if (getVFS().exists(P))686return std::string(P);687if (Path.empty())688Path = P;689}690if (getTriple().isOSAIX())691Path.clear();692693// Check the filename for the old layout if the new one does not exist.694CRTBasename =695buildCompilerRTBasename(Args, Component, Type, /*AddArch=*/true);696SmallString<128> OldPath(getCompilerRTPath());697llvm::sys::path::append(OldPath, CRTBasename);698if (Path.empty() || getVFS().exists(OldPath))699return std::string(OldPath);700701// If none is found, use a file name from the new layout, which may get702// printed in an error message, aiding users in knowing what Clang is703// looking for.704return std::string(Path);705}706707const char *ToolChain::getCompilerRTArgString(const llvm::opt::ArgList &Args,708StringRef Component,709FileType Type) const {710return Args.MakeArgString(getCompilerRT(Args, Component, Type));711}712713// Android target triples contain a target version. If we don't have libraries714// for the exact target version, we should fall back to the next newest version715// or a versionless path, if any.716std::optional<std::string>717ToolChain::getFallbackAndroidTargetPath(StringRef BaseDir) const {718llvm::Triple TripleWithoutLevel(getTriple());719TripleWithoutLevel.setEnvironmentName("android"); // remove any version number720const std::string &TripleWithoutLevelStr = TripleWithoutLevel.str();721unsigned TripleVersion = getTriple().getEnvironmentVersion().getMajor();722unsigned BestVersion = 0;723724SmallString<32> TripleDir;725bool UsingUnversionedDir = false;726std::error_code EC;727for (llvm::vfs::directory_iterator LI = getVFS().dir_begin(BaseDir, EC), LE;728!EC && LI != LE; LI = LI.increment(EC)) {729StringRef DirName = llvm::sys::path::filename(LI->path());730StringRef DirNameSuffix = DirName;731if (DirNameSuffix.consume_front(TripleWithoutLevelStr)) {732if (DirNameSuffix.empty() && TripleDir.empty()) {733TripleDir = DirName;734UsingUnversionedDir = true;735} else {736unsigned Version;737if (!DirNameSuffix.getAsInteger(10, Version) && Version > BestVersion &&738Version < TripleVersion) {739BestVersion = Version;740TripleDir = DirName;741UsingUnversionedDir = false;742}743}744}745}746747if (TripleDir.empty())748return {};749750SmallString<128> P(BaseDir);751llvm::sys::path::append(P, TripleDir);752if (UsingUnversionedDir)753D.Diag(diag::warn_android_unversioned_fallback) << P << getTripleString();754return std::string(P);755}756757std::optional<std::string>758ToolChain::getTargetSubDirPath(StringRef BaseDir) const {759auto getPathForTriple =760[&](const llvm::Triple &Triple) -> std::optional<std::string> {761SmallString<128> P(BaseDir);762llvm::sys::path::append(P, Triple.str());763if (getVFS().exists(P))764return std::string(P);765return {};766};767768if (auto Path = getPathForTriple(getTriple()))769return *Path;770771// When building with per target runtime directories, various ways of naming772// the Arm architecture may have been normalised to simply "arm".773// For example "armv8l" (Armv8 AArch32 little endian) is replaced with "arm".774// Since an armv8l system can use libraries built for earlier architecture775// versions assuming endian and float ABI match.776//777// Original triple: armv8l-unknown-linux-gnueabihf778// Runtime triple: arm-unknown-linux-gnueabihf779//780// We do not do this for armeb (big endian) because doing so could make us781// select little endian libraries. In addition, all known armeb triples only782// use the "armeb" architecture name.783//784// M profile Arm is bare metal and we know they will not be using the per785// target runtime directory layout.786if (getTriple().getArch() == Triple::arm && !getTriple().isArmMClass()) {787llvm::Triple ArmTriple = getTriple();788ArmTriple.setArch(Triple::arm);789if (auto Path = getPathForTriple(ArmTriple))790return *Path;791}792793if (getTriple().isAndroid())794return getFallbackAndroidTargetPath(BaseDir);795796return {};797}798799std::optional<std::string> ToolChain::getRuntimePath() const {800SmallString<128> P(D.ResourceDir);801llvm::sys::path::append(P, "lib");802if (auto Ret = getTargetSubDirPath(P))803return Ret;804// Darwin does not use per-target runtime directory.805if (Triple.isOSDarwin())806return {};807llvm::sys::path::append(P, Triple.str());808return std::string(P);809}810811std::optional<std::string> ToolChain::getStdlibPath() const {812SmallString<128> P(D.Dir);813llvm::sys::path::append(P, "..", "lib");814return getTargetSubDirPath(P);815}816817std::optional<std::string> ToolChain::getStdlibIncludePath() const {818SmallString<128> P(D.Dir);819llvm::sys::path::append(P, "..", "include");820return getTargetSubDirPath(P);821}822823ToolChain::path_list ToolChain::getArchSpecificLibPaths() const {824path_list Paths;825826auto AddPath = [&](const ArrayRef<StringRef> &SS) {827SmallString<128> Path(getDriver().ResourceDir);828llvm::sys::path::append(Path, "lib");829for (auto &S : SS)830llvm::sys::path::append(Path, S);831Paths.push_back(std::string(Path));832};833834AddPath({getTriple().str()});835AddPath({getOSLibName(), llvm::Triple::getArchTypeName(getArch())});836return Paths;837}838839bool ToolChain::needsProfileRT(const ArgList &Args) {840if (Args.hasArg(options::OPT_noprofilelib))841return false;842843return Args.hasArg(options::OPT_fprofile_generate) ||844Args.hasArg(options::OPT_fprofile_generate_EQ) ||845Args.hasArg(options::OPT_fcs_profile_generate) ||846Args.hasArg(options::OPT_fcs_profile_generate_EQ) ||847Args.hasArg(options::OPT_fprofile_instr_generate) ||848Args.hasArg(options::OPT_fprofile_instr_generate_EQ) ||849Args.hasArg(options::OPT_fcreate_profile) ||850Args.hasArg(options::OPT_forder_file_instrumentation);851}852853bool ToolChain::needsGCovInstrumentation(const llvm::opt::ArgList &Args) {854return Args.hasArg(options::OPT_coverage) ||855Args.hasFlag(options::OPT_fprofile_arcs, options::OPT_fno_profile_arcs,856false);857}858859Tool *ToolChain::SelectTool(const JobAction &JA) const {860if (D.IsFlangMode() && getDriver().ShouldUseFlangCompiler(JA)) return getFlang();861if (getDriver().ShouldUseClangCompiler(JA)) return getClang();862Action::ActionClass AC = JA.getKind();863if (AC == Action::AssembleJobClass && useIntegratedAs() &&864!getTriple().isOSAIX())865return getClangAs();866return getTool(AC);867}868869std::string ToolChain::GetFilePath(const char *Name) const {870return D.GetFilePath(Name, *this);871}872873std::string ToolChain::GetProgramPath(const char *Name) const {874return D.GetProgramPath(Name, *this);875}876877std::string ToolChain::GetLinkerPath(bool *LinkerIsLLD) const {878if (LinkerIsLLD)879*LinkerIsLLD = false;880881// Get -fuse-ld= first to prevent -Wunused-command-line-argument. -fuse-ld= is882// considered as the linker flavor, e.g. "bfd", "gold", or "lld".883const Arg* A = Args.getLastArg(options::OPT_fuse_ld_EQ);884StringRef UseLinker = A ? A->getValue() : CLANG_DEFAULT_LINKER;885886// --ld-path= takes precedence over -fuse-ld= and specifies the executable887// name. -B, COMPILER_PATH and PATH and consulted if the value does not888// contain a path component separator.889// -fuse-ld=lld can be used with --ld-path= to inform clang that the binary890// that --ld-path= points to is lld.891if (const Arg *A = Args.getLastArg(options::OPT_ld_path_EQ)) {892std::string Path(A->getValue());893if (!Path.empty()) {894if (llvm::sys::path::parent_path(Path).empty())895Path = GetProgramPath(A->getValue());896if (llvm::sys::fs::can_execute(Path)) {897if (LinkerIsLLD)898*LinkerIsLLD = UseLinker == "lld";899return std::string(Path);900}901}902getDriver().Diag(diag::err_drv_invalid_linker_name) << A->getAsString(Args);903return GetProgramPath(getDefaultLinker());904}905// If we're passed -fuse-ld= with no argument, or with the argument ld,906// then use whatever the default system linker is.907if (UseLinker.empty() || UseLinker == "ld") {908const char *DefaultLinker = getDefaultLinker();909if (llvm::sys::path::is_absolute(DefaultLinker))910return std::string(DefaultLinker);911else912return GetProgramPath(DefaultLinker);913}914915// Extending -fuse-ld= to an absolute or relative path is unexpected. Checking916// for the linker flavor is brittle. In addition, prepending "ld." or "ld64."917// to a relative path is surprising. This is more complex due to priorities918// among -B, COMPILER_PATH and PATH. --ld-path= should be used instead.919if (UseLinker.contains('/'))920getDriver().Diag(diag::warn_drv_fuse_ld_path);921922if (llvm::sys::path::is_absolute(UseLinker)) {923// If we're passed what looks like an absolute path, don't attempt to924// second-guess that.925if (llvm::sys::fs::can_execute(UseLinker))926return std::string(UseLinker);927} else {928llvm::SmallString<8> LinkerName;929if (Triple.isOSDarwin())930LinkerName.append("ld64.");931else932LinkerName.append("ld.");933LinkerName.append(UseLinker);934935std::string LinkerPath(GetProgramPath(LinkerName.c_str()));936if (llvm::sys::fs::can_execute(LinkerPath)) {937if (LinkerIsLLD)938*LinkerIsLLD = UseLinker == "lld";939return LinkerPath;940}941}942943if (A)944getDriver().Diag(diag::err_drv_invalid_linker_name) << A->getAsString(Args);945946return GetProgramPath(getDefaultLinker());947}948949std::string ToolChain::GetStaticLibToolPath() const {950// TODO: Add support for static lib archiving on Windows951if (Triple.isOSDarwin())952return GetProgramPath("libtool");953return GetProgramPath("llvm-ar");954}955956types::ID ToolChain::LookupTypeForExtension(StringRef Ext) const {957types::ID id = types::lookupTypeForExtension(Ext);958959// Flang always runs the preprocessor and has no notion of "preprocessed960// fortran". Here, TY_PP_Fortran is coerced to TY_Fortran to avoid treating961// them differently.962if (D.IsFlangMode() && id == types::TY_PP_Fortran)963id = types::TY_Fortran;964965return id;966}967968bool ToolChain::HasNativeLLVMSupport() const {969return false;970}971972bool ToolChain::isCrossCompiling() const {973llvm::Triple HostTriple(LLVM_HOST_TRIPLE);974switch (HostTriple.getArch()) {975// The A32/T32/T16 instruction sets are not separate architectures in this976// context.977case llvm::Triple::arm:978case llvm::Triple::armeb:979case llvm::Triple::thumb:980case llvm::Triple::thumbeb:981return getArch() != llvm::Triple::arm && getArch() != llvm::Triple::thumb &&982getArch() != llvm::Triple::armeb && getArch() != llvm::Triple::thumbeb;983default:984return HostTriple.getArch() != getArch();985}986}987988ObjCRuntime ToolChain::getDefaultObjCRuntime(bool isNonFragile) const {989return ObjCRuntime(isNonFragile ? ObjCRuntime::GNUstep : ObjCRuntime::GCC,990VersionTuple());991}992993llvm::ExceptionHandling994ToolChain::GetExceptionModel(const llvm::opt::ArgList &Args) const {995return llvm::ExceptionHandling::None;996}997998bool ToolChain::isThreadModelSupported(const StringRef Model) const {999if (Model == "single") {1000// FIXME: 'single' is only supported on ARM and WebAssembly so far.1001return Triple.getArch() == llvm::Triple::arm ||1002Triple.getArch() == llvm::Triple::armeb ||1003Triple.getArch() == llvm::Triple::thumb ||1004Triple.getArch() == llvm::Triple::thumbeb || Triple.isWasm();1005} else if (Model == "posix")1006return true;10071008return false;1009}10101011std::string ToolChain::ComputeLLVMTriple(const ArgList &Args,1012types::ID InputType) const {1013switch (getTriple().getArch()) {1014default:1015return getTripleString();10161017case llvm::Triple::x86_64: {1018llvm::Triple Triple = getTriple();1019if (!Triple.isOSBinFormatMachO())1020return getTripleString();10211022if (Arg *A = Args.getLastArg(options::OPT_march_EQ)) {1023// x86_64h goes in the triple. Other -march options just use the1024// vanilla triple we already have.1025StringRef MArch = A->getValue();1026if (MArch == "x86_64h")1027Triple.setArchName(MArch);1028}1029return Triple.getTriple();1030}1031case llvm::Triple::aarch64: {1032llvm::Triple Triple = getTriple();1033tools::aarch64::setPAuthABIInTriple(getDriver(), Args, Triple);1034if (!Triple.isOSBinFormatMachO())1035return Triple.getTriple();10361037if (Triple.isArm64e())1038return Triple.getTriple();10391040// FIXME: older versions of ld64 expect the "arm64" component in the actual1041// triple string and query it to determine whether an LTO file can be1042// handled. Remove this when we don't care any more.1043Triple.setArchName("arm64");1044return Triple.getTriple();1045}1046case llvm::Triple::aarch64_32:1047return getTripleString();1048case llvm::Triple::arm:1049case llvm::Triple::armeb:1050case llvm::Triple::thumb:1051case llvm::Triple::thumbeb: {1052llvm::Triple Triple = getTriple();1053tools::arm::setArchNameInTriple(getDriver(), Args, InputType, Triple);1054tools::arm::setFloatABIInTriple(getDriver(), Args, Triple);1055return Triple.getTriple();1056}1057}1058}10591060std::string ToolChain::ComputeEffectiveClangTriple(const ArgList &Args,1061types::ID InputType) const {1062return ComputeLLVMTriple(Args, InputType);1063}10641065std::string ToolChain::computeSysRoot() const {1066return D.SysRoot;1067}10681069void ToolChain::AddClangSystemIncludeArgs(const ArgList &DriverArgs,1070ArgStringList &CC1Args) const {1071// Each toolchain should provide the appropriate include flags.1072}10731074void ToolChain::addClangTargetOptions(1075const ArgList &DriverArgs, ArgStringList &CC1Args,1076Action::OffloadKind DeviceOffloadKind) const {}10771078void ToolChain::addClangCC1ASTargetOptions(const ArgList &Args,1079ArgStringList &CC1ASArgs) const {}10801081void ToolChain::addClangWarningOptions(ArgStringList &CC1Args) const {}10821083void ToolChain::addProfileRTLibs(const llvm::opt::ArgList &Args,1084llvm::opt::ArgStringList &CmdArgs) const {1085if (!needsProfileRT(Args) && !needsGCovInstrumentation(Args))1086return;10871088CmdArgs.push_back(getCompilerRTArgString(Args, "profile"));1089}10901091ToolChain::RuntimeLibType ToolChain::GetRuntimeLibType(1092const ArgList &Args) const {1093if (runtimeLibType)1094return *runtimeLibType;10951096const Arg* A = Args.getLastArg(options::OPT_rtlib_EQ);1097StringRef LibName = A ? A->getValue() : CLANG_DEFAULT_RTLIB;10981099// Only use "platform" in tests to override CLANG_DEFAULT_RTLIB!1100if (LibName == "compiler-rt")1101runtimeLibType = ToolChain::RLT_CompilerRT;1102else if (LibName == "libgcc")1103runtimeLibType = ToolChain::RLT_Libgcc;1104else if (LibName == "platform")1105runtimeLibType = GetDefaultRuntimeLibType();1106else {1107if (A)1108getDriver().Diag(diag::err_drv_invalid_rtlib_name)1109<< A->getAsString(Args);11101111runtimeLibType = GetDefaultRuntimeLibType();1112}11131114return *runtimeLibType;1115}11161117ToolChain::UnwindLibType ToolChain::GetUnwindLibType(1118const ArgList &Args) const {1119if (unwindLibType)1120return *unwindLibType;11211122const Arg *A = Args.getLastArg(options::OPT_unwindlib_EQ);1123StringRef LibName = A ? A->getValue() : CLANG_DEFAULT_UNWINDLIB;11241125if (LibName == "none")1126unwindLibType = ToolChain::UNW_None;1127else if (LibName == "platform" || LibName == "") {1128ToolChain::RuntimeLibType RtLibType = GetRuntimeLibType(Args);1129if (RtLibType == ToolChain::RLT_CompilerRT) {1130if (getTriple().isAndroid() || getTriple().isOSAIX())1131unwindLibType = ToolChain::UNW_CompilerRT;1132else1133unwindLibType = ToolChain::UNW_None;1134} else if (RtLibType == ToolChain::RLT_Libgcc)1135unwindLibType = ToolChain::UNW_Libgcc;1136} else if (LibName == "libunwind") {1137if (GetRuntimeLibType(Args) == RLT_Libgcc)1138getDriver().Diag(diag::err_drv_incompatible_unwindlib);1139unwindLibType = ToolChain::UNW_CompilerRT;1140} else if (LibName == "libgcc")1141unwindLibType = ToolChain::UNW_Libgcc;1142else {1143if (A)1144getDriver().Diag(diag::err_drv_invalid_unwindlib_name)1145<< A->getAsString(Args);11461147unwindLibType = GetDefaultUnwindLibType();1148}11491150return *unwindLibType;1151}11521153ToolChain::CXXStdlibType ToolChain::GetCXXStdlibType(const ArgList &Args) const{1154if (cxxStdlibType)1155return *cxxStdlibType;11561157const Arg *A = Args.getLastArg(options::OPT_stdlib_EQ);1158StringRef LibName = A ? A->getValue() : CLANG_DEFAULT_CXX_STDLIB;11591160// Only use "platform" in tests to override CLANG_DEFAULT_CXX_STDLIB!1161if (LibName == "libc++")1162cxxStdlibType = ToolChain::CST_Libcxx;1163else if (LibName == "libstdc++")1164cxxStdlibType = ToolChain::CST_Libstdcxx;1165else if (LibName == "platform")1166cxxStdlibType = GetDefaultCXXStdlibType();1167else {1168if (A)1169getDriver().Diag(diag::err_drv_invalid_stdlib_name)1170<< A->getAsString(Args);11711172cxxStdlibType = GetDefaultCXXStdlibType();1173}11741175return *cxxStdlibType;1176}11771178/// Utility function to add a system include directory to CC1 arguments.1179/*static*/ void ToolChain::addSystemInclude(const ArgList &DriverArgs,1180ArgStringList &CC1Args,1181const Twine &Path) {1182CC1Args.push_back("-internal-isystem");1183CC1Args.push_back(DriverArgs.MakeArgString(Path));1184}11851186/// Utility function to add a system include directory with extern "C"1187/// semantics to CC1 arguments.1188///1189/// Note that this should be used rarely, and only for directories that1190/// historically and for legacy reasons are treated as having implicit extern1191/// "C" semantics. These semantics are *ignored* by and large today, but its1192/// important to preserve the preprocessor changes resulting from the1193/// classification.1194/*static*/ void ToolChain::addExternCSystemInclude(const ArgList &DriverArgs,1195ArgStringList &CC1Args,1196const Twine &Path) {1197CC1Args.push_back("-internal-externc-isystem");1198CC1Args.push_back(DriverArgs.MakeArgString(Path));1199}12001201void ToolChain::addExternCSystemIncludeIfExists(const ArgList &DriverArgs,1202ArgStringList &CC1Args,1203const Twine &Path) {1204if (llvm::sys::fs::exists(Path))1205addExternCSystemInclude(DriverArgs, CC1Args, Path);1206}12071208/// Utility function to add a list of system include directories to CC1.1209/*static*/ void ToolChain::addSystemIncludes(const ArgList &DriverArgs,1210ArgStringList &CC1Args,1211ArrayRef<StringRef> Paths) {1212for (const auto &Path : Paths) {1213CC1Args.push_back("-internal-isystem");1214CC1Args.push_back(DriverArgs.MakeArgString(Path));1215}1216}12171218/*static*/ std::string ToolChain::concat(StringRef Path, const Twine &A,1219const Twine &B, const Twine &C,1220const Twine &D) {1221SmallString<128> Result(Path);1222llvm::sys::path::append(Result, llvm::sys::path::Style::posix, A, B, C, D);1223return std::string(Result);1224}12251226std::string ToolChain::detectLibcxxVersion(StringRef IncludePath) const {1227std::error_code EC;1228int MaxVersion = 0;1229std::string MaxVersionString;1230SmallString<128> Path(IncludePath);1231llvm::sys::path::append(Path, "c++");1232for (llvm::vfs::directory_iterator LI = getVFS().dir_begin(Path, EC), LE;1233!EC && LI != LE; LI = LI.increment(EC)) {1234StringRef VersionText = llvm::sys::path::filename(LI->path());1235int Version;1236if (VersionText[0] == 'v' &&1237!VersionText.slice(1, StringRef::npos).getAsInteger(10, Version)) {1238if (Version > MaxVersion) {1239MaxVersion = Version;1240MaxVersionString = std::string(VersionText);1241}1242}1243}1244if (!MaxVersion)1245return "";1246return MaxVersionString;1247}12481249void ToolChain::AddClangCXXStdlibIncludeArgs(const ArgList &DriverArgs,1250ArgStringList &CC1Args) const {1251// Header search paths should be handled by each of the subclasses.1252// Historically, they have not been, and instead have been handled inside of1253// the CC1-layer frontend. As the logic is hoisted out, this generic function1254// will slowly stop being called.1255//1256// While it is being called, replicate a bit of a hack to propagate the1257// '-stdlib=' flag down to CC1 so that it can in turn customize the C++1258// header search paths with it. Once all systems are overriding this1259// function, the CC1 flag and this line can be removed.1260DriverArgs.AddAllArgs(CC1Args, options::OPT_stdlib_EQ);1261}12621263void ToolChain::AddClangCXXStdlibIsystemArgs(1264const llvm::opt::ArgList &DriverArgs,1265llvm::opt::ArgStringList &CC1Args) const {1266DriverArgs.ClaimAllArgs(options::OPT_stdlibxx_isystem);1267// This intentionally only looks at -nostdinc++, and not -nostdinc or1268// -nostdlibinc. The purpose of -stdlib++-isystem is to support toolchain1269// setups with non-standard search logic for the C++ headers, while still1270// allowing users of the toolchain to bring their own C++ headers. Such a1271// toolchain likely also has non-standard search logic for the C headers and1272// uses -nostdinc to suppress the default logic, but -stdlib++-isystem should1273// still work in that case and only be suppressed by an explicit -nostdinc++1274// in a project using the toolchain.1275if (!DriverArgs.hasArg(options::OPT_nostdincxx))1276for (const auto &P :1277DriverArgs.getAllArgValues(options::OPT_stdlibxx_isystem))1278addSystemInclude(DriverArgs, CC1Args, P);1279}12801281bool ToolChain::ShouldLinkCXXStdlib(const llvm::opt::ArgList &Args) const {1282return getDriver().CCCIsCXX() &&1283!Args.hasArg(options::OPT_nostdlib, options::OPT_nodefaultlibs,1284options::OPT_nostdlibxx);1285}12861287void ToolChain::AddCXXStdlibLibArgs(const ArgList &Args,1288ArgStringList &CmdArgs) const {1289assert(!Args.hasArg(options::OPT_nostdlibxx) &&1290"should not have called this");1291CXXStdlibType Type = GetCXXStdlibType(Args);12921293switch (Type) {1294case ToolChain::CST_Libcxx:1295CmdArgs.push_back("-lc++");1296if (Args.hasArg(options::OPT_fexperimental_library))1297CmdArgs.push_back("-lc++experimental");1298break;12991300case ToolChain::CST_Libstdcxx:1301CmdArgs.push_back("-lstdc++");1302break;1303}1304}13051306void ToolChain::AddFilePathLibArgs(const ArgList &Args,1307ArgStringList &CmdArgs) const {1308for (const auto &LibPath : getFilePaths())1309if(LibPath.length() > 0)1310CmdArgs.push_back(Args.MakeArgString(StringRef("-L") + LibPath));1311}13121313void ToolChain::AddCCKextLibArgs(const ArgList &Args,1314ArgStringList &CmdArgs) const {1315CmdArgs.push_back("-lcc_kext");1316}13171318bool ToolChain::isFastMathRuntimeAvailable(const ArgList &Args,1319std::string &Path) const {1320// Don't implicitly link in mode-changing libraries in a shared library, since1321// this can have very deleterious effects. See the various links from1322// https://github.com/llvm/llvm-project/issues/57589 for more information.1323bool Default = !Args.hasArgNoClaim(options::OPT_shared);13241325// Do not check for -fno-fast-math or -fno-unsafe-math when -Ofast passed1326// (to keep the linker options consistent with gcc and clang itself).1327if (Default && !isOptimizationLevelFast(Args)) {1328// Check if -ffast-math or -funsafe-math.1329Arg *A = Args.getLastArg(1330options::OPT_ffast_math, options::OPT_fno_fast_math,1331options::OPT_funsafe_math_optimizations,1332options::OPT_fno_unsafe_math_optimizations, options::OPT_ffp_model_EQ);13331334if (!A || A->getOption().getID() == options::OPT_fno_fast_math ||1335A->getOption().getID() == options::OPT_fno_unsafe_math_optimizations)1336Default = false;1337if (A && A->getOption().getID() == options::OPT_ffp_model_EQ) {1338StringRef Model = A->getValue();1339if (Model != "fast")1340Default = false;1341}1342}13431344// Whatever decision came as a result of the above implicit settings, either1345// -mdaz-ftz or -mno-daz-ftz is capable of overriding it.1346if (!Args.hasFlag(options::OPT_mdaz_ftz, options::OPT_mno_daz_ftz, Default))1347return false;13481349// If crtfastmath.o exists add it to the arguments.1350Path = GetFilePath("crtfastmath.o");1351return (Path != "crtfastmath.o"); // Not found.1352}13531354bool ToolChain::addFastMathRuntimeIfAvailable(const ArgList &Args,1355ArgStringList &CmdArgs) const {1356std::string Path;1357if (isFastMathRuntimeAvailable(Args, Path)) {1358CmdArgs.push_back(Args.MakeArgString(Path));1359return true;1360}13611362return false;1363}13641365Expected<SmallVector<std::string>>1366ToolChain::getSystemGPUArchs(const llvm::opt::ArgList &Args) const {1367return SmallVector<std::string>();1368}13691370SanitizerMask ToolChain::getSupportedSanitizers() const {1371// Return sanitizers which don't require runtime support and are not1372// platform dependent.13731374SanitizerMask Res =1375(SanitizerKind::Undefined & ~SanitizerKind::Vptr) |1376(SanitizerKind::CFI & ~SanitizerKind::CFIICall) |1377SanitizerKind::CFICastStrict | SanitizerKind::FloatDivideByZero |1378SanitizerKind::KCFI | SanitizerKind::UnsignedIntegerOverflow |1379SanitizerKind::UnsignedShiftBase | SanitizerKind::ImplicitConversion |1380SanitizerKind::Nullability | SanitizerKind::LocalBounds;1381if (getTriple().getArch() == llvm::Triple::x86 ||1382getTriple().getArch() == llvm::Triple::x86_64 ||1383getTriple().getArch() == llvm::Triple::arm || getTriple().isWasm() ||1384getTriple().isAArch64() || getTriple().isRISCV() ||1385getTriple().isLoongArch64())1386Res |= SanitizerKind::CFIICall;1387if (getTriple().getArch() == llvm::Triple::x86_64 ||1388getTriple().isAArch64(64) || getTriple().isRISCV())1389Res |= SanitizerKind::ShadowCallStack;1390if (getTriple().isAArch64(64))1391Res |= SanitizerKind::MemTag;1392return Res;1393}13941395void ToolChain::AddCudaIncludeArgs(const ArgList &DriverArgs,1396ArgStringList &CC1Args) const {}13971398void ToolChain::AddHIPIncludeArgs(const ArgList &DriverArgs,1399ArgStringList &CC1Args) const {}14001401llvm::SmallVector<ToolChain::BitCodeLibraryInfo, 12>1402ToolChain::getDeviceLibs(const ArgList &DriverArgs) const {1403return {};1404}14051406void ToolChain::AddIAMCUIncludeArgs(const ArgList &DriverArgs,1407ArgStringList &CC1Args) const {}14081409static VersionTuple separateMSVCFullVersion(unsigned Version) {1410if (Version < 100)1411return VersionTuple(Version);14121413if (Version < 10000)1414return VersionTuple(Version / 100, Version % 100);14151416unsigned Build = 0, Factor = 1;1417for (; Version > 10000; Version = Version / 10, Factor = Factor * 10)1418Build = Build + (Version % 10) * Factor;1419return VersionTuple(Version / 100, Version % 100, Build);1420}14211422VersionTuple1423ToolChain::computeMSVCVersion(const Driver *D,1424const llvm::opt::ArgList &Args) const {1425const Arg *MSCVersion = Args.getLastArg(options::OPT_fmsc_version);1426const Arg *MSCompatibilityVersion =1427Args.getLastArg(options::OPT_fms_compatibility_version);14281429if (MSCVersion && MSCompatibilityVersion) {1430if (D)1431D->Diag(diag::err_drv_argument_not_allowed_with)1432<< MSCVersion->getAsString(Args)1433<< MSCompatibilityVersion->getAsString(Args);1434return VersionTuple();1435}14361437if (MSCompatibilityVersion) {1438VersionTuple MSVT;1439if (MSVT.tryParse(MSCompatibilityVersion->getValue())) {1440if (D)1441D->Diag(diag::err_drv_invalid_value)1442<< MSCompatibilityVersion->getAsString(Args)1443<< MSCompatibilityVersion->getValue();1444} else {1445return MSVT;1446}1447}14481449if (MSCVersion) {1450unsigned Version = 0;1451if (StringRef(MSCVersion->getValue()).getAsInteger(10, Version)) {1452if (D)1453D->Diag(diag::err_drv_invalid_value)1454<< MSCVersion->getAsString(Args) << MSCVersion->getValue();1455} else {1456return separateMSVCFullVersion(Version);1457}1458}14591460return VersionTuple();1461}14621463llvm::opt::DerivedArgList *ToolChain::TranslateOpenMPTargetArgs(1464const llvm::opt::DerivedArgList &Args, bool SameTripleAsHost,1465SmallVectorImpl<llvm::opt::Arg *> &AllocatedArgs) const {1466DerivedArgList *DAL = new DerivedArgList(Args.getBaseArgs());1467const OptTable &Opts = getDriver().getOpts();1468bool Modified = false;14691470// Handle -Xopenmp-target flags1471for (auto *A : Args) {1472// Exclude flags which may only apply to the host toolchain.1473// Do not exclude flags when the host triple (AuxTriple)1474// matches the current toolchain triple. If it is not present1475// at all, target and host share a toolchain.1476if (A->getOption().matches(options::OPT_m_Group)) {1477// Pass code object version to device toolchain1478// to correctly set metadata in intermediate files.1479if (SameTripleAsHost ||1480A->getOption().matches(options::OPT_mcode_object_version_EQ))1481DAL->append(A);1482else1483Modified = true;1484continue;1485}14861487unsigned Index;1488unsigned Prev;1489bool XOpenMPTargetNoTriple =1490A->getOption().matches(options::OPT_Xopenmp_target);14911492if (A->getOption().matches(options::OPT_Xopenmp_target_EQ)) {1493llvm::Triple TT(getOpenMPTriple(A->getValue(0)));14941495// Passing device args: -Xopenmp-target=<triple> -opt=val.1496if (TT.getTriple() == getTripleString())1497Index = Args.getBaseArgs().MakeIndex(A->getValue(1));1498else1499continue;1500} else if (XOpenMPTargetNoTriple) {1501// Passing device args: -Xopenmp-target -opt=val.1502Index = Args.getBaseArgs().MakeIndex(A->getValue(0));1503} else {1504DAL->append(A);1505continue;1506}15071508// Parse the argument to -Xopenmp-target.1509Prev = Index;1510std::unique_ptr<Arg> XOpenMPTargetArg(Opts.ParseOneArg(Args, Index));1511if (!XOpenMPTargetArg || Index > Prev + 1) {1512getDriver().Diag(diag::err_drv_invalid_Xopenmp_target_with_args)1513<< A->getAsString(Args);1514continue;1515}1516if (XOpenMPTargetNoTriple && XOpenMPTargetArg &&1517Args.getAllArgValues(options::OPT_fopenmp_targets_EQ).size() != 1) {1518getDriver().Diag(diag::err_drv_Xopenmp_target_missing_triple);1519continue;1520}1521XOpenMPTargetArg->setBaseArg(A);1522A = XOpenMPTargetArg.release();1523AllocatedArgs.push_back(A);1524DAL->append(A);1525Modified = true;1526}15271528if (Modified)1529return DAL;15301531delete DAL;1532return nullptr;1533}15341535// TODO: Currently argument values separated by space e.g.1536// -Xclang -mframe-pointer=no cannot be passed by -Xarch_. This should be1537// fixed.1538void ToolChain::TranslateXarchArgs(1539const llvm::opt::DerivedArgList &Args, llvm::opt::Arg *&A,1540llvm::opt::DerivedArgList *DAL,1541SmallVectorImpl<llvm::opt::Arg *> *AllocatedArgs) const {1542const OptTable &Opts = getDriver().getOpts();1543unsigned ValuePos = 1;1544if (A->getOption().matches(options::OPT_Xarch_device) ||1545A->getOption().matches(options::OPT_Xarch_host))1546ValuePos = 0;15471548unsigned Index = Args.getBaseArgs().MakeIndex(A->getValue(ValuePos));1549unsigned Prev = Index;1550std::unique_ptr<llvm::opt::Arg> XarchArg(Opts.ParseOneArg(Args, Index));15511552// If the argument parsing failed or more than one argument was1553// consumed, the -Xarch_ argument's parameter tried to consume1554// extra arguments. Emit an error and ignore.1555//1556// We also want to disallow any options which would alter the1557// driver behavior; that isn't going to work in our model. We1558// use options::NoXarchOption to control this.1559if (!XarchArg || Index > Prev + 1) {1560getDriver().Diag(diag::err_drv_invalid_Xarch_argument_with_args)1561<< A->getAsString(Args);1562return;1563} else if (XarchArg->getOption().hasFlag(options::NoXarchOption)) {1564auto &Diags = getDriver().getDiags();1565unsigned DiagID =1566Diags.getCustomDiagID(DiagnosticsEngine::Error,1567"invalid Xarch argument: '%0', not all driver "1568"options can be forwared via Xarch argument");1569Diags.Report(DiagID) << A->getAsString(Args);1570return;1571}1572XarchArg->setBaseArg(A);1573A = XarchArg.release();1574if (!AllocatedArgs)1575DAL->AddSynthesizedArg(A);1576else1577AllocatedArgs->push_back(A);1578}15791580llvm::opt::DerivedArgList *ToolChain::TranslateXarchArgs(1581const llvm::opt::DerivedArgList &Args, StringRef BoundArch,1582Action::OffloadKind OFK,1583SmallVectorImpl<llvm::opt::Arg *> *AllocatedArgs) const {1584DerivedArgList *DAL = new DerivedArgList(Args.getBaseArgs());1585bool Modified = false;15861587bool IsDevice = OFK != Action::OFK_None && OFK != Action::OFK_Host;1588for (Arg *A : Args) {1589bool NeedTrans = false;1590bool Skip = false;1591if (A->getOption().matches(options::OPT_Xarch_device)) {1592NeedTrans = IsDevice;1593Skip = !IsDevice;1594} else if (A->getOption().matches(options::OPT_Xarch_host)) {1595NeedTrans = !IsDevice;1596Skip = IsDevice;1597} else if (A->getOption().matches(options::OPT_Xarch__) && IsDevice) {1598// Do not translate -Xarch_ options for non CUDA/HIP toolchain since1599// they may need special translation.1600// Skip this argument unless the architecture matches BoundArch1601if (BoundArch.empty() || A->getValue(0) != BoundArch)1602Skip = true;1603else1604NeedTrans = true;1605}1606if (NeedTrans || Skip)1607Modified = true;1608if (NeedTrans)1609TranslateXarchArgs(Args, A, DAL, AllocatedArgs);1610if (!Skip)1611DAL->append(A);1612}16131614if (Modified)1615return DAL;16161617delete DAL;1618return nullptr;1619}162016211622