xref: /freebsd-src/contrib/llvm-project/clang/lib/Driver/ToolChain.cpp (revision 0fca6ea1d4eea4c934cfff25ac9ee8ad6fe95583)
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