1901 lines · cpp
1//===- ToolChain.cpp - Collections of tools for one platform --------------===//2//3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.4// See https://llvm.org/LICENSE.txt for license information.5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception6//7//===----------------------------------------------------------------------===//8 9#include "clang/Driver/ToolChain.h"10#include "ToolChains/Arch/AArch64.h"11#include "ToolChains/Arch/ARM.h"12#include "ToolChains/Arch/RISCV.h"13#include "ToolChains/Clang.h"14#include "ToolChains/Flang.h"15#include "ToolChains/InterfaceStubs.h"16#include "clang/Basic/ObjCRuntime.h"17#include "clang/Basic/Sanitizers.h"18#include "clang/Config/config.h"19#include "clang/Driver/Action.h"20#include "clang/Driver/CommonArgs.h"21#include "clang/Driver/Driver.h"22#include "clang/Driver/InputInfo.h"23#include "clang/Driver/Job.h"24#include "clang/Driver/SanitizerArgs.h"25#include "clang/Driver/XRayArgs.h"26#include "clang/Options/Options.h"27#include "llvm/ADT/SmallString.h"28#include "llvm/ADT/StringExtras.h"29#include "llvm/ADT/StringRef.h"30#include "llvm/ADT/Twine.h"31#include "llvm/Config/llvm-config.h"32#include "llvm/MC/MCTargetOptions.h"33#include "llvm/MC/TargetRegistry.h"34#include "llvm/Option/Arg.h"35#include "llvm/Option/ArgList.h"36#include "llvm/Option/OptTable.h"37#include "llvm/Option/Option.h"38#include "llvm/Support/ErrorHandling.h"39#include "llvm/Support/FileSystem.h"40#include "llvm/Support/FileUtilities.h"41#include "llvm/Support/Path.h"42#include "llvm/Support/Process.h"43#include "llvm/Support/VersionTuple.h"44#include "llvm/Support/VirtualFileSystem.h"45#include "llvm/TargetParser/AArch64TargetParser.h"46#include "llvm/TargetParser/RISCVISAInfo.h"47#include "llvm/TargetParser/TargetParser.h"48#include "llvm/TargetParser/Triple.h"49#include <cassert>50#include <cstddef>51#include <cstring>52#include <string>53 54using namespace clang;55using namespace driver;56using namespace tools;57using namespace llvm;58using namespace llvm::opt;59 60static llvm::opt::Arg *GetRTTIArgument(const ArgList &Args) {61 return Args.getLastArg(options::OPT_mkernel, options::OPT_fapple_kext,62 options::OPT_fno_rtti, options::OPT_frtti);63}64 65static ToolChain::RTTIMode CalculateRTTIMode(const ArgList &Args,66 const llvm::Triple &Triple,67 const Arg *CachedRTTIArg) {68 // Explicit rtti/no-rtti args69 if (CachedRTTIArg) {70 if (CachedRTTIArg->getOption().matches(options::OPT_frtti))71 return ToolChain::RM_Enabled;72 else73 return ToolChain::RM_Disabled;74 }75 76 // -frtti is default, except for the PS4/PS5 and DriverKit.77 bool NoRTTI = Triple.isPS() || Triple.isDriverKit();78 return NoRTTI ? ToolChain::RM_Disabled : ToolChain::RM_Enabled;79}80 81static ToolChain::ExceptionsMode CalculateExceptionsMode(const ArgList &Args) {82 if (Args.hasFlag(options::OPT_fexceptions, options::OPT_fno_exceptions,83 true)) {84 return ToolChain::EM_Enabled;85 }86 return ToolChain::EM_Disabled;87}88 89ToolChain::ToolChain(const Driver &D, const llvm::Triple &T,90 const ArgList &Args)91 : D(D), Triple(T), Args(Args), CachedRTTIArg(GetRTTIArgument(Args)),92 CachedRTTIMode(CalculateRTTIMode(Args, Triple, CachedRTTIArg)),93 CachedExceptionsMode(CalculateExceptionsMode(Args)) {94 auto addIfExists = [this](path_list &List, const std::string &Path) {95 if (getVFS().exists(Path))96 List.push_back(Path);97 };98 99 if (std::optional<std::string> Path = getRuntimePath())100 getLibraryPaths().push_back(*Path);101 if (std::optional<std::string> Path = getStdlibPath())102 getFilePaths().push_back(*Path);103 for (const auto &Path : getArchSpecificLibPaths())104 addIfExists(getFilePaths(), Path);105}106 107void ToolChain::setTripleEnvironment(llvm::Triple::EnvironmentType Env) {108 Triple.setEnvironment(Env);109 if (EffectiveTriple != llvm::Triple())110 EffectiveTriple.setEnvironment(Env);111}112 113ToolChain::~ToolChain() = default;114 115llvm::vfs::FileSystem &ToolChain::getVFS() const {116 return getDriver().getVFS();117}118 119bool ToolChain::useIntegratedAs() const {120 return Args.hasFlag(options::OPT_fintegrated_as,121 options::OPT_fno_integrated_as,122 IsIntegratedAssemblerDefault());123}124 125bool ToolChain::useIntegratedBackend() const {126 assert(127 ((IsIntegratedBackendDefault() && IsIntegratedBackendSupported()) ||128 (!IsIntegratedBackendDefault() || IsNonIntegratedBackendSupported())) &&129 "(Non-)integrated backend set incorrectly!");130 131 bool IBackend = Args.hasFlag(options::OPT_fintegrated_objemitter,132 options::OPT_fno_integrated_objemitter,133 IsIntegratedBackendDefault());134 135 // Diagnose when integrated-objemitter options are not supported by this136 // toolchain.137 unsigned DiagID;138 if ((IBackend && !IsIntegratedBackendSupported()) ||139 (!IBackend && !IsNonIntegratedBackendSupported()))140 DiagID = clang::diag::err_drv_unsupported_opt_for_target;141 else142 DiagID = clang::diag::warn_drv_unsupported_opt_for_target;143 Arg *A = Args.getLastArg(options::OPT_fno_integrated_objemitter);144 if (A && !IsNonIntegratedBackendSupported())145 D.Diag(DiagID) << A->getAsString(Args) << Triple.getTriple();146 A = Args.getLastArg(options::OPT_fintegrated_objemitter);147 if (A && !IsIntegratedBackendSupported())148 D.Diag(DiagID) << A->getAsString(Args) << Triple.getTriple();149 150 return IBackend;151}152 153bool ToolChain::useRelaxRelocations() const {154 return ENABLE_X86_RELAX_RELOCATIONS;155}156 157bool ToolChain::defaultToIEEELongDouble() const {158 return PPC_LINUX_DEFAULT_IEEELONGDOUBLE && getTriple().isOSLinux();159}160 161static void processMultilibCustomFlags(Multilib::flags_list &List,162 const llvm::opt::ArgList &Args) {163 for (const Arg *MultilibFlagArg :164 Args.filtered(options::OPT_fmultilib_flag)) {165 List.push_back(MultilibFlagArg->getAsString(Args));166 MultilibFlagArg->claim();167 }168}169 170static void getAArch64MultilibFlags(const Driver &D,171 const llvm::Triple &Triple,172 const llvm::opt::ArgList &Args,173 Multilib::flags_list &Result) {174 std::vector<StringRef> Features;175 tools::aarch64::getAArch64TargetFeatures(D, Triple, Args, Features,176 /*ForAS=*/false,177 /*ForMultilib=*/true);178 const auto UnifiedFeatures = tools::unifyTargetFeatures(Features);179 llvm::DenseSet<StringRef> FeatureSet(UnifiedFeatures.begin(),180 UnifiedFeatures.end());181 std::vector<std::string> MArch;182 for (const auto &Ext : AArch64::Extensions)183 if (!Ext.UserVisibleName.empty())184 if (FeatureSet.contains(Ext.PosTargetFeature))185 MArch.push_back(Ext.UserVisibleName.str());186 for (const auto &Ext : AArch64::Extensions)187 if (!Ext.UserVisibleName.empty())188 if (FeatureSet.contains(Ext.NegTargetFeature))189 MArch.push_back(("no" + Ext.UserVisibleName).str());190 StringRef ArchName;191 for (const auto &ArchInfo : AArch64::ArchInfos)192 if (FeatureSet.contains(ArchInfo->ArchFeature))193 ArchName = ArchInfo->Name;194 if (!ArchName.empty()) {195 MArch.insert(MArch.begin(), ("-march=" + ArchName).str());196 Result.push_back(llvm::join(MArch, "+"));197 }198 199 const Arg *BranchProtectionArg =200 Args.getLastArgNoClaim(options::OPT_mbranch_protection_EQ);201 if (BranchProtectionArg) {202 Result.push_back(BranchProtectionArg->getAsString(Args));203 }204 205 if (FeatureSet.contains("+strict-align"))206 Result.push_back("-mno-unaligned-access");207 else208 Result.push_back("-munaligned-access");209 210 if (Arg *Endian = Args.getLastArg(options::OPT_mbig_endian,211 options::OPT_mlittle_endian)) {212 if (Endian->getOption().matches(options::OPT_mbig_endian))213 Result.push_back(Endian->getAsString(Args));214 }215 216 const Arg *ABIArg = Args.getLastArgNoClaim(options::OPT_mabi_EQ);217 if (ABIArg) {218 Result.push_back(ABIArg->getAsString(Args));219 }220 221 if (const Arg *A = Args.getLastArg(options::OPT_O_Group);222 A && A->getOption().matches(options::OPT_O)) {223 switch (A->getValue()[0]) {224 case 's':225 Result.push_back("-Os");226 break;227 case 'z':228 Result.push_back("-Oz");229 break;230 }231 }232 233 processMultilibCustomFlags(Result, Args);234}235 236static void getARMMultilibFlags(const Driver &D, const llvm::Triple &Triple,237 llvm::Reloc::Model RelocationModel,238 const llvm::opt::ArgList &Args,239 Multilib::flags_list &Result) {240 std::vector<StringRef> Features;241 llvm::ARM::FPUKind FPUKind = tools::arm::getARMTargetFeatures(242 D, Triple, Args, Features, false /*ForAs*/, true /*ForMultilib*/);243 const auto UnifiedFeatures = tools::unifyTargetFeatures(Features);244 llvm::DenseSet<StringRef> FeatureSet(UnifiedFeatures.begin(),245 UnifiedFeatures.end());246 std::vector<std::string> MArch;247 for (const auto &Ext : ARM::ARCHExtNames)248 if (!Ext.Name.empty())249 if (FeatureSet.contains(Ext.Feature))250 MArch.push_back(Ext.Name.str());251 for (const auto &Ext : ARM::ARCHExtNames)252 if (!Ext.Name.empty())253 if (FeatureSet.contains(Ext.NegFeature))254 MArch.push_back(("no" + Ext.Name).str());255 MArch.insert(MArch.begin(), ("-march=" + Triple.getArchName()).str());256 Result.push_back(llvm::join(MArch, "+"));257 258 switch (FPUKind) {259#define ARM_FPU(NAME, KIND, VERSION, NEON_SUPPORT, RESTRICTION) \260 case llvm::ARM::KIND: \261 Result.push_back("-mfpu=" NAME); \262 break;263#include "llvm/TargetParser/ARMTargetParser.def"264 default:265 llvm_unreachable("Invalid FPUKind");266 }267 268 switch (arm::getARMFloatABI(D, Triple, Args)) {269 case arm::FloatABI::Soft:270 Result.push_back("-mfloat-abi=soft");271 break;272 case arm::FloatABI::SoftFP:273 Result.push_back("-mfloat-abi=softfp");274 break;275 case arm::FloatABI::Hard:276 Result.push_back("-mfloat-abi=hard");277 break;278 case arm::FloatABI::Invalid:279 llvm_unreachable("Invalid float ABI");280 }281 282 if (RelocationModel == llvm::Reloc::ROPI ||283 RelocationModel == llvm::Reloc::ROPI_RWPI)284 Result.push_back("-fropi");285 else286 Result.push_back("-fno-ropi");287 288 if (RelocationModel == llvm::Reloc::RWPI ||289 RelocationModel == llvm::Reloc::ROPI_RWPI)290 Result.push_back("-frwpi");291 else292 Result.push_back("-fno-rwpi");293 294 const Arg *BranchProtectionArg =295 Args.getLastArgNoClaim(options::OPT_mbranch_protection_EQ);296 if (BranchProtectionArg) {297 Result.push_back(BranchProtectionArg->getAsString(Args));298 }299 300 if (FeatureSet.contains("+strict-align"))301 Result.push_back("-mno-unaligned-access");302 else303 Result.push_back("-munaligned-access");304 305 if (Arg *Endian = Args.getLastArg(options::OPT_mbig_endian,306 options::OPT_mlittle_endian)) {307 if (Endian->getOption().matches(options::OPT_mbig_endian))308 Result.push_back(Endian->getAsString(Args));309 }310 311 if (const Arg *A = Args.getLastArg(options::OPT_O_Group);312 A && A->getOption().matches(options::OPT_O)) {313 switch (A->getValue()[0]) {314 case 's':315 Result.push_back("-Os");316 break;317 case 'z':318 Result.push_back("-Oz");319 break;320 }321 }322 323 processMultilibCustomFlags(Result, Args);324}325 326static void getRISCVMultilibFlags(const Driver &D, const llvm::Triple &Triple,327 const llvm::opt::ArgList &Args,328 Multilib::flags_list &Result) {329 std::string Arch = riscv::getRISCVArch(Args, Triple);330 // Canonicalize arch for easier matching331 auto ISAInfo = llvm::RISCVISAInfo::parseArchString(332 Arch, /*EnableExperimentalExtensions*/ true);333 if (!llvm::errorToBool(ISAInfo.takeError()))334 Result.push_back("-march=" + (*ISAInfo)->toString());335 336 Result.push_back(("-mabi=" + riscv::getRISCVABI(Args, Triple)).str());337}338 339Multilib::flags_list340ToolChain::getMultilibFlags(const llvm::opt::ArgList &Args) const {341 using namespace clang::options;342 343 std::vector<std::string> Result;344 const llvm::Triple Triple(ComputeEffectiveClangTriple(Args));345 Result.push_back("--target=" + Triple.str());346 347 // A difference of relocation model (absolutely addressed data, PIC, Arm348 // ROPI/RWPI) is likely to change whether a particular multilib variant is349 // compatible with a given link. Determine the relocation model of the350 // current link, so as to add appropriate multilib flags.351 llvm::Reloc::Model RelocationModel;352 unsigned PICLevel;353 bool IsPIE;354 {355 RegisterEffectiveTriple TripleRAII(*this, Triple);356 std::tie(RelocationModel, PICLevel, IsPIE) = ParsePICArgs(*this, Args);357 }358 359 switch (Triple.getArch()) {360 case llvm::Triple::aarch64:361 case llvm::Triple::aarch64_32:362 case llvm::Triple::aarch64_be:363 getAArch64MultilibFlags(D, Triple, Args, Result);364 break;365 case llvm::Triple::arm:366 case llvm::Triple::armeb:367 case llvm::Triple::thumb:368 case llvm::Triple::thumbeb:369 getARMMultilibFlags(D, Triple, RelocationModel, Args, Result);370 break;371 case llvm::Triple::riscv32:372 case llvm::Triple::riscv64:373 getRISCVMultilibFlags(D, Triple, Args, Result);374 break;375 default:376 break;377 }378 379 // Include fno-exceptions and fno-rtti380 // to improve multilib selection381 if (getRTTIMode() == ToolChain::RTTIMode::RM_Disabled)382 Result.push_back("-fno-rtti");383 else384 Result.push_back("-frtti");385 386 if (getExceptionsMode() == ToolChain::ExceptionsMode::EM_Disabled)387 Result.push_back("-fno-exceptions");388 else389 Result.push_back("-fexceptions");390 391 if (RelocationModel == llvm::Reloc::PIC_)392 Result.push_back(IsPIE ? (PICLevel > 1 ? "-fPIE" : "-fpie")393 : (PICLevel > 1 ? "-fPIC" : "-fpic"));394 else395 Result.push_back("-fno-pic");396 397 // Sort and remove duplicates.398 std::sort(Result.begin(), Result.end());399 Result.erase(llvm::unique(Result), Result.end());400 return Result;401}402 403SanitizerArgs404ToolChain::getSanitizerArgs(const llvm::opt::ArgList &JobArgs) const {405 SanitizerArgs SanArgs(*this, JobArgs, !SanitizerArgsChecked);406 SanitizerArgsChecked = true;407 return SanArgs;408}409 410const XRayArgs ToolChain::getXRayArgs(const llvm::opt::ArgList &JobArgs) const {411 XRayArgs XRayArguments(*this, JobArgs);412 return XRayArguments;413}414 415namespace {416 417struct DriverSuffix {418 const char *Suffix;419 const char *ModeFlag;420};421 422} // namespace423 424static const DriverSuffix *FindDriverSuffix(StringRef ProgName, size_t &Pos) {425 // A list of known driver suffixes. Suffixes are compared against the426 // program name in order. If there is a match, the frontend type is updated as427 // necessary by applying the ModeFlag.428 static const DriverSuffix DriverSuffixes[] = {429 {"clang", nullptr},430 {"clang++", "--driver-mode=g++"},431 {"clang-c++", "--driver-mode=g++"},432 {"clang-cc", nullptr},433 {"clang-cpp", "--driver-mode=cpp"},434 {"clang-g++", "--driver-mode=g++"},435 {"clang-gcc", nullptr},436 {"clang-cl", "--driver-mode=cl"},437 {"cc", nullptr},438 {"cpp", "--driver-mode=cpp"},439 {"cl", "--driver-mode=cl"},440 {"++", "--driver-mode=g++"},441 {"flang", "--driver-mode=flang"},442 // For backwards compatibility, we create a symlink for `flang` called443 // `flang-new`. This will be removed in the future.444 {"flang-new", "--driver-mode=flang"},445 {"clang-dxc", "--driver-mode=dxc"},446 };447 448 for (const auto &DS : DriverSuffixes) {449 StringRef Suffix(DS.Suffix);450 if (ProgName.ends_with(Suffix)) {451 Pos = ProgName.size() - Suffix.size();452 return &DS;453 }454 }455 return nullptr;456}457 458/// Normalize the program name from argv[0] by stripping the file extension if459/// present and lower-casing the string on Windows.460static std::string normalizeProgramName(llvm::StringRef Argv0) {461 std::string ProgName = std::string(llvm::sys::path::filename(Argv0));462 if (is_style_windows(llvm::sys::path::Style::native)) {463 // Transform to lowercase for case insensitive file systems.464 std::transform(ProgName.begin(), ProgName.end(), ProgName.begin(),465 ::tolower);466 }467 return ProgName;468}469 470static const DriverSuffix *parseDriverSuffix(StringRef ProgName, size_t &Pos) {471 // Try to infer frontend type and default target from the program name by472 // comparing it against DriverSuffixes in order.473 474 // If there is a match, the function tries to identify a target as prefix.475 // E.g. "x86_64-linux-clang" as interpreted as suffix "clang" with target476 // prefix "x86_64-linux". If such a target prefix is found, it may be477 // added via -target as implicit first argument.478 const DriverSuffix *DS = FindDriverSuffix(ProgName, Pos);479 480 if (!DS && ProgName.ends_with(".exe")) {481 // Try again after stripping the executable suffix:482 // clang++.exe -> clang++483 ProgName = ProgName.drop_back(StringRef(".exe").size());484 DS = FindDriverSuffix(ProgName, Pos);485 }486 487 if (!DS) {488 // Try again after stripping any trailing version number:489 // clang++3.5 -> clang++490 ProgName = ProgName.rtrim("0123456789.");491 DS = FindDriverSuffix(ProgName, Pos);492 }493 494 if (!DS) {495 // Try again after stripping trailing -component.496 // clang++-tot -> clang++497 ProgName = ProgName.slice(0, ProgName.rfind('-'));498 DS = FindDriverSuffix(ProgName, Pos);499 }500 return DS;501}502 503ParsedClangName504ToolChain::getTargetAndModeFromProgramName(StringRef PN) {505 std::string ProgName = normalizeProgramName(PN);506 size_t SuffixPos;507 const DriverSuffix *DS = parseDriverSuffix(ProgName, SuffixPos);508 if (!DS)509 return {};510 size_t SuffixEnd = SuffixPos + strlen(DS->Suffix);511 512 size_t LastComponent = ProgName.rfind('-', SuffixPos);513 if (LastComponent == std::string::npos)514 return ParsedClangName(ProgName.substr(0, SuffixEnd), DS->ModeFlag);515 std::string ModeSuffix = ProgName.substr(LastComponent + 1,516 SuffixEnd - LastComponent - 1);517 518 // Infer target from the prefix.519 StringRef Prefix(ProgName);520 Prefix = Prefix.slice(0, LastComponent);521 std::string IgnoredError;522 523 llvm::Triple Triple(Prefix);524 bool IsRegistered = llvm::TargetRegistry::lookupTarget(Triple, IgnoredError);525 return ParsedClangName{std::string(Prefix), ModeSuffix, DS->ModeFlag,526 IsRegistered};527}528 529StringRef ToolChain::getDefaultUniversalArchName() const {530 // In universal driver terms, the arch name accepted by -arch isn't exactly531 // the same as the ones that appear in the triple. Roughly speaking, this is532 // an inverse of the darwin::getArchTypeForDarwinArchName() function.533 switch (Triple.getArch()) {534 case llvm::Triple::aarch64: {535 if (getTriple().isArm64e())536 return "arm64e";537 return "arm64";538 }539 case llvm::Triple::aarch64_32:540 return "arm64_32";541 case llvm::Triple::ppc:542 return "ppc";543 case llvm::Triple::ppcle:544 return "ppcle";545 case llvm::Triple::ppc64:546 return "ppc64";547 case llvm::Triple::ppc64le:548 return "ppc64le";549 default:550 return Triple.getArchName();551 }552}553 554std::string ToolChain::getInputFilename(const InputInfo &Input) const {555 return Input.getFilename();556}557 558ToolChain::UnwindTableLevel559ToolChain::getDefaultUnwindTableLevel(const ArgList &Args) const {560 return UnwindTableLevel::None;561}562 563Tool *ToolChain::getClang() const {564 if (!Clang)565 Clang.reset(new tools::Clang(*this, useIntegratedBackend()));566 return Clang.get();567}568 569Tool *ToolChain::getFlang() const {570 if (!Flang)571 Flang.reset(new tools::Flang(*this));572 return Flang.get();573}574 575Tool *ToolChain::buildAssembler() const {576 return new tools::ClangAs(*this);577}578 579Tool *ToolChain::buildLinker() const {580 llvm_unreachable("Linking is not supported by this toolchain");581}582 583Tool *ToolChain::buildStaticLibTool() const {584 llvm_unreachable("Creating static lib is not supported by this toolchain");585}586 587Tool *ToolChain::getAssemble() const {588 if (!Assemble)589 Assemble.reset(buildAssembler());590 return Assemble.get();591}592 593Tool *ToolChain::getClangAs() const {594 if (!Assemble)595 Assemble.reset(new tools::ClangAs(*this));596 return Assemble.get();597}598 599Tool *ToolChain::getLink() const {600 if (!Link)601 Link.reset(buildLinker());602 return Link.get();603}604 605Tool *ToolChain::getStaticLibTool() const {606 if (!StaticLibTool)607 StaticLibTool.reset(buildStaticLibTool());608 return StaticLibTool.get();609}610 611Tool *ToolChain::getIfsMerge() const {612 if (!IfsMerge)613 IfsMerge.reset(new tools::ifstool::Merger(*this));614 return IfsMerge.get();615}616 617Tool *ToolChain::getOffloadBundler() const {618 if (!OffloadBundler)619 OffloadBundler.reset(new tools::OffloadBundler(*this));620 return OffloadBundler.get();621}622 623Tool *ToolChain::getOffloadPackager() const {624 if (!OffloadPackager)625 OffloadPackager.reset(new tools::OffloadPackager(*this));626 return OffloadPackager.get();627}628 629Tool *ToolChain::getLinkerWrapper() const {630 if (!LinkerWrapper)631 LinkerWrapper.reset(new tools::LinkerWrapper(*this, getLink()));632 return LinkerWrapper.get();633}634 635Tool *ToolChain::getTool(Action::ActionClass AC) const {636 switch (AC) {637 case Action::AssembleJobClass:638 return getAssemble();639 640 case Action::IfsMergeJobClass:641 return getIfsMerge();642 643 case Action::LinkJobClass:644 return getLink();645 646 case Action::StaticLibJobClass:647 return getStaticLibTool();648 649 case Action::InputClass:650 case Action::BindArchClass:651 case Action::OffloadClass:652 case Action::LipoJobClass:653 case Action::DsymutilJobClass:654 case Action::VerifyDebugInfoJobClass:655 case Action::BinaryAnalyzeJobClass:656 case Action::BinaryTranslatorJobClass:657 case Action::ObjcopyJobClass:658 llvm_unreachable("Invalid tool kind.");659 660 case Action::CompileJobClass:661 case Action::PrecompileJobClass:662 case Action::PreprocessJobClass:663 case Action::ExtractAPIJobClass:664 case Action::AnalyzeJobClass:665 case Action::VerifyPCHJobClass:666 case Action::BackendJobClass:667 return getClang();668 669 case Action::OffloadBundlingJobClass:670 case Action::OffloadUnbundlingJobClass:671 return getOffloadBundler();672 673 case Action::OffloadPackagerJobClass:674 return getOffloadPackager();675 case Action::LinkerWrapperJobClass:676 return getLinkerWrapper();677 }678 679 llvm_unreachable("Invalid tool kind.");680}681 682static StringRef getArchNameForCompilerRTLib(const ToolChain &TC,683 const ArgList &Args) {684 const llvm::Triple &Triple = TC.getTriple();685 bool IsWindows = Triple.isOSWindows();686 687 if (TC.isBareMetal())688 return Triple.getArchName();689 690 if (TC.getArch() == llvm::Triple::arm || TC.getArch() == llvm::Triple::armeb)691 return (arm::getARMFloatABI(TC, Args) == arm::FloatABI::Hard && !IsWindows)692 ? "armhf"693 : "arm";694 695 // For historic reasons, Android library is using i686 instead of i386.696 if (TC.getArch() == llvm::Triple::x86 && Triple.isAndroid())697 return "i686";698 699 if (TC.getArch() == llvm::Triple::x86_64 && Triple.isX32())700 return "x32";701 702 return llvm::Triple::getArchTypeName(TC.getArch());703}704 705StringRef ToolChain::getOSLibName() const {706 if (Triple.isOSDarwin())707 return "darwin";708 709 switch (Triple.getOS()) {710 case llvm::Triple::FreeBSD:711 return "freebsd";712 case llvm::Triple::NetBSD:713 return "netbsd";714 case llvm::Triple::OpenBSD:715 return "openbsd";716 case llvm::Triple::Solaris:717 return "sunos";718 case llvm::Triple::AIX:719 return "aix";720 default:721 return getOS();722 }723}724 725std::string ToolChain::getCompilerRTPath() const {726 SmallString<128> Path(getDriver().ResourceDir);727 if (isBareMetal()) {728 llvm::sys::path::append(Path, "lib", getOSLibName());729 if (!SelectedMultilibs.empty()) {730 Path += SelectedMultilibs.back().gccSuffix();731 }732 } else if (Triple.isOSUnknown()) {733 llvm::sys::path::append(Path, "lib");734 } else {735 llvm::sys::path::append(Path, "lib", getOSLibName());736 }737 return std::string(Path);738}739 740std::string ToolChain::getCompilerRTBasename(const ArgList &Args,741 StringRef Component,742 FileType Type) const {743 std::string CRTAbsolutePath = getCompilerRT(Args, Component, Type);744 return llvm::sys::path::filename(CRTAbsolutePath).str();745}746 747std::string ToolChain::buildCompilerRTBasename(const llvm::opt::ArgList &Args,748 StringRef Component,749 FileType Type, bool AddArch,750 bool IsFortran) const {751 const llvm::Triple &TT = getTriple();752 bool IsITANMSVCWindows =753 TT.isWindowsMSVCEnvironment() || TT.isWindowsItaniumEnvironment();754 755 const char *Prefix =756 IsITANMSVCWindows || Type == ToolChain::FT_Object ? "" : "lib";757 const char *Suffix;758 switch (Type) {759 case ToolChain::FT_Object:760 Suffix = IsITANMSVCWindows ? ".obj" : ".o";761 break;762 case ToolChain::FT_Static:763 Suffix = IsITANMSVCWindows ? ".lib" : ".a";764 break;765 case ToolChain::FT_Shared:766 if (TT.isOSWindows())767 Suffix = TT.isOSCygMing() ? ".dll.a" : ".lib";768 else if (TT.isOSAIX())769 Suffix = ".a";770 else771 Suffix = ".so";772 break;773 }774 775 std::string ArchAndEnv;776 if (AddArch) {777 StringRef Arch = getArchNameForCompilerRTLib(*this, Args);778 const char *Env = TT.isAndroid() ? "-android" : "";779 ArchAndEnv = ("-" + Arch + Env).str();780 }781 782 std::string LibName = IsFortran ? "flang_rt." : "clang_rt.";783 return (Prefix + Twine(LibName) + Component + ArchAndEnv + Suffix).str();784}785 786std::string ToolChain::getCompilerRT(const ArgList &Args, StringRef Component,787 FileType Type, bool IsFortran) const {788 // Check for runtime files in the new layout without the architecture first.789 std::string CRTBasename = buildCompilerRTBasename(790 Args, Component, Type, /*AddArch=*/false, IsFortran);791 SmallString<128> Path;792 for (const auto &LibPath : getLibraryPaths()) {793 SmallString<128> P(LibPath);794 llvm::sys::path::append(P, CRTBasename);795 if (getVFS().exists(P))796 return std::string(P);797 if (Path.empty())798 Path = P;799 }800 801 // Check the filename for the old layout if the new one does not exist.802 CRTBasename = buildCompilerRTBasename(Args, Component, Type,803 /*AddArch=*/!IsFortran, IsFortran);804 SmallString<128> OldPath(getCompilerRTPath());805 llvm::sys::path::append(OldPath, CRTBasename);806 if (Path.empty() || getVFS().exists(OldPath))807 return std::string(OldPath);808 809 // If none is found, use a file name from the new layout, which may get810 // printed in an error message, aiding users in knowing what Clang is811 // looking for.812 return std::string(Path);813}814 815const char *ToolChain::getCompilerRTArgString(const llvm::opt::ArgList &Args,816 StringRef Component,817 FileType Type,818 bool isFortran) const {819 return Args.MakeArgString(getCompilerRT(Args, Component, Type, isFortran));820}821 822/// Add Fortran runtime libs823void ToolChain::addFortranRuntimeLibs(const ArgList &Args,824 llvm::opt::ArgStringList &CmdArgs) const {825 // Link flang_rt.runtime826 // These are handled earlier on Windows by telling the frontend driver to827 // add the correct libraries to link against as dependents in the object828 // file.829 if (!getTriple().isKnownWindowsMSVCEnvironment()) {830 StringRef F128LibName = getDriver().getFlangF128MathLibrary();831 F128LibName.consume_front_insensitive("lib");832 if (!F128LibName.empty()) {833 bool AsNeeded = !getTriple().isOSAIX();834 CmdArgs.push_back("-lflang_rt.quadmath");835 if (AsNeeded)836 addAsNeededOption(*this, Args, CmdArgs, /*as_needed=*/true);837 CmdArgs.push_back(Args.MakeArgString("-l" + F128LibName));838 if (AsNeeded)839 addAsNeededOption(*this, Args, CmdArgs, /*as_needed=*/false);840 }841 addFlangRTLibPath(Args, CmdArgs);842 843 // needs libexecinfo for backtrace functions844 if (getTriple().isOSFreeBSD() || getTriple().isOSNetBSD() ||845 getTriple().isOSOpenBSD() || getTriple().isOSDragonFly())846 CmdArgs.push_back("-lexecinfo");847 }848 849 // libomp needs libatomic for atomic operations if using libgcc850 if (Args.hasFlag(options::OPT_fopenmp, options::OPT_fopenmp_EQ,851 options::OPT_fno_openmp, false)) {852 Driver::OpenMPRuntimeKind OMPRuntime = getDriver().getOpenMPRuntime(Args);853 ToolChain::RuntimeLibType RuntimeLib = GetRuntimeLibType(Args);854 if ((OMPRuntime == Driver::OMPRT_OMP &&855 RuntimeLib == ToolChain::RLT_Libgcc) &&856 !getTriple().isKnownWindowsMSVCEnvironment()) {857 CmdArgs.push_back("-latomic");858 }859 }860}861 862void ToolChain::addFortranRuntimeLibraryPath(const llvm::opt::ArgList &Args,863 ArgStringList &CmdArgs) const {864 auto AddLibSearchPathIfExists = [&](const Twine &Path) {865 // Linker may emit warnings about non-existing directories866 if (!llvm::sys::fs::is_directory(Path))867 return;868 869 if (getTriple().isKnownWindowsMSVCEnvironment())870 CmdArgs.push_back(Args.MakeArgString("-libpath:" + Path));871 else872 CmdArgs.push_back(Args.MakeArgString("-L" + Path));873 };874 875 // Search for flang_rt.* at the same location as clang_rt.* with876 // LLVM_ENABLE_PER_TARGET_RUNTIME_DIR=0. On most platforms, flang_rt is877 // located at the path returned by getRuntimePath() which is already added to878 // the library search path. This exception is for Apple-Darwin.879 AddLibSearchPathIfExists(getCompilerRTPath());880 881 // Fall back to the non-resource directory <driver-path>/../lib. We will882 // probably have to refine this in the future. In particular, on some883 // platforms, we may need to use lib64 instead of lib.884 SmallString<256> DefaultLibPath =885 llvm::sys::path::parent_path(getDriver().Dir);886 llvm::sys::path::append(DefaultLibPath, "lib");887 AddLibSearchPathIfExists(DefaultLibPath);888}889 890void ToolChain::addFlangRTLibPath(const ArgList &Args,891 llvm::opt::ArgStringList &CmdArgs) const {892 // Link static flang_rt.runtime.a or shared flang_rt.runtime.so.893 // On AIX, default to static flang-rt.894 if (Args.hasFlag(options::OPT_static_libflangrt,895 options::OPT_shared_libflangrt, getTriple().isOSAIX()))896 CmdArgs.push_back(897 getCompilerRTArgString(Args, "runtime", ToolChain::FT_Static, true));898 else {899 CmdArgs.push_back("-lflang_rt.runtime");900 addArchSpecificRPath(*this, Args, CmdArgs);901 }902}903 904// Android target triples contain a target version. If we don't have libraries905// for the exact target version, we should fall back to the next newest version906// or a versionless path, if any.907std::optional<std::string>908ToolChain::getFallbackAndroidTargetPath(StringRef BaseDir) const {909 llvm::Triple TripleWithoutLevel(getTriple());910 TripleWithoutLevel.setEnvironmentName("android"); // remove any version number911 const std::string &TripleWithoutLevelStr = TripleWithoutLevel.str();912 unsigned TripleVersion = getTriple().getEnvironmentVersion().getMajor();913 unsigned BestVersion = 0;914 915 SmallString<32> TripleDir;916 bool UsingUnversionedDir = false;917 std::error_code EC;918 for (llvm::vfs::directory_iterator LI = getVFS().dir_begin(BaseDir, EC), LE;919 !EC && LI != LE; LI = LI.increment(EC)) {920 StringRef DirName = llvm::sys::path::filename(LI->path());921 StringRef DirNameSuffix = DirName;922 if (DirNameSuffix.consume_front(TripleWithoutLevelStr)) {923 if (DirNameSuffix.empty() && TripleDir.empty()) {924 TripleDir = DirName;925 UsingUnversionedDir = true;926 } else {927 unsigned Version;928 if (!DirNameSuffix.getAsInteger(10, Version) && Version > BestVersion &&929 Version < TripleVersion) {930 BestVersion = Version;931 TripleDir = DirName;932 UsingUnversionedDir = false;933 }934 }935 }936 }937 938 if (TripleDir.empty())939 return {};940 941 SmallString<128> P(BaseDir);942 llvm::sys::path::append(P, TripleDir);943 if (UsingUnversionedDir)944 D.Diag(diag::warn_android_unversioned_fallback) << P << getTripleString();945 return std::string(P);946}947 948llvm::Triple ToolChain::getTripleWithoutOSVersion() const {949 return (Triple.hasEnvironment()950 ? llvm::Triple(Triple.getArchName(), Triple.getVendorName(),951 llvm::Triple::getOSTypeName(Triple.getOS()),952 llvm::Triple::getEnvironmentTypeName(953 Triple.getEnvironment()))954 : llvm::Triple(Triple.getArchName(), Triple.getVendorName(),955 llvm::Triple::getOSTypeName(Triple.getOS())));956}957 958std::optional<std::string>959ToolChain::getTargetSubDirPath(StringRef BaseDir) const {960 auto getPathForTriple =961 [&](const llvm::Triple &Triple) -> std::optional<std::string> {962 SmallString<128> P(BaseDir);963 llvm::sys::path::append(P, Triple.str());964 if (getVFS().exists(P))965 return std::string(P);966 return {};967 };968 969 const llvm::Triple &T = getTriple();970 if (auto Path = getPathForTriple(T))971 return *Path;972 973 if (T.isOSAIX()) {974 llvm::Triple AIXTriple;975 if (T.getEnvironment() == Triple::UnknownEnvironment) {976 // Strip unknown environment and the OS version from the triple.977 AIXTriple = llvm::Triple(T.getArchName(), T.getVendorName(),978 llvm::Triple::getOSTypeName(T.getOS()));979 } else {980 // Strip the OS version from the triple.981 AIXTriple = getTripleWithoutOSVersion();982 }983 if (auto Path = getPathForTriple(AIXTriple))984 return *Path;985 }986 987 if (T.isOSzOS() &&988 (!T.getOSVersion().empty() || !T.getEnvironmentVersion().empty())) {989 // Build the triple without version information990 const llvm::Triple &TripleWithoutVersion = getTripleWithoutOSVersion();991 if (auto Path = getPathForTriple(TripleWithoutVersion))992 return *Path;993 }994 995 // When building with per target runtime directories, various ways of naming996 // the Arm architecture may have been normalised to simply "arm".997 // For example "armv8l" (Armv8 AArch32 little endian) is replaced with "arm".998 // Since an armv8l system can use libraries built for earlier architecture999 // versions assuming endian and float ABI match.1000 //1001 // Original triple: armv8l-unknown-linux-gnueabihf1002 // Runtime triple: arm-unknown-linux-gnueabihf1003 //1004 // We do not do this for armeb (big endian) because doing so could make us1005 // select little endian libraries. In addition, all known armeb triples only1006 // use the "armeb" architecture name.1007 //1008 // M profile Arm is bare metal and we know they will not be using the per1009 // target runtime directory layout.1010 if (T.getArch() == Triple::arm && !T.isArmMClass()) {1011 llvm::Triple ArmTriple = T;1012 ArmTriple.setArch(Triple::arm);1013 if (auto Path = getPathForTriple(ArmTriple))1014 return *Path;1015 }1016 1017 if (T.isAndroid())1018 return getFallbackAndroidTargetPath(BaseDir);1019 1020 return {};1021}1022 1023std::optional<std::string> ToolChain::getRuntimePath() const {1024 SmallString<128> P(D.ResourceDir);1025 llvm::sys::path::append(P, "lib");1026 if (auto Ret = getTargetSubDirPath(P))1027 return Ret;1028 // Darwin does not use per-target runtime directory.1029 if (Triple.isOSDarwin())1030 return {};1031 1032 llvm::sys::path::append(P, Triple.str());1033 return std::string(P);1034}1035 1036std::optional<std::string> ToolChain::getStdlibPath() const {1037 SmallString<128> P(D.Dir);1038 llvm::sys::path::append(P, "..", "lib");1039 return getTargetSubDirPath(P);1040}1041 1042std::optional<std::string> ToolChain::getStdlibIncludePath() const {1043 SmallString<128> P(D.Dir);1044 llvm::sys::path::append(P, "..", "include");1045 return getTargetSubDirPath(P);1046}1047 1048ToolChain::path_list ToolChain::getArchSpecificLibPaths() const {1049 path_list Paths;1050 1051 auto AddPath = [&](const ArrayRef<StringRef> &SS) {1052 SmallString<128> Path(getDriver().ResourceDir);1053 llvm::sys::path::append(Path, "lib");1054 for (auto &S : SS)1055 llvm::sys::path::append(Path, S);1056 Paths.push_back(std::string(Path));1057 };1058 1059 AddPath({getTriple().str()});1060 AddPath({getOSLibName(), llvm::Triple::getArchTypeName(getArch())});1061 return Paths;1062}1063 1064bool ToolChain::needsProfileRT(const ArgList &Args) {1065 if (Args.hasArg(options::OPT_noprofilelib))1066 return false;1067 1068 return Args.hasArg(options::OPT_fprofile_generate) ||1069 Args.hasArg(options::OPT_fprofile_generate_EQ) ||1070 Args.hasArg(options::OPT_fcs_profile_generate) ||1071 Args.hasArg(options::OPT_fcs_profile_generate_EQ) ||1072 Args.hasArg(options::OPT_fprofile_instr_generate) ||1073 Args.hasArg(options::OPT_fprofile_instr_generate_EQ) ||1074 Args.hasArg(options::OPT_fcreate_profile) ||1075 Args.hasArg(options::OPT_fprofile_generate_cold_function_coverage) ||1076 Args.hasArg(options::OPT_fprofile_generate_cold_function_coverage_EQ);1077}1078 1079bool ToolChain::needsGCovInstrumentation(const llvm::opt::ArgList &Args) {1080 return Args.hasArg(options::OPT_coverage) ||1081 Args.hasFlag(options::OPT_fprofile_arcs, options::OPT_fno_profile_arcs,1082 false);1083}1084 1085Tool *ToolChain::SelectTool(const JobAction &JA) const {1086 if (D.IsFlangMode() && getDriver().ShouldUseFlangCompiler(JA)) return getFlang();1087 if (getDriver().ShouldUseClangCompiler(JA)) return getClang();1088 Action::ActionClass AC = JA.getKind();1089 if (AC == Action::AssembleJobClass && useIntegratedAs() &&1090 !getTriple().isOSAIX())1091 return getClangAs();1092 return getTool(AC);1093}1094 1095std::string ToolChain::GetFilePath(const char *Name) const {1096 return D.GetFilePath(Name, *this);1097}1098 1099std::string ToolChain::GetProgramPath(const char *Name) const {1100 return D.GetProgramPath(Name, *this);1101}1102 1103std::string ToolChain::GetLinkerPath(bool *LinkerIsLLD) const {1104 if (LinkerIsLLD)1105 *LinkerIsLLD = false;1106 1107 // Get -fuse-ld= first to prevent -Wunused-command-line-argument. -fuse-ld= is1108 // considered as the linker flavor, e.g. "bfd", "gold", or "lld".1109 const Arg* A = Args.getLastArg(options::OPT_fuse_ld_EQ);1110 StringRef UseLinker = A ? A->getValue() : getDriver().getPreferredLinker();1111 1112 // --ld-path= takes precedence over -fuse-ld= and specifies the executable1113 // name. -B, COMPILER_PATH and PATH and consulted if the value does not1114 // contain a path component separator.1115 // -fuse-ld=lld can be used with --ld-path= to inform clang that the binary1116 // that --ld-path= points to is lld.1117 if (const Arg *A = Args.getLastArg(options::OPT_ld_path_EQ)) {1118 std::string Path(A->getValue());1119 if (!Path.empty()) {1120 if (llvm::sys::path::parent_path(Path).empty())1121 Path = GetProgramPath(A->getValue());1122 if (llvm::sys::fs::can_execute(Path)) {1123 if (LinkerIsLLD)1124 *LinkerIsLLD = UseLinker == "lld";1125 return std::string(Path);1126 }1127 }1128 getDriver().Diag(diag::err_drv_invalid_linker_name) << A->getAsString(Args);1129 return GetProgramPath(getDefaultLinker());1130 }1131 // If we're passed -fuse-ld= with no argument, or with the argument ld,1132 // then use whatever the default system linker is.1133 if (UseLinker.empty() || UseLinker == "ld") {1134 const char *DefaultLinker = getDefaultLinker();1135 if (llvm::sys::path::is_absolute(DefaultLinker))1136 return std::string(DefaultLinker);1137 else1138 return GetProgramPath(DefaultLinker);1139 }1140 1141 // Extending -fuse-ld= to an absolute or relative path is unexpected. Checking1142 // for the linker flavor is brittle. In addition, prepending "ld." or "ld64."1143 // to a relative path is surprising. This is more complex due to priorities1144 // among -B, COMPILER_PATH and PATH. --ld-path= should be used instead.1145 if (UseLinker.contains('/'))1146 getDriver().Diag(diag::warn_drv_fuse_ld_path);1147 1148 if (llvm::sys::path::is_absolute(UseLinker)) {1149 // If we're passed what looks like an absolute path, don't attempt to1150 // second-guess that.1151 if (llvm::sys::fs::can_execute(UseLinker))1152 return std::string(UseLinker);1153 } else {1154 llvm::SmallString<8> LinkerName;1155 if (Triple.isOSDarwin())1156 LinkerName.append("ld64.");1157 else1158 LinkerName.append("ld.");1159 LinkerName.append(UseLinker);1160 1161 std::string LinkerPath(GetProgramPath(LinkerName.c_str()));1162 if (llvm::sys::fs::can_execute(LinkerPath)) {1163 if (LinkerIsLLD)1164 *LinkerIsLLD = UseLinker == "lld";1165 return LinkerPath;1166 }1167 }1168 1169 if (A)1170 getDriver().Diag(diag::err_drv_invalid_linker_name) << A->getAsString(Args);1171 1172 return GetProgramPath(getDefaultLinker());1173}1174 1175std::string ToolChain::GetStaticLibToolPath() const {1176 // TODO: Add support for static lib archiving on Windows1177 if (Triple.isOSDarwin())1178 return GetProgramPath("libtool");1179 return GetProgramPath("llvm-ar");1180}1181 1182types::ID ToolChain::LookupTypeForExtension(StringRef Ext) const {1183 types::ID id = types::lookupTypeForExtension(Ext);1184 1185 // Flang always runs the preprocessor and has no notion of "preprocessed1186 // fortran". Here, TY_PP_Fortran is coerced to TY_Fortran to avoid treating1187 // them differently.1188 if (D.IsFlangMode() && id == types::TY_PP_Fortran)1189 id = types::TY_Fortran;1190 1191 return id;1192}1193 1194bool ToolChain::HasNativeLLVMSupport() const {1195 return false;1196}1197 1198bool ToolChain::isCrossCompiling() const {1199 llvm::Triple HostTriple(LLVM_HOST_TRIPLE);1200 switch (HostTriple.getArch()) {1201 // The A32/T32/T16 instruction sets are not separate architectures in this1202 // context.1203 case llvm::Triple::arm:1204 case llvm::Triple::armeb:1205 case llvm::Triple::thumb:1206 case llvm::Triple::thumbeb:1207 return getArch() != llvm::Triple::arm && getArch() != llvm::Triple::thumb &&1208 getArch() != llvm::Triple::armeb && getArch() != llvm::Triple::thumbeb;1209 default:1210 return HostTriple.getArch() != getArch();1211 }1212}1213 1214ObjCRuntime ToolChain::getDefaultObjCRuntime(bool isNonFragile) const {1215 return ObjCRuntime(isNonFragile ? ObjCRuntime::GNUstep : ObjCRuntime::GCC,1216 VersionTuple());1217}1218 1219llvm::ExceptionHandling1220ToolChain::GetExceptionModel(const llvm::opt::ArgList &Args) const {1221 return llvm::ExceptionHandling::None;1222}1223 1224bool ToolChain::isThreadModelSupported(const StringRef Model) const {1225 if (Model == "single") {1226 // FIXME: 'single' is only supported on ARM and WebAssembly so far.1227 return Triple.getArch() == llvm::Triple::arm ||1228 Triple.getArch() == llvm::Triple::armeb ||1229 Triple.getArch() == llvm::Triple::thumb ||1230 Triple.getArch() == llvm::Triple::thumbeb || Triple.isWasm();1231 } else if (Model == "posix")1232 return true;1233 1234 return false;1235}1236 1237std::string ToolChain::ComputeLLVMTriple(const ArgList &Args,1238 types::ID InputType) const {1239 switch (getTriple().getArch()) {1240 default:1241 return getTripleString();1242 1243 case llvm::Triple::x86_64: {1244 llvm::Triple Triple = getTriple();1245 if (!Triple.isOSBinFormatMachO())1246 return getTripleString();1247 1248 if (Arg *A = Args.getLastArg(options::OPT_march_EQ)) {1249 // x86_64h goes in the triple. Other -march options just use the1250 // vanilla triple we already have.1251 StringRef MArch = A->getValue();1252 if (MArch == "x86_64h")1253 Triple.setArchName(MArch);1254 }1255 return Triple.getTriple();1256 }1257 case llvm::Triple::aarch64: {1258 llvm::Triple Triple = getTriple();1259 if (!Triple.isOSBinFormatMachO())1260 return Triple.getTriple();1261 1262 if (Triple.isArm64e())1263 return Triple.getTriple();1264 1265 // FIXME: older versions of ld64 expect the "arm64" component in the actual1266 // triple string and query it to determine whether an LTO file can be1267 // handled. Remove this when we don't care any more.1268 Triple.setArchName("arm64");1269 return Triple.getTriple();1270 }1271 case llvm::Triple::aarch64_32:1272 return getTripleString();1273 case llvm::Triple::amdgcn: {1274 llvm::Triple Triple = getTriple();1275 if (Args.getLastArgValue(options::OPT_mcpu_EQ) == "amdgcnspirv")1276 Triple.setArch(llvm::Triple::ArchType::spirv64);1277 return Triple.getTriple();1278 }1279 case llvm::Triple::arm:1280 case llvm::Triple::armeb:1281 case llvm::Triple::thumb:1282 case llvm::Triple::thumbeb: {1283 llvm::Triple Triple = getTriple();1284 tools::arm::setArchNameInTriple(getDriver(), Args, InputType, Triple);1285 tools::arm::setFloatABIInTriple(getDriver(), Args, Triple);1286 return Triple.getTriple();1287 }1288 }1289}1290 1291std::string ToolChain::ComputeEffectiveClangTriple(const ArgList &Args,1292 types::ID InputType) const {1293 return ComputeLLVMTriple(Args, InputType);1294}1295 1296std::string ToolChain::computeSysRoot() const {1297 return D.SysRoot;1298}1299 1300void ToolChain::AddClangSystemIncludeArgs(const ArgList &DriverArgs,1301 ArgStringList &CC1Args) const {1302 // Each toolchain should provide the appropriate include flags.1303}1304 1305void ToolChain::addClangTargetOptions(1306 const ArgList &DriverArgs, ArgStringList &CC1Args,1307 Action::OffloadKind DeviceOffloadKind) const {}1308 1309void ToolChain::addClangCC1ASTargetOptions(const ArgList &Args,1310 ArgStringList &CC1ASArgs) const {}1311 1312void ToolChain::addClangWarningOptions(ArgStringList &CC1Args) const {}1313 1314void ToolChain::addProfileRTLibs(const llvm::opt::ArgList &Args,1315 llvm::opt::ArgStringList &CmdArgs) const {1316 if (!needsProfileRT(Args) && !needsGCovInstrumentation(Args))1317 return;1318 1319 CmdArgs.push_back(getCompilerRTArgString(Args, "profile"));1320}1321 1322ToolChain::RuntimeLibType ToolChain::GetRuntimeLibType(1323 const ArgList &Args) const {1324 if (runtimeLibType)1325 return *runtimeLibType;1326 1327 const Arg* A = Args.getLastArg(options::OPT_rtlib_EQ);1328 StringRef LibName = A ? A->getValue() : CLANG_DEFAULT_RTLIB;1329 1330 // Only use "platform" in tests to override CLANG_DEFAULT_RTLIB!1331 if (LibName == "compiler-rt")1332 runtimeLibType = ToolChain::RLT_CompilerRT;1333 else if (LibName == "libgcc")1334 runtimeLibType = ToolChain::RLT_Libgcc;1335 else if (LibName == "platform")1336 runtimeLibType = GetDefaultRuntimeLibType();1337 else {1338 if (A)1339 getDriver().Diag(diag::err_drv_invalid_rtlib_name)1340 << A->getAsString(Args);1341 1342 runtimeLibType = GetDefaultRuntimeLibType();1343 }1344 1345 return *runtimeLibType;1346}1347 1348ToolChain::UnwindLibType ToolChain::GetUnwindLibType(1349 const ArgList &Args) const {1350 if (unwindLibType)1351 return *unwindLibType;1352 1353 const Arg *A = Args.getLastArg(options::OPT_unwindlib_EQ);1354 StringRef LibName = A ? A->getValue() : CLANG_DEFAULT_UNWINDLIB;1355 1356 if (LibName == "none")1357 unwindLibType = ToolChain::UNW_None;1358 else if (LibName == "platform" || LibName == "") {1359 ToolChain::RuntimeLibType RtLibType = GetRuntimeLibType(Args);1360 if (RtLibType == ToolChain::RLT_CompilerRT) {1361 if (getTriple().isAndroid() || getTriple().isOSAIX())1362 unwindLibType = ToolChain::UNW_CompilerRT;1363 else1364 unwindLibType = ToolChain::UNW_None;1365 } else if (RtLibType == ToolChain::RLT_Libgcc)1366 unwindLibType = ToolChain::UNW_Libgcc;1367 } else if (LibName == "libunwind") {1368 if (GetRuntimeLibType(Args) == RLT_Libgcc)1369 getDriver().Diag(diag::err_drv_incompatible_unwindlib);1370 unwindLibType = ToolChain::UNW_CompilerRT;1371 } else if (LibName == "libgcc")1372 unwindLibType = ToolChain::UNW_Libgcc;1373 else {1374 if (A)1375 getDriver().Diag(diag::err_drv_invalid_unwindlib_name)1376 << A->getAsString(Args);1377 1378 unwindLibType = GetDefaultUnwindLibType();1379 }1380 1381 return *unwindLibType;1382}1383 1384ToolChain::CXXStdlibType ToolChain::GetCXXStdlibType(const ArgList &Args) const{1385 if (cxxStdlibType)1386 return *cxxStdlibType;1387 1388 const Arg *A = Args.getLastArg(options::OPT_stdlib_EQ);1389 StringRef LibName = A ? A->getValue() : CLANG_DEFAULT_CXX_STDLIB;1390 1391 // Only use "platform" in tests to override CLANG_DEFAULT_CXX_STDLIB!1392 if (LibName == "libc++")1393 cxxStdlibType = ToolChain::CST_Libcxx;1394 else if (LibName == "libstdc++")1395 cxxStdlibType = ToolChain::CST_Libstdcxx;1396 else if (LibName == "platform")1397 cxxStdlibType = GetDefaultCXXStdlibType();1398 else {1399 if (A)1400 getDriver().Diag(diag::err_drv_invalid_stdlib_name)1401 << A->getAsString(Args);1402 1403 cxxStdlibType = GetDefaultCXXStdlibType();1404 }1405 1406 return *cxxStdlibType;1407}1408 1409/// Utility function to add a system framework directory to CC1 arguments.1410void ToolChain::addSystemFrameworkInclude(const llvm::opt::ArgList &DriverArgs,1411 llvm::opt::ArgStringList &CC1Args,1412 const Twine &Path) {1413 CC1Args.push_back("-internal-iframework");1414 CC1Args.push_back(DriverArgs.MakeArgString(Path));1415}1416 1417/// Utility function to add a system include directory with extern "C"1418/// semantics to CC1 arguments.1419///1420/// Note that this should be used rarely, and only for directories that1421/// historically and for legacy reasons are treated as having implicit extern1422/// "C" semantics. These semantics are *ignored* by and large today, but its1423/// important to preserve the preprocessor changes resulting from the1424/// classification.1425void ToolChain::addExternCSystemInclude(const ArgList &DriverArgs,1426 ArgStringList &CC1Args,1427 const Twine &Path) {1428 CC1Args.push_back("-internal-externc-isystem");1429 CC1Args.push_back(DriverArgs.MakeArgString(Path));1430}1431 1432void ToolChain::addExternCSystemIncludeIfExists(const ArgList &DriverArgs,1433 ArgStringList &CC1Args,1434 const Twine &Path) {1435 if (llvm::sys::fs::exists(Path))1436 addExternCSystemInclude(DriverArgs, CC1Args, Path);1437}1438 1439/// Utility function to add a system include directory to CC1 arguments.1440/*static*/ void ToolChain::addSystemInclude(const ArgList &DriverArgs,1441 ArgStringList &CC1Args,1442 const Twine &Path) {1443 CC1Args.push_back("-internal-isystem");1444 CC1Args.push_back(DriverArgs.MakeArgString(Path));1445}1446 1447/// Utility function to add a list of system framework directories to CC1.1448void ToolChain::addSystemFrameworkIncludes(const ArgList &DriverArgs,1449 ArgStringList &CC1Args,1450 ArrayRef<StringRef> Paths) {1451 for (const auto &Path : Paths) {1452 CC1Args.push_back("-internal-iframework");1453 CC1Args.push_back(DriverArgs.MakeArgString(Path));1454 }1455}1456 1457/// Utility function to add a list of system include directories to CC1.1458void ToolChain::addSystemIncludes(const ArgList &DriverArgs,1459 ArgStringList &CC1Args,1460 ArrayRef<StringRef> Paths) {1461 for (const auto &Path : Paths) {1462 CC1Args.push_back("-internal-isystem");1463 CC1Args.push_back(DriverArgs.MakeArgString(Path));1464 }1465}1466 1467std::string ToolChain::concat(StringRef Path, const Twine &A, const Twine &B,1468 const Twine &C, const Twine &D) {1469 SmallString<128> Result(Path);1470 llvm::sys::path::append(Result, llvm::sys::path::Style::posix, A, B, C, D);1471 return std::string(Result);1472}1473 1474std::string ToolChain::detectLibcxxVersion(StringRef IncludePath) const {1475 std::error_code EC;1476 int MaxVersion = 0;1477 std::string MaxVersionString;1478 SmallString<128> Path(IncludePath);1479 llvm::sys::path::append(Path, "c++");1480 for (llvm::vfs::directory_iterator LI = getVFS().dir_begin(Path, EC), LE;1481 !EC && LI != LE; LI = LI.increment(EC)) {1482 StringRef VersionText = llvm::sys::path::filename(LI->path());1483 int Version;1484 if (VersionText[0] == 'v' &&1485 !VersionText.substr(1).getAsInteger(10, Version)) {1486 if (Version > MaxVersion) {1487 MaxVersion = Version;1488 MaxVersionString = std::string(VersionText);1489 }1490 }1491 }1492 if (!MaxVersion)1493 return "";1494 return MaxVersionString;1495}1496 1497void ToolChain::AddClangCXXStdlibIncludeArgs(const ArgList &DriverArgs,1498 ArgStringList &CC1Args) const {1499 // Header search paths should be handled by each of the subclasses.1500 // Historically, they have not been, and instead have been handled inside of1501 // the CC1-layer frontend. As the logic is hoisted out, this generic function1502 // will slowly stop being called.1503 //1504 // While it is being called, replicate a bit of a hack to propagate the1505 // '-stdlib=' flag down to CC1 so that it can in turn customize the C++1506 // header search paths with it. Once all systems are overriding this1507 // function, the CC1 flag and this line can be removed.1508 DriverArgs.AddAllArgs(CC1Args, options::OPT_stdlib_EQ);1509}1510 1511void ToolChain::AddClangCXXStdlibIsystemArgs(1512 const llvm::opt::ArgList &DriverArgs,1513 llvm::opt::ArgStringList &CC1Args) const {1514 DriverArgs.ClaimAllArgs(options::OPT_stdlibxx_isystem);1515 // This intentionally only looks at -nostdinc++, and not -nostdinc or1516 // -nostdlibinc. The purpose of -stdlib++-isystem is to support toolchain1517 // setups with non-standard search logic for the C++ headers, while still1518 // allowing users of the toolchain to bring their own C++ headers. Such a1519 // toolchain likely also has non-standard search logic for the C headers and1520 // uses -nostdinc to suppress the default logic, but -stdlib++-isystem should1521 // still work in that case and only be suppressed by an explicit -nostdinc++1522 // in a project using the toolchain.1523 if (!DriverArgs.hasArg(options::OPT_nostdincxx))1524 for (const auto &P :1525 DriverArgs.getAllArgValues(options::OPT_stdlibxx_isystem))1526 addSystemInclude(DriverArgs, CC1Args, P);1527}1528 1529bool ToolChain::ShouldLinkCXXStdlib(const llvm::opt::ArgList &Args) const {1530 return getDriver().CCCIsCXX() &&1531 !Args.hasArg(options::OPT_nostdlib, options::OPT_nodefaultlibs,1532 options::OPT_nostdlibxx);1533}1534 1535void ToolChain::AddCXXStdlibLibArgs(const ArgList &Args,1536 ArgStringList &CmdArgs) const {1537 assert(!Args.hasArg(options::OPT_nostdlibxx) &&1538 "should not have called this");1539 CXXStdlibType Type = GetCXXStdlibType(Args);1540 1541 switch (Type) {1542 case ToolChain::CST_Libcxx:1543 CmdArgs.push_back("-lc++");1544 if (Args.hasArg(options::OPT_fexperimental_library))1545 CmdArgs.push_back("-lc++experimental");1546 break;1547 1548 case ToolChain::CST_Libstdcxx:1549 CmdArgs.push_back("-lstdc++");1550 break;1551 }1552}1553 1554void ToolChain::AddFilePathLibArgs(const ArgList &Args,1555 ArgStringList &CmdArgs) const {1556 for (const auto &LibPath : getFilePaths())1557 if(LibPath.length() > 0)1558 CmdArgs.push_back(Args.MakeArgString(StringRef("-L") + LibPath));1559}1560 1561void ToolChain::AddCCKextLibArgs(const ArgList &Args,1562 ArgStringList &CmdArgs) const {1563 CmdArgs.push_back("-lcc_kext");1564}1565 1566bool ToolChain::isFastMathRuntimeAvailable(const ArgList &Args,1567 std::string &Path) const {1568 // Don't implicitly link in mode-changing libraries in a shared library, since1569 // this can have very deleterious effects. See the various links from1570 // https://github.com/llvm/llvm-project/issues/57589 for more information.1571 bool Default = !Args.hasArgNoClaim(options::OPT_shared);1572 1573 // Do not check for -fno-fast-math or -fno-unsafe-math when -Ofast passed1574 // (to keep the linker options consistent with gcc and clang itself).1575 if (Default && !isOptimizationLevelFast(Args)) {1576 // Check if -ffast-math or -funsafe-math.1577 Arg *A = Args.getLastArg(1578 options::OPT_ffast_math, options::OPT_fno_fast_math,1579 options::OPT_funsafe_math_optimizations,1580 options::OPT_fno_unsafe_math_optimizations, options::OPT_ffp_model_EQ);1581 1582 if (!A || A->getOption().getID() == options::OPT_fno_fast_math ||1583 A->getOption().getID() == options::OPT_fno_unsafe_math_optimizations)1584 Default = false;1585 if (A && A->getOption().getID() == options::OPT_ffp_model_EQ) {1586 StringRef Model = A->getValue();1587 if (Model != "fast" && Model != "aggressive")1588 Default = false;1589 }1590 }1591 1592 // Whatever decision came as a result of the above implicit settings, either1593 // -mdaz-ftz or -mno-daz-ftz is capable of overriding it.1594 if (!Args.hasFlag(options::OPT_mdaz_ftz, options::OPT_mno_daz_ftz, Default))1595 return false;1596 1597 // If crtfastmath.o exists add it to the arguments.1598 Path = GetFilePath("crtfastmath.o");1599 return (Path != "crtfastmath.o"); // Not found.1600}1601 1602bool ToolChain::addFastMathRuntimeIfAvailable(const ArgList &Args,1603 ArgStringList &CmdArgs) const {1604 std::string Path;1605 if (isFastMathRuntimeAvailable(Args, Path)) {1606 CmdArgs.push_back(Args.MakeArgString(Path));1607 return true;1608 }1609 1610 return false;1611}1612 1613Expected<SmallVector<std::string>>1614ToolChain::getSystemGPUArchs(const llvm::opt::ArgList &Args) const {1615 return SmallVector<std::string>();1616}1617 1618SanitizerMask ToolChain::getSupportedSanitizers() const {1619 // Return sanitizers which don't require runtime support and are not1620 // platform dependent.1621 1622 SanitizerMask Res =1623 (SanitizerKind::Undefined & ~SanitizerKind::Vptr) |1624 (SanitizerKind::CFI & ~SanitizerKind::CFIICall) |1625 SanitizerKind::CFICastStrict | SanitizerKind::FloatDivideByZero |1626 SanitizerKind::KCFI | SanitizerKind::UnsignedIntegerOverflow |1627 SanitizerKind::UnsignedShiftBase | SanitizerKind::ImplicitConversion |1628 SanitizerKind::Nullability | SanitizerKind::LocalBounds |1629 SanitizerKind::AllocToken;1630 if (getTriple().getArch() == llvm::Triple::x86 ||1631 getTriple().getArch() == llvm::Triple::x86_64 ||1632 getTriple().getArch() == llvm::Triple::arm ||1633 getTriple().getArch() == llvm::Triple::thumb || getTriple().isWasm() ||1634 getTriple().isAArch64() || getTriple().isRISCV() ||1635 getTriple().isLoongArch64())1636 Res |= SanitizerKind::CFIICall;1637 if (getTriple().getArch() == llvm::Triple::x86_64 ||1638 getTriple().isAArch64(64) || getTriple().isRISCV())1639 Res |= SanitizerKind::ShadowCallStack;1640 if (getTriple().isAArch64(64))1641 Res |= SanitizerKind::MemTag;1642 if (getTriple().isBPF())1643 Res |= SanitizerKind::KernelAddress;1644 return Res;1645}1646 1647void ToolChain::AddCudaIncludeArgs(const ArgList &DriverArgs,1648 ArgStringList &CC1Args) const {}1649 1650void ToolChain::AddHIPIncludeArgs(const ArgList &DriverArgs,1651 ArgStringList &CC1Args) const {}1652 1653void ToolChain::addSYCLIncludeArgs(const ArgList &DriverArgs,1654 ArgStringList &CC1Args) const {}1655 1656llvm::SmallVector<ToolChain::BitCodeLibraryInfo, 12>1657ToolChain::getDeviceLibs(const ArgList &DriverArgs,1658 const Action::OffloadKind DeviceOffloadingKind) const {1659 return {};1660}1661 1662void ToolChain::AddIAMCUIncludeArgs(const ArgList &DriverArgs,1663 ArgStringList &CC1Args) const {}1664 1665static VersionTuple separateMSVCFullVersion(unsigned Version) {1666 if (Version < 100)1667 return VersionTuple(Version);1668 1669 if (Version < 10000)1670 return VersionTuple(Version / 100, Version % 100);1671 1672 unsigned Build = 0, Factor = 1;1673 for (; Version > 10000; Version = Version / 10, Factor = Factor * 10)1674 Build = Build + (Version % 10) * Factor;1675 return VersionTuple(Version / 100, Version % 100, Build);1676}1677 1678VersionTuple1679ToolChain::computeMSVCVersion(const Driver *D,1680 const llvm::opt::ArgList &Args) const {1681 const Arg *MSCVersion = Args.getLastArg(options::OPT_fmsc_version);1682 const Arg *MSCompatibilityVersion =1683 Args.getLastArg(options::OPT_fms_compatibility_version);1684 1685 if (MSCVersion && MSCompatibilityVersion) {1686 if (D)1687 D->Diag(diag::err_drv_argument_not_allowed_with)1688 << MSCVersion->getAsString(Args)1689 << MSCompatibilityVersion->getAsString(Args);1690 return VersionTuple();1691 }1692 1693 if (MSCompatibilityVersion) {1694 VersionTuple MSVT;1695 if (MSVT.tryParse(MSCompatibilityVersion->getValue())) {1696 if (D)1697 D->Diag(diag::err_drv_invalid_value)1698 << MSCompatibilityVersion->getAsString(Args)1699 << MSCompatibilityVersion->getValue();1700 } else {1701 return MSVT;1702 }1703 }1704 1705 if (MSCVersion) {1706 unsigned Version = 0;1707 if (StringRef(MSCVersion->getValue()).getAsInteger(10, Version)) {1708 if (D)1709 D->Diag(diag::err_drv_invalid_value)1710 << MSCVersion->getAsString(Args) << MSCVersion->getValue();1711 } else {1712 return separateMSVCFullVersion(Version);1713 }1714 }1715 1716 return VersionTuple();1717}1718 1719llvm::opt::DerivedArgList *ToolChain::TranslateOpenMPTargetArgs(1720 const llvm::opt::DerivedArgList &Args, bool SameTripleAsHost,1721 SmallVectorImpl<llvm::opt::Arg *> &AllocatedArgs) const {1722 DerivedArgList *DAL = new DerivedArgList(Args.getBaseArgs());1723 const OptTable &Opts = getDriver().getOpts();1724 bool Modified = false;1725 1726 // Handle -Xopenmp-target flags1727 for (auto *A : Args) {1728 // Exclude flags which may only apply to the host toolchain.1729 // Do not exclude flags when the host triple (AuxTriple)1730 // matches the current toolchain triple. If it is not present1731 // at all, target and host share a toolchain.1732 if (A->getOption().matches(options::OPT_m_Group)) {1733 // Pass code object version to device toolchain1734 // to correctly set metadata in intermediate files.1735 if (SameTripleAsHost ||1736 A->getOption().matches(options::OPT_mcode_object_version_EQ))1737 DAL->append(A);1738 else1739 Modified = true;1740 continue;1741 }1742 1743 unsigned Index;1744 unsigned Prev;1745 bool XOpenMPTargetNoTriple =1746 A->getOption().matches(options::OPT_Xopenmp_target);1747 1748 if (A->getOption().matches(options::OPT_Xopenmp_target_EQ)) {1749 llvm::Triple TT(getOpenMPTriple(A->getValue(0)));1750 1751 // Passing device args: -Xopenmp-target=<triple> -opt=val.1752 if (TT.getTriple() == getTripleString())1753 Index = Args.getBaseArgs().MakeIndex(A->getValue(1));1754 else1755 continue;1756 } else if (XOpenMPTargetNoTriple) {1757 // Passing device args: -Xopenmp-target -opt=val.1758 Index = Args.getBaseArgs().MakeIndex(A->getValue(0));1759 } else {1760 DAL->append(A);1761 continue;1762 }1763 1764 // Parse the argument to -Xopenmp-target.1765 Prev = Index;1766 std::unique_ptr<Arg> XOpenMPTargetArg(Opts.ParseOneArg(Args, Index));1767 if (!XOpenMPTargetArg || Index > Prev + 1) {1768 if (!A->isClaimed()) {1769 getDriver().Diag(diag::err_drv_invalid_Xopenmp_target_with_args)1770 << A->getAsString(Args);1771 }1772 continue;1773 }1774 if (XOpenMPTargetNoTriple && XOpenMPTargetArg &&1775 Args.getAllArgValues(options::OPT_offload_targets_EQ).size() != 1) {1776 getDriver().Diag(diag::err_drv_Xopenmp_target_missing_triple);1777 continue;1778 }1779 XOpenMPTargetArg->setBaseArg(A);1780 A = XOpenMPTargetArg.release();1781 AllocatedArgs.push_back(A);1782 DAL->append(A);1783 Modified = true;1784 }1785 1786 if (Modified)1787 return DAL;1788 1789 delete DAL;1790 return nullptr;1791}1792 1793// TODO: Currently argument values separated by space e.g.1794// -Xclang -mframe-pointer=no cannot be passed by -Xarch_. This should be1795// fixed.1796void ToolChain::TranslateXarchArgs(1797 const llvm::opt::DerivedArgList &Args, llvm::opt::Arg *&A,1798 llvm::opt::DerivedArgList *DAL,1799 SmallVectorImpl<llvm::opt::Arg *> *AllocatedArgs) const {1800 const OptTable &Opts = getDriver().getOpts();1801 unsigned ValuePos = 1;1802 if (A->getOption().matches(options::OPT_Xarch_device) ||1803 A->getOption().matches(options::OPT_Xarch_host))1804 ValuePos = 0;1805 1806 const InputArgList &BaseArgs = Args.getBaseArgs();1807 unsigned Index = BaseArgs.MakeIndex(A->getValue(ValuePos));1808 unsigned Prev = Index;1809 std::unique_ptr<llvm::opt::Arg> XarchArg(Opts.ParseOneArg(1810 Args, Index, llvm::opt::Visibility(options::ClangOption)));1811 1812 // If the argument parsing failed or more than one argument was1813 // consumed, the -Xarch_ argument's parameter tried to consume1814 // extra arguments. Emit an error and ignore.1815 //1816 // We also want to disallow any options which would alter the1817 // driver behavior; that isn't going to work in our model. We1818 // use options::NoXarchOption to control this.1819 if (!XarchArg || Index > Prev + 1) {1820 getDriver().Diag(diag::err_drv_invalid_Xarch_argument_with_args)1821 << A->getAsString(Args);1822 return;1823 } else if (XarchArg->getOption().hasFlag(options::NoXarchOption)) {1824 auto &Diags = getDriver().getDiags();1825 unsigned DiagID =1826 Diags.getCustomDiagID(DiagnosticsEngine::Error,1827 "invalid Xarch argument: '%0', not all driver "1828 "options can be forwared via Xarch argument");1829 Diags.Report(DiagID) << A->getAsString(Args);1830 return;1831 }1832 1833 XarchArg->setBaseArg(A);1834 A = XarchArg.release();1835 1836 // Linker input arguments require custom handling. The problem is that we1837 // have already constructed the phase actions, so we can not treat them as1838 // "input arguments".1839 if (A->getOption().hasFlag(options::LinkerInput)) {1840 // Convert the argument into individual Zlinker_input_args. Need to do this1841 // manually to avoid memory leaks with the allocated arguments.1842 for (const char *Value : A->getValues()) {1843 auto Opt = Opts.getOption(options::OPT_Zlinker_input);1844 unsigned Index = BaseArgs.MakeIndex(Opt.getName(), Value);1845 auto NewArg =1846 new Arg(Opt, BaseArgs.MakeArgString(Opt.getPrefix() + Opt.getName()),1847 Index, BaseArgs.getArgString(Index + 1), A);1848 1849 DAL->append(NewArg);1850 if (!AllocatedArgs)1851 DAL->AddSynthesizedArg(NewArg);1852 else1853 AllocatedArgs->push_back(NewArg);1854 }1855 }1856 1857 if (!AllocatedArgs)1858 DAL->AddSynthesizedArg(A);1859 else1860 AllocatedArgs->push_back(A);1861}1862 1863llvm::opt::DerivedArgList *ToolChain::TranslateXarchArgs(1864 const llvm::opt::DerivedArgList &Args, StringRef BoundArch,1865 Action::OffloadKind OFK,1866 SmallVectorImpl<llvm::opt::Arg *> *AllocatedArgs) const {1867 DerivedArgList *DAL = new DerivedArgList(Args.getBaseArgs());1868 bool Modified = false;1869 1870 bool IsDevice = OFK != Action::OFK_None && OFK != Action::OFK_Host;1871 for (Arg *A : Args) {1872 bool NeedTrans = false;1873 bool Skip = false;1874 if (A->getOption().matches(options::OPT_Xarch_device)) {1875 NeedTrans = IsDevice;1876 Skip = !IsDevice;1877 } else if (A->getOption().matches(options::OPT_Xarch_host)) {1878 NeedTrans = !IsDevice;1879 Skip = IsDevice;1880 } else if (A->getOption().matches(options::OPT_Xarch__)) {1881 NeedTrans = A->getValue() == getArchName() ||1882 (!BoundArch.empty() && A->getValue() == BoundArch);1883 Skip = !NeedTrans;1884 }1885 if (NeedTrans || Skip)1886 Modified = true;1887 if (NeedTrans) {1888 A->claim();1889 TranslateXarchArgs(Args, A, DAL, AllocatedArgs);1890 }1891 if (!Skip)1892 DAL->append(A);1893 }1894 1895 if (Modified)1896 return DAL;1897 1898 delete DAL;1899 return nullptr;1900}1901