10b57cec5SDimitry Andric //===- ToolChain.cpp - Collections of tools for one platform --------------===// 20b57cec5SDimitry Andric // 30b57cec5SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 40b57cec5SDimitry Andric // See https://llvm.org/LICENSE.txt for license information. 50b57cec5SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 60b57cec5SDimitry Andric // 70b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 80b57cec5SDimitry Andric 90b57cec5SDimitry Andric #include "clang/Driver/ToolChain.h" 1006c3fb27SDimitry Andric #include "ToolChains/Arch/AArch64.h" 110b57cec5SDimitry Andric #include "ToolChains/Arch/ARM.h" 120b57cec5SDimitry Andric #include "ToolChains/Clang.h" 1306c3fb27SDimitry Andric #include "ToolChains/CommonArgs.h" 14480093f4SDimitry Andric #include "ToolChains/Flang.h" 15349cc55cSDimitry Andric #include "ToolChains/InterfaceStubs.h" 160b57cec5SDimitry Andric #include "clang/Basic/ObjCRuntime.h" 170b57cec5SDimitry Andric #include "clang/Basic/Sanitizers.h" 180b57cec5SDimitry Andric #include "clang/Config/config.h" 190b57cec5SDimitry Andric #include "clang/Driver/Action.h" 200b57cec5SDimitry Andric #include "clang/Driver/Driver.h" 210b57cec5SDimitry Andric #include "clang/Driver/DriverDiagnostic.h" 22fe6060f1SDimitry Andric #include "clang/Driver/InputInfo.h" 230b57cec5SDimitry Andric #include "clang/Driver/Job.h" 240b57cec5SDimitry Andric #include "clang/Driver/Options.h" 250b57cec5SDimitry Andric #include "clang/Driver/SanitizerArgs.h" 260b57cec5SDimitry Andric #include "clang/Driver/XRayArgs.h" 270b57cec5SDimitry Andric #include "llvm/ADT/STLExtras.h" 280b57cec5SDimitry Andric #include "llvm/ADT/SmallString.h" 2906c3fb27SDimitry Andric #include "llvm/ADT/StringExtras.h" 300b57cec5SDimitry Andric #include "llvm/ADT/StringRef.h" 310b57cec5SDimitry Andric #include "llvm/ADT/Twine.h" 320b57cec5SDimitry Andric #include "llvm/Config/llvm-config.h" 330b57cec5SDimitry Andric #include "llvm/MC/MCTargetOptions.h" 34349cc55cSDimitry Andric #include "llvm/MC/TargetRegistry.h" 350b57cec5SDimitry Andric #include "llvm/Option/Arg.h" 360b57cec5SDimitry Andric #include "llvm/Option/ArgList.h" 370b57cec5SDimitry Andric #include "llvm/Option/OptTable.h" 380b57cec5SDimitry Andric #include "llvm/Option/Option.h" 390b57cec5SDimitry Andric #include "llvm/Support/ErrorHandling.h" 400b57cec5SDimitry Andric #include "llvm/Support/FileSystem.h" 41bdd1243dSDimitry Andric #include "llvm/Support/FileUtilities.h" 420b57cec5SDimitry Andric #include "llvm/Support/Path.h" 430b57cec5SDimitry Andric #include "llvm/Support/VersionTuple.h" 440b57cec5SDimitry Andric #include "llvm/Support/VirtualFileSystem.h" 4506c3fb27SDimitry Andric #include "llvm/TargetParser/AArch64TargetParser.h" 4606c3fb27SDimitry Andric #include "llvm/TargetParser/TargetParser.h" 4706c3fb27SDimitry Andric #include "llvm/TargetParser/Triple.h" 480b57cec5SDimitry Andric #include <cassert> 490b57cec5SDimitry Andric #include <cstddef> 500b57cec5SDimitry Andric #include <cstring> 510b57cec5SDimitry Andric #include <string> 520b57cec5SDimitry Andric 530b57cec5SDimitry Andric using namespace clang; 540b57cec5SDimitry Andric using namespace driver; 550b57cec5SDimitry Andric using namespace tools; 560b57cec5SDimitry Andric using namespace llvm; 570b57cec5SDimitry Andric using namespace llvm::opt; 580b57cec5SDimitry Andric 590b57cec5SDimitry Andric static llvm::opt::Arg *GetRTTIArgument(const ArgList &Args) { 600b57cec5SDimitry Andric return Args.getLastArg(options::OPT_mkernel, options::OPT_fapple_kext, 610b57cec5SDimitry Andric options::OPT_fno_rtti, options::OPT_frtti); 620b57cec5SDimitry Andric } 630b57cec5SDimitry Andric 640b57cec5SDimitry Andric static ToolChain::RTTIMode CalculateRTTIMode(const ArgList &Args, 650b57cec5SDimitry Andric const llvm::Triple &Triple, 660b57cec5SDimitry Andric const Arg *CachedRTTIArg) { 670b57cec5SDimitry Andric // Explicit rtti/no-rtti args 680b57cec5SDimitry Andric if (CachedRTTIArg) { 690b57cec5SDimitry Andric if (CachedRTTIArg->getOption().matches(options::OPT_frtti)) 700b57cec5SDimitry Andric return ToolChain::RM_Enabled; 710b57cec5SDimitry Andric else 720b57cec5SDimitry Andric return ToolChain::RM_Disabled; 730b57cec5SDimitry Andric } 740b57cec5SDimitry Andric 7581ad6265SDimitry Andric // -frtti is default, except for the PS4/PS5 and DriverKit. 7681ad6265SDimitry Andric bool NoRTTI = Triple.isPS() || Triple.isDriverKit(); 7781ad6265SDimitry Andric return NoRTTI ? ToolChain::RM_Disabled : ToolChain::RM_Enabled; 780b57cec5SDimitry Andric } 790b57cec5SDimitry Andric 80*0fca6ea1SDimitry Andric static ToolChain::ExceptionsMode CalculateExceptionsMode(const ArgList &Args) { 81*0fca6ea1SDimitry Andric if (Args.hasFlag(options::OPT_fexceptions, options::OPT_fno_exceptions, 82*0fca6ea1SDimitry Andric true)) { 83*0fca6ea1SDimitry Andric return ToolChain::EM_Enabled; 84*0fca6ea1SDimitry Andric } 85*0fca6ea1SDimitry Andric return ToolChain::EM_Disabled; 86*0fca6ea1SDimitry Andric } 87*0fca6ea1SDimitry Andric 880b57cec5SDimitry Andric ToolChain::ToolChain(const Driver &D, const llvm::Triple &T, 890b57cec5SDimitry Andric const ArgList &Args) 900b57cec5SDimitry Andric : D(D), Triple(T), Args(Args), CachedRTTIArg(GetRTTIArgument(Args)), 91*0fca6ea1SDimitry Andric CachedRTTIMode(CalculateRTTIMode(Args, Triple, CachedRTTIArg)), 92*0fca6ea1SDimitry Andric CachedExceptionsMode(CalculateExceptionsMode(Args)) { 9304eeddc0SDimitry Andric auto addIfExists = [this](path_list &List, const std::string &Path) { 9404eeddc0SDimitry Andric if (getVFS().exists(Path)) 9504eeddc0SDimitry Andric List.push_back(Path); 9604eeddc0SDimitry Andric }; 970b57cec5SDimitry Andric 985f757f3fSDimitry Andric if (std::optional<std::string> Path = getRuntimePath()) 995f757f3fSDimitry Andric getLibraryPaths().push_back(*Path); 1005f757f3fSDimitry Andric if (std::optional<std::string> Path = getStdlibPath()) 1015f757f3fSDimitry Andric getFilePaths().push_back(*Path); 10206c3fb27SDimitry Andric for (const auto &Path : getArchSpecificLibPaths()) 10306c3fb27SDimitry Andric addIfExists(getFilePaths(), Path); 1040b57cec5SDimitry Andric } 1050b57cec5SDimitry Andric 106bdd1243dSDimitry Andric llvm::Expected<std::unique_ptr<llvm::MemoryBuffer>> 107*0fca6ea1SDimitry Andric ToolChain::executeToolChainProgram(StringRef Executable, 108*0fca6ea1SDimitry Andric unsigned SecondsToWait) const { 109bdd1243dSDimitry Andric llvm::SmallString<64> OutputFile; 110bdd1243dSDimitry Andric llvm::sys::fs::createTemporaryFile("toolchain-program", "txt", OutputFile); 111bdd1243dSDimitry Andric llvm::FileRemover OutputRemover(OutputFile.c_str()); 112bdd1243dSDimitry Andric std::optional<llvm::StringRef> Redirects[] = { 113bdd1243dSDimitry Andric {""}, 114bdd1243dSDimitry Andric OutputFile.str(), 115bdd1243dSDimitry Andric {""}, 116bdd1243dSDimitry Andric }; 117bdd1243dSDimitry Andric 118bdd1243dSDimitry Andric std::string ErrorMessage; 119*0fca6ea1SDimitry Andric if (llvm::sys::ExecuteAndWait(Executable, {}, {}, Redirects, SecondsToWait, 120*0fca6ea1SDimitry Andric /*MemoryLimit=*/0, &ErrorMessage)) 121bdd1243dSDimitry Andric return llvm::createStringError(std::error_code(), 122bdd1243dSDimitry Andric Executable + ": " + ErrorMessage); 123bdd1243dSDimitry Andric 124bdd1243dSDimitry Andric llvm::ErrorOr<std::unique_ptr<llvm::MemoryBuffer>> OutputBuf = 125bdd1243dSDimitry Andric llvm::MemoryBuffer::getFile(OutputFile.c_str()); 126bdd1243dSDimitry Andric if (!OutputBuf) 127bdd1243dSDimitry Andric return llvm::createStringError(OutputBuf.getError(), 128bdd1243dSDimitry Andric "Failed to read stdout of " + Executable + 129bdd1243dSDimitry Andric ": " + OutputBuf.getError().message()); 130bdd1243dSDimitry Andric return std::move(*OutputBuf); 131bdd1243dSDimitry Andric } 132bdd1243dSDimitry Andric 1330b57cec5SDimitry Andric void ToolChain::setTripleEnvironment(llvm::Triple::EnvironmentType Env) { 1340b57cec5SDimitry Andric Triple.setEnvironment(Env); 1350b57cec5SDimitry Andric if (EffectiveTriple != llvm::Triple()) 1360b57cec5SDimitry Andric EffectiveTriple.setEnvironment(Env); 1370b57cec5SDimitry Andric } 1380b57cec5SDimitry Andric 1390b57cec5SDimitry Andric ToolChain::~ToolChain() = default; 1400b57cec5SDimitry Andric 1410b57cec5SDimitry Andric llvm::vfs::FileSystem &ToolChain::getVFS() const { 1420b57cec5SDimitry Andric return getDriver().getVFS(); 1430b57cec5SDimitry Andric } 1440b57cec5SDimitry Andric 1450b57cec5SDimitry Andric bool ToolChain::useIntegratedAs() const { 1460b57cec5SDimitry Andric return Args.hasFlag(options::OPT_fintegrated_as, 1470b57cec5SDimitry Andric options::OPT_fno_integrated_as, 1480b57cec5SDimitry Andric IsIntegratedAssemblerDefault()); 1490b57cec5SDimitry Andric } 1500b57cec5SDimitry Andric 15181ad6265SDimitry Andric bool ToolChain::useIntegratedBackend() const { 15281ad6265SDimitry Andric assert( 15381ad6265SDimitry Andric ((IsIntegratedBackendDefault() && IsIntegratedBackendSupported()) || 15481ad6265SDimitry Andric (!IsIntegratedBackendDefault() || IsNonIntegratedBackendSupported())) && 15581ad6265SDimitry Andric "(Non-)integrated backend set incorrectly!"); 15681ad6265SDimitry Andric 15781ad6265SDimitry Andric bool IBackend = Args.hasFlag(options::OPT_fintegrated_objemitter, 15881ad6265SDimitry Andric options::OPT_fno_integrated_objemitter, 15981ad6265SDimitry Andric IsIntegratedBackendDefault()); 16081ad6265SDimitry Andric 16181ad6265SDimitry Andric // Diagnose when integrated-objemitter options are not supported by this 16281ad6265SDimitry Andric // toolchain. 16381ad6265SDimitry Andric unsigned DiagID; 16481ad6265SDimitry Andric if ((IBackend && !IsIntegratedBackendSupported()) || 16581ad6265SDimitry Andric (!IBackend && !IsNonIntegratedBackendSupported())) 16681ad6265SDimitry Andric DiagID = clang::diag::err_drv_unsupported_opt_for_target; 16781ad6265SDimitry Andric else 16881ad6265SDimitry Andric DiagID = clang::diag::warn_drv_unsupported_opt_for_target; 16981ad6265SDimitry Andric Arg *A = Args.getLastArg(options::OPT_fno_integrated_objemitter); 17081ad6265SDimitry Andric if (A && !IsNonIntegratedBackendSupported()) 17181ad6265SDimitry Andric D.Diag(DiagID) << A->getAsString(Args) << Triple.getTriple(); 17281ad6265SDimitry Andric A = Args.getLastArg(options::OPT_fintegrated_objemitter); 17381ad6265SDimitry Andric if (A && !IsIntegratedBackendSupported()) 17481ad6265SDimitry Andric D.Diag(DiagID) << A->getAsString(Args) << Triple.getTriple(); 17581ad6265SDimitry Andric 17681ad6265SDimitry Andric return IBackend; 17781ad6265SDimitry Andric } 17881ad6265SDimitry Andric 1790b57cec5SDimitry Andric bool ToolChain::useRelaxRelocations() const { 1800b57cec5SDimitry Andric return ENABLE_X86_RELAX_RELOCATIONS; 1810b57cec5SDimitry Andric } 1820b57cec5SDimitry Andric 18304eeddc0SDimitry Andric bool ToolChain::defaultToIEEELongDouble() const { 18404eeddc0SDimitry Andric return PPC_LINUX_DEFAULT_IEEELONGDOUBLE && getTriple().isOSLinux(); 18504eeddc0SDimitry Andric } 18604eeddc0SDimitry Andric 18706c3fb27SDimitry Andric static void getAArch64MultilibFlags(const Driver &D, 18806c3fb27SDimitry Andric const llvm::Triple &Triple, 18906c3fb27SDimitry Andric const llvm::opt::ArgList &Args, 19006c3fb27SDimitry Andric Multilib::flags_list &Result) { 19106c3fb27SDimitry Andric std::vector<StringRef> Features; 19206c3fb27SDimitry Andric tools::aarch64::getAArch64TargetFeatures(D, Triple, Args, Features, false); 19306c3fb27SDimitry Andric const auto UnifiedFeatures = tools::unifyTargetFeatures(Features); 19406c3fb27SDimitry Andric llvm::DenseSet<StringRef> FeatureSet(UnifiedFeatures.begin(), 19506c3fb27SDimitry Andric UnifiedFeatures.end()); 19606c3fb27SDimitry Andric std::vector<std::string> MArch; 19706c3fb27SDimitry Andric for (const auto &Ext : AArch64::Extensions) 198*0fca6ea1SDimitry Andric if (!Ext.UserVisibleName.empty()) 199*0fca6ea1SDimitry Andric if (FeatureSet.contains(Ext.PosTargetFeature)) 200*0fca6ea1SDimitry Andric MArch.push_back(Ext.UserVisibleName.str()); 20106c3fb27SDimitry Andric for (const auto &Ext : AArch64::Extensions) 202*0fca6ea1SDimitry Andric if (!Ext.UserVisibleName.empty()) 203*0fca6ea1SDimitry Andric if (FeatureSet.contains(Ext.NegTargetFeature)) 204*0fca6ea1SDimitry Andric MArch.push_back(("no" + Ext.UserVisibleName).str()); 205*0fca6ea1SDimitry Andric StringRef ArchName; 206*0fca6ea1SDimitry Andric for (const auto &ArchInfo : AArch64::ArchInfos) 207*0fca6ea1SDimitry Andric if (FeatureSet.contains(ArchInfo->ArchFeature)) 208*0fca6ea1SDimitry Andric ArchName = ArchInfo->Name; 209*0fca6ea1SDimitry Andric assert(!ArchName.empty() && "at least one architecture should be found"); 210*0fca6ea1SDimitry Andric MArch.insert(MArch.begin(), ("-march=" + ArchName).str()); 21106c3fb27SDimitry Andric Result.push_back(llvm::join(MArch, "+")); 21206c3fb27SDimitry Andric } 21306c3fb27SDimitry Andric 21406c3fb27SDimitry Andric static void getARMMultilibFlags(const Driver &D, 21506c3fb27SDimitry Andric const llvm::Triple &Triple, 21606c3fb27SDimitry Andric const llvm::opt::ArgList &Args, 21706c3fb27SDimitry Andric Multilib::flags_list &Result) { 21806c3fb27SDimitry Andric std::vector<StringRef> Features; 21906c3fb27SDimitry Andric llvm::ARM::FPUKind FPUKind = tools::arm::getARMTargetFeatures( 22006c3fb27SDimitry Andric D, Triple, Args, Features, false /*ForAs*/, true /*ForMultilib*/); 22106c3fb27SDimitry Andric const auto UnifiedFeatures = tools::unifyTargetFeatures(Features); 22206c3fb27SDimitry Andric llvm::DenseSet<StringRef> FeatureSet(UnifiedFeatures.begin(), 22306c3fb27SDimitry Andric UnifiedFeatures.end()); 22406c3fb27SDimitry Andric std::vector<std::string> MArch; 22506c3fb27SDimitry Andric for (const auto &Ext : ARM::ARCHExtNames) 226*0fca6ea1SDimitry Andric if (!Ext.Name.empty()) 22706c3fb27SDimitry Andric if (FeatureSet.contains(Ext.Feature)) 22806c3fb27SDimitry Andric MArch.push_back(Ext.Name.str()); 22906c3fb27SDimitry Andric for (const auto &Ext : ARM::ARCHExtNames) 230*0fca6ea1SDimitry Andric if (!Ext.Name.empty()) 23106c3fb27SDimitry Andric if (FeatureSet.contains(Ext.NegFeature)) 23206c3fb27SDimitry Andric MArch.push_back(("no" + Ext.Name).str()); 23306c3fb27SDimitry Andric MArch.insert(MArch.begin(), ("-march=" + Triple.getArchName()).str()); 23406c3fb27SDimitry Andric Result.push_back(llvm::join(MArch, "+")); 23506c3fb27SDimitry Andric 23606c3fb27SDimitry Andric switch (FPUKind) { 23706c3fb27SDimitry Andric #define ARM_FPU(NAME, KIND, VERSION, NEON_SUPPORT, RESTRICTION) \ 23806c3fb27SDimitry Andric case llvm::ARM::KIND: \ 23906c3fb27SDimitry Andric Result.push_back("-mfpu=" NAME); \ 24006c3fb27SDimitry Andric break; 24106c3fb27SDimitry Andric #include "llvm/TargetParser/ARMTargetParser.def" 24206c3fb27SDimitry Andric default: 24306c3fb27SDimitry Andric llvm_unreachable("Invalid FPUKind"); 24406c3fb27SDimitry Andric } 24506c3fb27SDimitry Andric 24606c3fb27SDimitry Andric switch (arm::getARMFloatABI(D, Triple, Args)) { 24706c3fb27SDimitry Andric case arm::FloatABI::Soft: 24806c3fb27SDimitry Andric Result.push_back("-mfloat-abi=soft"); 24906c3fb27SDimitry Andric break; 25006c3fb27SDimitry Andric case arm::FloatABI::SoftFP: 25106c3fb27SDimitry Andric Result.push_back("-mfloat-abi=softfp"); 25206c3fb27SDimitry Andric break; 25306c3fb27SDimitry Andric case arm::FloatABI::Hard: 25406c3fb27SDimitry Andric Result.push_back("-mfloat-abi=hard"); 25506c3fb27SDimitry Andric break; 25606c3fb27SDimitry Andric case arm::FloatABI::Invalid: 25706c3fb27SDimitry Andric llvm_unreachable("Invalid float ABI"); 25806c3fb27SDimitry Andric } 25906c3fb27SDimitry Andric } 26006c3fb27SDimitry Andric 26106c3fb27SDimitry Andric Multilib::flags_list 26206c3fb27SDimitry Andric ToolChain::getMultilibFlags(const llvm::opt::ArgList &Args) const { 26306c3fb27SDimitry Andric using namespace clang::driver::options; 26406c3fb27SDimitry Andric 26506c3fb27SDimitry Andric std::vector<std::string> Result; 26606c3fb27SDimitry Andric const llvm::Triple Triple(ComputeEffectiveClangTriple(Args)); 26706c3fb27SDimitry Andric Result.push_back("--target=" + Triple.str()); 26806c3fb27SDimitry Andric 26906c3fb27SDimitry Andric switch (Triple.getArch()) { 27006c3fb27SDimitry Andric case llvm::Triple::aarch64: 27106c3fb27SDimitry Andric case llvm::Triple::aarch64_32: 27206c3fb27SDimitry Andric case llvm::Triple::aarch64_be: 27306c3fb27SDimitry Andric getAArch64MultilibFlags(D, Triple, Args, Result); 27406c3fb27SDimitry Andric break; 27506c3fb27SDimitry Andric case llvm::Triple::arm: 27606c3fb27SDimitry Andric case llvm::Triple::armeb: 27706c3fb27SDimitry Andric case llvm::Triple::thumb: 27806c3fb27SDimitry Andric case llvm::Triple::thumbeb: 27906c3fb27SDimitry Andric getARMMultilibFlags(D, Triple, Args, Result); 28006c3fb27SDimitry Andric break; 28106c3fb27SDimitry Andric default: 28206c3fb27SDimitry Andric break; 28306c3fb27SDimitry Andric } 28406c3fb27SDimitry Andric 285*0fca6ea1SDimitry Andric // Include fno-exceptions and fno-rtti 286*0fca6ea1SDimitry Andric // to improve multilib selection 287*0fca6ea1SDimitry Andric if (getRTTIMode() == ToolChain::RTTIMode::RM_Disabled) 288*0fca6ea1SDimitry Andric Result.push_back("-fno-rtti"); 289*0fca6ea1SDimitry Andric else 290*0fca6ea1SDimitry Andric Result.push_back("-frtti"); 291*0fca6ea1SDimitry Andric 292*0fca6ea1SDimitry Andric if (getExceptionsMode() == ToolChain::ExceptionsMode::EM_Disabled) 293*0fca6ea1SDimitry Andric Result.push_back("-fno-exceptions"); 294*0fca6ea1SDimitry Andric else 295*0fca6ea1SDimitry Andric Result.push_back("-fexceptions"); 296*0fca6ea1SDimitry Andric 29706c3fb27SDimitry Andric // Sort and remove duplicates. 29806c3fb27SDimitry Andric std::sort(Result.begin(), Result.end()); 29906c3fb27SDimitry Andric Result.erase(std::unique(Result.begin(), Result.end()), Result.end()); 30006c3fb27SDimitry Andric return Result; 30106c3fb27SDimitry Andric } 30206c3fb27SDimitry Andric 303349cc55cSDimitry Andric SanitizerArgs 304349cc55cSDimitry Andric ToolChain::getSanitizerArgs(const llvm::opt::ArgList &JobArgs) const { 305349cc55cSDimitry Andric SanitizerArgs SanArgs(*this, JobArgs, !SanitizerArgsChecked); 306349cc55cSDimitry Andric SanitizerArgsChecked = true; 307349cc55cSDimitry Andric return SanArgs; 3080b57cec5SDimitry Andric } 3090b57cec5SDimitry Andric 3100b57cec5SDimitry Andric const XRayArgs& ToolChain::getXRayArgs() const { 311bdd1243dSDimitry Andric if (!XRayArguments) 3120b57cec5SDimitry Andric XRayArguments.reset(new XRayArgs(*this, Args)); 313bdd1243dSDimitry Andric return *XRayArguments; 3140b57cec5SDimitry Andric } 3150b57cec5SDimitry Andric 3160b57cec5SDimitry Andric namespace { 3170b57cec5SDimitry Andric 3180b57cec5SDimitry Andric struct DriverSuffix { 3190b57cec5SDimitry Andric const char *Suffix; 3200b57cec5SDimitry Andric const char *ModeFlag; 3210b57cec5SDimitry Andric }; 3220b57cec5SDimitry Andric 3230b57cec5SDimitry Andric } // namespace 3240b57cec5SDimitry Andric 3250b57cec5SDimitry Andric static const DriverSuffix *FindDriverSuffix(StringRef ProgName, size_t &Pos) { 3260b57cec5SDimitry Andric // A list of known driver suffixes. Suffixes are compared against the 3270b57cec5SDimitry Andric // program name in order. If there is a match, the frontend type is updated as 3280b57cec5SDimitry Andric // necessary by applying the ModeFlag. 3290b57cec5SDimitry Andric static const DriverSuffix DriverSuffixes[] = { 3300b57cec5SDimitry Andric {"clang", nullptr}, 3310b57cec5SDimitry Andric {"clang++", "--driver-mode=g++"}, 3320b57cec5SDimitry Andric {"clang-c++", "--driver-mode=g++"}, 3330b57cec5SDimitry Andric {"clang-cc", nullptr}, 3340b57cec5SDimitry Andric {"clang-cpp", "--driver-mode=cpp"}, 3350b57cec5SDimitry Andric {"clang-g++", "--driver-mode=g++"}, 3360b57cec5SDimitry Andric {"clang-gcc", nullptr}, 3370b57cec5SDimitry Andric {"clang-cl", "--driver-mode=cl"}, 3380b57cec5SDimitry Andric {"cc", nullptr}, 3390b57cec5SDimitry Andric {"cpp", "--driver-mode=cpp"}, 3400b57cec5SDimitry Andric {"cl", "--driver-mode=cl"}, 3410b57cec5SDimitry Andric {"++", "--driver-mode=g++"}, 342480093f4SDimitry Andric {"flang", "--driver-mode=flang"}, 34381ad6265SDimitry Andric {"clang-dxc", "--driver-mode=dxc"}, 3440b57cec5SDimitry Andric }; 3450b57cec5SDimitry Andric 346bdd1243dSDimitry Andric for (const auto &DS : DriverSuffixes) { 347bdd1243dSDimitry Andric StringRef Suffix(DS.Suffix); 3485f757f3fSDimitry Andric if (ProgName.ends_with(Suffix)) { 3490b57cec5SDimitry Andric Pos = ProgName.size() - Suffix.size(); 350bdd1243dSDimitry Andric return &DS; 3510b57cec5SDimitry Andric } 3520b57cec5SDimitry Andric } 3530b57cec5SDimitry Andric return nullptr; 3540b57cec5SDimitry Andric } 3550b57cec5SDimitry Andric 3560b57cec5SDimitry Andric /// Normalize the program name from argv[0] by stripping the file extension if 3570b57cec5SDimitry Andric /// present and lower-casing the string on Windows. 3580b57cec5SDimitry Andric static std::string normalizeProgramName(llvm::StringRef Argv0) { 359bdd1243dSDimitry Andric std::string ProgName = std::string(llvm::sys::path::filename(Argv0)); 360349cc55cSDimitry Andric if (is_style_windows(llvm::sys::path::Style::native)) { 3610b57cec5SDimitry Andric // Transform to lowercase for case insensitive file systems. 362349cc55cSDimitry Andric std::transform(ProgName.begin(), ProgName.end(), ProgName.begin(), 363349cc55cSDimitry Andric ::tolower); 364349cc55cSDimitry Andric } 3650b57cec5SDimitry Andric return ProgName; 3660b57cec5SDimitry Andric } 3670b57cec5SDimitry Andric 3680b57cec5SDimitry Andric static const DriverSuffix *parseDriverSuffix(StringRef ProgName, size_t &Pos) { 3690b57cec5SDimitry Andric // Try to infer frontend type and default target from the program name by 3700b57cec5SDimitry Andric // comparing it against DriverSuffixes in order. 3710b57cec5SDimitry Andric 3720b57cec5SDimitry Andric // If there is a match, the function tries to identify a target as prefix. 3730b57cec5SDimitry Andric // E.g. "x86_64-linux-clang" as interpreted as suffix "clang" with target 3740b57cec5SDimitry Andric // prefix "x86_64-linux". If such a target prefix is found, it may be 3750b57cec5SDimitry Andric // added via -target as implicit first argument. 3760b57cec5SDimitry Andric const DriverSuffix *DS = FindDriverSuffix(ProgName, Pos); 3770b57cec5SDimitry Andric 3785f757f3fSDimitry Andric if (!DS && ProgName.ends_with(".exe")) { 379bdd1243dSDimitry Andric // Try again after stripping the executable suffix: 380bdd1243dSDimitry Andric // clang++.exe -> clang++ 381bdd1243dSDimitry Andric ProgName = ProgName.drop_back(StringRef(".exe").size()); 382bdd1243dSDimitry Andric DS = FindDriverSuffix(ProgName, Pos); 383bdd1243dSDimitry Andric } 384bdd1243dSDimitry Andric 3850b57cec5SDimitry Andric if (!DS) { 3860b57cec5SDimitry Andric // Try again after stripping any trailing version number: 3870b57cec5SDimitry Andric // clang++3.5 -> clang++ 3880b57cec5SDimitry Andric ProgName = ProgName.rtrim("0123456789."); 3890b57cec5SDimitry Andric DS = FindDriverSuffix(ProgName, Pos); 3900b57cec5SDimitry Andric } 3910b57cec5SDimitry Andric 3920b57cec5SDimitry Andric if (!DS) { 3930b57cec5SDimitry Andric // Try again after stripping trailing -component. 3940b57cec5SDimitry Andric // clang++-tot -> clang++ 3950b57cec5SDimitry Andric ProgName = ProgName.slice(0, ProgName.rfind('-')); 3960b57cec5SDimitry Andric DS = FindDriverSuffix(ProgName, Pos); 3970b57cec5SDimitry Andric } 3980b57cec5SDimitry Andric return DS; 3990b57cec5SDimitry Andric } 4000b57cec5SDimitry Andric 4010b57cec5SDimitry Andric ParsedClangName 4020b57cec5SDimitry Andric ToolChain::getTargetAndModeFromProgramName(StringRef PN) { 4030b57cec5SDimitry Andric std::string ProgName = normalizeProgramName(PN); 4040b57cec5SDimitry Andric size_t SuffixPos; 4050b57cec5SDimitry Andric const DriverSuffix *DS = parseDriverSuffix(ProgName, SuffixPos); 4060b57cec5SDimitry Andric if (!DS) 4070b57cec5SDimitry Andric return {}; 4080b57cec5SDimitry Andric size_t SuffixEnd = SuffixPos + strlen(DS->Suffix); 4090b57cec5SDimitry Andric 4100b57cec5SDimitry Andric size_t LastComponent = ProgName.rfind('-', SuffixPos); 4110b57cec5SDimitry Andric if (LastComponent == std::string::npos) 4120b57cec5SDimitry Andric return ParsedClangName(ProgName.substr(0, SuffixEnd), DS->ModeFlag); 4130b57cec5SDimitry Andric std::string ModeSuffix = ProgName.substr(LastComponent + 1, 4140b57cec5SDimitry Andric SuffixEnd - LastComponent - 1); 4150b57cec5SDimitry Andric 4160b57cec5SDimitry Andric // Infer target from the prefix. 4170b57cec5SDimitry Andric StringRef Prefix(ProgName); 4180b57cec5SDimitry Andric Prefix = Prefix.slice(0, LastComponent); 4190b57cec5SDimitry Andric std::string IgnoredError; 4205ffd83dbSDimitry Andric bool IsRegistered = 4215ffd83dbSDimitry Andric llvm::TargetRegistry::lookupTarget(std::string(Prefix), IgnoredError); 4225ffd83dbSDimitry Andric return ParsedClangName{std::string(Prefix), ModeSuffix, DS->ModeFlag, 4235ffd83dbSDimitry Andric IsRegistered}; 4240b57cec5SDimitry Andric } 4250b57cec5SDimitry Andric 4260b57cec5SDimitry Andric StringRef ToolChain::getDefaultUniversalArchName() const { 4270b57cec5SDimitry Andric // In universal driver terms, the arch name accepted by -arch isn't exactly 4280b57cec5SDimitry Andric // the same as the ones that appear in the triple. Roughly speaking, this is 4295ffd83dbSDimitry Andric // an inverse of the darwin::getArchTypeForDarwinArchName() function. 4300b57cec5SDimitry Andric switch (Triple.getArch()) { 431e8d8bef9SDimitry Andric case llvm::Triple::aarch64: { 432e8d8bef9SDimitry Andric if (getTriple().isArm64e()) 433e8d8bef9SDimitry Andric return "arm64e"; 4345ffd83dbSDimitry Andric return "arm64"; 435e8d8bef9SDimitry Andric } 4365ffd83dbSDimitry Andric case llvm::Triple::aarch64_32: 4375ffd83dbSDimitry Andric return "arm64_32"; 4380b57cec5SDimitry Andric case llvm::Triple::ppc: 4390b57cec5SDimitry Andric return "ppc"; 440e8d8bef9SDimitry Andric case llvm::Triple::ppcle: 441e8d8bef9SDimitry Andric return "ppcle"; 4420b57cec5SDimitry Andric case llvm::Triple::ppc64: 4430b57cec5SDimitry Andric return "ppc64"; 4440b57cec5SDimitry Andric case llvm::Triple::ppc64le: 4450b57cec5SDimitry Andric return "ppc64le"; 4460b57cec5SDimitry Andric default: 4470b57cec5SDimitry Andric return Triple.getArchName(); 4480b57cec5SDimitry Andric } 4490b57cec5SDimitry Andric } 4500b57cec5SDimitry Andric 4510b57cec5SDimitry Andric std::string ToolChain::getInputFilename(const InputInfo &Input) const { 4520b57cec5SDimitry Andric return Input.getFilename(); 4530b57cec5SDimitry Andric } 4540b57cec5SDimitry Andric 455bdd1243dSDimitry Andric ToolChain::UnwindTableLevel 456bdd1243dSDimitry Andric ToolChain::getDefaultUnwindTableLevel(const ArgList &Args) const { 457bdd1243dSDimitry Andric return UnwindTableLevel::None; 4580b57cec5SDimitry Andric } 4590b57cec5SDimitry Andric 4600b57cec5SDimitry Andric Tool *ToolChain::getClang() const { 4610b57cec5SDimitry Andric if (!Clang) 4620eae32dcSDimitry Andric Clang.reset(new tools::Clang(*this, useIntegratedBackend())); 4630b57cec5SDimitry Andric return Clang.get(); 4640b57cec5SDimitry Andric } 4650b57cec5SDimitry Andric 466480093f4SDimitry Andric Tool *ToolChain::getFlang() const { 467480093f4SDimitry Andric if (!Flang) 468480093f4SDimitry Andric Flang.reset(new tools::Flang(*this)); 469480093f4SDimitry Andric return Flang.get(); 470480093f4SDimitry Andric } 471480093f4SDimitry Andric 4720b57cec5SDimitry Andric Tool *ToolChain::buildAssembler() const { 4730b57cec5SDimitry Andric return new tools::ClangAs(*this); 4740b57cec5SDimitry Andric } 4750b57cec5SDimitry Andric 4760b57cec5SDimitry Andric Tool *ToolChain::buildLinker() const { 4770b57cec5SDimitry Andric llvm_unreachable("Linking is not supported by this toolchain"); 4780b57cec5SDimitry Andric } 4790b57cec5SDimitry Andric 4805ffd83dbSDimitry Andric Tool *ToolChain::buildStaticLibTool() const { 4815ffd83dbSDimitry Andric llvm_unreachable("Creating static lib is not supported by this toolchain"); 4825ffd83dbSDimitry Andric } 4835ffd83dbSDimitry Andric 4840b57cec5SDimitry Andric Tool *ToolChain::getAssemble() const { 4850b57cec5SDimitry Andric if (!Assemble) 4860b57cec5SDimitry Andric Assemble.reset(buildAssembler()); 4870b57cec5SDimitry Andric return Assemble.get(); 4880b57cec5SDimitry Andric } 4890b57cec5SDimitry Andric 4900b57cec5SDimitry Andric Tool *ToolChain::getClangAs() const { 4910b57cec5SDimitry Andric if (!Assemble) 4920b57cec5SDimitry Andric Assemble.reset(new tools::ClangAs(*this)); 4930b57cec5SDimitry Andric return Assemble.get(); 4940b57cec5SDimitry Andric } 4950b57cec5SDimitry Andric 4960b57cec5SDimitry Andric Tool *ToolChain::getLink() const { 4970b57cec5SDimitry Andric if (!Link) 4980b57cec5SDimitry Andric Link.reset(buildLinker()); 4990b57cec5SDimitry Andric return Link.get(); 5000b57cec5SDimitry Andric } 5010b57cec5SDimitry Andric 5025ffd83dbSDimitry Andric Tool *ToolChain::getStaticLibTool() const { 5035ffd83dbSDimitry Andric if (!StaticLibTool) 5045ffd83dbSDimitry Andric StaticLibTool.reset(buildStaticLibTool()); 5055ffd83dbSDimitry Andric return StaticLibTool.get(); 5065ffd83dbSDimitry Andric } 5075ffd83dbSDimitry Andric 508a7dea167SDimitry Andric Tool *ToolChain::getIfsMerge() const { 509a7dea167SDimitry Andric if (!IfsMerge) 510a7dea167SDimitry Andric IfsMerge.reset(new tools::ifstool::Merger(*this)); 511a7dea167SDimitry Andric return IfsMerge.get(); 512a7dea167SDimitry Andric } 513a7dea167SDimitry Andric 5140b57cec5SDimitry Andric Tool *ToolChain::getOffloadBundler() const { 5150b57cec5SDimitry Andric if (!OffloadBundler) 5160b57cec5SDimitry Andric OffloadBundler.reset(new tools::OffloadBundler(*this)); 5170b57cec5SDimitry Andric return OffloadBundler.get(); 5180b57cec5SDimitry Andric } 5190b57cec5SDimitry Andric 52081ad6265SDimitry Andric Tool *ToolChain::getOffloadPackager() const { 52181ad6265SDimitry Andric if (!OffloadPackager) 52281ad6265SDimitry Andric OffloadPackager.reset(new tools::OffloadPackager(*this)); 52381ad6265SDimitry Andric return OffloadPackager.get(); 52481ad6265SDimitry Andric } 52581ad6265SDimitry Andric 5261fd87a68SDimitry Andric Tool *ToolChain::getLinkerWrapper() const { 5271fd87a68SDimitry Andric if (!LinkerWrapper) 5281fd87a68SDimitry Andric LinkerWrapper.reset(new tools::LinkerWrapper(*this, getLink())); 5291fd87a68SDimitry Andric return LinkerWrapper.get(); 5301fd87a68SDimitry Andric } 5311fd87a68SDimitry Andric 5320b57cec5SDimitry Andric Tool *ToolChain::getTool(Action::ActionClass AC) const { 5330b57cec5SDimitry Andric switch (AC) { 5340b57cec5SDimitry Andric case Action::AssembleJobClass: 5350b57cec5SDimitry Andric return getAssemble(); 5360b57cec5SDimitry Andric 537a7dea167SDimitry Andric case Action::IfsMergeJobClass: 538a7dea167SDimitry Andric return getIfsMerge(); 539a7dea167SDimitry Andric 5400b57cec5SDimitry Andric case Action::LinkJobClass: 5410b57cec5SDimitry Andric return getLink(); 5420b57cec5SDimitry Andric 5435ffd83dbSDimitry Andric case Action::StaticLibJobClass: 5445ffd83dbSDimitry Andric return getStaticLibTool(); 5455ffd83dbSDimitry Andric 5460b57cec5SDimitry Andric case Action::InputClass: 5470b57cec5SDimitry Andric case Action::BindArchClass: 5480b57cec5SDimitry Andric case Action::OffloadClass: 5490b57cec5SDimitry Andric case Action::LipoJobClass: 5500b57cec5SDimitry Andric case Action::DsymutilJobClass: 5510b57cec5SDimitry Andric case Action::VerifyDebugInfoJobClass: 55206c3fb27SDimitry Andric case Action::BinaryAnalyzeJobClass: 5530b57cec5SDimitry Andric llvm_unreachable("Invalid tool kind."); 5540b57cec5SDimitry Andric 5550b57cec5SDimitry Andric case Action::CompileJobClass: 5560b57cec5SDimitry Andric case Action::PrecompileJobClass: 5570b57cec5SDimitry Andric case Action::PreprocessJobClass: 55881ad6265SDimitry Andric case Action::ExtractAPIJobClass: 5590b57cec5SDimitry Andric case Action::AnalyzeJobClass: 5600b57cec5SDimitry Andric case Action::MigrateJobClass: 5610b57cec5SDimitry Andric case Action::VerifyPCHJobClass: 5620b57cec5SDimitry Andric case Action::BackendJobClass: 5630b57cec5SDimitry Andric return getClang(); 5640b57cec5SDimitry Andric 5650b57cec5SDimitry Andric case Action::OffloadBundlingJobClass: 5660b57cec5SDimitry Andric case Action::OffloadUnbundlingJobClass: 5670b57cec5SDimitry Andric return getOffloadBundler(); 568a7dea167SDimitry Andric 56981ad6265SDimitry Andric case Action::OffloadPackagerJobClass: 57081ad6265SDimitry Andric return getOffloadPackager(); 5711fd87a68SDimitry Andric case Action::LinkerWrapperJobClass: 5721fd87a68SDimitry Andric return getLinkerWrapper(); 5730b57cec5SDimitry Andric } 5740b57cec5SDimitry Andric 5750b57cec5SDimitry Andric llvm_unreachable("Invalid tool kind."); 5760b57cec5SDimitry Andric } 5770b57cec5SDimitry Andric 5780b57cec5SDimitry Andric static StringRef getArchNameForCompilerRTLib(const ToolChain &TC, 5790b57cec5SDimitry Andric const ArgList &Args) { 5800b57cec5SDimitry Andric const llvm::Triple &Triple = TC.getTriple(); 5810b57cec5SDimitry Andric bool IsWindows = Triple.isOSWindows(); 5820b57cec5SDimitry Andric 583bdd1243dSDimitry Andric if (TC.isBareMetal()) 584bdd1243dSDimitry Andric return Triple.getArchName(); 585bdd1243dSDimitry Andric 5860b57cec5SDimitry Andric if (TC.getArch() == llvm::Triple::arm || TC.getArch() == llvm::Triple::armeb) 5870b57cec5SDimitry Andric return (arm::getARMFloatABI(TC, Args) == arm::FloatABI::Hard && !IsWindows) 5880b57cec5SDimitry Andric ? "armhf" 5890b57cec5SDimitry Andric : "arm"; 5900b57cec5SDimitry Andric 5910b57cec5SDimitry Andric // For historic reasons, Android library is using i686 instead of i386. 5920b57cec5SDimitry Andric if (TC.getArch() == llvm::Triple::x86 && Triple.isAndroid()) 5930b57cec5SDimitry Andric return "i686"; 5940b57cec5SDimitry Andric 595fe6060f1SDimitry Andric if (TC.getArch() == llvm::Triple::x86_64 && Triple.isX32()) 596fe6060f1SDimitry Andric return "x32"; 597fe6060f1SDimitry Andric 5980b57cec5SDimitry Andric return llvm::Triple::getArchTypeName(TC.getArch()); 5990b57cec5SDimitry Andric } 6000b57cec5SDimitry Andric 6010b57cec5SDimitry Andric StringRef ToolChain::getOSLibName() const { 602fe6060f1SDimitry Andric if (Triple.isOSDarwin()) 603fe6060f1SDimitry Andric return "darwin"; 604fe6060f1SDimitry Andric 6050b57cec5SDimitry Andric switch (Triple.getOS()) { 6060b57cec5SDimitry Andric case llvm::Triple::FreeBSD: 6070b57cec5SDimitry Andric return "freebsd"; 6080b57cec5SDimitry Andric case llvm::Triple::NetBSD: 6090b57cec5SDimitry Andric return "netbsd"; 6100b57cec5SDimitry Andric case llvm::Triple::OpenBSD: 6110b57cec5SDimitry Andric return "openbsd"; 6120b57cec5SDimitry Andric case llvm::Triple::Solaris: 6130b57cec5SDimitry Andric return "sunos"; 614e8d8bef9SDimitry Andric case llvm::Triple::AIX: 615e8d8bef9SDimitry Andric return "aix"; 6160b57cec5SDimitry Andric default: 6170b57cec5SDimitry Andric return getOS(); 6180b57cec5SDimitry Andric } 6190b57cec5SDimitry Andric } 6200b57cec5SDimitry Andric 6210b57cec5SDimitry Andric std::string ToolChain::getCompilerRTPath() const { 6220b57cec5SDimitry Andric SmallString<128> Path(getDriver().ResourceDir); 623bdd1243dSDimitry Andric if (isBareMetal()) { 624bdd1243dSDimitry Andric llvm::sys::path::append(Path, "lib", getOSLibName()); 62506c3fb27SDimitry Andric if (!SelectedMultilibs.empty()) { 62606c3fb27SDimitry Andric Path += SelectedMultilibs.back().gccSuffix(); 62706c3fb27SDimitry Andric } 628bdd1243dSDimitry Andric } else if (Triple.isOSUnknown()) { 6290b57cec5SDimitry Andric llvm::sys::path::append(Path, "lib"); 6300b57cec5SDimitry Andric } else { 6310b57cec5SDimitry Andric llvm::sys::path::append(Path, "lib", getOSLibName()); 6320b57cec5SDimitry Andric } 6337a6dacacSDimitry Andric return std::string(Path); 6340b57cec5SDimitry Andric } 6350b57cec5SDimitry Andric 6365ffd83dbSDimitry Andric std::string ToolChain::getCompilerRTBasename(const ArgList &Args, 637fe6060f1SDimitry Andric StringRef Component, 638fe6060f1SDimitry Andric FileType Type) const { 639fe6060f1SDimitry Andric std::string CRTAbsolutePath = getCompilerRT(Args, Component, Type); 640fe6060f1SDimitry Andric return llvm::sys::path::filename(CRTAbsolutePath).str(); 641fe6060f1SDimitry Andric } 642fe6060f1SDimitry Andric 643fe6060f1SDimitry Andric std::string ToolChain::buildCompilerRTBasename(const llvm::opt::ArgList &Args, 644fe6060f1SDimitry Andric StringRef Component, 645fe6060f1SDimitry Andric FileType Type, 6465ffd83dbSDimitry Andric bool AddArch) const { 6470b57cec5SDimitry Andric const llvm::Triple &TT = getTriple(); 6480b57cec5SDimitry Andric bool IsITANMSVCWindows = 6490b57cec5SDimitry Andric TT.isWindowsMSVCEnvironment() || TT.isWindowsItaniumEnvironment(); 6500b57cec5SDimitry Andric 6510b57cec5SDimitry Andric const char *Prefix = 6520b57cec5SDimitry Andric IsITANMSVCWindows || Type == ToolChain::FT_Object ? "" : "lib"; 6530b57cec5SDimitry Andric const char *Suffix; 6540b57cec5SDimitry Andric switch (Type) { 6550b57cec5SDimitry Andric case ToolChain::FT_Object: 6560b57cec5SDimitry Andric Suffix = IsITANMSVCWindows ? ".obj" : ".o"; 6570b57cec5SDimitry Andric break; 6580b57cec5SDimitry Andric case ToolChain::FT_Static: 6590b57cec5SDimitry Andric Suffix = IsITANMSVCWindows ? ".lib" : ".a"; 6600b57cec5SDimitry Andric break; 6610b57cec5SDimitry Andric case ToolChain::FT_Shared: 662fe6060f1SDimitry Andric Suffix = TT.isOSWindows() 663fe6060f1SDimitry Andric ? (TT.isWindowsGNUEnvironment() ? ".dll.a" : ".lib") 6640b57cec5SDimitry Andric : ".so"; 6650b57cec5SDimitry Andric break; 6660b57cec5SDimitry Andric } 6670b57cec5SDimitry Andric 6685ffd83dbSDimitry Andric std::string ArchAndEnv; 6695ffd83dbSDimitry Andric if (AddArch) { 6700b57cec5SDimitry Andric StringRef Arch = getArchNameForCompilerRTLib(*this, Args); 6710b57cec5SDimitry Andric const char *Env = TT.isAndroid() ? "-android" : ""; 6725ffd83dbSDimitry Andric ArchAndEnv = ("-" + Arch + Env).str(); 6735ffd83dbSDimitry Andric } 6745ffd83dbSDimitry Andric return (Prefix + Twine("clang_rt.") + Component + ArchAndEnv + Suffix).str(); 6755ffd83dbSDimitry Andric } 6765ffd83dbSDimitry Andric 6775ffd83dbSDimitry Andric std::string ToolChain::getCompilerRT(const ArgList &Args, StringRef Component, 6785ffd83dbSDimitry Andric FileType Type) const { 6795ffd83dbSDimitry Andric // Check for runtime files in the new layout without the architecture first. 6805ffd83dbSDimitry Andric std::string CRTBasename = 681fe6060f1SDimitry Andric buildCompilerRTBasename(Args, Component, Type, /*AddArch=*/false); 682*0fca6ea1SDimitry Andric SmallString<128> Path; 6835ffd83dbSDimitry Andric for (const auto &LibPath : getLibraryPaths()) { 6845ffd83dbSDimitry Andric SmallString<128> P(LibPath); 6855ffd83dbSDimitry Andric llvm::sys::path::append(P, CRTBasename); 6865ffd83dbSDimitry Andric if (getVFS().exists(P)) 6877a6dacacSDimitry Andric return std::string(P); 688*0fca6ea1SDimitry Andric if (Path.empty()) 689*0fca6ea1SDimitry Andric Path = P; 6905ffd83dbSDimitry Andric } 691*0fca6ea1SDimitry Andric if (getTriple().isOSAIX()) 692*0fca6ea1SDimitry Andric Path.clear(); 6935ffd83dbSDimitry Andric 694*0fca6ea1SDimitry Andric // Check the filename for the old layout if the new one does not exist. 695fe6060f1SDimitry Andric CRTBasename = 696fe6060f1SDimitry Andric buildCompilerRTBasename(Args, Component, Type, /*AddArch=*/true); 697*0fca6ea1SDimitry Andric SmallString<128> OldPath(getCompilerRTPath()); 698*0fca6ea1SDimitry Andric llvm::sys::path::append(OldPath, CRTBasename); 699*0fca6ea1SDimitry Andric if (Path.empty() || getVFS().exists(OldPath)) 700*0fca6ea1SDimitry Andric return std::string(OldPath); 701*0fca6ea1SDimitry Andric 702*0fca6ea1SDimitry Andric // If none is found, use a file name from the new layout, which may get 703*0fca6ea1SDimitry Andric // printed in an error message, aiding users in knowing what Clang is 704*0fca6ea1SDimitry Andric // looking for. 7057a6dacacSDimitry Andric return std::string(Path); 7060b57cec5SDimitry Andric } 7070b57cec5SDimitry Andric 7080b57cec5SDimitry Andric const char *ToolChain::getCompilerRTArgString(const llvm::opt::ArgList &Args, 7090b57cec5SDimitry Andric StringRef Component, 7100b57cec5SDimitry Andric FileType Type) const { 7110b57cec5SDimitry Andric return Args.MakeArgString(getCompilerRT(Args, Component, Type)); 7120b57cec5SDimitry Andric } 7130b57cec5SDimitry Andric 7145f757f3fSDimitry Andric // Android target triples contain a target version. If we don't have libraries 7155f757f3fSDimitry Andric // for the exact target version, we should fall back to the next newest version 7165f757f3fSDimitry Andric // or a versionless path, if any. 7175f757f3fSDimitry Andric std::optional<std::string> 7185f757f3fSDimitry Andric ToolChain::getFallbackAndroidTargetPath(StringRef BaseDir) const { 7195f757f3fSDimitry Andric llvm::Triple TripleWithoutLevel(getTriple()); 7205f757f3fSDimitry Andric TripleWithoutLevel.setEnvironmentName("android"); // remove any version number 7215f757f3fSDimitry Andric const std::string &TripleWithoutLevelStr = TripleWithoutLevel.str(); 7225f757f3fSDimitry Andric unsigned TripleVersion = getTriple().getEnvironmentVersion().getMajor(); 7235f757f3fSDimitry Andric unsigned BestVersion = 0; 7245f757f3fSDimitry Andric 7255f757f3fSDimitry Andric SmallString<32> TripleDir; 7265f757f3fSDimitry Andric bool UsingUnversionedDir = false; 7275f757f3fSDimitry Andric std::error_code EC; 7285f757f3fSDimitry Andric for (llvm::vfs::directory_iterator LI = getVFS().dir_begin(BaseDir, EC), LE; 7295f757f3fSDimitry Andric !EC && LI != LE; LI = LI.increment(EC)) { 7305f757f3fSDimitry Andric StringRef DirName = llvm::sys::path::filename(LI->path()); 7315f757f3fSDimitry Andric StringRef DirNameSuffix = DirName; 7325f757f3fSDimitry Andric if (DirNameSuffix.consume_front(TripleWithoutLevelStr)) { 7335f757f3fSDimitry Andric if (DirNameSuffix.empty() && TripleDir.empty()) { 7345f757f3fSDimitry Andric TripleDir = DirName; 7355f757f3fSDimitry Andric UsingUnversionedDir = true; 7365f757f3fSDimitry Andric } else { 7375f757f3fSDimitry Andric unsigned Version; 7385f757f3fSDimitry Andric if (!DirNameSuffix.getAsInteger(10, Version) && Version > BestVersion && 7395f757f3fSDimitry Andric Version < TripleVersion) { 7405f757f3fSDimitry Andric BestVersion = Version; 7415f757f3fSDimitry Andric TripleDir = DirName; 7425f757f3fSDimitry Andric UsingUnversionedDir = false; 7435f757f3fSDimitry Andric } 7445f757f3fSDimitry Andric } 7455f757f3fSDimitry Andric } 7465f757f3fSDimitry Andric } 7475f757f3fSDimitry Andric 7485f757f3fSDimitry Andric if (TripleDir.empty()) 7495f757f3fSDimitry Andric return {}; 7505f757f3fSDimitry Andric 7515f757f3fSDimitry Andric SmallString<128> P(BaseDir); 7525f757f3fSDimitry Andric llvm::sys::path::append(P, TripleDir); 7535f757f3fSDimitry Andric if (UsingUnversionedDir) 7545f757f3fSDimitry Andric D.Diag(diag::warn_android_unversioned_fallback) << P << getTripleString(); 7555f757f3fSDimitry Andric return std::string(P); 7565f757f3fSDimitry Andric } 7575f757f3fSDimitry Andric 7585f757f3fSDimitry Andric std::optional<std::string> 7595f757f3fSDimitry Andric ToolChain::getTargetSubDirPath(StringRef BaseDir) const { 7605f757f3fSDimitry Andric auto getPathForTriple = 7615f757f3fSDimitry Andric [&](const llvm::Triple &Triple) -> std::optional<std::string> { 7625f757f3fSDimitry Andric SmallString<128> P(BaseDir); 7635f757f3fSDimitry Andric llvm::sys::path::append(P, Triple.str()); 7645f757f3fSDimitry Andric if (getVFS().exists(P)) 7655f757f3fSDimitry Andric return std::string(P); 7665f757f3fSDimitry Andric return {}; 76704eeddc0SDimitry Andric }; 76804eeddc0SDimitry Andric 7695f757f3fSDimitry Andric if (auto Path = getPathForTriple(getTriple())) 7705f757f3fSDimitry Andric return *Path; 77104eeddc0SDimitry Andric 77206c3fb27SDimitry Andric // When building with per target runtime directories, various ways of naming 77306c3fb27SDimitry Andric // the Arm architecture may have been normalised to simply "arm". 77406c3fb27SDimitry Andric // For example "armv8l" (Armv8 AArch32 little endian) is replaced with "arm". 77506c3fb27SDimitry Andric // Since an armv8l system can use libraries built for earlier architecture 77606c3fb27SDimitry Andric // versions assuming endian and float ABI match. 77706c3fb27SDimitry Andric // 77806c3fb27SDimitry Andric // Original triple: armv8l-unknown-linux-gnueabihf 77906c3fb27SDimitry Andric // Runtime triple: arm-unknown-linux-gnueabihf 78006c3fb27SDimitry Andric // 78106c3fb27SDimitry Andric // We do not do this for armeb (big endian) because doing so could make us 78206c3fb27SDimitry Andric // select little endian libraries. In addition, all known armeb triples only 78306c3fb27SDimitry Andric // use the "armeb" architecture name. 78406c3fb27SDimitry Andric // 78506c3fb27SDimitry Andric // M profile Arm is bare metal and we know they will not be using the per 78606c3fb27SDimitry Andric // target runtime directory layout. 78706c3fb27SDimitry Andric if (getTriple().getArch() == Triple::arm && !getTriple().isArmMClass()) { 78806c3fb27SDimitry Andric llvm::Triple ArmTriple = getTriple(); 78906c3fb27SDimitry Andric ArmTriple.setArch(Triple::arm); 7905f757f3fSDimitry Andric if (auto Path = getPathForTriple(ArmTriple)) 7915f757f3fSDimitry Andric return *Path; 79206c3fb27SDimitry Andric } 79306c3fb27SDimitry Andric 7945f757f3fSDimitry Andric if (getTriple().isAndroid()) 7955f757f3fSDimitry Andric return getFallbackAndroidTargetPath(BaseDir); 7965f757f3fSDimitry Andric 7975f757f3fSDimitry Andric return {}; 7980b57cec5SDimitry Andric } 7990b57cec5SDimitry Andric 8005f757f3fSDimitry Andric std::optional<std::string> ToolChain::getRuntimePath() const { 8015f757f3fSDimitry Andric SmallString<128> P(D.ResourceDir); 8025f757f3fSDimitry Andric llvm::sys::path::append(P, "lib"); 803*0fca6ea1SDimitry Andric if (auto Ret = getTargetSubDirPath(P)) 804*0fca6ea1SDimitry Andric return Ret; 805*0fca6ea1SDimitry Andric // Darwin does not use per-target runtime directory. 806*0fca6ea1SDimitry Andric if (Triple.isOSDarwin()) 807*0fca6ea1SDimitry Andric return {}; 808*0fca6ea1SDimitry Andric llvm::sys::path::append(P, Triple.str()); 809*0fca6ea1SDimitry Andric return std::string(P); 81004eeddc0SDimitry Andric } 81104eeddc0SDimitry Andric 8125f757f3fSDimitry Andric std::optional<std::string> ToolChain::getStdlibPath() const { 813fe6060f1SDimitry Andric SmallString<128> P(D.Dir); 8145f757f3fSDimitry Andric llvm::sys::path::append(P, "..", "lib"); 8155f757f3fSDimitry Andric return getTargetSubDirPath(P); 8160b57cec5SDimitry Andric } 8170b57cec5SDimitry Andric 818*0fca6ea1SDimitry Andric std::optional<std::string> ToolChain::getStdlibIncludePath() const { 819*0fca6ea1SDimitry Andric SmallString<128> P(D.Dir); 820*0fca6ea1SDimitry Andric llvm::sys::path::append(P, "..", "include"); 821*0fca6ea1SDimitry Andric return getTargetSubDirPath(P); 822*0fca6ea1SDimitry Andric } 823*0fca6ea1SDimitry Andric 82406c3fb27SDimitry Andric ToolChain::path_list ToolChain::getArchSpecificLibPaths() const { 82506c3fb27SDimitry Andric path_list Paths; 82606c3fb27SDimitry Andric 82706c3fb27SDimitry Andric auto AddPath = [&](const ArrayRef<StringRef> &SS) { 8280b57cec5SDimitry Andric SmallString<128> Path(getDriver().ResourceDir); 82906c3fb27SDimitry Andric llvm::sys::path::append(Path, "lib"); 83006c3fb27SDimitry Andric for (auto &S : SS) 83106c3fb27SDimitry Andric llvm::sys::path::append(Path, S); 8327a6dacacSDimitry Andric Paths.push_back(std::string(Path)); 83306c3fb27SDimitry Andric }; 83406c3fb27SDimitry Andric 83506c3fb27SDimitry Andric AddPath({getTriple().str()}); 83606c3fb27SDimitry Andric AddPath({getOSLibName(), llvm::Triple::getArchTypeName(getArch())}); 83706c3fb27SDimitry Andric return Paths; 8380b57cec5SDimitry Andric } 8390b57cec5SDimitry Andric 8400b57cec5SDimitry Andric bool ToolChain::needsProfileRT(const ArgList &Args) { 8410b57cec5SDimitry Andric if (Args.hasArg(options::OPT_noprofilelib)) 8420b57cec5SDimitry Andric return false; 8430b57cec5SDimitry Andric 8445ffd83dbSDimitry Andric return Args.hasArg(options::OPT_fprofile_generate) || 8450b57cec5SDimitry Andric Args.hasArg(options::OPT_fprofile_generate_EQ) || 8460b57cec5SDimitry Andric Args.hasArg(options::OPT_fcs_profile_generate) || 8470b57cec5SDimitry Andric Args.hasArg(options::OPT_fcs_profile_generate_EQ) || 8480b57cec5SDimitry Andric Args.hasArg(options::OPT_fprofile_instr_generate) || 8490b57cec5SDimitry Andric Args.hasArg(options::OPT_fprofile_instr_generate_EQ) || 8500b57cec5SDimitry Andric Args.hasArg(options::OPT_fcreate_profile) || 8515ffd83dbSDimitry Andric Args.hasArg(options::OPT_forder_file_instrumentation); 8520b57cec5SDimitry Andric } 8530b57cec5SDimitry Andric 8540b57cec5SDimitry Andric bool ToolChain::needsGCovInstrumentation(const llvm::opt::ArgList &Args) { 8555ffd83dbSDimitry Andric return Args.hasArg(options::OPT_coverage) || 8565ffd83dbSDimitry Andric Args.hasFlag(options::OPT_fprofile_arcs, options::OPT_fno_profile_arcs, 8575ffd83dbSDimitry Andric false); 8580b57cec5SDimitry Andric } 8590b57cec5SDimitry Andric 8600b57cec5SDimitry Andric Tool *ToolChain::SelectTool(const JobAction &JA) const { 861480093f4SDimitry Andric if (D.IsFlangMode() && getDriver().ShouldUseFlangCompiler(JA)) return getFlang(); 8620b57cec5SDimitry Andric if (getDriver().ShouldUseClangCompiler(JA)) return getClang(); 8630b57cec5SDimitry Andric Action::ActionClass AC = JA.getKind(); 86406c3fb27SDimitry Andric if (AC == Action::AssembleJobClass && useIntegratedAs() && 86506c3fb27SDimitry Andric !getTriple().isOSAIX()) 8660b57cec5SDimitry Andric return getClangAs(); 8670b57cec5SDimitry Andric return getTool(AC); 8680b57cec5SDimitry Andric } 8690b57cec5SDimitry Andric 8700b57cec5SDimitry Andric std::string ToolChain::GetFilePath(const char *Name) const { 8710b57cec5SDimitry Andric return D.GetFilePath(Name, *this); 8720b57cec5SDimitry Andric } 8730b57cec5SDimitry Andric 8740b57cec5SDimitry Andric std::string ToolChain::GetProgramPath(const char *Name) const { 8750b57cec5SDimitry Andric return D.GetProgramPath(Name, *this); 8760b57cec5SDimitry Andric } 8770b57cec5SDimitry Andric 8780eae32dcSDimitry Andric std::string ToolChain::GetLinkerPath(bool *LinkerIsLLD) const { 879e8d8bef9SDimitry Andric if (LinkerIsLLD) 880e8d8bef9SDimitry Andric *LinkerIsLLD = false; 881e8d8bef9SDimitry Andric 882e8d8bef9SDimitry Andric // Get -fuse-ld= first to prevent -Wunused-command-line-argument. -fuse-ld= is 883e8d8bef9SDimitry Andric // considered as the linker flavor, e.g. "bfd", "gold", or "lld". 8840b57cec5SDimitry Andric const Arg* A = Args.getLastArg(options::OPT_fuse_ld_EQ); 8850b57cec5SDimitry Andric StringRef UseLinker = A ? A->getValue() : CLANG_DEFAULT_LINKER; 8860b57cec5SDimitry Andric 887e8d8bef9SDimitry Andric // --ld-path= takes precedence over -fuse-ld= and specifies the executable 888e8d8bef9SDimitry Andric // name. -B, COMPILER_PATH and PATH and consulted if the value does not 889e8d8bef9SDimitry Andric // contain a path component separator. 890bdd1243dSDimitry Andric // -fuse-ld=lld can be used with --ld-path= to inform clang that the binary 891bdd1243dSDimitry Andric // that --ld-path= points to is lld. 892e8d8bef9SDimitry Andric if (const Arg *A = Args.getLastArg(options::OPT_ld_path_EQ)) { 893e8d8bef9SDimitry Andric std::string Path(A->getValue()); 894e8d8bef9SDimitry Andric if (!Path.empty()) { 895e8d8bef9SDimitry Andric if (llvm::sys::path::parent_path(Path).empty()) 896e8d8bef9SDimitry Andric Path = GetProgramPath(A->getValue()); 897bdd1243dSDimitry Andric if (llvm::sys::fs::can_execute(Path)) { 898bdd1243dSDimitry Andric if (LinkerIsLLD) 899bdd1243dSDimitry Andric *LinkerIsLLD = UseLinker == "lld"; 900e8d8bef9SDimitry Andric return std::string(Path); 901e8d8bef9SDimitry Andric } 902bdd1243dSDimitry Andric } 903e8d8bef9SDimitry Andric getDriver().Diag(diag::err_drv_invalid_linker_name) << A->getAsString(Args); 904e8d8bef9SDimitry Andric return GetProgramPath(getDefaultLinker()); 905e8d8bef9SDimitry Andric } 906e8d8bef9SDimitry Andric // If we're passed -fuse-ld= with no argument, or with the argument ld, 907e8d8bef9SDimitry Andric // then use whatever the default system linker is. 908e8d8bef9SDimitry Andric if (UseLinker.empty() || UseLinker == "ld") { 909e8d8bef9SDimitry Andric const char *DefaultLinker = getDefaultLinker(); 910e8d8bef9SDimitry Andric if (llvm::sys::path::is_absolute(DefaultLinker)) 911e8d8bef9SDimitry Andric return std::string(DefaultLinker); 912e8d8bef9SDimitry Andric else 913e8d8bef9SDimitry Andric return GetProgramPath(DefaultLinker); 914e8d8bef9SDimitry Andric } 915e8d8bef9SDimitry Andric 916e8d8bef9SDimitry Andric // Extending -fuse-ld= to an absolute or relative path is unexpected. Checking 917e8d8bef9SDimitry Andric // for the linker flavor is brittle. In addition, prepending "ld." or "ld64." 918e8d8bef9SDimitry Andric // to a relative path is surprising. This is more complex due to priorities 919e8d8bef9SDimitry Andric // among -B, COMPILER_PATH and PATH. --ld-path= should be used instead. 920349cc55cSDimitry Andric if (UseLinker.contains('/')) 921e8d8bef9SDimitry Andric getDriver().Diag(diag::warn_drv_fuse_ld_path); 922e8d8bef9SDimitry Andric 9230b57cec5SDimitry Andric if (llvm::sys::path::is_absolute(UseLinker)) { 9240b57cec5SDimitry Andric // If we're passed what looks like an absolute path, don't attempt to 9250b57cec5SDimitry Andric // second-guess that. 9260b57cec5SDimitry Andric if (llvm::sys::fs::can_execute(UseLinker)) 9275ffd83dbSDimitry Andric return std::string(UseLinker); 9280b57cec5SDimitry Andric } else { 9290b57cec5SDimitry Andric llvm::SmallString<8> LinkerName; 9300b57cec5SDimitry Andric if (Triple.isOSDarwin()) 9310b57cec5SDimitry Andric LinkerName.append("ld64."); 9320b57cec5SDimitry Andric else 9330b57cec5SDimitry Andric LinkerName.append("ld."); 9340b57cec5SDimitry Andric LinkerName.append(UseLinker); 9350b57cec5SDimitry Andric 9360b57cec5SDimitry Andric std::string LinkerPath(GetProgramPath(LinkerName.c_str())); 937e8d8bef9SDimitry Andric if (llvm::sys::fs::can_execute(LinkerPath)) { 938e8d8bef9SDimitry Andric if (LinkerIsLLD) 9390eae32dcSDimitry Andric *LinkerIsLLD = UseLinker == "lld"; 9400b57cec5SDimitry Andric return LinkerPath; 9410b57cec5SDimitry Andric } 942e8d8bef9SDimitry Andric } 9430b57cec5SDimitry Andric 9440b57cec5SDimitry Andric if (A) 9450b57cec5SDimitry Andric getDriver().Diag(diag::err_drv_invalid_linker_name) << A->getAsString(Args); 9460b57cec5SDimitry Andric 9470b57cec5SDimitry Andric return GetProgramPath(getDefaultLinker()); 9480b57cec5SDimitry Andric } 9490b57cec5SDimitry Andric 9505ffd83dbSDimitry Andric std::string ToolChain::GetStaticLibToolPath() const { 9515ffd83dbSDimitry Andric // TODO: Add support for static lib archiving on Windows 952349cc55cSDimitry Andric if (Triple.isOSDarwin()) 953349cc55cSDimitry Andric return GetProgramPath("libtool"); 9545ffd83dbSDimitry Andric return GetProgramPath("llvm-ar"); 9555ffd83dbSDimitry Andric } 9565ffd83dbSDimitry Andric 9570b57cec5SDimitry Andric types::ID ToolChain::LookupTypeForExtension(StringRef Ext) const { 958480093f4SDimitry Andric types::ID id = types::lookupTypeForExtension(Ext); 959480093f4SDimitry Andric 960480093f4SDimitry Andric // Flang always runs the preprocessor and has no notion of "preprocessed 961480093f4SDimitry Andric // fortran". Here, TY_PP_Fortran is coerced to TY_Fortran to avoid treating 962480093f4SDimitry Andric // them differently. 963480093f4SDimitry Andric if (D.IsFlangMode() && id == types::TY_PP_Fortran) 964480093f4SDimitry Andric id = types::TY_Fortran; 965480093f4SDimitry Andric 966480093f4SDimitry Andric return id; 9670b57cec5SDimitry Andric } 9680b57cec5SDimitry Andric 9690b57cec5SDimitry Andric bool ToolChain::HasNativeLLVMSupport() const { 9700b57cec5SDimitry Andric return false; 9710b57cec5SDimitry Andric } 9720b57cec5SDimitry Andric 9730b57cec5SDimitry Andric bool ToolChain::isCrossCompiling() const { 9740b57cec5SDimitry Andric llvm::Triple HostTriple(LLVM_HOST_TRIPLE); 9750b57cec5SDimitry Andric switch (HostTriple.getArch()) { 9760b57cec5SDimitry Andric // The A32/T32/T16 instruction sets are not separate architectures in this 9770b57cec5SDimitry Andric // context. 9780b57cec5SDimitry Andric case llvm::Triple::arm: 9790b57cec5SDimitry Andric case llvm::Triple::armeb: 9800b57cec5SDimitry Andric case llvm::Triple::thumb: 9810b57cec5SDimitry Andric case llvm::Triple::thumbeb: 9820b57cec5SDimitry Andric return getArch() != llvm::Triple::arm && getArch() != llvm::Triple::thumb && 9830b57cec5SDimitry Andric getArch() != llvm::Triple::armeb && getArch() != llvm::Triple::thumbeb; 9840b57cec5SDimitry Andric default: 9850b57cec5SDimitry Andric return HostTriple.getArch() != getArch(); 9860b57cec5SDimitry Andric } 9870b57cec5SDimitry Andric } 9880b57cec5SDimitry Andric 9890b57cec5SDimitry Andric ObjCRuntime ToolChain::getDefaultObjCRuntime(bool isNonFragile) const { 9900b57cec5SDimitry Andric return ObjCRuntime(isNonFragile ? ObjCRuntime::GNUstep : ObjCRuntime::GCC, 9910b57cec5SDimitry Andric VersionTuple()); 9920b57cec5SDimitry Andric } 9930b57cec5SDimitry Andric 9940b57cec5SDimitry Andric llvm::ExceptionHandling 9950b57cec5SDimitry Andric ToolChain::GetExceptionModel(const llvm::opt::ArgList &Args) const { 9960b57cec5SDimitry Andric return llvm::ExceptionHandling::None; 9970b57cec5SDimitry Andric } 9980b57cec5SDimitry Andric 9990b57cec5SDimitry Andric bool ToolChain::isThreadModelSupported(const StringRef Model) const { 10000b57cec5SDimitry Andric if (Model == "single") { 10010b57cec5SDimitry Andric // FIXME: 'single' is only supported on ARM and WebAssembly so far. 10020b57cec5SDimitry Andric return Triple.getArch() == llvm::Triple::arm || 10030b57cec5SDimitry Andric Triple.getArch() == llvm::Triple::armeb || 10040b57cec5SDimitry Andric Triple.getArch() == llvm::Triple::thumb || 1005e8d8bef9SDimitry Andric Triple.getArch() == llvm::Triple::thumbeb || Triple.isWasm(); 10060b57cec5SDimitry Andric } else if (Model == "posix") 10070b57cec5SDimitry Andric return true; 10080b57cec5SDimitry Andric 10090b57cec5SDimitry Andric return false; 10100b57cec5SDimitry Andric } 10110b57cec5SDimitry Andric 10120b57cec5SDimitry Andric std::string ToolChain::ComputeLLVMTriple(const ArgList &Args, 10130b57cec5SDimitry Andric types::ID InputType) const { 10140b57cec5SDimitry Andric switch (getTriple().getArch()) { 10150b57cec5SDimitry Andric default: 10160b57cec5SDimitry Andric return getTripleString(); 10170b57cec5SDimitry Andric 10180b57cec5SDimitry Andric case llvm::Triple::x86_64: { 10190b57cec5SDimitry Andric llvm::Triple Triple = getTriple(); 10200b57cec5SDimitry Andric if (!Triple.isOSBinFormatMachO()) 10210b57cec5SDimitry Andric return getTripleString(); 10220b57cec5SDimitry Andric 10230b57cec5SDimitry Andric if (Arg *A = Args.getLastArg(options::OPT_march_EQ)) { 10240b57cec5SDimitry Andric // x86_64h goes in the triple. Other -march options just use the 10250b57cec5SDimitry Andric // vanilla triple we already have. 10260b57cec5SDimitry Andric StringRef MArch = A->getValue(); 10270b57cec5SDimitry Andric if (MArch == "x86_64h") 10280b57cec5SDimitry Andric Triple.setArchName(MArch); 10290b57cec5SDimitry Andric } 10300b57cec5SDimitry Andric return Triple.getTriple(); 10310b57cec5SDimitry Andric } 10320b57cec5SDimitry Andric case llvm::Triple::aarch64: { 10330b57cec5SDimitry Andric llvm::Triple Triple = getTriple(); 1034*0fca6ea1SDimitry Andric tools::aarch64::setPAuthABIInTriple(getDriver(), Args, Triple); 10350b57cec5SDimitry Andric if (!Triple.isOSBinFormatMachO()) 1036*0fca6ea1SDimitry Andric return Triple.getTriple(); 10370b57cec5SDimitry Andric 1038e8d8bef9SDimitry Andric if (Triple.isArm64e()) 1039*0fca6ea1SDimitry Andric return Triple.getTriple(); 1040e8d8bef9SDimitry Andric 10410b57cec5SDimitry Andric // FIXME: older versions of ld64 expect the "arm64" component in the actual 10420b57cec5SDimitry Andric // triple string and query it to determine whether an LTO file can be 10430b57cec5SDimitry Andric // handled. Remove this when we don't care any more. 10440b57cec5SDimitry Andric Triple.setArchName("arm64"); 10450b57cec5SDimitry Andric return Triple.getTriple(); 10460b57cec5SDimitry Andric } 1047480093f4SDimitry Andric case llvm::Triple::aarch64_32: 1048480093f4SDimitry Andric return getTripleString(); 10490b57cec5SDimitry Andric case llvm::Triple::arm: 10500b57cec5SDimitry Andric case llvm::Triple::armeb: 10510b57cec5SDimitry Andric case llvm::Triple::thumb: 10520b57cec5SDimitry Andric case llvm::Triple::thumbeb: { 10530b57cec5SDimitry Andric llvm::Triple Triple = getTriple(); 1054fe6060f1SDimitry Andric tools::arm::setArchNameInTriple(getDriver(), Args, InputType, Triple); 1055fe6060f1SDimitry Andric tools::arm::setFloatABIInTriple(getDriver(), Args, Triple); 10560b57cec5SDimitry Andric return Triple.getTriple(); 10570b57cec5SDimitry Andric } 10580b57cec5SDimitry Andric } 10590b57cec5SDimitry Andric } 10600b57cec5SDimitry Andric 10610b57cec5SDimitry Andric std::string ToolChain::ComputeEffectiveClangTriple(const ArgList &Args, 10620b57cec5SDimitry Andric types::ID InputType) const { 10630b57cec5SDimitry Andric return ComputeLLVMTriple(Args, InputType); 10640b57cec5SDimitry Andric } 10650b57cec5SDimitry Andric 10665ffd83dbSDimitry Andric std::string ToolChain::computeSysRoot() const { 10675ffd83dbSDimitry Andric return D.SysRoot; 10685ffd83dbSDimitry Andric } 10695ffd83dbSDimitry Andric 10700b57cec5SDimitry Andric void ToolChain::AddClangSystemIncludeArgs(const ArgList &DriverArgs, 10710b57cec5SDimitry Andric ArgStringList &CC1Args) const { 10720b57cec5SDimitry Andric // Each toolchain should provide the appropriate include flags. 10730b57cec5SDimitry Andric } 10740b57cec5SDimitry Andric 10750b57cec5SDimitry Andric void ToolChain::addClangTargetOptions( 10760b57cec5SDimitry Andric const ArgList &DriverArgs, ArgStringList &CC1Args, 10770b57cec5SDimitry Andric Action::OffloadKind DeviceOffloadKind) const {} 10780b57cec5SDimitry Andric 1079bdd1243dSDimitry Andric void ToolChain::addClangCC1ASTargetOptions(const ArgList &Args, 1080bdd1243dSDimitry Andric ArgStringList &CC1ASArgs) const {} 1081bdd1243dSDimitry Andric 10820b57cec5SDimitry Andric void ToolChain::addClangWarningOptions(ArgStringList &CC1Args) const {} 10830b57cec5SDimitry Andric 10840b57cec5SDimitry Andric void ToolChain::addProfileRTLibs(const llvm::opt::ArgList &Args, 10850b57cec5SDimitry Andric llvm::opt::ArgStringList &CmdArgs) const { 10865ffd83dbSDimitry Andric if (!needsProfileRT(Args) && !needsGCovInstrumentation(Args)) 10875ffd83dbSDimitry Andric return; 10880b57cec5SDimitry Andric 10890b57cec5SDimitry Andric CmdArgs.push_back(getCompilerRTArgString(Args, "profile")); 10900b57cec5SDimitry Andric } 10910b57cec5SDimitry Andric 10920b57cec5SDimitry Andric ToolChain::RuntimeLibType ToolChain::GetRuntimeLibType( 10930b57cec5SDimitry Andric const ArgList &Args) const { 1094fe6060f1SDimitry Andric if (runtimeLibType) 1095fe6060f1SDimitry Andric return *runtimeLibType; 1096fe6060f1SDimitry Andric 10970b57cec5SDimitry Andric const Arg* A = Args.getLastArg(options::OPT_rtlib_EQ); 10980b57cec5SDimitry Andric StringRef LibName = A ? A->getValue() : CLANG_DEFAULT_RTLIB; 10990b57cec5SDimitry Andric 11000b57cec5SDimitry Andric // Only use "platform" in tests to override CLANG_DEFAULT_RTLIB! 11010b57cec5SDimitry Andric if (LibName == "compiler-rt") 1102fe6060f1SDimitry Andric runtimeLibType = ToolChain::RLT_CompilerRT; 11030b57cec5SDimitry Andric else if (LibName == "libgcc") 1104fe6060f1SDimitry Andric runtimeLibType = ToolChain::RLT_Libgcc; 11050b57cec5SDimitry Andric else if (LibName == "platform") 1106fe6060f1SDimitry Andric runtimeLibType = GetDefaultRuntimeLibType(); 1107fe6060f1SDimitry Andric else { 11080b57cec5SDimitry Andric if (A) 1109fe6060f1SDimitry Andric getDriver().Diag(diag::err_drv_invalid_rtlib_name) 1110fe6060f1SDimitry Andric << A->getAsString(Args); 11110b57cec5SDimitry Andric 1112fe6060f1SDimitry Andric runtimeLibType = GetDefaultRuntimeLibType(); 1113fe6060f1SDimitry Andric } 1114fe6060f1SDimitry Andric 1115fe6060f1SDimitry Andric return *runtimeLibType; 11160b57cec5SDimitry Andric } 11170b57cec5SDimitry Andric 11180b57cec5SDimitry Andric ToolChain::UnwindLibType ToolChain::GetUnwindLibType( 11190b57cec5SDimitry Andric const ArgList &Args) const { 1120fe6060f1SDimitry Andric if (unwindLibType) 1121fe6060f1SDimitry Andric return *unwindLibType; 1122fe6060f1SDimitry Andric 11230b57cec5SDimitry Andric const Arg *A = Args.getLastArg(options::OPT_unwindlib_EQ); 11240b57cec5SDimitry Andric StringRef LibName = A ? A->getValue() : CLANG_DEFAULT_UNWINDLIB; 11250b57cec5SDimitry Andric 11260b57cec5SDimitry Andric if (LibName == "none") 1127fe6060f1SDimitry Andric unwindLibType = ToolChain::UNW_None; 11280b57cec5SDimitry Andric else if (LibName == "platform" || LibName == "") { 11290b57cec5SDimitry Andric ToolChain::RuntimeLibType RtLibType = GetRuntimeLibType(Args); 1130fe6060f1SDimitry Andric if (RtLibType == ToolChain::RLT_CompilerRT) { 1131fe6060f1SDimitry Andric if (getTriple().isAndroid() || getTriple().isOSAIX()) 1132fe6060f1SDimitry Andric unwindLibType = ToolChain::UNW_CompilerRT; 1133fe6060f1SDimitry Andric else 1134fe6060f1SDimitry Andric unwindLibType = ToolChain::UNW_None; 1135fe6060f1SDimitry Andric } else if (RtLibType == ToolChain::RLT_Libgcc) 1136fe6060f1SDimitry Andric unwindLibType = ToolChain::UNW_Libgcc; 11370b57cec5SDimitry Andric } else if (LibName == "libunwind") { 11380b57cec5SDimitry Andric if (GetRuntimeLibType(Args) == RLT_Libgcc) 11390b57cec5SDimitry Andric getDriver().Diag(diag::err_drv_incompatible_unwindlib); 1140fe6060f1SDimitry Andric unwindLibType = ToolChain::UNW_CompilerRT; 11410b57cec5SDimitry Andric } else if (LibName == "libgcc") 1142fe6060f1SDimitry Andric unwindLibType = ToolChain::UNW_Libgcc; 1143fe6060f1SDimitry Andric else { 11440b57cec5SDimitry Andric if (A) 11450b57cec5SDimitry Andric getDriver().Diag(diag::err_drv_invalid_unwindlib_name) 11460b57cec5SDimitry Andric << A->getAsString(Args); 11470b57cec5SDimitry Andric 1148fe6060f1SDimitry Andric unwindLibType = GetDefaultUnwindLibType(); 1149fe6060f1SDimitry Andric } 1150fe6060f1SDimitry Andric 1151fe6060f1SDimitry Andric return *unwindLibType; 11520b57cec5SDimitry Andric } 11530b57cec5SDimitry Andric 11540b57cec5SDimitry Andric ToolChain::CXXStdlibType ToolChain::GetCXXStdlibType(const ArgList &Args) const{ 1155fe6060f1SDimitry Andric if (cxxStdlibType) 1156fe6060f1SDimitry Andric return *cxxStdlibType; 1157fe6060f1SDimitry Andric 11580b57cec5SDimitry Andric const Arg *A = Args.getLastArg(options::OPT_stdlib_EQ); 11590b57cec5SDimitry Andric StringRef LibName = A ? A->getValue() : CLANG_DEFAULT_CXX_STDLIB; 11600b57cec5SDimitry Andric 11610b57cec5SDimitry Andric // Only use "platform" in tests to override CLANG_DEFAULT_CXX_STDLIB! 11620b57cec5SDimitry Andric if (LibName == "libc++") 1163fe6060f1SDimitry Andric cxxStdlibType = ToolChain::CST_Libcxx; 11640b57cec5SDimitry Andric else if (LibName == "libstdc++") 1165fe6060f1SDimitry Andric cxxStdlibType = ToolChain::CST_Libstdcxx; 11660b57cec5SDimitry Andric else if (LibName == "platform") 1167fe6060f1SDimitry Andric cxxStdlibType = GetDefaultCXXStdlibType(); 1168fe6060f1SDimitry Andric else { 11690b57cec5SDimitry Andric if (A) 1170fe6060f1SDimitry Andric getDriver().Diag(diag::err_drv_invalid_stdlib_name) 1171fe6060f1SDimitry Andric << A->getAsString(Args); 11720b57cec5SDimitry Andric 1173fe6060f1SDimitry Andric cxxStdlibType = GetDefaultCXXStdlibType(); 1174fe6060f1SDimitry Andric } 1175fe6060f1SDimitry Andric 1176fe6060f1SDimitry Andric return *cxxStdlibType; 11770b57cec5SDimitry Andric } 11780b57cec5SDimitry Andric 11790b57cec5SDimitry Andric /// Utility function to add a system include directory to CC1 arguments. 11800b57cec5SDimitry Andric /*static*/ void ToolChain::addSystemInclude(const ArgList &DriverArgs, 11810b57cec5SDimitry Andric ArgStringList &CC1Args, 11820b57cec5SDimitry Andric const Twine &Path) { 11830b57cec5SDimitry Andric CC1Args.push_back("-internal-isystem"); 11840b57cec5SDimitry Andric CC1Args.push_back(DriverArgs.MakeArgString(Path)); 11850b57cec5SDimitry Andric } 11860b57cec5SDimitry Andric 11870b57cec5SDimitry Andric /// Utility function to add a system include directory with extern "C" 11880b57cec5SDimitry Andric /// semantics to CC1 arguments. 11890b57cec5SDimitry Andric /// 11900b57cec5SDimitry Andric /// Note that this should be used rarely, and only for directories that 11910b57cec5SDimitry Andric /// historically and for legacy reasons are treated as having implicit extern 11920b57cec5SDimitry Andric /// "C" semantics. These semantics are *ignored* by and large today, but its 11930b57cec5SDimitry Andric /// important to preserve the preprocessor changes resulting from the 11940b57cec5SDimitry Andric /// classification. 11950b57cec5SDimitry Andric /*static*/ void ToolChain::addExternCSystemInclude(const ArgList &DriverArgs, 11960b57cec5SDimitry Andric ArgStringList &CC1Args, 11970b57cec5SDimitry Andric const Twine &Path) { 11980b57cec5SDimitry Andric CC1Args.push_back("-internal-externc-isystem"); 11990b57cec5SDimitry Andric CC1Args.push_back(DriverArgs.MakeArgString(Path)); 12000b57cec5SDimitry Andric } 12010b57cec5SDimitry Andric 12020b57cec5SDimitry Andric void ToolChain::addExternCSystemIncludeIfExists(const ArgList &DriverArgs, 12030b57cec5SDimitry Andric ArgStringList &CC1Args, 12040b57cec5SDimitry Andric const Twine &Path) { 12050b57cec5SDimitry Andric if (llvm::sys::fs::exists(Path)) 12060b57cec5SDimitry Andric addExternCSystemInclude(DriverArgs, CC1Args, Path); 12070b57cec5SDimitry Andric } 12080b57cec5SDimitry Andric 12090b57cec5SDimitry Andric /// Utility function to add a list of system include directories to CC1. 12100b57cec5SDimitry Andric /*static*/ void ToolChain::addSystemIncludes(const ArgList &DriverArgs, 12110b57cec5SDimitry Andric ArgStringList &CC1Args, 12120b57cec5SDimitry Andric ArrayRef<StringRef> Paths) { 1213480093f4SDimitry Andric for (const auto &Path : Paths) { 12140b57cec5SDimitry Andric CC1Args.push_back("-internal-isystem"); 12150b57cec5SDimitry Andric CC1Args.push_back(DriverArgs.MakeArgString(Path)); 12160b57cec5SDimitry Andric } 12170b57cec5SDimitry Andric } 12180b57cec5SDimitry Andric 121981ad6265SDimitry Andric /*static*/ std::string ToolChain::concat(StringRef Path, const Twine &A, 122081ad6265SDimitry Andric const Twine &B, const Twine &C, 122181ad6265SDimitry Andric const Twine &D) { 122281ad6265SDimitry Andric SmallString<128> Result(Path); 122381ad6265SDimitry Andric llvm::sys::path::append(Result, llvm::sys::path::Style::posix, A, B, C, D); 122481ad6265SDimitry Andric return std::string(Result); 122581ad6265SDimitry Andric } 122681ad6265SDimitry Andric 1227fe6060f1SDimitry Andric std::string ToolChain::detectLibcxxVersion(StringRef IncludePath) const { 1228fe6060f1SDimitry Andric std::error_code EC; 1229fe6060f1SDimitry Andric int MaxVersion = 0; 1230fe6060f1SDimitry Andric std::string MaxVersionString; 1231fe6060f1SDimitry Andric SmallString<128> Path(IncludePath); 1232fe6060f1SDimitry Andric llvm::sys::path::append(Path, "c++"); 1233fe6060f1SDimitry Andric for (llvm::vfs::directory_iterator LI = getVFS().dir_begin(Path, EC), LE; 1234fe6060f1SDimitry Andric !EC && LI != LE; LI = LI.increment(EC)) { 1235fe6060f1SDimitry Andric StringRef VersionText = llvm::sys::path::filename(LI->path()); 1236fe6060f1SDimitry Andric int Version; 1237fe6060f1SDimitry Andric if (VersionText[0] == 'v' && 1238fe6060f1SDimitry Andric !VersionText.slice(1, StringRef::npos).getAsInteger(10, Version)) { 1239fe6060f1SDimitry Andric if (Version > MaxVersion) { 1240fe6060f1SDimitry Andric MaxVersion = Version; 1241fe6060f1SDimitry Andric MaxVersionString = std::string(VersionText); 1242fe6060f1SDimitry Andric } 1243fe6060f1SDimitry Andric } 1244fe6060f1SDimitry Andric } 1245fe6060f1SDimitry Andric if (!MaxVersion) 1246fe6060f1SDimitry Andric return ""; 1247fe6060f1SDimitry Andric return MaxVersionString; 1248fe6060f1SDimitry Andric } 1249fe6060f1SDimitry Andric 12500b57cec5SDimitry Andric void ToolChain::AddClangCXXStdlibIncludeArgs(const ArgList &DriverArgs, 12510b57cec5SDimitry Andric ArgStringList &CC1Args) const { 12520b57cec5SDimitry Andric // Header search paths should be handled by each of the subclasses. 12530b57cec5SDimitry Andric // Historically, they have not been, and instead have been handled inside of 12540b57cec5SDimitry Andric // the CC1-layer frontend. As the logic is hoisted out, this generic function 12550b57cec5SDimitry Andric // will slowly stop being called. 12560b57cec5SDimitry Andric // 12570b57cec5SDimitry Andric // While it is being called, replicate a bit of a hack to propagate the 12580b57cec5SDimitry Andric // '-stdlib=' flag down to CC1 so that it can in turn customize the C++ 12590b57cec5SDimitry Andric // header search paths with it. Once all systems are overriding this 12600b57cec5SDimitry Andric // function, the CC1 flag and this line can be removed. 12610b57cec5SDimitry Andric DriverArgs.AddAllArgs(CC1Args, options::OPT_stdlib_EQ); 12620b57cec5SDimitry Andric } 12630b57cec5SDimitry Andric 1264a7dea167SDimitry Andric void ToolChain::AddClangCXXStdlibIsystemArgs( 1265a7dea167SDimitry Andric const llvm::opt::ArgList &DriverArgs, 1266a7dea167SDimitry Andric llvm::opt::ArgStringList &CC1Args) const { 1267a7dea167SDimitry Andric DriverArgs.ClaimAllArgs(options::OPT_stdlibxx_isystem); 1268bdd1243dSDimitry Andric // This intentionally only looks at -nostdinc++, and not -nostdinc or 1269bdd1243dSDimitry Andric // -nostdlibinc. The purpose of -stdlib++-isystem is to support toolchain 1270bdd1243dSDimitry Andric // setups with non-standard search logic for the C++ headers, while still 1271bdd1243dSDimitry Andric // allowing users of the toolchain to bring their own C++ headers. Such a 1272bdd1243dSDimitry Andric // toolchain likely also has non-standard search logic for the C headers and 1273bdd1243dSDimitry Andric // uses -nostdinc to suppress the default logic, but -stdlib++-isystem should 1274bdd1243dSDimitry Andric // still work in that case and only be suppressed by an explicit -nostdinc++ 1275bdd1243dSDimitry Andric // in a project using the toolchain. 1276bdd1243dSDimitry Andric if (!DriverArgs.hasArg(options::OPT_nostdincxx)) 1277a7dea167SDimitry Andric for (const auto &P : 1278a7dea167SDimitry Andric DriverArgs.getAllArgValues(options::OPT_stdlibxx_isystem)) 1279a7dea167SDimitry Andric addSystemInclude(DriverArgs, CC1Args, P); 1280a7dea167SDimitry Andric } 1281a7dea167SDimitry Andric 12820b57cec5SDimitry Andric bool ToolChain::ShouldLinkCXXStdlib(const llvm::opt::ArgList &Args) const { 12830b57cec5SDimitry Andric return getDriver().CCCIsCXX() && 12840b57cec5SDimitry Andric !Args.hasArg(options::OPT_nostdlib, options::OPT_nodefaultlibs, 12850b57cec5SDimitry Andric options::OPT_nostdlibxx); 12860b57cec5SDimitry Andric } 12870b57cec5SDimitry Andric 12880b57cec5SDimitry Andric void ToolChain::AddCXXStdlibLibArgs(const ArgList &Args, 12890b57cec5SDimitry Andric ArgStringList &CmdArgs) const { 12900b57cec5SDimitry Andric assert(!Args.hasArg(options::OPT_nostdlibxx) && 12910b57cec5SDimitry Andric "should not have called this"); 12920b57cec5SDimitry Andric CXXStdlibType Type = GetCXXStdlibType(Args); 12930b57cec5SDimitry Andric 12940b57cec5SDimitry Andric switch (Type) { 12950b57cec5SDimitry Andric case ToolChain::CST_Libcxx: 12960b57cec5SDimitry Andric CmdArgs.push_back("-lc++"); 1297fcaf7f86SDimitry Andric if (Args.hasArg(options::OPT_fexperimental_library)) 1298fcaf7f86SDimitry Andric CmdArgs.push_back("-lc++experimental"); 12990b57cec5SDimitry Andric break; 13000b57cec5SDimitry Andric 13010b57cec5SDimitry Andric case ToolChain::CST_Libstdcxx: 13020b57cec5SDimitry Andric CmdArgs.push_back("-lstdc++"); 13030b57cec5SDimitry Andric break; 13040b57cec5SDimitry Andric } 13050b57cec5SDimitry Andric } 13060b57cec5SDimitry Andric 13070b57cec5SDimitry Andric void ToolChain::AddFilePathLibArgs(const ArgList &Args, 13080b57cec5SDimitry Andric ArgStringList &CmdArgs) const { 13090b57cec5SDimitry Andric for (const auto &LibPath : getFilePaths()) 13100b57cec5SDimitry Andric if(LibPath.length() > 0) 13110b57cec5SDimitry Andric CmdArgs.push_back(Args.MakeArgString(StringRef("-L") + LibPath)); 13120b57cec5SDimitry Andric } 13130b57cec5SDimitry Andric 13140b57cec5SDimitry Andric void ToolChain::AddCCKextLibArgs(const ArgList &Args, 13150b57cec5SDimitry Andric ArgStringList &CmdArgs) const { 13160b57cec5SDimitry Andric CmdArgs.push_back("-lcc_kext"); 13170b57cec5SDimitry Andric } 13180b57cec5SDimitry Andric 13195ffd83dbSDimitry Andric bool ToolChain::isFastMathRuntimeAvailable(const ArgList &Args, 13205ffd83dbSDimitry Andric std::string &Path) const { 1321*0fca6ea1SDimitry Andric // Don't implicitly link in mode-changing libraries in a shared library, since 1322*0fca6ea1SDimitry Andric // this can have very deleterious effects. See the various links from 1323*0fca6ea1SDimitry Andric // https://github.com/llvm/llvm-project/issues/57589 for more information. 1324*0fca6ea1SDimitry Andric bool Default = !Args.hasArgNoClaim(options::OPT_shared); 1325*0fca6ea1SDimitry Andric 13260b57cec5SDimitry Andric // Do not check for -fno-fast-math or -fno-unsafe-math when -Ofast passed 13270b57cec5SDimitry Andric // (to keep the linker options consistent with gcc and clang itself). 1328*0fca6ea1SDimitry Andric if (Default && !isOptimizationLevelFast(Args)) { 13290b57cec5SDimitry Andric // Check if -ffast-math or -funsafe-math. 1330*0fca6ea1SDimitry Andric Arg *A = Args.getLastArg( 1331*0fca6ea1SDimitry Andric options::OPT_ffast_math, options::OPT_fno_fast_math, 13320b57cec5SDimitry Andric options::OPT_funsafe_math_optimizations, 1333*0fca6ea1SDimitry Andric options::OPT_fno_unsafe_math_optimizations, options::OPT_ffp_model_EQ); 13340b57cec5SDimitry Andric 13350b57cec5SDimitry Andric if (!A || A->getOption().getID() == options::OPT_fno_fast_math || 13360b57cec5SDimitry Andric A->getOption().getID() == options::OPT_fno_unsafe_math_optimizations) 1337*0fca6ea1SDimitry Andric Default = false; 1338*0fca6ea1SDimitry Andric if (A && A->getOption().getID() == options::OPT_ffp_model_EQ) { 1339*0fca6ea1SDimitry Andric StringRef Model = A->getValue(); 1340*0fca6ea1SDimitry Andric if (Model != "fast") 1341*0fca6ea1SDimitry Andric Default = false; 13420b57cec5SDimitry Andric } 1343*0fca6ea1SDimitry Andric } 1344*0fca6ea1SDimitry Andric 1345*0fca6ea1SDimitry Andric // Whatever decision came as a result of the above implicit settings, either 1346*0fca6ea1SDimitry Andric // -mdaz-ftz or -mno-daz-ftz is capable of overriding it. 1347*0fca6ea1SDimitry Andric if (!Args.hasFlag(options::OPT_mdaz_ftz, options::OPT_mno_daz_ftz, Default)) 1348*0fca6ea1SDimitry Andric return false; 1349*0fca6ea1SDimitry Andric 13500b57cec5SDimitry Andric // If crtfastmath.o exists add it to the arguments. 13515ffd83dbSDimitry Andric Path = GetFilePath("crtfastmath.o"); 13525ffd83dbSDimitry Andric return (Path != "crtfastmath.o"); // Not found. 13535ffd83dbSDimitry Andric } 13540b57cec5SDimitry Andric 13555ffd83dbSDimitry Andric bool ToolChain::addFastMathRuntimeIfAvailable(const ArgList &Args, 13565ffd83dbSDimitry Andric ArgStringList &CmdArgs) const { 13575ffd83dbSDimitry Andric std::string Path; 13585ffd83dbSDimitry Andric if (isFastMathRuntimeAvailable(Args, Path)) { 13590b57cec5SDimitry Andric CmdArgs.push_back(Args.MakeArgString(Path)); 13600b57cec5SDimitry Andric return true; 13610b57cec5SDimitry Andric } 13620b57cec5SDimitry Andric 13635ffd83dbSDimitry Andric return false; 13645ffd83dbSDimitry Andric } 13655ffd83dbSDimitry Andric 1366bdd1243dSDimitry Andric Expected<SmallVector<std::string>> 1367bdd1243dSDimitry Andric ToolChain::getSystemGPUArchs(const llvm::opt::ArgList &Args) const { 1368bdd1243dSDimitry Andric return SmallVector<std::string>(); 1369bdd1243dSDimitry Andric } 1370bdd1243dSDimitry Andric 13710b57cec5SDimitry Andric SanitizerMask ToolChain::getSupportedSanitizers() const { 13720b57cec5SDimitry Andric // Return sanitizers which don't require runtime support and are not 13730b57cec5SDimitry Andric // platform dependent. 13740b57cec5SDimitry Andric 1375e8d8bef9SDimitry Andric SanitizerMask Res = 137606c3fb27SDimitry Andric (SanitizerKind::Undefined & ~SanitizerKind::Vptr) | 13770b57cec5SDimitry Andric (SanitizerKind::CFI & ~SanitizerKind::CFIICall) | 1378e8d8bef9SDimitry Andric SanitizerKind::CFICastStrict | SanitizerKind::FloatDivideByZero | 1379bdd1243dSDimitry Andric SanitizerKind::KCFI | SanitizerKind::UnsignedIntegerOverflow | 1380e8d8bef9SDimitry Andric SanitizerKind::UnsignedShiftBase | SanitizerKind::ImplicitConversion | 13810b57cec5SDimitry Andric SanitizerKind::Nullability | SanitizerKind::LocalBounds; 13820b57cec5SDimitry Andric if (getTriple().getArch() == llvm::Triple::x86 || 13830b57cec5SDimitry Andric getTriple().getArch() == llvm::Triple::x86_64 || 1384e8d8bef9SDimitry Andric getTriple().getArch() == llvm::Triple::arm || getTriple().isWasm() || 13855f757f3fSDimitry Andric getTriple().isAArch64() || getTriple().isRISCV() || 13865f757f3fSDimitry Andric getTriple().isLoongArch64()) 13870b57cec5SDimitry Andric Res |= SanitizerKind::CFIICall; 1388e8d8bef9SDimitry Andric if (getTriple().getArch() == llvm::Triple::x86_64 || 1389e8d8bef9SDimitry Andric getTriple().isAArch64(64) || getTriple().isRISCV()) 13900b57cec5SDimitry Andric Res |= SanitizerKind::ShadowCallStack; 1391e8d8bef9SDimitry Andric if (getTriple().isAArch64(64)) 1392a7dea167SDimitry Andric Res |= SanitizerKind::MemTag; 13930b57cec5SDimitry Andric return Res; 13940b57cec5SDimitry Andric } 13950b57cec5SDimitry Andric 13960b57cec5SDimitry Andric void ToolChain::AddCudaIncludeArgs(const ArgList &DriverArgs, 13970b57cec5SDimitry Andric ArgStringList &CC1Args) const {} 13980b57cec5SDimitry Andric 13995ffd83dbSDimitry Andric void ToolChain::AddHIPIncludeArgs(const ArgList &DriverArgs, 14005ffd83dbSDimitry Andric ArgStringList &CC1Args) const {} 14015ffd83dbSDimitry Andric 1402349cc55cSDimitry Andric llvm::SmallVector<ToolChain::BitCodeLibraryInfo, 12> 1403bdd1243dSDimitry Andric ToolChain::getDeviceLibs(const ArgList &DriverArgs) const { 1404fe6060f1SDimitry Andric return {}; 1405fe6060f1SDimitry Andric } 1406fe6060f1SDimitry Andric 14070b57cec5SDimitry Andric void ToolChain::AddIAMCUIncludeArgs(const ArgList &DriverArgs, 14080b57cec5SDimitry Andric ArgStringList &CC1Args) const {} 14090b57cec5SDimitry Andric 14100b57cec5SDimitry Andric static VersionTuple separateMSVCFullVersion(unsigned Version) { 14110b57cec5SDimitry Andric if (Version < 100) 14120b57cec5SDimitry Andric return VersionTuple(Version); 14130b57cec5SDimitry Andric 14140b57cec5SDimitry Andric if (Version < 10000) 14150b57cec5SDimitry Andric return VersionTuple(Version / 100, Version % 100); 14160b57cec5SDimitry Andric 14170b57cec5SDimitry Andric unsigned Build = 0, Factor = 1; 14180b57cec5SDimitry Andric for (; Version > 10000; Version = Version / 10, Factor = Factor * 10) 14190b57cec5SDimitry Andric Build = Build + (Version % 10) * Factor; 14200b57cec5SDimitry Andric return VersionTuple(Version / 100, Version % 100, Build); 14210b57cec5SDimitry Andric } 14220b57cec5SDimitry Andric 14230b57cec5SDimitry Andric VersionTuple 14240b57cec5SDimitry Andric ToolChain::computeMSVCVersion(const Driver *D, 14250b57cec5SDimitry Andric const llvm::opt::ArgList &Args) const { 14260b57cec5SDimitry Andric const Arg *MSCVersion = Args.getLastArg(options::OPT_fmsc_version); 14270b57cec5SDimitry Andric const Arg *MSCompatibilityVersion = 14280b57cec5SDimitry Andric Args.getLastArg(options::OPT_fms_compatibility_version); 14290b57cec5SDimitry Andric 14300b57cec5SDimitry Andric if (MSCVersion && MSCompatibilityVersion) { 14310b57cec5SDimitry Andric if (D) 14320b57cec5SDimitry Andric D->Diag(diag::err_drv_argument_not_allowed_with) 14330b57cec5SDimitry Andric << MSCVersion->getAsString(Args) 14340b57cec5SDimitry Andric << MSCompatibilityVersion->getAsString(Args); 14350b57cec5SDimitry Andric return VersionTuple(); 14360b57cec5SDimitry Andric } 14370b57cec5SDimitry Andric 14380b57cec5SDimitry Andric if (MSCompatibilityVersion) { 14390b57cec5SDimitry Andric VersionTuple MSVT; 14400b57cec5SDimitry Andric if (MSVT.tryParse(MSCompatibilityVersion->getValue())) { 14410b57cec5SDimitry Andric if (D) 14420b57cec5SDimitry Andric D->Diag(diag::err_drv_invalid_value) 14430b57cec5SDimitry Andric << MSCompatibilityVersion->getAsString(Args) 14440b57cec5SDimitry Andric << MSCompatibilityVersion->getValue(); 14450b57cec5SDimitry Andric } else { 14460b57cec5SDimitry Andric return MSVT; 14470b57cec5SDimitry Andric } 14480b57cec5SDimitry Andric } 14490b57cec5SDimitry Andric 14500b57cec5SDimitry Andric if (MSCVersion) { 14510b57cec5SDimitry Andric unsigned Version = 0; 14520b57cec5SDimitry Andric if (StringRef(MSCVersion->getValue()).getAsInteger(10, Version)) { 14530b57cec5SDimitry Andric if (D) 14540b57cec5SDimitry Andric D->Diag(diag::err_drv_invalid_value) 14550b57cec5SDimitry Andric << MSCVersion->getAsString(Args) << MSCVersion->getValue(); 14560b57cec5SDimitry Andric } else { 14570b57cec5SDimitry Andric return separateMSVCFullVersion(Version); 14580b57cec5SDimitry Andric } 14590b57cec5SDimitry Andric } 14600b57cec5SDimitry Andric 14610b57cec5SDimitry Andric return VersionTuple(); 14620b57cec5SDimitry Andric } 14630b57cec5SDimitry Andric 14640b57cec5SDimitry Andric llvm::opt::DerivedArgList *ToolChain::TranslateOpenMPTargetArgs( 14650b57cec5SDimitry Andric const llvm::opt::DerivedArgList &Args, bool SameTripleAsHost, 14660b57cec5SDimitry Andric SmallVectorImpl<llvm::opt::Arg *> &AllocatedArgs) const { 14670b57cec5SDimitry Andric DerivedArgList *DAL = new DerivedArgList(Args.getBaseArgs()); 14680b57cec5SDimitry Andric const OptTable &Opts = getDriver().getOpts(); 14690b57cec5SDimitry Andric bool Modified = false; 14700b57cec5SDimitry Andric 14710b57cec5SDimitry Andric // Handle -Xopenmp-target flags 14720b57cec5SDimitry Andric for (auto *A : Args) { 14730b57cec5SDimitry Andric // Exclude flags which may only apply to the host toolchain. 14740b57cec5SDimitry Andric // Do not exclude flags when the host triple (AuxTriple) 14750b57cec5SDimitry Andric // matches the current toolchain triple. If it is not present 14760b57cec5SDimitry Andric // at all, target and host share a toolchain. 14770b57cec5SDimitry Andric if (A->getOption().matches(options::OPT_m_Group)) { 14785f757f3fSDimitry Andric // Pass code object version to device toolchain 14795f757f3fSDimitry Andric // to correctly set metadata in intermediate files. 14805f757f3fSDimitry Andric if (SameTripleAsHost || 14815f757f3fSDimitry Andric A->getOption().matches(options::OPT_mcode_object_version_EQ)) 14820b57cec5SDimitry Andric DAL->append(A); 14830b57cec5SDimitry Andric else 14840b57cec5SDimitry Andric Modified = true; 14850b57cec5SDimitry Andric continue; 14860b57cec5SDimitry Andric } 14870b57cec5SDimitry Andric 14880b57cec5SDimitry Andric unsigned Index; 14890b57cec5SDimitry Andric unsigned Prev; 14900b57cec5SDimitry Andric bool XOpenMPTargetNoTriple = 14910b57cec5SDimitry Andric A->getOption().matches(options::OPT_Xopenmp_target); 14920b57cec5SDimitry Andric 14930b57cec5SDimitry Andric if (A->getOption().matches(options::OPT_Xopenmp_target_EQ)) { 14941fd87a68SDimitry Andric llvm::Triple TT(getOpenMPTriple(A->getValue(0))); 14951fd87a68SDimitry Andric 14960b57cec5SDimitry Andric // Passing device args: -Xopenmp-target=<triple> -opt=val. 14971fd87a68SDimitry Andric if (TT.getTriple() == getTripleString()) 14980b57cec5SDimitry Andric Index = Args.getBaseArgs().MakeIndex(A->getValue(1)); 14990b57cec5SDimitry Andric else 15000b57cec5SDimitry Andric continue; 15010b57cec5SDimitry Andric } else if (XOpenMPTargetNoTriple) { 15020b57cec5SDimitry Andric // Passing device args: -Xopenmp-target -opt=val. 15030b57cec5SDimitry Andric Index = Args.getBaseArgs().MakeIndex(A->getValue(0)); 15040b57cec5SDimitry Andric } else { 15050b57cec5SDimitry Andric DAL->append(A); 15060b57cec5SDimitry Andric continue; 15070b57cec5SDimitry Andric } 15080b57cec5SDimitry Andric 15090b57cec5SDimitry Andric // Parse the argument to -Xopenmp-target. 15100b57cec5SDimitry Andric Prev = Index; 15110b57cec5SDimitry Andric std::unique_ptr<Arg> XOpenMPTargetArg(Opts.ParseOneArg(Args, Index)); 15120b57cec5SDimitry Andric if (!XOpenMPTargetArg || Index > Prev + 1) { 15130b57cec5SDimitry Andric getDriver().Diag(diag::err_drv_invalid_Xopenmp_target_with_args) 15140b57cec5SDimitry Andric << A->getAsString(Args); 15150b57cec5SDimitry Andric continue; 15160b57cec5SDimitry Andric } 15170b57cec5SDimitry Andric if (XOpenMPTargetNoTriple && XOpenMPTargetArg && 15180b57cec5SDimitry Andric Args.getAllArgValues(options::OPT_fopenmp_targets_EQ).size() != 1) { 15190b57cec5SDimitry Andric getDriver().Diag(diag::err_drv_Xopenmp_target_missing_triple); 15200b57cec5SDimitry Andric continue; 15210b57cec5SDimitry Andric } 15220b57cec5SDimitry Andric XOpenMPTargetArg->setBaseArg(A); 15230b57cec5SDimitry Andric A = XOpenMPTargetArg.release(); 15240b57cec5SDimitry Andric AllocatedArgs.push_back(A); 15250b57cec5SDimitry Andric DAL->append(A); 15260b57cec5SDimitry Andric Modified = true; 15270b57cec5SDimitry Andric } 15280b57cec5SDimitry Andric 15290b57cec5SDimitry Andric if (Modified) 15300b57cec5SDimitry Andric return DAL; 15310b57cec5SDimitry Andric 15320b57cec5SDimitry Andric delete DAL; 15330b57cec5SDimitry Andric return nullptr; 15340b57cec5SDimitry Andric } 15355ffd83dbSDimitry Andric 15365ffd83dbSDimitry Andric // TODO: Currently argument values separated by space e.g. 15375ffd83dbSDimitry Andric // -Xclang -mframe-pointer=no cannot be passed by -Xarch_. This should be 15385ffd83dbSDimitry Andric // fixed. 15395ffd83dbSDimitry Andric void ToolChain::TranslateXarchArgs( 15405ffd83dbSDimitry Andric const llvm::opt::DerivedArgList &Args, llvm::opt::Arg *&A, 15415ffd83dbSDimitry Andric llvm::opt::DerivedArgList *DAL, 15425ffd83dbSDimitry Andric SmallVectorImpl<llvm::opt::Arg *> *AllocatedArgs) const { 15435ffd83dbSDimitry Andric const OptTable &Opts = getDriver().getOpts(); 15445ffd83dbSDimitry Andric unsigned ValuePos = 1; 15455ffd83dbSDimitry Andric if (A->getOption().matches(options::OPT_Xarch_device) || 15465ffd83dbSDimitry Andric A->getOption().matches(options::OPT_Xarch_host)) 15475ffd83dbSDimitry Andric ValuePos = 0; 15485ffd83dbSDimitry Andric 15495ffd83dbSDimitry Andric unsigned Index = Args.getBaseArgs().MakeIndex(A->getValue(ValuePos)); 15505ffd83dbSDimitry Andric unsigned Prev = Index; 15515ffd83dbSDimitry Andric std::unique_ptr<llvm::opt::Arg> XarchArg(Opts.ParseOneArg(Args, Index)); 15525ffd83dbSDimitry Andric 15535ffd83dbSDimitry Andric // If the argument parsing failed or more than one argument was 15545ffd83dbSDimitry Andric // consumed, the -Xarch_ argument's parameter tried to consume 15555ffd83dbSDimitry Andric // extra arguments. Emit an error and ignore. 15565ffd83dbSDimitry Andric // 15575ffd83dbSDimitry Andric // We also want to disallow any options which would alter the 15585ffd83dbSDimitry Andric // driver behavior; that isn't going to work in our model. We 1559e8d8bef9SDimitry Andric // use options::NoXarchOption to control this. 15605ffd83dbSDimitry Andric if (!XarchArg || Index > Prev + 1) { 15615ffd83dbSDimitry Andric getDriver().Diag(diag::err_drv_invalid_Xarch_argument_with_args) 15625ffd83dbSDimitry Andric << A->getAsString(Args); 15635ffd83dbSDimitry Andric return; 1564e8d8bef9SDimitry Andric } else if (XarchArg->getOption().hasFlag(options::NoXarchOption)) { 1565e8d8bef9SDimitry Andric auto &Diags = getDriver().getDiags(); 1566e8d8bef9SDimitry Andric unsigned DiagID = 1567e8d8bef9SDimitry Andric Diags.getCustomDiagID(DiagnosticsEngine::Error, 1568e8d8bef9SDimitry Andric "invalid Xarch argument: '%0', not all driver " 1569e8d8bef9SDimitry Andric "options can be forwared via Xarch argument"); 1570e8d8bef9SDimitry Andric Diags.Report(DiagID) << A->getAsString(Args); 15715ffd83dbSDimitry Andric return; 15725ffd83dbSDimitry Andric } 15735ffd83dbSDimitry Andric XarchArg->setBaseArg(A); 15745ffd83dbSDimitry Andric A = XarchArg.release(); 15755ffd83dbSDimitry Andric if (!AllocatedArgs) 15765ffd83dbSDimitry Andric DAL->AddSynthesizedArg(A); 15775ffd83dbSDimitry Andric else 15785ffd83dbSDimitry Andric AllocatedArgs->push_back(A); 15795ffd83dbSDimitry Andric } 15805ffd83dbSDimitry Andric 15815ffd83dbSDimitry Andric llvm::opt::DerivedArgList *ToolChain::TranslateXarchArgs( 15825ffd83dbSDimitry Andric const llvm::opt::DerivedArgList &Args, StringRef BoundArch, 15835ffd83dbSDimitry Andric Action::OffloadKind OFK, 15845ffd83dbSDimitry Andric SmallVectorImpl<llvm::opt::Arg *> *AllocatedArgs) const { 15855ffd83dbSDimitry Andric DerivedArgList *DAL = new DerivedArgList(Args.getBaseArgs()); 15865ffd83dbSDimitry Andric bool Modified = false; 15875ffd83dbSDimitry Andric 1588bdd1243dSDimitry Andric bool IsDevice = OFK != Action::OFK_None && OFK != Action::OFK_Host; 15895ffd83dbSDimitry Andric for (Arg *A : Args) { 15905ffd83dbSDimitry Andric bool NeedTrans = false; 15915ffd83dbSDimitry Andric bool Skip = false; 15925ffd83dbSDimitry Andric if (A->getOption().matches(options::OPT_Xarch_device)) { 1593bdd1243dSDimitry Andric NeedTrans = IsDevice; 1594bdd1243dSDimitry Andric Skip = !IsDevice; 15955ffd83dbSDimitry Andric } else if (A->getOption().matches(options::OPT_Xarch_host)) { 1596bdd1243dSDimitry Andric NeedTrans = !IsDevice; 1597bdd1243dSDimitry Andric Skip = IsDevice; 1598bdd1243dSDimitry Andric } else if (A->getOption().matches(options::OPT_Xarch__) && IsDevice) { 15995ffd83dbSDimitry Andric // Do not translate -Xarch_ options for non CUDA/HIP toolchain since 16005ffd83dbSDimitry Andric // they may need special translation. 16015ffd83dbSDimitry Andric // Skip this argument unless the architecture matches BoundArch 16025ffd83dbSDimitry Andric if (BoundArch.empty() || A->getValue(0) != BoundArch) 16035ffd83dbSDimitry Andric Skip = true; 16045ffd83dbSDimitry Andric else 16055ffd83dbSDimitry Andric NeedTrans = true; 16065ffd83dbSDimitry Andric } 16075ffd83dbSDimitry Andric if (NeedTrans || Skip) 16085ffd83dbSDimitry Andric Modified = true; 16095ffd83dbSDimitry Andric if (NeedTrans) 16105ffd83dbSDimitry Andric TranslateXarchArgs(Args, A, DAL, AllocatedArgs); 16115ffd83dbSDimitry Andric if (!Skip) 16125ffd83dbSDimitry Andric DAL->append(A); 16135ffd83dbSDimitry Andric } 16145ffd83dbSDimitry Andric 16155ffd83dbSDimitry Andric if (Modified) 16165ffd83dbSDimitry Andric return DAL; 16175ffd83dbSDimitry Andric 16185ffd83dbSDimitry Andric delete DAL; 16195ffd83dbSDimitry Andric return nullptr; 16205ffd83dbSDimitry Andric } 1621