Path: blob/main/contrib/llvm-project/clang/lib/Driver/ToolChains/Darwin.cpp
35294 views
//===--- Darwin.cpp - Darwin Tool and ToolChain Implementations -*- C++ -*-===//1//2// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.3// See https://llvm.org/LICENSE.txt for license information.4// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception5//6//===----------------------------------------------------------------------===//78#include "Darwin.h"9#include "Arch/AArch64.h"10#include "Arch/ARM.h"11#include "CommonArgs.h"12#include "clang/Basic/AlignedAllocation.h"13#include "clang/Basic/ObjCRuntime.h"14#include "clang/Config/config.h"15#include "clang/Driver/Compilation.h"16#include "clang/Driver/Driver.h"17#include "clang/Driver/DriverDiagnostic.h"18#include "clang/Driver/Options.h"19#include "clang/Driver/SanitizerArgs.h"20#include "llvm/ADT/StringSwitch.h"21#include "llvm/Option/ArgList.h"22#include "llvm/ProfileData/InstrProf.h"23#include "llvm/Support/Path.h"24#include "llvm/Support/ScopedPrinter.h"25#include "llvm/Support/Threading.h"26#include "llvm/Support/VirtualFileSystem.h"27#include "llvm/TargetParser/TargetParser.h"28#include "llvm/TargetParser/Triple.h"29#include <cstdlib> // ::getenv3031using namespace clang::driver;32using namespace clang::driver::tools;33using namespace clang::driver::toolchains;34using namespace clang;35using namespace llvm::opt;3637static VersionTuple minimumMacCatalystDeploymentTarget() {38return VersionTuple(13, 1);39}4041llvm::Triple::ArchType darwin::getArchTypeForMachOArchName(StringRef Str) {42// See arch(3) and llvm-gcc's driver-driver.c. We don't implement support for43// archs which Darwin doesn't use.4445// The matching this routine does is fairly pointless, since it is neither the46// complete architecture list, nor a reasonable subset. The problem is that47// historically the driver accepts this and also ties its -march=48// handling to the architecture name, so we need to be careful before removing49// support for it.5051// This code must be kept in sync with Clang's Darwin specific argument52// translation.5354return llvm::StringSwitch<llvm::Triple::ArchType>(Str)55.Cases("i386", "i486", "i486SX", "i586", "i686", llvm::Triple::x86)56.Cases("pentium", "pentpro", "pentIIm3", "pentIIm5", "pentium4",57llvm::Triple::x86)58.Cases("x86_64", "x86_64h", llvm::Triple::x86_64)59// This is derived from the driver.60.Cases("arm", "armv4t", "armv5", "armv6", "armv6m", llvm::Triple::arm)61.Cases("armv7", "armv7em", "armv7k", "armv7m", llvm::Triple::arm)62.Cases("armv7s", "xscale", llvm::Triple::arm)63.Cases("arm64", "arm64e", llvm::Triple::aarch64)64.Case("arm64_32", llvm::Triple::aarch64_32)65.Case("r600", llvm::Triple::r600)66.Case("amdgcn", llvm::Triple::amdgcn)67.Case("nvptx", llvm::Triple::nvptx)68.Case("nvptx64", llvm::Triple::nvptx64)69.Case("amdil", llvm::Triple::amdil)70.Case("spir", llvm::Triple::spir)71.Default(llvm::Triple::UnknownArch);72}7374void darwin::setTripleTypeForMachOArchName(llvm::Triple &T, StringRef Str,75const ArgList &Args) {76const llvm::Triple::ArchType Arch = getArchTypeForMachOArchName(Str);77llvm::ARM::ArchKind ArchKind = llvm::ARM::parseArch(Str);78T.setArch(Arch);79if (Arch != llvm::Triple::UnknownArch)80T.setArchName(Str);8182if (ArchKind == llvm::ARM::ArchKind::ARMV6M ||83ArchKind == llvm::ARM::ArchKind::ARMV7M ||84ArchKind == llvm::ARM::ArchKind::ARMV7EM) {85// Don't reject these -version-min= if we have the appropriate triple.86if (T.getOS() == llvm::Triple::IOS)87for (Arg *A : Args.filtered(options::OPT_mios_version_min_EQ))88A->ignoreTargetSpecific();89if (T.getOS() == llvm::Triple::WatchOS)90for (Arg *A : Args.filtered(options::OPT_mwatchos_version_min_EQ))91A->ignoreTargetSpecific();92if (T.getOS() == llvm::Triple::TvOS)93for (Arg *A : Args.filtered(options::OPT_mtvos_version_min_EQ))94A->ignoreTargetSpecific();9596T.setOS(llvm::Triple::UnknownOS);97T.setObjectFormat(llvm::Triple::MachO);98}99}100101void darwin::Assembler::ConstructJob(Compilation &C, const JobAction &JA,102const InputInfo &Output,103const InputInfoList &Inputs,104const ArgList &Args,105const char *LinkingOutput) const {106const llvm::Triple &T(getToolChain().getTriple());107108ArgStringList CmdArgs;109110assert(Inputs.size() == 1 && "Unexpected number of inputs.");111const InputInfo &Input = Inputs[0];112113// Determine the original source input.114const Action *SourceAction = &JA;115while (SourceAction->getKind() != Action::InputClass) {116assert(!SourceAction->getInputs().empty() && "unexpected root action!");117SourceAction = SourceAction->getInputs()[0];118}119120// If -fno-integrated-as is used add -Q to the darwin assembler driver to make121// sure it runs its system assembler not clang's integrated assembler.122// Applicable to darwin11+ and Xcode 4+. darwin<10 lacked integrated-as.123// FIXME: at run-time detect assembler capabilities or rely on version124// information forwarded by -target-assembler-version.125if (Args.hasArg(options::OPT_fno_integrated_as)) {126if (!(T.isMacOSX() && T.isMacOSXVersionLT(10, 7)))127CmdArgs.push_back("-Q");128}129130// Forward -g, assuming we are dealing with an actual assembly file.131if (SourceAction->getType() == types::TY_Asm ||132SourceAction->getType() == types::TY_PP_Asm) {133if (Args.hasArg(options::OPT_gstabs))134CmdArgs.push_back("--gstabs");135else if (Args.hasArg(options::OPT_g_Group))136CmdArgs.push_back("-g");137}138139// Derived from asm spec.140AddMachOArch(Args, CmdArgs);141142// Use -force_cpusubtype_ALL on x86 by default.143if (T.isX86() || Args.hasArg(options::OPT_force__cpusubtype__ALL))144CmdArgs.push_back("-force_cpusubtype_ALL");145146if (getToolChain().getArch() != llvm::Triple::x86_64 &&147(((Args.hasArg(options::OPT_mkernel) ||148Args.hasArg(options::OPT_fapple_kext)) &&149getMachOToolChain().isKernelStatic()) ||150Args.hasArg(options::OPT_static)))151CmdArgs.push_back("-static");152153Args.AddAllArgValues(CmdArgs, options::OPT_Wa_COMMA, options::OPT_Xassembler);154155assert(Output.isFilename() && "Unexpected lipo output.");156CmdArgs.push_back("-o");157CmdArgs.push_back(Output.getFilename());158159assert(Input.isFilename() && "Invalid input.");160CmdArgs.push_back(Input.getFilename());161162// asm_final spec is empty.163164const char *Exec = Args.MakeArgString(getToolChain().GetProgramPath("as"));165C.addCommand(std::make_unique<Command>(JA, *this, ResponseFileSupport::None(),166Exec, CmdArgs, Inputs, Output));167}168169void darwin::MachOTool::anchor() {}170171void darwin::MachOTool::AddMachOArch(const ArgList &Args,172ArgStringList &CmdArgs) const {173StringRef ArchName = getMachOToolChain().getMachOArchName(Args);174175// Derived from darwin_arch spec.176CmdArgs.push_back("-arch");177CmdArgs.push_back(Args.MakeArgString(ArchName));178179// FIXME: Is this needed anymore?180if (ArchName == "arm")181CmdArgs.push_back("-force_cpusubtype_ALL");182}183184bool darwin::Linker::NeedsTempPath(const InputInfoList &Inputs) const {185// We only need to generate a temp path for LTO if we aren't compiling object186// files. When compiling source files, we run 'dsymutil' after linking. We187// don't run 'dsymutil' when compiling object files.188for (const auto &Input : Inputs)189if (Input.getType() != types::TY_Object)190return true;191192return false;193}194195/// Pass -no_deduplicate to ld64 under certain conditions:196///197/// - Either -O0 or -O1 is explicitly specified198/// - No -O option is specified *and* this is a compile+link (implicit -O0)199///200/// Also do *not* add -no_deduplicate when no -O option is specified and this201/// is just a link (we can't imply -O0)202static bool shouldLinkerNotDedup(bool IsLinkerOnlyAction, const ArgList &Args) {203if (Arg *A = Args.getLastArg(options::OPT_O_Group)) {204if (A->getOption().matches(options::OPT_O0))205return true;206if (A->getOption().matches(options::OPT_O))207return llvm::StringSwitch<bool>(A->getValue())208.Case("1", true)209.Default(false);210return false; // OPT_Ofast & OPT_O4211}212213if (!IsLinkerOnlyAction) // Implicit -O0 for compile+linker only.214return true;215return false;216}217218void darwin::Linker::AddLinkArgs(Compilation &C, const ArgList &Args,219ArgStringList &CmdArgs,220const InputInfoList &Inputs,221VersionTuple Version, bool LinkerIsLLD,222bool UsePlatformVersion) const {223const Driver &D = getToolChain().getDriver();224const toolchains::MachO &MachOTC = getMachOToolChain();225226// Newer linkers support -demangle. Pass it if supported and not disabled by227// the user.228if ((Version >= VersionTuple(100) || LinkerIsLLD) &&229!Args.hasArg(options::OPT_Z_Xlinker__no_demangle))230CmdArgs.push_back("-demangle");231232if (Args.hasArg(options::OPT_rdynamic) &&233(Version >= VersionTuple(137) || LinkerIsLLD))234CmdArgs.push_back("-export_dynamic");235236// If we are using App Extension restrictions, pass a flag to the linker237// telling it that the compiled code has been audited.238if (Args.hasFlag(options::OPT_fapplication_extension,239options::OPT_fno_application_extension, false))240CmdArgs.push_back("-application_extension");241242if (D.isUsingLTO() && (Version >= VersionTuple(116) || LinkerIsLLD) &&243NeedsTempPath(Inputs)) {244std::string TmpPathName;245if (D.getLTOMode() == LTOK_Full) {246// If we are using full LTO, then automatically create a temporary file247// path for the linker to use, so that it's lifetime will extend past a248// possible dsymutil step.249TmpPathName =250D.GetTemporaryPath("cc", types::getTypeTempSuffix(types::TY_Object));251} else if (D.getLTOMode() == LTOK_Thin)252// If we are using thin LTO, then create a directory instead.253TmpPathName = D.GetTemporaryDirectory("thinlto");254255if (!TmpPathName.empty()) {256auto *TmpPath = C.getArgs().MakeArgString(TmpPathName);257C.addTempFile(TmpPath);258CmdArgs.push_back("-object_path_lto");259CmdArgs.push_back(TmpPath);260}261}262263// Use -lto_library option to specify the libLTO.dylib path. Try to find264// it in clang installed libraries. ld64 will only look at this argument265// when it actually uses LTO, so libLTO.dylib only needs to exist at link266// time if ld64 decides that it needs to use LTO.267// Since this is passed unconditionally, ld64 will never look for libLTO.dylib268// next to it. That's ok since ld64 using a libLTO.dylib not matching the269// clang version won't work anyways.270// lld is built at the same revision as clang and statically links in271// LLVM libraries, so it doesn't need libLTO.dylib.272if (Version >= VersionTuple(133) && !LinkerIsLLD) {273// Search for libLTO in <InstalledDir>/../lib/libLTO.dylib274StringRef P = llvm::sys::path::parent_path(D.Dir);275SmallString<128> LibLTOPath(P);276llvm::sys::path::append(LibLTOPath, "lib");277llvm::sys::path::append(LibLTOPath, "libLTO.dylib");278CmdArgs.push_back("-lto_library");279CmdArgs.push_back(C.getArgs().MakeArgString(LibLTOPath));280}281282// ld64 version 262 and above runs the deduplicate pass by default.283// FIXME: lld doesn't dedup by default. Should we pass `--icf=safe`284// if `!shouldLinkerNotDedup()` if LinkerIsLLD here?285if (Version >= VersionTuple(262) &&286shouldLinkerNotDedup(C.getJobs().empty(), Args))287CmdArgs.push_back("-no_deduplicate");288289// Derived from the "link" spec.290Args.AddAllArgs(CmdArgs, options::OPT_static);291if (!Args.hasArg(options::OPT_static))292CmdArgs.push_back("-dynamic");293if (Args.hasArg(options::OPT_fgnu_runtime)) {294// FIXME: gcc replaces -lobjc in forward args with -lobjc-gnu295// here. How do we wish to handle such things?296}297298if (!Args.hasArg(options::OPT_dynamiclib)) {299AddMachOArch(Args, CmdArgs);300// FIXME: Why do this only on this path?301Args.AddLastArg(CmdArgs, options::OPT_force__cpusubtype__ALL);302303Args.AddLastArg(CmdArgs, options::OPT_bundle);304Args.AddAllArgs(CmdArgs, options::OPT_bundle__loader);305Args.AddAllArgs(CmdArgs, options::OPT_client__name);306307Arg *A;308if ((A = Args.getLastArg(options::OPT_compatibility__version)) ||309(A = Args.getLastArg(options::OPT_current__version)) ||310(A = Args.getLastArg(options::OPT_install__name)))311D.Diag(diag::err_drv_argument_only_allowed_with) << A->getAsString(Args)312<< "-dynamiclib";313314Args.AddLastArg(CmdArgs, options::OPT_force__flat__namespace);315Args.AddLastArg(CmdArgs, options::OPT_keep__private__externs);316Args.AddLastArg(CmdArgs, options::OPT_private__bundle);317} else {318CmdArgs.push_back("-dylib");319320Arg *A;321if ((A = Args.getLastArg(options::OPT_bundle)) ||322(A = Args.getLastArg(options::OPT_bundle__loader)) ||323(A = Args.getLastArg(options::OPT_client__name)) ||324(A = Args.getLastArg(options::OPT_force__flat__namespace)) ||325(A = Args.getLastArg(options::OPT_keep__private__externs)) ||326(A = Args.getLastArg(options::OPT_private__bundle)))327D.Diag(diag::err_drv_argument_not_allowed_with) << A->getAsString(Args)328<< "-dynamiclib";329330Args.AddAllArgsTranslated(CmdArgs, options::OPT_compatibility__version,331"-dylib_compatibility_version");332Args.AddAllArgsTranslated(CmdArgs, options::OPT_current__version,333"-dylib_current_version");334335AddMachOArch(Args, CmdArgs);336337Args.AddAllArgsTranslated(CmdArgs, options::OPT_install__name,338"-dylib_install_name");339}340341Args.AddLastArg(CmdArgs, options::OPT_all__load);342Args.AddAllArgs(CmdArgs, options::OPT_allowable__client);343Args.AddLastArg(CmdArgs, options::OPT_bind__at__load);344if (MachOTC.isTargetIOSBased())345Args.AddLastArg(CmdArgs, options::OPT_arch__errors__fatal);346Args.AddLastArg(CmdArgs, options::OPT_dead__strip);347Args.AddLastArg(CmdArgs, options::OPT_no__dead__strip__inits__and__terms);348Args.AddAllArgs(CmdArgs, options::OPT_dylib__file);349Args.AddLastArg(CmdArgs, options::OPT_dynamic);350Args.AddAllArgs(CmdArgs, options::OPT_exported__symbols__list);351Args.AddLastArg(CmdArgs, options::OPT_flat__namespace);352Args.AddAllArgs(CmdArgs, options::OPT_force__load);353Args.AddAllArgs(CmdArgs, options::OPT_headerpad__max__install__names);354Args.AddAllArgs(CmdArgs, options::OPT_image__base);355Args.AddAllArgs(CmdArgs, options::OPT_init);356357// Add the deployment target.358if (Version >= VersionTuple(520) || LinkerIsLLD || UsePlatformVersion)359MachOTC.addPlatformVersionArgs(Args, CmdArgs);360else361MachOTC.addMinVersionArgs(Args, CmdArgs);362363Args.AddLastArg(CmdArgs, options::OPT_nomultidefs);364Args.AddLastArg(CmdArgs, options::OPT_multi__module);365Args.AddLastArg(CmdArgs, options::OPT_single__module);366Args.AddAllArgs(CmdArgs, options::OPT_multiply__defined);367Args.AddAllArgs(CmdArgs, options::OPT_multiply__defined__unused);368369if (const Arg *A =370Args.getLastArg(options::OPT_fpie, options::OPT_fPIE,371options::OPT_fno_pie, options::OPT_fno_PIE)) {372if (A->getOption().matches(options::OPT_fpie) ||373A->getOption().matches(options::OPT_fPIE))374CmdArgs.push_back("-pie");375else376CmdArgs.push_back("-no_pie");377}378379// for embed-bitcode, use -bitcode_bundle in linker command380if (C.getDriver().embedBitcodeEnabled()) {381// Check if the toolchain supports bitcode build flow.382if (MachOTC.SupportsEmbeddedBitcode()) {383CmdArgs.push_back("-bitcode_bundle");384// FIXME: Pass this if LinkerIsLLD too, once it implements this flag.385if (C.getDriver().embedBitcodeMarkerOnly() &&386Version >= VersionTuple(278)) {387CmdArgs.push_back("-bitcode_process_mode");388CmdArgs.push_back("marker");389}390} else391D.Diag(diag::err_drv_bitcode_unsupported_on_toolchain);392}393394// If GlobalISel is enabled, pass it through to LLVM.395if (Arg *A = Args.getLastArg(options::OPT_fglobal_isel,396options::OPT_fno_global_isel)) {397if (A->getOption().matches(options::OPT_fglobal_isel)) {398CmdArgs.push_back("-mllvm");399CmdArgs.push_back("-global-isel");400// Disable abort and fall back to SDAG silently.401CmdArgs.push_back("-mllvm");402CmdArgs.push_back("-global-isel-abort=0");403}404}405406if (Args.hasArg(options::OPT_mkernel) ||407Args.hasArg(options::OPT_fapple_kext) ||408Args.hasArg(options::OPT_ffreestanding)) {409CmdArgs.push_back("-mllvm");410CmdArgs.push_back("-disable-atexit-based-global-dtor-lowering");411}412413Args.AddLastArg(CmdArgs, options::OPT_prebind);414Args.AddLastArg(CmdArgs, options::OPT_noprebind);415Args.AddLastArg(CmdArgs, options::OPT_nofixprebinding);416Args.AddLastArg(CmdArgs, options::OPT_prebind__all__twolevel__modules);417Args.AddLastArg(CmdArgs, options::OPT_read__only__relocs);418Args.AddAllArgs(CmdArgs, options::OPT_sectcreate);419Args.AddAllArgs(CmdArgs, options::OPT_sectorder);420Args.AddAllArgs(CmdArgs, options::OPT_seg1addr);421Args.AddAllArgs(CmdArgs, options::OPT_segprot);422Args.AddAllArgs(CmdArgs, options::OPT_segaddr);423Args.AddAllArgs(CmdArgs, options::OPT_segs__read__only__addr);424Args.AddAllArgs(CmdArgs, options::OPT_segs__read__write__addr);425Args.AddAllArgs(CmdArgs, options::OPT_seg__addr__table);426Args.AddAllArgs(CmdArgs, options::OPT_seg__addr__table__filename);427Args.AddAllArgs(CmdArgs, options::OPT_sub__library);428Args.AddAllArgs(CmdArgs, options::OPT_sub__umbrella);429430// Give --sysroot= preference, over the Apple specific behavior to also use431// --isysroot as the syslibroot.432StringRef sysroot = C.getSysRoot();433if (sysroot != "") {434CmdArgs.push_back("-syslibroot");435CmdArgs.push_back(C.getArgs().MakeArgString(sysroot));436} else if (const Arg *A = Args.getLastArg(options::OPT_isysroot)) {437CmdArgs.push_back("-syslibroot");438CmdArgs.push_back(A->getValue());439}440441Args.AddLastArg(CmdArgs, options::OPT_twolevel__namespace);442Args.AddLastArg(CmdArgs, options::OPT_twolevel__namespace__hints);443Args.AddAllArgs(CmdArgs, options::OPT_umbrella);444Args.AddAllArgs(CmdArgs, options::OPT_undefined);445Args.AddAllArgs(CmdArgs, options::OPT_unexported__symbols__list);446Args.AddAllArgs(CmdArgs, options::OPT_weak__reference__mismatches);447Args.AddLastArg(CmdArgs, options::OPT_X_Flag);448Args.AddAllArgs(CmdArgs, options::OPT_y);449Args.AddLastArg(CmdArgs, options::OPT_w);450Args.AddAllArgs(CmdArgs, options::OPT_pagezero__size);451Args.AddAllArgs(CmdArgs, options::OPT_segs__read__);452Args.AddLastArg(CmdArgs, options::OPT_seglinkedit);453Args.AddLastArg(CmdArgs, options::OPT_noseglinkedit);454Args.AddAllArgs(CmdArgs, options::OPT_sectalign);455Args.AddAllArgs(CmdArgs, options::OPT_sectobjectsymbols);456Args.AddAllArgs(CmdArgs, options::OPT_segcreate);457Args.AddLastArg(CmdArgs, options::OPT_why_load);458Args.AddLastArg(CmdArgs, options::OPT_whatsloaded);459Args.AddAllArgs(CmdArgs, options::OPT_dylinker__install__name);460Args.AddLastArg(CmdArgs, options::OPT_dylinker);461Args.AddLastArg(CmdArgs, options::OPT_Mach);462463if (LinkerIsLLD) {464if (auto *CSPGOGenerateArg = getLastCSProfileGenerateArg(Args)) {465SmallString<128> Path(CSPGOGenerateArg->getNumValues() == 0466? ""467: CSPGOGenerateArg->getValue());468llvm::sys::path::append(Path, "default_%m.profraw");469CmdArgs.push_back("--cs-profile-generate");470CmdArgs.push_back(Args.MakeArgString(Twine("--cs-profile-path=") + Path));471} else if (auto *ProfileUseArg = getLastProfileUseArg(Args)) {472SmallString<128> Path(473ProfileUseArg->getNumValues() == 0 ? "" : ProfileUseArg->getValue());474if (Path.empty() || llvm::sys::fs::is_directory(Path))475llvm::sys::path::append(Path, "default.profdata");476CmdArgs.push_back(Args.MakeArgString(Twine("--cs-profile-path=") + Path));477}478}479}480481/// Determine whether we are linking the ObjC runtime.482static bool isObjCRuntimeLinked(const ArgList &Args) {483if (isObjCAutoRefCount(Args)) {484Args.ClaimAllArgs(options::OPT_fobjc_link_runtime);485return true;486}487return Args.hasArg(options::OPT_fobjc_link_runtime);488}489490static bool checkRemarksOptions(const Driver &D, const ArgList &Args,491const llvm::Triple &Triple) {492// When enabling remarks, we need to error if:493// * The remark file is specified but we're targeting multiple architectures,494// which means more than one remark file is being generated.495bool hasMultipleInvocations =496Args.getAllArgValues(options::OPT_arch).size() > 1;497bool hasExplicitOutputFile =498Args.getLastArg(options::OPT_foptimization_record_file_EQ);499if (hasMultipleInvocations && hasExplicitOutputFile) {500D.Diag(diag::err_drv_invalid_output_with_multiple_archs)501<< "-foptimization-record-file";502return false;503}504return true;505}506507static void renderRemarksOptions(const ArgList &Args, ArgStringList &CmdArgs,508const llvm::Triple &Triple,509const InputInfo &Output, const JobAction &JA) {510StringRef Format = "yaml";511if (const Arg *A = Args.getLastArg(options::OPT_fsave_optimization_record_EQ))512Format = A->getValue();513514CmdArgs.push_back("-mllvm");515CmdArgs.push_back("-lto-pass-remarks-output");516CmdArgs.push_back("-mllvm");517518const Arg *A = Args.getLastArg(options::OPT_foptimization_record_file_EQ);519if (A) {520CmdArgs.push_back(A->getValue());521} else {522assert(Output.isFilename() && "Unexpected ld output.");523SmallString<128> F;524F = Output.getFilename();525F += ".opt.";526F += Format;527528CmdArgs.push_back(Args.MakeArgString(F));529}530531if (const Arg *A =532Args.getLastArg(options::OPT_foptimization_record_passes_EQ)) {533CmdArgs.push_back("-mllvm");534std::string Passes =535std::string("-lto-pass-remarks-filter=") + A->getValue();536CmdArgs.push_back(Args.MakeArgString(Passes));537}538539if (!Format.empty()) {540CmdArgs.push_back("-mllvm");541Twine FormatArg = Twine("-lto-pass-remarks-format=") + Format;542CmdArgs.push_back(Args.MakeArgString(FormatArg));543}544545if (getLastProfileUseArg(Args)) {546CmdArgs.push_back("-mllvm");547CmdArgs.push_back("-lto-pass-remarks-with-hotness");548549if (const Arg *A =550Args.getLastArg(options::OPT_fdiagnostics_hotness_threshold_EQ)) {551CmdArgs.push_back("-mllvm");552std::string Opt =553std::string("-lto-pass-remarks-hotness-threshold=") + A->getValue();554CmdArgs.push_back(Args.MakeArgString(Opt));555}556}557}558559static void AppendPlatformPrefix(SmallString<128> &Path, const llvm::Triple &T);560561void darwin::Linker::ConstructJob(Compilation &C, const JobAction &JA,562const InputInfo &Output,563const InputInfoList &Inputs,564const ArgList &Args,565const char *LinkingOutput) const {566assert(Output.getType() == types::TY_Image && "Invalid linker output type.");567568// If the number of arguments surpasses the system limits, we will encode the569// input files in a separate file, shortening the command line. To this end,570// build a list of input file names that can be passed via a file with the571// -filelist linker option.572llvm::opt::ArgStringList InputFileList;573574// The logic here is derived from gcc's behavior; most of which575// comes from specs (starting with link_command). Consult gcc for576// more information.577ArgStringList CmdArgs;578579/// Hack(tm) to ignore linking errors when we are doing ARC migration.580if (Args.hasArg(options::OPT_ccc_arcmt_check,581options::OPT_ccc_arcmt_migrate)) {582for (const auto &Arg : Args)583Arg->claim();584const char *Exec =585Args.MakeArgString(getToolChain().GetProgramPath("touch"));586CmdArgs.push_back(Output.getFilename());587C.addCommand(std::make_unique<Command>(JA, *this,588ResponseFileSupport::None(), Exec,589CmdArgs, std::nullopt, Output));590return;591}592593VersionTuple Version = getMachOToolChain().getLinkerVersion(Args);594595bool LinkerIsLLD;596const char *Exec =597Args.MakeArgString(getToolChain().GetLinkerPath(&LinkerIsLLD));598599// xrOS always uses -platform-version.600bool UsePlatformVersion = getToolChain().getTriple().isXROS();601602// I'm not sure why this particular decomposition exists in gcc, but603// we follow suite for ease of comparison.604AddLinkArgs(C, Args, CmdArgs, Inputs, Version, LinkerIsLLD,605UsePlatformVersion);606607if (willEmitRemarks(Args) &&608checkRemarksOptions(getToolChain().getDriver(), Args,609getToolChain().getTriple()))610renderRemarksOptions(Args, CmdArgs, getToolChain().getTriple(), Output, JA);611612// Propagate the -moutline flag to the linker in LTO.613if (Arg *A =614Args.getLastArg(options::OPT_moutline, options::OPT_mno_outline)) {615if (A->getOption().matches(options::OPT_moutline)) {616if (getMachOToolChain().getMachOArchName(Args) == "arm64") {617CmdArgs.push_back("-mllvm");618CmdArgs.push_back("-enable-machine-outliner");619}620} else {621// Disable all outlining behaviour if we have mno-outline. We need to do622// this explicitly, because targets which support default outlining will623// try to do work if we don't.624CmdArgs.push_back("-mllvm");625CmdArgs.push_back("-enable-machine-outliner=never");626}627}628629// Outline from linkonceodr functions by default in LTO, whenever the outliner630// is enabled. Note that the target may enable the machine outliner631// independently of -moutline.632CmdArgs.push_back("-mllvm");633CmdArgs.push_back("-enable-linkonceodr-outlining");634635// Setup statistics file output.636SmallString<128> StatsFile =637getStatsFileName(Args, Output, Inputs[0], getToolChain().getDriver());638if (!StatsFile.empty()) {639CmdArgs.push_back("-mllvm");640CmdArgs.push_back(Args.MakeArgString("-lto-stats-file=" + StatsFile.str()));641}642643// It seems that the 'e' option is completely ignored for dynamic executables644// (the default), and with static executables, the last one wins, as expected.645Args.addAllArgs(CmdArgs, {options::OPT_d_Flag, options::OPT_s, options::OPT_t,646options::OPT_Z_Flag, options::OPT_u_Group});647648// Forward -ObjC when either -ObjC or -ObjC++ is used, to force loading649// members of static archive libraries which implement Objective-C classes or650// categories.651if (Args.hasArg(options::OPT_ObjC) || Args.hasArg(options::OPT_ObjCXX))652CmdArgs.push_back("-ObjC");653654CmdArgs.push_back("-o");655CmdArgs.push_back(Output.getFilename());656657if (!Args.hasArg(options::OPT_nostdlib, options::OPT_nostartfiles))658getMachOToolChain().addStartObjectFileArgs(Args, CmdArgs);659660Args.AddAllArgs(CmdArgs, options::OPT_L);661662AddLinkerInputs(getToolChain(), Inputs, Args, CmdArgs, JA);663// Build the input file for -filelist (list of linker input files) in case we664// need it later665for (const auto &II : Inputs) {666if (!II.isFilename()) {667// This is a linker input argument.668// We cannot mix input arguments and file names in a -filelist input, thus669// we prematurely stop our list (remaining files shall be passed as670// arguments).671if (InputFileList.size() > 0)672break;673674continue;675}676677InputFileList.push_back(II.getFilename());678}679680// Additional linker set-up and flags for Fortran. This is required in order681// to generate executables.682if (getToolChain().getDriver().IsFlangMode()) {683addFortranRuntimeLibraryPath(getToolChain(), Args, CmdArgs);684addFortranRuntimeLibs(getToolChain(), Args, CmdArgs);685}686687if (!Args.hasArg(options::OPT_nostdlib, options::OPT_nodefaultlibs))688addOpenMPRuntime(C, CmdArgs, getToolChain(), Args);689690if (isObjCRuntimeLinked(Args) &&691!Args.hasArg(options::OPT_nostdlib, options::OPT_nodefaultlibs)) {692// We use arclite library for both ARC and subscripting support.693getMachOToolChain().AddLinkARCArgs(Args, CmdArgs);694695CmdArgs.push_back("-framework");696CmdArgs.push_back("Foundation");697// Link libobj.698CmdArgs.push_back("-lobjc");699}700701if (LinkingOutput) {702CmdArgs.push_back("-arch_multiple");703CmdArgs.push_back("-final_output");704CmdArgs.push_back(LinkingOutput);705}706707if (Args.hasArg(options::OPT_fnested_functions))708CmdArgs.push_back("-allow_stack_execute");709710getMachOToolChain().addProfileRTLibs(Args, CmdArgs);711712StringRef Parallelism = getLTOParallelism(Args, getToolChain().getDriver());713if (!Parallelism.empty()) {714CmdArgs.push_back("-mllvm");715unsigned NumThreads =716llvm::get_threadpool_strategy(Parallelism)->compute_thread_count();717CmdArgs.push_back(Args.MakeArgString("-threads=" + Twine(NumThreads)));718}719720if (getToolChain().ShouldLinkCXXStdlib(Args))721getToolChain().AddCXXStdlibLibArgs(Args, CmdArgs);722723bool NoStdOrDefaultLibs =724Args.hasArg(options::OPT_nostdlib, options::OPT_nodefaultlibs);725bool ForceLinkBuiltins = Args.hasArg(options::OPT_fapple_link_rtlib);726if (!NoStdOrDefaultLibs || ForceLinkBuiltins) {727// link_ssp spec is empty.728729// If we have both -nostdlib/nodefaultlibs and -fapple-link-rtlib then730// we just want to link the builtins, not the other libs like libSystem.731if (NoStdOrDefaultLibs && ForceLinkBuiltins) {732getMachOToolChain().AddLinkRuntimeLib(Args, CmdArgs, "builtins");733} else {734// Let the tool chain choose which runtime library to link.735getMachOToolChain().AddLinkRuntimeLibArgs(Args, CmdArgs,736ForceLinkBuiltins);737738// No need to do anything for pthreads. Claim argument to avoid warning.739Args.ClaimAllArgs(options::OPT_pthread);740Args.ClaimAllArgs(options::OPT_pthreads);741}742}743744if (!Args.hasArg(options::OPT_nostdlib, options::OPT_nostartfiles)) {745// endfile_spec is empty.746}747748Args.AddAllArgs(CmdArgs, options::OPT_T_Group);749Args.AddAllArgs(CmdArgs, options::OPT_F);750751// -iframework should be forwarded as -F.752for (const Arg *A : Args.filtered(options::OPT_iframework))753CmdArgs.push_back(Args.MakeArgString(std::string("-F") + A->getValue()));754755if (!Args.hasArg(options::OPT_nostdlib, options::OPT_nodefaultlibs)) {756if (Arg *A = Args.getLastArg(options::OPT_fveclib)) {757if (A->getValue() == StringRef("Accelerate")) {758CmdArgs.push_back("-framework");759CmdArgs.push_back("Accelerate");760}761}762}763764// Add non-standard, platform-specific search paths, e.g., for DriverKit:765// -L<sysroot>/System/DriverKit/usr/lib766// -F<sysroot>/System/DriverKit/System/Library/Framework767{768bool NonStandardSearchPath = false;769const auto &Triple = getToolChain().getTriple();770if (Triple.isDriverKit()) {771// ld64 fixed the implicit -F and -L paths in ld64-605.1+.772NonStandardSearchPath =773Version.getMajor() < 605 ||774(Version.getMajor() == 605 && Version.getMinor().value_or(0) < 1);775}776777if (NonStandardSearchPath) {778if (auto *Sysroot = Args.getLastArg(options::OPT_isysroot)) {779auto AddSearchPath = [&](StringRef Flag, StringRef SearchPath) {780SmallString<128> P(Sysroot->getValue());781AppendPlatformPrefix(P, Triple);782llvm::sys::path::append(P, SearchPath);783if (getToolChain().getVFS().exists(P)) {784CmdArgs.push_back(Args.MakeArgString(Flag + P));785}786};787AddSearchPath("-L", "/usr/lib");788AddSearchPath("-F", "/System/Library/Frameworks");789}790}791}792793ResponseFileSupport ResponseSupport;794if (Version >= VersionTuple(705) || LinkerIsLLD) {795ResponseSupport = ResponseFileSupport::AtFileUTF8();796} else {797// For older versions of the linker, use the legacy filelist method instead.798ResponseSupport = {ResponseFileSupport::RF_FileList, llvm::sys::WEM_UTF8,799"-filelist"};800}801802std::unique_ptr<Command> Cmd = std::make_unique<Command>(803JA, *this, ResponseSupport, Exec, CmdArgs, Inputs, Output);804Cmd->setInputFileList(std::move(InputFileList));805C.addCommand(std::move(Cmd));806}807808void darwin::StaticLibTool::ConstructJob(Compilation &C, const JobAction &JA,809const InputInfo &Output,810const InputInfoList &Inputs,811const ArgList &Args,812const char *LinkingOutput) const {813const Driver &D = getToolChain().getDriver();814815// Silence warning for "clang -g foo.o -o foo"816Args.ClaimAllArgs(options::OPT_g_Group);817// and "clang -emit-llvm foo.o -o foo"818Args.ClaimAllArgs(options::OPT_emit_llvm);819// and for "clang -w foo.o -o foo". Other warning options are already820// handled somewhere else.821Args.ClaimAllArgs(options::OPT_w);822// Silence warnings when linking C code with a C++ '-stdlib' argument.823Args.ClaimAllArgs(options::OPT_stdlib_EQ);824825// libtool <options> <output_file> <input_files>826ArgStringList CmdArgs;827// Create and insert file members with a deterministic index.828CmdArgs.push_back("-static");829CmdArgs.push_back("-D");830CmdArgs.push_back("-no_warning_for_no_symbols");831CmdArgs.push_back("-o");832CmdArgs.push_back(Output.getFilename());833834for (const auto &II : Inputs) {835if (II.isFilename()) {836CmdArgs.push_back(II.getFilename());837}838}839840// Delete old output archive file if it already exists before generating a new841// archive file.842const auto *OutputFileName = Output.getFilename();843if (Output.isFilename() && llvm::sys::fs::exists(OutputFileName)) {844if (std::error_code EC = llvm::sys::fs::remove(OutputFileName)) {845D.Diag(diag::err_drv_unable_to_remove_file) << EC.message();846return;847}848}849850const char *Exec = Args.MakeArgString(getToolChain().GetStaticLibToolPath());851C.addCommand(std::make_unique<Command>(JA, *this,852ResponseFileSupport::AtFileUTF8(),853Exec, CmdArgs, Inputs, Output));854}855856void darwin::Lipo::ConstructJob(Compilation &C, const JobAction &JA,857const InputInfo &Output,858const InputInfoList &Inputs,859const ArgList &Args,860const char *LinkingOutput) const {861ArgStringList CmdArgs;862863CmdArgs.push_back("-create");864assert(Output.isFilename() && "Unexpected lipo output.");865866CmdArgs.push_back("-output");867CmdArgs.push_back(Output.getFilename());868869for (const auto &II : Inputs) {870assert(II.isFilename() && "Unexpected lipo input.");871CmdArgs.push_back(II.getFilename());872}873874const char *Exec = Args.MakeArgString(getToolChain().GetProgramPath("lipo"));875C.addCommand(std::make_unique<Command>(JA, *this, ResponseFileSupport::None(),876Exec, CmdArgs, Inputs, Output));877}878879void darwin::Dsymutil::ConstructJob(Compilation &C, const JobAction &JA,880const InputInfo &Output,881const InputInfoList &Inputs,882const ArgList &Args,883const char *LinkingOutput) const {884ArgStringList CmdArgs;885886CmdArgs.push_back("-o");887CmdArgs.push_back(Output.getFilename());888889assert(Inputs.size() == 1 && "Unable to handle multiple inputs.");890const InputInfo &Input = Inputs[0];891assert(Input.isFilename() && "Unexpected dsymutil input.");892CmdArgs.push_back(Input.getFilename());893894const char *Exec =895Args.MakeArgString(getToolChain().GetProgramPath("dsymutil"));896C.addCommand(std::make_unique<Command>(JA, *this, ResponseFileSupport::None(),897Exec, CmdArgs, Inputs, Output));898}899900void darwin::VerifyDebug::ConstructJob(Compilation &C, const JobAction &JA,901const InputInfo &Output,902const InputInfoList &Inputs,903const ArgList &Args,904const char *LinkingOutput) const {905ArgStringList CmdArgs;906CmdArgs.push_back("--verify");907CmdArgs.push_back("--debug-info");908CmdArgs.push_back("--eh-frame");909CmdArgs.push_back("--quiet");910911assert(Inputs.size() == 1 && "Unable to handle multiple inputs.");912const InputInfo &Input = Inputs[0];913assert(Input.isFilename() && "Unexpected verify input");914915// Grabbing the output of the earlier dsymutil run.916CmdArgs.push_back(Input.getFilename());917918const char *Exec =919Args.MakeArgString(getToolChain().GetProgramPath("dwarfdump"));920C.addCommand(std::make_unique<Command>(JA, *this, ResponseFileSupport::None(),921Exec, CmdArgs, Inputs, Output));922}923924MachO::MachO(const Driver &D, const llvm::Triple &Triple, const ArgList &Args)925: ToolChain(D, Triple, Args) {926// We expect 'as', 'ld', etc. to be adjacent to our install dir.927getProgramPaths().push_back(getDriver().Dir);928}929930/// Darwin - Darwin tool chain for i386 and x86_64.931Darwin::Darwin(const Driver &D, const llvm::Triple &Triple, const ArgList &Args)932: MachO(D, Triple, Args), TargetInitialized(false),933CudaInstallation(D, Triple, Args), RocmInstallation(D, Triple, Args) {}934935types::ID MachO::LookupTypeForExtension(StringRef Ext) const {936types::ID Ty = ToolChain::LookupTypeForExtension(Ext);937938// Darwin always preprocesses assembly files (unless -x is used explicitly).939if (Ty == types::TY_PP_Asm)940return types::TY_Asm;941942return Ty;943}944945bool MachO::HasNativeLLVMSupport() const { return true; }946947ToolChain::CXXStdlibType Darwin::GetDefaultCXXStdlibType() const {948// Always use libc++ by default949return ToolChain::CST_Libcxx;950}951952/// Darwin provides an ARC runtime starting in MacOS X 10.7 and iOS 5.0.953ObjCRuntime Darwin::getDefaultObjCRuntime(bool isNonFragile) const {954if (isTargetWatchOSBased())955return ObjCRuntime(ObjCRuntime::WatchOS, TargetVersion);956if (isTargetIOSBased())957return ObjCRuntime(ObjCRuntime::iOS, TargetVersion);958if (isTargetXROS()) {959// XROS uses the iOS runtime.960auto T = llvm::Triple(Twine("arm64-apple-") +961llvm::Triple::getOSTypeName(llvm::Triple::XROS) +962TargetVersion.getAsString());963return ObjCRuntime(ObjCRuntime::iOS, T.getiOSVersion());964}965if (isNonFragile)966return ObjCRuntime(ObjCRuntime::MacOSX, TargetVersion);967return ObjCRuntime(ObjCRuntime::FragileMacOSX, TargetVersion);968}969970/// Darwin provides a blocks runtime starting in MacOS X 10.6 and iOS 3.2.971bool Darwin::hasBlocksRuntime() const {972if (isTargetWatchOSBased() || isTargetDriverKit() || isTargetXROS())973return true;974else if (isTargetIOSBased())975return !isIPhoneOSVersionLT(3, 2);976else {977assert(isTargetMacOSBased() && "unexpected darwin target");978return !isMacosxVersionLT(10, 6);979}980}981982void Darwin::AddCudaIncludeArgs(const ArgList &DriverArgs,983ArgStringList &CC1Args) const {984CudaInstallation->AddCudaIncludeArgs(DriverArgs, CC1Args);985}986987void Darwin::AddHIPIncludeArgs(const ArgList &DriverArgs,988ArgStringList &CC1Args) const {989RocmInstallation->AddHIPIncludeArgs(DriverArgs, CC1Args);990}991992// This is just a MachO name translation routine and there's no993// way to join this into ARMTargetParser without breaking all994// other assumptions. Maybe MachO should consider standardising995// their nomenclature.996static const char *ArmMachOArchName(StringRef Arch) {997return llvm::StringSwitch<const char *>(Arch)998.Case("armv6k", "armv6")999.Case("armv6m", "armv6m")1000.Case("armv5tej", "armv5")1001.Case("xscale", "xscale")1002.Case("armv4t", "armv4t")1003.Case("armv7", "armv7")1004.Cases("armv7a", "armv7-a", "armv7")1005.Cases("armv7r", "armv7-r", "armv7")1006.Cases("armv7em", "armv7e-m", "armv7em")1007.Cases("armv7k", "armv7-k", "armv7k")1008.Cases("armv7m", "armv7-m", "armv7m")1009.Cases("armv7s", "armv7-s", "armv7s")1010.Default(nullptr);1011}10121013static const char *ArmMachOArchNameCPU(StringRef CPU) {1014llvm::ARM::ArchKind ArchKind = llvm::ARM::parseCPUArch(CPU);1015if (ArchKind == llvm::ARM::ArchKind::INVALID)1016return nullptr;1017StringRef Arch = llvm::ARM::getArchName(ArchKind);10181019// FIXME: Make sure this MachO triple mangling is really necessary.1020// ARMv5* normalises to ARMv5.1021if (Arch.starts_with("armv5"))1022Arch = Arch.substr(0, 5);1023// ARMv6*, except ARMv6M, normalises to ARMv6.1024else if (Arch.starts_with("armv6") && !Arch.ends_with("6m"))1025Arch = Arch.substr(0, 5);1026// ARMv7A normalises to ARMv7.1027else if (Arch.ends_with("v7a"))1028Arch = Arch.substr(0, 5);1029return Arch.data();1030}10311032StringRef MachO::getMachOArchName(const ArgList &Args) const {1033switch (getTriple().getArch()) {1034default:1035return getDefaultUniversalArchName();10361037case llvm::Triple::aarch64_32:1038return "arm64_32";10391040case llvm::Triple::aarch64: {1041if (getTriple().isArm64e())1042return "arm64e";1043return "arm64";1044}10451046case llvm::Triple::thumb:1047case llvm::Triple::arm:1048if (const Arg *A = Args.getLastArg(clang::driver::options::OPT_march_EQ))1049if (const char *Arch = ArmMachOArchName(A->getValue()))1050return Arch;10511052if (const Arg *A = Args.getLastArg(options::OPT_mcpu_EQ))1053if (const char *Arch = ArmMachOArchNameCPU(A->getValue()))1054return Arch;10551056return "arm";1057}1058}10591060VersionTuple MachO::getLinkerVersion(const llvm::opt::ArgList &Args) const {1061if (LinkerVersion) {1062#ifndef NDEBUG1063VersionTuple NewLinkerVersion;1064if (Arg *A = Args.getLastArg(options::OPT_mlinker_version_EQ))1065(void)NewLinkerVersion.tryParse(A->getValue());1066assert(NewLinkerVersion == LinkerVersion);1067#endif1068return *LinkerVersion;1069}10701071VersionTuple NewLinkerVersion;1072if (Arg *A = Args.getLastArg(options::OPT_mlinker_version_EQ))1073if (NewLinkerVersion.tryParse(A->getValue()))1074getDriver().Diag(diag::err_drv_invalid_version_number)1075<< A->getAsString(Args);10761077LinkerVersion = NewLinkerVersion;1078return *LinkerVersion;1079}10801081Darwin::~Darwin() {}10821083MachO::~MachO() {}10841085std::string Darwin::ComputeEffectiveClangTriple(const ArgList &Args,1086types::ID InputType) const {1087llvm::Triple Triple(ComputeLLVMTriple(Args, InputType));10881089// If the target isn't initialized (e.g., an unknown Darwin platform, return1090// the default triple).1091if (!isTargetInitialized())1092return Triple.getTriple();10931094SmallString<16> Str;1095if (isTargetWatchOSBased())1096Str += "watchos";1097else if (isTargetTvOSBased())1098Str += "tvos";1099else if (isTargetDriverKit())1100Str += "driverkit";1101else if (isTargetIOSBased() || isTargetMacCatalyst())1102Str += "ios";1103else if (isTargetXROS())1104Str += llvm::Triple::getOSTypeName(llvm::Triple::XROS);1105else1106Str += "macosx";1107Str += getTripleTargetVersion().getAsString();1108Triple.setOSName(Str);11091110return Triple.getTriple();1111}11121113Tool *MachO::getTool(Action::ActionClass AC) const {1114switch (AC) {1115case Action::LipoJobClass:1116if (!Lipo)1117Lipo.reset(new tools::darwin::Lipo(*this));1118return Lipo.get();1119case Action::DsymutilJobClass:1120if (!Dsymutil)1121Dsymutil.reset(new tools::darwin::Dsymutil(*this));1122return Dsymutil.get();1123case Action::VerifyDebugInfoJobClass:1124if (!VerifyDebug)1125VerifyDebug.reset(new tools::darwin::VerifyDebug(*this));1126return VerifyDebug.get();1127default:1128return ToolChain::getTool(AC);1129}1130}11311132Tool *MachO::buildLinker() const { return new tools::darwin::Linker(*this); }11331134Tool *MachO::buildStaticLibTool() const {1135return new tools::darwin::StaticLibTool(*this);1136}11371138Tool *MachO::buildAssembler() const {1139return new tools::darwin::Assembler(*this);1140}11411142DarwinClang::DarwinClang(const Driver &D, const llvm::Triple &Triple,1143const ArgList &Args)1144: Darwin(D, Triple, Args) {}11451146void DarwinClang::addClangWarningOptions(ArgStringList &CC1Args) const {1147// Always error about undefined 'TARGET_OS_*' macros.1148CC1Args.push_back("-Wundef-prefix=TARGET_OS_");1149CC1Args.push_back("-Werror=undef-prefix");11501151// For modern targets, promote certain warnings to errors.1152if (isTargetWatchOSBased() || getTriple().isArch64Bit()) {1153// Always enable -Wdeprecated-objc-isa-usage and promote it1154// to an error.1155CC1Args.push_back("-Wdeprecated-objc-isa-usage");1156CC1Args.push_back("-Werror=deprecated-objc-isa-usage");11571158// For iOS and watchOS, also error about implicit function declarations,1159// as that can impact calling conventions.1160if (!isTargetMacOS())1161CC1Args.push_back("-Werror=implicit-function-declaration");1162}1163}11641165/// Take a path that speculatively points into Xcode and return the1166/// `XCODE/Contents/Developer` path if it is an Xcode path, or an empty path1167/// otherwise.1168static StringRef getXcodeDeveloperPath(StringRef PathIntoXcode) {1169static constexpr llvm::StringLiteral XcodeAppSuffix(1170".app/Contents/Developer");1171size_t Index = PathIntoXcode.find(XcodeAppSuffix);1172if (Index == StringRef::npos)1173return "";1174return PathIntoXcode.take_front(Index + XcodeAppSuffix.size());1175}11761177void DarwinClang::AddLinkARCArgs(const ArgList &Args,1178ArgStringList &CmdArgs) const {1179// Avoid linking compatibility stubs on i386 mac.1180if (isTargetMacOSBased() && getArch() == llvm::Triple::x86)1181return;1182if (isTargetAppleSiliconMac())1183return;1184// ARC runtime is supported everywhere on arm64e.1185if (getTriple().isArm64e())1186return;1187if (isTargetXROS())1188return;11891190ObjCRuntime runtime = getDefaultObjCRuntime(/*nonfragile*/ true);11911192if ((runtime.hasNativeARC() || !isObjCAutoRefCount(Args)) &&1193runtime.hasSubscripting())1194return;11951196SmallString<128> P(getDriver().ClangExecutable);1197llvm::sys::path::remove_filename(P); // 'clang'1198llvm::sys::path::remove_filename(P); // 'bin'1199llvm::sys::path::append(P, "lib", "arc");12001201// 'libarclite' usually lives in the same toolchain as 'clang'. However, the1202// Swift open source toolchains for macOS distribute Clang without libarclite.1203// In that case, to allow the linker to find 'libarclite', we point to the1204// 'libarclite' in the XcodeDefault toolchain instead.1205if (!getVFS().exists(P)) {1206auto updatePath = [&](const Arg *A) {1207// Try to infer the path to 'libarclite' in the toolchain from the1208// specified SDK path.1209StringRef XcodePathForSDK = getXcodeDeveloperPath(A->getValue());1210if (XcodePathForSDK.empty())1211return false;12121213P = XcodePathForSDK;1214llvm::sys::path::append(P, "Toolchains/XcodeDefault.xctoolchain/usr",1215"lib", "arc");1216return getVFS().exists(P);1217};12181219bool updated = false;1220if (const Arg *A = Args.getLastArg(options::OPT_isysroot))1221updated = updatePath(A);12221223if (!updated) {1224if (const Arg *A = Args.getLastArg(options::OPT__sysroot_EQ))1225updatePath(A);1226}1227}12281229CmdArgs.push_back("-force_load");1230llvm::sys::path::append(P, "libarclite_");1231// Mash in the platform.1232if (isTargetWatchOSSimulator())1233P += "watchsimulator";1234else if (isTargetWatchOS())1235P += "watchos";1236else if (isTargetTvOSSimulator())1237P += "appletvsimulator";1238else if (isTargetTvOS())1239P += "appletvos";1240else if (isTargetIOSSimulator())1241P += "iphonesimulator";1242else if (isTargetIPhoneOS())1243P += "iphoneos";1244else1245P += "macosx";1246P += ".a";12471248if (!getVFS().exists(P))1249getDriver().Diag(clang::diag::err_drv_darwin_sdk_missing_arclite) << P;12501251CmdArgs.push_back(Args.MakeArgString(P));1252}12531254unsigned DarwinClang::GetDefaultDwarfVersion() const {1255// Default to use DWARF 2 on OS X 10.10 / iOS 8 and lower.1256if ((isTargetMacOSBased() && isMacosxVersionLT(10, 11)) ||1257(isTargetIOSBased() && isIPhoneOSVersionLT(9)))1258return 2;1259// Default to use DWARF 4 on OS X 10.11 - macOS 14 / iOS 9 - iOS 17.1260if ((isTargetMacOSBased() && isMacosxVersionLT(15)) ||1261(isTargetIOSBased() && isIPhoneOSVersionLT(18)) ||1262(isTargetWatchOSBased() && TargetVersion < llvm::VersionTuple(11)) ||1263(isTargetXROS() && TargetVersion < llvm::VersionTuple(2)) ||1264(isTargetDriverKit() && TargetVersion < llvm::VersionTuple(24)) ||1265(isTargetMacOSBased() &&1266TargetVersion.empty())) // apple-darwin, no version.1267return 4;1268return 5;1269}12701271void MachO::AddLinkRuntimeLib(const ArgList &Args, ArgStringList &CmdArgs,1272StringRef Component, RuntimeLinkOptions Opts,1273bool IsShared) const {1274std::string P = getCompilerRT(1275Args, Component, IsShared ? ToolChain::FT_Shared : ToolChain::FT_Static);12761277// For now, allow missing resource libraries to support developers who may1278// not have compiler-rt checked out or integrated into their build (unless1279// we explicitly force linking with this library).1280if ((Opts & RLO_AlwaysLink) || getVFS().exists(P)) {1281const char *LibArg = Args.MakeArgString(P);1282CmdArgs.push_back(LibArg);1283}12841285// Adding the rpaths might negatively interact when other rpaths are involved,1286// so we should make sure we add the rpaths last, after all user-specified1287// rpaths. This is currently true from this place, but we need to be1288// careful if this function is ever called before user's rpaths are emitted.1289if (Opts & RLO_AddRPath) {1290assert(StringRef(P).ends_with(".dylib") && "must be a dynamic library");12911292// Add @executable_path to rpath to support having the dylib copied with1293// the executable.1294CmdArgs.push_back("-rpath");1295CmdArgs.push_back("@executable_path");12961297// Add the compiler-rt library's directory to rpath to support using the1298// dylib from the default location without copying.1299CmdArgs.push_back("-rpath");1300CmdArgs.push_back(Args.MakeArgString(llvm::sys::path::parent_path(P)));1301}1302}13031304std::string MachO::getCompilerRT(const ArgList &, StringRef Component,1305FileType Type) const {1306assert(Type != ToolChain::FT_Object &&1307"it doesn't make sense to ask for the compiler-rt library name as an "1308"object file");1309SmallString<64> MachOLibName = StringRef("libclang_rt");1310// On MachO, the builtins component is not in the library name1311if (Component != "builtins") {1312MachOLibName += '.';1313MachOLibName += Component;1314}1315MachOLibName += Type == ToolChain::FT_Shared ? "_dynamic.dylib" : ".a";13161317SmallString<128> FullPath(getDriver().ResourceDir);1318llvm::sys::path::append(FullPath, "lib", "darwin", "macho_embedded",1319MachOLibName);1320return std::string(FullPath);1321}13221323std::string Darwin::getCompilerRT(const ArgList &, StringRef Component,1324FileType Type) const {1325assert(Type != ToolChain::FT_Object &&1326"it doesn't make sense to ask for the compiler-rt library name as an "1327"object file");1328SmallString<64> DarwinLibName = StringRef("libclang_rt.");1329// On Darwin, the builtins component is not in the library name1330if (Component != "builtins") {1331DarwinLibName += Component;1332DarwinLibName += '_';1333}1334DarwinLibName += getOSLibraryNameSuffix();1335DarwinLibName += Type == ToolChain::FT_Shared ? "_dynamic.dylib" : ".a";13361337SmallString<128> FullPath(getDriver().ResourceDir);1338llvm::sys::path::append(FullPath, "lib", "darwin", DarwinLibName);1339return std::string(FullPath);1340}13411342StringRef Darwin::getPlatformFamily() const {1343switch (TargetPlatform) {1344case DarwinPlatformKind::MacOS:1345return "MacOSX";1346case DarwinPlatformKind::IPhoneOS:1347if (TargetEnvironment == MacCatalyst)1348return "MacOSX";1349return "iPhone";1350case DarwinPlatformKind::TvOS:1351return "AppleTV";1352case DarwinPlatformKind::WatchOS:1353return "Watch";1354case DarwinPlatformKind::DriverKit:1355return "DriverKit";1356case DarwinPlatformKind::XROS:1357return "XR";1358}1359llvm_unreachable("Unsupported platform");1360}13611362StringRef Darwin::getSDKName(StringRef isysroot) {1363// Assume SDK has path: SOME_PATH/SDKs/PlatformXX.YY.sdk1364auto BeginSDK = llvm::sys::path::rbegin(isysroot);1365auto EndSDK = llvm::sys::path::rend(isysroot);1366for (auto IT = BeginSDK; IT != EndSDK; ++IT) {1367StringRef SDK = *IT;1368if (SDK.ends_with(".sdk"))1369return SDK.slice(0, SDK.size() - 4);1370}1371return "";1372}13731374StringRef Darwin::getOSLibraryNameSuffix(bool IgnoreSim) const {1375switch (TargetPlatform) {1376case DarwinPlatformKind::MacOS:1377return "osx";1378case DarwinPlatformKind::IPhoneOS:1379if (TargetEnvironment == MacCatalyst)1380return "osx";1381return TargetEnvironment == NativeEnvironment || IgnoreSim ? "ios"1382: "iossim";1383case DarwinPlatformKind::TvOS:1384return TargetEnvironment == NativeEnvironment || IgnoreSim ? "tvos"1385: "tvossim";1386case DarwinPlatformKind::WatchOS:1387return TargetEnvironment == NativeEnvironment || IgnoreSim ? "watchos"1388: "watchossim";1389case DarwinPlatformKind::XROS:1390return TargetEnvironment == NativeEnvironment || IgnoreSim ? "xros"1391: "xrossim";1392case DarwinPlatformKind::DriverKit:1393return "driverkit";1394}1395llvm_unreachable("Unsupported platform");1396}13971398/// Check if the link command contains a symbol export directive.1399static bool hasExportSymbolDirective(const ArgList &Args) {1400for (Arg *A : Args) {1401if (A->getOption().matches(options::OPT_exported__symbols__list))1402return true;1403if (!A->getOption().matches(options::OPT_Wl_COMMA) &&1404!A->getOption().matches(options::OPT_Xlinker))1405continue;1406if (A->containsValue("-exported_symbols_list") ||1407A->containsValue("-exported_symbol"))1408return true;1409}1410return false;1411}14121413/// Add an export directive for \p Symbol to the link command.1414static void addExportedSymbol(ArgStringList &CmdArgs, const char *Symbol) {1415CmdArgs.push_back("-exported_symbol");1416CmdArgs.push_back(Symbol);1417}14181419/// Add a sectalign directive for \p Segment and \p Section to the maximum1420/// expected page size for Darwin.1421///1422/// On iPhone 6+ the max supported page size is 16K. On macOS, the max is 4K.1423/// Use a common alignment constant (16K) for now, and reduce the alignment on1424/// macOS if it proves important.1425static void addSectalignToPage(const ArgList &Args, ArgStringList &CmdArgs,1426StringRef Segment, StringRef Section) {1427for (const char *A : {"-sectalign", Args.MakeArgString(Segment),1428Args.MakeArgString(Section), "0x4000"})1429CmdArgs.push_back(A);1430}14311432void Darwin::addProfileRTLibs(const ArgList &Args,1433ArgStringList &CmdArgs) const {1434if (!needsProfileRT(Args) && !needsGCovInstrumentation(Args))1435return;14361437AddLinkRuntimeLib(Args, CmdArgs, "profile",1438RuntimeLinkOptions(RLO_AlwaysLink));14391440bool ForGCOV = needsGCovInstrumentation(Args);14411442// If we have a symbol export directive and we're linking in the profile1443// runtime, automatically export symbols necessary to implement some of the1444// runtime's functionality.1445if (hasExportSymbolDirective(Args) && ForGCOV) {1446addExportedSymbol(CmdArgs, "___gcov_dump");1447addExportedSymbol(CmdArgs, "___gcov_reset");1448addExportedSymbol(CmdArgs, "_writeout_fn_list");1449addExportedSymbol(CmdArgs, "_reset_fn_list");1450}14511452// Align __llvm_prf_{cnts,bits,data} sections to the maximum expected page1453// alignment. This allows profile counters to be mmap()'d to disk. Note that1454// it's not enough to just page-align __llvm_prf_cnts: the following section1455// must also be page-aligned so that its data is not clobbered by mmap().1456//1457// The section alignment is only needed when continuous profile sync is1458// enabled, but this is expected to be the default in Xcode. Specifying the1459// extra alignment also allows the same binary to be used with/without sync1460// enabled.1461if (!ForGCOV) {1462for (auto IPSK : {llvm::IPSK_cnts, llvm::IPSK_bitmap, llvm::IPSK_data}) {1463addSectalignToPage(1464Args, CmdArgs, "__DATA",1465llvm::getInstrProfSectionName(IPSK, llvm::Triple::MachO,1466/*AddSegmentInfo=*/false));1467}1468}1469}14701471void DarwinClang::AddLinkSanitizerLibArgs(const ArgList &Args,1472ArgStringList &CmdArgs,1473StringRef Sanitizer,1474bool Shared) const {1475auto RLO = RuntimeLinkOptions(RLO_AlwaysLink | (Shared ? RLO_AddRPath : 0U));1476AddLinkRuntimeLib(Args, CmdArgs, Sanitizer, RLO, Shared);1477}14781479ToolChain::RuntimeLibType DarwinClang::GetRuntimeLibType(1480const ArgList &Args) const {1481if (Arg* A = Args.getLastArg(options::OPT_rtlib_EQ)) {1482StringRef Value = A->getValue();1483if (Value != "compiler-rt" && Value != "platform")1484getDriver().Diag(clang::diag::err_drv_unsupported_rtlib_for_platform)1485<< Value << "darwin";1486}14871488return ToolChain::RLT_CompilerRT;1489}14901491void DarwinClang::AddLinkRuntimeLibArgs(const ArgList &Args,1492ArgStringList &CmdArgs,1493bool ForceLinkBuiltinRT) const {1494// Call once to ensure diagnostic is printed if wrong value was specified1495GetRuntimeLibType(Args);14961497// Darwin doesn't support real static executables, don't link any runtime1498// libraries with -static.1499if (Args.hasArg(options::OPT_static) ||1500Args.hasArg(options::OPT_fapple_kext) ||1501Args.hasArg(options::OPT_mkernel)) {1502if (ForceLinkBuiltinRT)1503AddLinkRuntimeLib(Args, CmdArgs, "builtins");1504return;1505}15061507// Reject -static-libgcc for now, we can deal with this when and if someone1508// cares. This is useful in situations where someone wants to statically link1509// something like libstdc++, and needs its runtime support routines.1510if (const Arg *A = Args.getLastArg(options::OPT_static_libgcc)) {1511getDriver().Diag(diag::err_drv_unsupported_opt) << A->getAsString(Args);1512return;1513}15141515const SanitizerArgs &Sanitize = getSanitizerArgs(Args);15161517if (!Sanitize.needsSharedRt()) {1518const char *sanitizer = nullptr;1519if (Sanitize.needsUbsanRt()) {1520sanitizer = "UndefinedBehaviorSanitizer";1521} else if (Sanitize.needsAsanRt()) {1522sanitizer = "AddressSanitizer";1523} else if (Sanitize.needsTsanRt()) {1524sanitizer = "ThreadSanitizer";1525}1526if (sanitizer) {1527getDriver().Diag(diag::err_drv_unsupported_static_sanitizer_darwin)1528<< sanitizer;1529return;1530}1531}15321533if (Sanitize.linkRuntimes()) {1534if (Sanitize.needsAsanRt()) {1535if (Sanitize.needsStableAbi()) {1536AddLinkSanitizerLibArgs(Args, CmdArgs, "asan_abi", /*shared=*/false);1537} else {1538assert(Sanitize.needsSharedRt() &&1539"Static sanitizer runtimes not supported");1540AddLinkSanitizerLibArgs(Args, CmdArgs, "asan");1541}1542}1543if (Sanitize.needsLsanRt())1544AddLinkSanitizerLibArgs(Args, CmdArgs, "lsan");1545if (Sanitize.needsUbsanRt()) {1546assert(Sanitize.needsSharedRt() &&1547"Static sanitizer runtimes not supported");1548AddLinkSanitizerLibArgs(1549Args, CmdArgs,1550Sanitize.requiresMinimalRuntime() ? "ubsan_minimal" : "ubsan");1551}1552if (Sanitize.needsTsanRt()) {1553assert(Sanitize.needsSharedRt() &&1554"Static sanitizer runtimes not supported");1555AddLinkSanitizerLibArgs(Args, CmdArgs, "tsan");1556}1557if (Sanitize.needsFuzzer() && !Args.hasArg(options::OPT_dynamiclib)) {1558AddLinkSanitizerLibArgs(Args, CmdArgs, "fuzzer", /*shared=*/false);15591560// Libfuzzer is written in C++ and requires libcxx.1561AddCXXStdlibLibArgs(Args, CmdArgs);1562}1563if (Sanitize.needsStatsRt()) {1564AddLinkRuntimeLib(Args, CmdArgs, "stats_client", RLO_AlwaysLink);1565AddLinkSanitizerLibArgs(Args, CmdArgs, "stats");1566}1567}15681569const XRayArgs &XRay = getXRayArgs();1570if (XRay.needsXRayRt()) {1571AddLinkRuntimeLib(Args, CmdArgs, "xray");1572AddLinkRuntimeLib(Args, CmdArgs, "xray-basic");1573AddLinkRuntimeLib(Args, CmdArgs, "xray-fdr");1574}15751576if (isTargetDriverKit() && !Args.hasArg(options::OPT_nodriverkitlib)) {1577CmdArgs.push_back("-framework");1578CmdArgs.push_back("DriverKit");1579}15801581// Otherwise link libSystem, then the dynamic runtime library, and finally any1582// target specific static runtime library.1583if (!isTargetDriverKit())1584CmdArgs.push_back("-lSystem");15851586// Select the dynamic runtime library and the target specific static library.1587if (isTargetIOSBased()) {1588// If we are compiling as iOS / simulator, don't attempt to link libgcc_s.1,1589// it never went into the SDK.1590// Linking against libgcc_s.1 isn't needed for iOS 5.0+1591if (isIPhoneOSVersionLT(5, 0) && !isTargetIOSSimulator() &&1592getTriple().getArch() != llvm::Triple::aarch64)1593CmdArgs.push_back("-lgcc_s.1");1594}1595AddLinkRuntimeLib(Args, CmdArgs, "builtins");1596}15971598/// Returns the most appropriate macOS target version for the current process.1599///1600/// If the macOS SDK version is the same or earlier than the system version,1601/// then the SDK version is returned. Otherwise the system version is returned.1602static std::string getSystemOrSDKMacOSVersion(StringRef MacOSSDKVersion) {1603llvm::Triple SystemTriple(llvm::sys::getProcessTriple());1604if (!SystemTriple.isMacOSX())1605return std::string(MacOSSDKVersion);1606VersionTuple SystemVersion;1607SystemTriple.getMacOSXVersion(SystemVersion);16081609unsigned Major, Minor, Micro;1610bool HadExtra;1611if (!Driver::GetReleaseVersion(MacOSSDKVersion, Major, Minor, Micro,1612HadExtra))1613return std::string(MacOSSDKVersion);1614VersionTuple SDKVersion(Major, Minor, Micro);16151616if (SDKVersion > SystemVersion)1617return SystemVersion.getAsString();1618return std::string(MacOSSDKVersion);1619}16201621namespace {16221623/// The Darwin OS that was selected or inferred from arguments / environment.1624struct DarwinPlatform {1625enum SourceKind {1626/// The OS was specified using the -target argument.1627TargetArg,1628/// The OS was specified using the -mtargetos= argument.1629MTargetOSArg,1630/// The OS was specified using the -m<os>-version-min argument.1631OSVersionArg,1632/// The OS was specified using the OS_DEPLOYMENT_TARGET environment.1633DeploymentTargetEnv,1634/// The OS was inferred from the SDK.1635InferredFromSDK,1636/// The OS was inferred from the -arch.1637InferredFromArch1638};16391640using DarwinPlatformKind = Darwin::DarwinPlatformKind;1641using DarwinEnvironmentKind = Darwin::DarwinEnvironmentKind;16421643DarwinPlatformKind getPlatform() const { return Platform; }16441645DarwinEnvironmentKind getEnvironment() const { return Environment; }16461647void setEnvironment(DarwinEnvironmentKind Kind) {1648Environment = Kind;1649InferSimulatorFromArch = false;1650}16511652StringRef getOSVersion() const {1653if (Kind == OSVersionArg)1654return Argument->getValue();1655return OSVersion;1656}16571658void setOSVersion(StringRef S) {1659assert(Kind == TargetArg && "Unexpected kind!");1660OSVersion = std::string(S);1661}16621663bool hasOSVersion() const { return HasOSVersion; }16641665VersionTuple getNativeTargetVersion() const {1666assert(Environment == DarwinEnvironmentKind::MacCatalyst &&1667"native target version is specified only for Mac Catalyst");1668return NativeTargetVersion;1669}16701671/// Returns true if the target OS was explicitly specified.1672bool isExplicitlySpecified() const { return Kind <= DeploymentTargetEnv; }16731674/// Returns true if the simulator environment can be inferred from the arch.1675bool canInferSimulatorFromArch() const { return InferSimulatorFromArch; }16761677const std::optional<llvm::Triple> &getTargetVariantTriple() const {1678return TargetVariantTriple;1679}16801681/// Adds the -m<os>-version-min argument to the compiler invocation.1682void addOSVersionMinArgument(DerivedArgList &Args, const OptTable &Opts) {1683if (Argument)1684return;1685assert(Kind != TargetArg && Kind != MTargetOSArg && Kind != OSVersionArg &&1686"Invalid kind");1687options::ID Opt;1688switch (Platform) {1689case DarwinPlatformKind::MacOS:1690Opt = options::OPT_mmacos_version_min_EQ;1691break;1692case DarwinPlatformKind::IPhoneOS:1693Opt = options::OPT_mios_version_min_EQ;1694break;1695case DarwinPlatformKind::TvOS:1696Opt = options::OPT_mtvos_version_min_EQ;1697break;1698case DarwinPlatformKind::WatchOS:1699Opt = options::OPT_mwatchos_version_min_EQ;1700break;1701case DarwinPlatformKind::XROS:1702// xrOS always explicitly provides a version in the triple.1703return;1704case DarwinPlatformKind::DriverKit:1705// DriverKit always explicitly provides a version in the triple.1706return;1707}1708Argument = Args.MakeJoinedArg(nullptr, Opts.getOption(Opt), OSVersion);1709Args.append(Argument);1710}17111712/// Returns the OS version with the argument / environment variable that1713/// specified it.1714std::string getAsString(DerivedArgList &Args, const OptTable &Opts) {1715switch (Kind) {1716case TargetArg:1717case MTargetOSArg:1718case OSVersionArg:1719case InferredFromSDK:1720case InferredFromArch:1721assert(Argument && "OS version argument not yet inferred");1722return Argument->getAsString(Args);1723case DeploymentTargetEnv:1724return (llvm::Twine(EnvVarName) + "=" + OSVersion).str();1725}1726llvm_unreachable("Unsupported Darwin Source Kind");1727}17281729void setEnvironment(llvm::Triple::EnvironmentType EnvType,1730const VersionTuple &OSVersion,1731const std::optional<DarwinSDKInfo> &SDKInfo) {1732switch (EnvType) {1733case llvm::Triple::Simulator:1734Environment = DarwinEnvironmentKind::Simulator;1735break;1736case llvm::Triple::MacABI: {1737Environment = DarwinEnvironmentKind::MacCatalyst;1738// The minimum native macOS target for MacCatalyst is macOS 10.15.1739NativeTargetVersion = VersionTuple(10, 15);1740if (HasOSVersion && SDKInfo) {1741if (const auto *MacCatalystToMacOSMapping = SDKInfo->getVersionMapping(1742DarwinSDKInfo::OSEnvPair::macCatalystToMacOSPair())) {1743if (auto MacOSVersion = MacCatalystToMacOSMapping->map(1744OSVersion, NativeTargetVersion, std::nullopt)) {1745NativeTargetVersion = *MacOSVersion;1746}1747}1748}1749// In a zippered build, we could be building for a macOS target that's1750// lower than the version that's implied by the OS version. In that case1751// we need to use the minimum version as the native target version.1752if (TargetVariantTriple) {1753auto TargetVariantVersion = TargetVariantTriple->getOSVersion();1754if (TargetVariantVersion.getMajor()) {1755if (TargetVariantVersion < NativeTargetVersion)1756NativeTargetVersion = TargetVariantVersion;1757}1758}1759break;1760}1761default:1762break;1763}1764}17651766static DarwinPlatform1767createFromTarget(const llvm::Triple &TT, StringRef OSVersion, Arg *A,1768std::optional<llvm::Triple> TargetVariantTriple,1769const std::optional<DarwinSDKInfo> &SDKInfo) {1770DarwinPlatform Result(TargetArg, getPlatformFromOS(TT.getOS()), OSVersion,1771A);1772VersionTuple OsVersion = TT.getOSVersion();1773if (OsVersion.getMajor() == 0)1774Result.HasOSVersion = false;1775Result.TargetVariantTriple = TargetVariantTriple;1776Result.setEnvironment(TT.getEnvironment(), OsVersion, SDKInfo);1777return Result;1778}1779static DarwinPlatform1780createFromMTargetOS(llvm::Triple::OSType OS, VersionTuple OSVersion,1781llvm::Triple::EnvironmentType Environment, Arg *A,1782const std::optional<DarwinSDKInfo> &SDKInfo) {1783DarwinPlatform Result(MTargetOSArg, getPlatformFromOS(OS),1784OSVersion.getAsString(), A);1785Result.InferSimulatorFromArch = false;1786Result.setEnvironment(Environment, OSVersion, SDKInfo);1787return Result;1788}1789static DarwinPlatform createOSVersionArg(DarwinPlatformKind Platform, Arg *A,1790bool IsSimulator) {1791DarwinPlatform Result{OSVersionArg, Platform, A};1792if (IsSimulator)1793Result.Environment = DarwinEnvironmentKind::Simulator;1794return Result;1795}1796static DarwinPlatform createDeploymentTargetEnv(DarwinPlatformKind Platform,1797StringRef EnvVarName,1798StringRef Value) {1799DarwinPlatform Result(DeploymentTargetEnv, Platform, Value);1800Result.EnvVarName = EnvVarName;1801return Result;1802}1803static DarwinPlatform createFromSDK(DarwinPlatformKind Platform,1804StringRef Value,1805bool IsSimulator = false) {1806DarwinPlatform Result(InferredFromSDK, Platform, Value);1807if (IsSimulator)1808Result.Environment = DarwinEnvironmentKind::Simulator;1809Result.InferSimulatorFromArch = false;1810return Result;1811}1812static DarwinPlatform createFromArch(llvm::Triple::OSType OS,1813StringRef Value) {1814return DarwinPlatform(InferredFromArch, getPlatformFromOS(OS), Value);1815}18161817/// Constructs an inferred SDKInfo value based on the version inferred from1818/// the SDK path itself. Only works for values that were created by inferring1819/// the platform from the SDKPath.1820DarwinSDKInfo inferSDKInfo() {1821assert(Kind == InferredFromSDK && "can infer SDK info only");1822llvm::VersionTuple Version;1823bool IsValid = !Version.tryParse(OSVersion);1824(void)IsValid;1825assert(IsValid && "invalid SDK version");1826return DarwinSDKInfo(1827Version,1828/*MaximumDeploymentTarget=*/VersionTuple(Version.getMajor(), 0, 99));1829}18301831private:1832DarwinPlatform(SourceKind Kind, DarwinPlatformKind Platform, Arg *Argument)1833: Kind(Kind), Platform(Platform), Argument(Argument) {}1834DarwinPlatform(SourceKind Kind, DarwinPlatformKind Platform, StringRef Value,1835Arg *Argument = nullptr)1836: Kind(Kind), Platform(Platform), OSVersion(Value), Argument(Argument) {}18371838static DarwinPlatformKind getPlatformFromOS(llvm::Triple::OSType OS) {1839switch (OS) {1840case llvm::Triple::Darwin:1841case llvm::Triple::MacOSX:1842return DarwinPlatformKind::MacOS;1843case llvm::Triple::IOS:1844return DarwinPlatformKind::IPhoneOS;1845case llvm::Triple::TvOS:1846return DarwinPlatformKind::TvOS;1847case llvm::Triple::WatchOS:1848return DarwinPlatformKind::WatchOS;1849case llvm::Triple::XROS:1850return DarwinPlatformKind::XROS;1851case llvm::Triple::DriverKit:1852return DarwinPlatformKind::DriverKit;1853default:1854llvm_unreachable("Unable to infer Darwin variant");1855}1856}18571858SourceKind Kind;1859DarwinPlatformKind Platform;1860DarwinEnvironmentKind Environment = DarwinEnvironmentKind::NativeEnvironment;1861VersionTuple NativeTargetVersion;1862std::string OSVersion;1863bool HasOSVersion = true, InferSimulatorFromArch = true;1864Arg *Argument;1865StringRef EnvVarName;1866std::optional<llvm::Triple> TargetVariantTriple;1867};18681869/// Returns the deployment target that's specified using the -m<os>-version-min1870/// argument.1871std::optional<DarwinPlatform>1872getDeploymentTargetFromOSVersionArg(DerivedArgList &Args,1873const Driver &TheDriver) {1874Arg *macOSVersion = Args.getLastArg(options::OPT_mmacos_version_min_EQ);1875Arg *iOSVersion = Args.getLastArg(options::OPT_mios_version_min_EQ,1876options::OPT_mios_simulator_version_min_EQ);1877Arg *TvOSVersion =1878Args.getLastArg(options::OPT_mtvos_version_min_EQ,1879options::OPT_mtvos_simulator_version_min_EQ);1880Arg *WatchOSVersion =1881Args.getLastArg(options::OPT_mwatchos_version_min_EQ,1882options::OPT_mwatchos_simulator_version_min_EQ);1883if (macOSVersion) {1884if (iOSVersion || TvOSVersion || WatchOSVersion) {1885TheDriver.Diag(diag::err_drv_argument_not_allowed_with)1886<< macOSVersion->getAsString(Args)1887<< (iOSVersion ? iOSVersion1888: TvOSVersion ? TvOSVersion : WatchOSVersion)1889->getAsString(Args);1890}1891return DarwinPlatform::createOSVersionArg(Darwin::MacOS, macOSVersion,1892/*IsSimulator=*/false);1893} else if (iOSVersion) {1894if (TvOSVersion || WatchOSVersion) {1895TheDriver.Diag(diag::err_drv_argument_not_allowed_with)1896<< iOSVersion->getAsString(Args)1897<< (TvOSVersion ? TvOSVersion : WatchOSVersion)->getAsString(Args);1898}1899return DarwinPlatform::createOSVersionArg(1900Darwin::IPhoneOS, iOSVersion,1901iOSVersion->getOption().getID() ==1902options::OPT_mios_simulator_version_min_EQ);1903} else if (TvOSVersion) {1904if (WatchOSVersion) {1905TheDriver.Diag(diag::err_drv_argument_not_allowed_with)1906<< TvOSVersion->getAsString(Args)1907<< WatchOSVersion->getAsString(Args);1908}1909return DarwinPlatform::createOSVersionArg(1910Darwin::TvOS, TvOSVersion,1911TvOSVersion->getOption().getID() ==1912options::OPT_mtvos_simulator_version_min_EQ);1913} else if (WatchOSVersion)1914return DarwinPlatform::createOSVersionArg(1915Darwin::WatchOS, WatchOSVersion,1916WatchOSVersion->getOption().getID() ==1917options::OPT_mwatchos_simulator_version_min_EQ);1918return std::nullopt;1919}19201921/// Returns the deployment target that's specified using the1922/// OS_DEPLOYMENT_TARGET environment variable.1923std::optional<DarwinPlatform>1924getDeploymentTargetFromEnvironmentVariables(const Driver &TheDriver,1925const llvm::Triple &Triple) {1926std::string Targets[Darwin::LastDarwinPlatform + 1];1927const char *EnvVars[] = {1928"MACOSX_DEPLOYMENT_TARGET",1929"IPHONEOS_DEPLOYMENT_TARGET",1930"TVOS_DEPLOYMENT_TARGET",1931"WATCHOS_DEPLOYMENT_TARGET",1932"DRIVERKIT_DEPLOYMENT_TARGET",1933"XROS_DEPLOYMENT_TARGET"1934};1935static_assert(std::size(EnvVars) == Darwin::LastDarwinPlatform + 1,1936"Missing platform");1937for (const auto &I : llvm::enumerate(llvm::ArrayRef(EnvVars))) {1938if (char *Env = ::getenv(I.value()))1939Targets[I.index()] = Env;1940}19411942// Allow conflicts among OSX and iOS for historical reasons, but choose the1943// default platform.1944if (!Targets[Darwin::MacOS].empty() &&1945(!Targets[Darwin::IPhoneOS].empty() ||1946!Targets[Darwin::WatchOS].empty() || !Targets[Darwin::TvOS].empty() ||1947!Targets[Darwin::XROS].empty())) {1948if (Triple.getArch() == llvm::Triple::arm ||1949Triple.getArch() == llvm::Triple::aarch64 ||1950Triple.getArch() == llvm::Triple::thumb)1951Targets[Darwin::MacOS] = "";1952else1953Targets[Darwin::IPhoneOS] = Targets[Darwin::WatchOS] =1954Targets[Darwin::TvOS] = Targets[Darwin::XROS] = "";1955} else {1956// Don't allow conflicts in any other platform.1957unsigned FirstTarget = std::size(Targets);1958for (unsigned I = 0; I != std::size(Targets); ++I) {1959if (Targets[I].empty())1960continue;1961if (FirstTarget == std::size(Targets))1962FirstTarget = I;1963else1964TheDriver.Diag(diag::err_drv_conflicting_deployment_targets)1965<< Targets[FirstTarget] << Targets[I];1966}1967}19681969for (const auto &Target : llvm::enumerate(llvm::ArrayRef(Targets))) {1970if (!Target.value().empty())1971return DarwinPlatform::createDeploymentTargetEnv(1972(Darwin::DarwinPlatformKind)Target.index(), EnvVars[Target.index()],1973Target.value());1974}1975return std::nullopt;1976}19771978/// Returns the SDK name without the optional prefix that ends with a '.' or an1979/// empty string otherwise.1980static StringRef dropSDKNamePrefix(StringRef SDKName) {1981size_t PrefixPos = SDKName.find('.');1982if (PrefixPos == StringRef::npos)1983return "";1984return SDKName.substr(PrefixPos + 1);1985}19861987/// Tries to infer the deployment target from the SDK specified by -isysroot1988/// (or SDKROOT). Uses the version specified in the SDKSettings.json file if1989/// it's available.1990std::optional<DarwinPlatform>1991inferDeploymentTargetFromSDK(DerivedArgList &Args,1992const std::optional<DarwinSDKInfo> &SDKInfo) {1993const Arg *A = Args.getLastArg(options::OPT_isysroot);1994if (!A)1995return std::nullopt;1996StringRef isysroot = A->getValue();1997StringRef SDK = Darwin::getSDKName(isysroot);1998if (!SDK.size())1999return std::nullopt;20002001std::string Version;2002if (SDKInfo) {2003// Get the version from the SDKSettings.json if it's available.2004Version = SDKInfo->getVersion().getAsString();2005} else {2006// Slice the version number out.2007// Version number is between the first and the last number.2008size_t StartVer = SDK.find_first_of("0123456789");2009size_t EndVer = SDK.find_last_of("0123456789");2010if (StartVer != StringRef::npos && EndVer > StartVer)2011Version = std::string(SDK.slice(StartVer, EndVer + 1));2012}2013if (Version.empty())2014return std::nullopt;20152016auto CreatePlatformFromSDKName =2017[&](StringRef SDK) -> std::optional<DarwinPlatform> {2018if (SDK.starts_with("iPhoneOS") || SDK.starts_with("iPhoneSimulator"))2019return DarwinPlatform::createFromSDK(2020Darwin::IPhoneOS, Version,2021/*IsSimulator=*/SDK.starts_with("iPhoneSimulator"));2022else if (SDK.starts_with("MacOSX"))2023return DarwinPlatform::createFromSDK(Darwin::MacOS,2024getSystemOrSDKMacOSVersion(Version));2025else if (SDK.starts_with("WatchOS") || SDK.starts_with("WatchSimulator"))2026return DarwinPlatform::createFromSDK(2027Darwin::WatchOS, Version,2028/*IsSimulator=*/SDK.starts_with("WatchSimulator"));2029else if (SDK.starts_with("AppleTVOS") ||2030SDK.starts_with("AppleTVSimulator"))2031return DarwinPlatform::createFromSDK(2032Darwin::TvOS, Version,2033/*IsSimulator=*/SDK.starts_with("AppleTVSimulator"));2034else if (SDK.starts_with("XR"))2035return DarwinPlatform::createFromSDK(2036Darwin::XROS, Version,2037/*IsSimulator=*/SDK.contains("Simulator"));2038else if (SDK.starts_with("DriverKit"))2039return DarwinPlatform::createFromSDK(Darwin::DriverKit, Version);2040return std::nullopt;2041};2042if (auto Result = CreatePlatformFromSDKName(SDK))2043return Result;2044// The SDK can be an SDK variant with a name like `<prefix>.<platform>`.2045return CreatePlatformFromSDKName(dropSDKNamePrefix(SDK));2046}20472048std::string getOSVersion(llvm::Triple::OSType OS, const llvm::Triple &Triple,2049const Driver &TheDriver) {2050VersionTuple OsVersion;2051llvm::Triple SystemTriple(llvm::sys::getProcessTriple());2052switch (OS) {2053case llvm::Triple::Darwin:2054case llvm::Triple::MacOSX:2055// If there is no version specified on triple, and both host and target are2056// macos, use the host triple to infer OS version.2057if (Triple.isMacOSX() && SystemTriple.isMacOSX() &&2058!Triple.getOSMajorVersion())2059SystemTriple.getMacOSXVersion(OsVersion);2060else if (!Triple.getMacOSXVersion(OsVersion))2061TheDriver.Diag(diag::err_drv_invalid_darwin_version)2062<< Triple.getOSName();2063break;2064case llvm::Triple::IOS:2065if (Triple.isMacCatalystEnvironment() && !Triple.getOSMajorVersion()) {2066OsVersion = VersionTuple(13, 1);2067} else2068OsVersion = Triple.getiOSVersion();2069break;2070case llvm::Triple::TvOS:2071OsVersion = Triple.getOSVersion();2072break;2073case llvm::Triple::WatchOS:2074OsVersion = Triple.getWatchOSVersion();2075break;2076case llvm::Triple::XROS:2077OsVersion = Triple.getOSVersion();2078if (!OsVersion.getMajor())2079OsVersion = OsVersion.withMajorReplaced(1);2080break;2081case llvm::Triple::DriverKit:2082OsVersion = Triple.getDriverKitVersion();2083break;2084default:2085llvm_unreachable("Unexpected OS type");2086break;2087}20882089std::string OSVersion;2090llvm::raw_string_ostream(OSVersion)2091<< OsVersion.getMajor() << '.' << OsVersion.getMinor().value_or(0) << '.'2092<< OsVersion.getSubminor().value_or(0);2093return OSVersion;2094}20952096/// Tries to infer the target OS from the -arch.2097std::optional<DarwinPlatform>2098inferDeploymentTargetFromArch(DerivedArgList &Args, const Darwin &Toolchain,2099const llvm::Triple &Triple,2100const Driver &TheDriver) {2101llvm::Triple::OSType OSTy = llvm::Triple::UnknownOS;21022103StringRef MachOArchName = Toolchain.getMachOArchName(Args);2104if (MachOArchName == "arm64" || MachOArchName == "arm64e")2105OSTy = llvm::Triple::MacOSX;2106else if (MachOArchName == "armv7" || MachOArchName == "armv7s")2107OSTy = llvm::Triple::IOS;2108else if (MachOArchName == "armv7k" || MachOArchName == "arm64_32")2109OSTy = llvm::Triple::WatchOS;2110else if (MachOArchName != "armv6m" && MachOArchName != "armv7m" &&2111MachOArchName != "armv7em")2112OSTy = llvm::Triple::MacOSX;2113if (OSTy == llvm::Triple::UnknownOS)2114return std::nullopt;2115return DarwinPlatform::createFromArch(OSTy,2116getOSVersion(OSTy, Triple, TheDriver));2117}21182119/// Returns the deployment target that's specified using the -target option.2120std::optional<DarwinPlatform> getDeploymentTargetFromTargetArg(2121DerivedArgList &Args, const llvm::Triple &Triple, const Driver &TheDriver,2122const std::optional<DarwinSDKInfo> &SDKInfo) {2123if (!Args.hasArg(options::OPT_target))2124return std::nullopt;2125if (Triple.getOS() == llvm::Triple::Darwin ||2126Triple.getOS() == llvm::Triple::UnknownOS)2127return std::nullopt;2128std::string OSVersion = getOSVersion(Triple.getOS(), Triple, TheDriver);2129std::optional<llvm::Triple> TargetVariantTriple;2130for (const Arg *A : Args.filtered(options::OPT_darwin_target_variant)) {2131llvm::Triple TVT(A->getValue());2132// Find a matching <arch>-<vendor> target variant triple that can be used.2133if ((Triple.getArch() == llvm::Triple::aarch64 ||2134TVT.getArchName() == Triple.getArchName()) &&2135TVT.getArch() == Triple.getArch() &&2136TVT.getSubArch() == Triple.getSubArch() &&2137TVT.getVendor() == Triple.getVendor()) {2138if (TargetVariantTriple)2139continue;2140A->claim();2141// Accept a -target-variant triple when compiling code that may run on2142// macOS or Mac Catalyst.2143if ((Triple.isMacOSX() && TVT.getOS() == llvm::Triple::IOS &&2144TVT.isMacCatalystEnvironment()) ||2145(TVT.isMacOSX() && Triple.getOS() == llvm::Triple::IOS &&2146Triple.isMacCatalystEnvironment())) {2147TargetVariantTriple = TVT;2148continue;2149}2150TheDriver.Diag(diag::err_drv_target_variant_invalid)2151<< A->getSpelling() << A->getValue();2152}2153}2154return DarwinPlatform::createFromTarget(Triple, OSVersion,2155Args.getLastArg(options::OPT_target),2156TargetVariantTriple, SDKInfo);2157}21582159/// Returns the deployment target that's specified using the -mtargetos option.2160std::optional<DarwinPlatform> getDeploymentTargetFromMTargetOSArg(2161DerivedArgList &Args, const Driver &TheDriver,2162const std::optional<DarwinSDKInfo> &SDKInfo) {2163auto *A = Args.getLastArg(options::OPT_mtargetos_EQ);2164if (!A)2165return std::nullopt;2166llvm::Triple TT(llvm::Twine("unknown-apple-") + A->getValue());2167switch (TT.getOS()) {2168case llvm::Triple::MacOSX:2169case llvm::Triple::IOS:2170case llvm::Triple::TvOS:2171case llvm::Triple::WatchOS:2172case llvm::Triple::XROS:2173break;2174default:2175TheDriver.Diag(diag::err_drv_invalid_os_in_arg)2176<< TT.getOSName() << A->getAsString(Args);2177return std::nullopt;2178}21792180VersionTuple Version = TT.getOSVersion();2181if (!Version.getMajor()) {2182TheDriver.Diag(diag::err_drv_invalid_version_number)2183<< A->getAsString(Args);2184return std::nullopt;2185}2186return DarwinPlatform::createFromMTargetOS(TT.getOS(), Version,2187TT.getEnvironment(), A, SDKInfo);2188}21892190std::optional<DarwinSDKInfo> parseSDKSettings(llvm::vfs::FileSystem &VFS,2191const ArgList &Args,2192const Driver &TheDriver) {2193const Arg *A = Args.getLastArg(options::OPT_isysroot);2194if (!A)2195return std::nullopt;2196StringRef isysroot = A->getValue();2197auto SDKInfoOrErr = parseDarwinSDKInfo(VFS, isysroot);2198if (!SDKInfoOrErr) {2199llvm::consumeError(SDKInfoOrErr.takeError());2200TheDriver.Diag(diag::warn_drv_darwin_sdk_invalid_settings);2201return std::nullopt;2202}2203return *SDKInfoOrErr;2204}22052206} // namespace22072208void Darwin::AddDeploymentTarget(DerivedArgList &Args) const {2209const OptTable &Opts = getDriver().getOpts();22102211// Support allowing the SDKROOT environment variable used by xcrun and other2212// Xcode tools to define the default sysroot, by making it the default for2213// isysroot.2214if (const Arg *A = Args.getLastArg(options::OPT_isysroot)) {2215// Warn if the path does not exist.2216if (!getVFS().exists(A->getValue()))2217getDriver().Diag(clang::diag::warn_missing_sysroot) << A->getValue();2218} else {2219if (char *env = ::getenv("SDKROOT")) {2220// We only use this value as the default if it is an absolute path,2221// exists, and it is not the root path.2222if (llvm::sys::path::is_absolute(env) && getVFS().exists(env) &&2223StringRef(env) != "/") {2224Args.append(Args.MakeSeparateArg(2225nullptr, Opts.getOption(options::OPT_isysroot), env));2226}2227}2228}22292230// Read the SDKSettings.json file for more information, like the SDK version2231// that we can pass down to the compiler.2232SDKInfo = parseSDKSettings(getVFS(), Args, getDriver());22332234// The OS and the version can be specified using the -target argument.2235std::optional<DarwinPlatform> OSTarget =2236getDeploymentTargetFromTargetArg(Args, getTriple(), getDriver(), SDKInfo);2237if (OSTarget) {2238// Disallow mixing -target and -mtargetos=.2239if (const auto *MTargetOSArg = Args.getLastArg(options::OPT_mtargetos_EQ)) {2240std::string TargetArgStr = OSTarget->getAsString(Args, Opts);2241std::string MTargetOSArgStr = MTargetOSArg->getAsString(Args);2242getDriver().Diag(diag::err_drv_cannot_mix_options)2243<< TargetArgStr << MTargetOSArgStr;2244}2245std::optional<DarwinPlatform> OSVersionArgTarget =2246getDeploymentTargetFromOSVersionArg(Args, getDriver());2247if (OSVersionArgTarget) {2248unsigned TargetMajor, TargetMinor, TargetMicro;2249bool TargetExtra;2250unsigned ArgMajor, ArgMinor, ArgMicro;2251bool ArgExtra;2252if (OSTarget->getPlatform() != OSVersionArgTarget->getPlatform() ||2253(Driver::GetReleaseVersion(OSTarget->getOSVersion(), TargetMajor,2254TargetMinor, TargetMicro, TargetExtra) &&2255Driver::GetReleaseVersion(OSVersionArgTarget->getOSVersion(),2256ArgMajor, ArgMinor, ArgMicro, ArgExtra) &&2257(VersionTuple(TargetMajor, TargetMinor, TargetMicro) !=2258VersionTuple(ArgMajor, ArgMinor, ArgMicro) ||2259TargetExtra != ArgExtra))) {2260// Select the OS version from the -m<os>-version-min argument when2261// the -target does not include an OS version.2262if (OSTarget->getPlatform() == OSVersionArgTarget->getPlatform() &&2263!OSTarget->hasOSVersion()) {2264OSTarget->setOSVersion(OSVersionArgTarget->getOSVersion());2265} else {2266// Warn about -m<os>-version-min that doesn't match the OS version2267// that's specified in the target.2268std::string OSVersionArg =2269OSVersionArgTarget->getAsString(Args, Opts);2270std::string TargetArg = OSTarget->getAsString(Args, Opts);2271getDriver().Diag(clang::diag::warn_drv_overriding_option)2272<< OSVersionArg << TargetArg;2273}2274}2275}2276} else if ((OSTarget = getDeploymentTargetFromMTargetOSArg(Args, getDriver(),2277SDKInfo))) {2278// The OS target can be specified using the -mtargetos= argument.2279// Disallow mixing -mtargetos= and -m<os>version-min=.2280std::optional<DarwinPlatform> OSVersionArgTarget =2281getDeploymentTargetFromOSVersionArg(Args, getDriver());2282if (OSVersionArgTarget) {2283std::string MTargetOSArgStr = OSTarget->getAsString(Args, Opts);2284std::string OSVersionArgStr = OSVersionArgTarget->getAsString(Args, Opts);2285getDriver().Diag(diag::err_drv_cannot_mix_options)2286<< MTargetOSArgStr << OSVersionArgStr;2287}2288} else {2289// The OS target can be specified using the -m<os>version-min argument.2290OSTarget = getDeploymentTargetFromOSVersionArg(Args, getDriver());2291// If no deployment target was specified on the command line, check for2292// environment defines.2293if (!OSTarget) {2294OSTarget =2295getDeploymentTargetFromEnvironmentVariables(getDriver(), getTriple());2296if (OSTarget) {2297// Don't infer simulator from the arch when the SDK is also specified.2298std::optional<DarwinPlatform> SDKTarget =2299inferDeploymentTargetFromSDK(Args, SDKInfo);2300if (SDKTarget)2301OSTarget->setEnvironment(SDKTarget->getEnvironment());2302}2303}2304// If there is no command-line argument to specify the Target version and2305// no environment variable defined, see if we can set the default based2306// on -isysroot using SDKSettings.json if it exists.2307if (!OSTarget) {2308OSTarget = inferDeploymentTargetFromSDK(Args, SDKInfo);2309/// If the target was successfully constructed from the SDK path, try to2310/// infer the SDK info if the SDK doesn't have it.2311if (OSTarget && !SDKInfo)2312SDKInfo = OSTarget->inferSDKInfo();2313}2314// If no OS targets have been specified, try to guess platform from -target2315// or arch name and compute the version from the triple.2316if (!OSTarget)2317OSTarget =2318inferDeploymentTargetFromArch(Args, *this, getTriple(), getDriver());2319}23202321assert(OSTarget && "Unable to infer Darwin variant");2322OSTarget->addOSVersionMinArgument(Args, Opts);2323DarwinPlatformKind Platform = OSTarget->getPlatform();23242325unsigned Major, Minor, Micro;2326bool HadExtra;2327// The major version should not be over this number.2328const unsigned MajorVersionLimit = 1000;2329// Set the tool chain target information.2330if (Platform == MacOS) {2331if (!Driver::GetReleaseVersion(OSTarget->getOSVersion(), Major, Minor,2332Micro, HadExtra) ||2333HadExtra || Major < 10 || Major >= MajorVersionLimit || Minor >= 100 ||2334Micro >= 100)2335getDriver().Diag(diag::err_drv_invalid_version_number)2336<< OSTarget->getAsString(Args, Opts);2337} else if (Platform == IPhoneOS) {2338if (!Driver::GetReleaseVersion(OSTarget->getOSVersion(), Major, Minor,2339Micro, HadExtra) ||2340HadExtra || Major >= MajorVersionLimit || Minor >= 100 || Micro >= 100)2341getDriver().Diag(diag::err_drv_invalid_version_number)2342<< OSTarget->getAsString(Args, Opts);2343;2344if (OSTarget->getEnvironment() == MacCatalyst &&2345(Major < 13 || (Major == 13 && Minor < 1))) {2346getDriver().Diag(diag::err_drv_invalid_version_number)2347<< OSTarget->getAsString(Args, Opts);2348Major = 13;2349Minor = 1;2350Micro = 0;2351}2352// For 32-bit targets, the deployment target for iOS has to be earlier than2353// iOS 11.2354if (getTriple().isArch32Bit() && Major >= 11) {2355// If the deployment target is explicitly specified, print a diagnostic.2356if (OSTarget->isExplicitlySpecified()) {2357if (OSTarget->getEnvironment() == MacCatalyst)2358getDriver().Diag(diag::err_invalid_macos_32bit_deployment_target);2359else2360getDriver().Diag(diag::warn_invalid_ios_deployment_target)2361<< OSTarget->getAsString(Args, Opts);2362// Otherwise, set it to 10.99.99.2363} else {2364Major = 10;2365Minor = 99;2366Micro = 99;2367}2368}2369} else if (Platform == TvOS) {2370if (!Driver::GetReleaseVersion(OSTarget->getOSVersion(), Major, Minor,2371Micro, HadExtra) ||2372HadExtra || Major >= MajorVersionLimit || Minor >= 100 || Micro >= 100)2373getDriver().Diag(diag::err_drv_invalid_version_number)2374<< OSTarget->getAsString(Args, Opts);2375} else if (Platform == WatchOS) {2376if (!Driver::GetReleaseVersion(OSTarget->getOSVersion(), Major, Minor,2377Micro, HadExtra) ||2378HadExtra || Major >= MajorVersionLimit || Minor >= 100 || Micro >= 100)2379getDriver().Diag(diag::err_drv_invalid_version_number)2380<< OSTarget->getAsString(Args, Opts);2381} else if (Platform == DriverKit) {2382if (!Driver::GetReleaseVersion(OSTarget->getOSVersion(), Major, Minor,2383Micro, HadExtra) ||2384HadExtra || Major < 19 || Major >= MajorVersionLimit || Minor >= 100 ||2385Micro >= 100)2386getDriver().Diag(diag::err_drv_invalid_version_number)2387<< OSTarget->getAsString(Args, Opts);2388} else if (Platform == XROS) {2389if (!Driver::GetReleaseVersion(OSTarget->getOSVersion(), Major, Minor,2390Micro, HadExtra) ||2391HadExtra || Major < 1 || Major >= MajorVersionLimit || Minor >= 100 ||2392Micro >= 100)2393getDriver().Diag(diag::err_drv_invalid_version_number)2394<< OSTarget->getAsString(Args, Opts);2395} else2396llvm_unreachable("unknown kind of Darwin platform");23972398DarwinEnvironmentKind Environment = OSTarget->getEnvironment();2399// Recognize iOS targets with an x86 architecture as the iOS simulator.2400if (Environment == NativeEnvironment && Platform != MacOS &&2401Platform != DriverKit && OSTarget->canInferSimulatorFromArch() &&2402getTriple().isX86())2403Environment = Simulator;24042405VersionTuple NativeTargetVersion;2406if (Environment == MacCatalyst)2407NativeTargetVersion = OSTarget->getNativeTargetVersion();2408setTarget(Platform, Environment, Major, Minor, Micro, NativeTargetVersion);2409TargetVariantTriple = OSTarget->getTargetVariantTriple();24102411if (const Arg *A = Args.getLastArg(options::OPT_isysroot)) {2412StringRef SDK = getSDKName(A->getValue());2413if (SDK.size() > 0) {2414size_t StartVer = SDK.find_first_of("0123456789");2415StringRef SDKName = SDK.slice(0, StartVer);2416if (!SDKName.starts_with(getPlatformFamily()) &&2417!dropSDKNamePrefix(SDKName).starts_with(getPlatformFamily()))2418getDriver().Diag(diag::warn_incompatible_sysroot)2419<< SDKName << getPlatformFamily();2420}2421}2422}24232424// For certain platforms/environments almost all resources (e.g., headers) are2425// located in sub-directories, e.g., for DriverKit they live in2426// <SYSROOT>/System/DriverKit/usr/include (instead of <SYSROOT>/usr/include).2427static void AppendPlatformPrefix(SmallString<128> &Path,2428const llvm::Triple &T) {2429if (T.isDriverKit()) {2430llvm::sys::path::append(Path, "System", "DriverKit");2431}2432}24332434// Returns the effective sysroot from either -isysroot or --sysroot, plus the2435// platform prefix (if any).2436llvm::SmallString<128>2437DarwinClang::GetEffectiveSysroot(const llvm::opt::ArgList &DriverArgs) const {2438llvm::SmallString<128> Path("/");2439if (DriverArgs.hasArg(options::OPT_isysroot))2440Path = DriverArgs.getLastArgValue(options::OPT_isysroot);2441else if (!getDriver().SysRoot.empty())2442Path = getDriver().SysRoot;24432444if (hasEffectiveTriple()) {2445AppendPlatformPrefix(Path, getEffectiveTriple());2446}2447return Path;2448}24492450void DarwinClang::AddClangSystemIncludeArgs(const llvm::opt::ArgList &DriverArgs,2451llvm::opt::ArgStringList &CC1Args) const {2452const Driver &D = getDriver();24532454llvm::SmallString<128> Sysroot = GetEffectiveSysroot(DriverArgs);24552456bool NoStdInc = DriverArgs.hasArg(options::OPT_nostdinc);2457bool NoStdlibInc = DriverArgs.hasArg(options::OPT_nostdlibinc);2458bool NoBuiltinInc = DriverArgs.hasFlag(2459options::OPT_nobuiltininc, options::OPT_ibuiltininc, /*Default=*/false);2460bool ForceBuiltinInc = DriverArgs.hasFlag(2461options::OPT_ibuiltininc, options::OPT_nobuiltininc, /*Default=*/false);24622463// Add <sysroot>/usr/local/include2464if (!NoStdInc && !NoStdlibInc) {2465SmallString<128> P(Sysroot);2466llvm::sys::path::append(P, "usr", "local", "include");2467addSystemInclude(DriverArgs, CC1Args, P);2468}24692470// Add the Clang builtin headers (<resource>/include)2471if (!(NoStdInc && !ForceBuiltinInc) && !NoBuiltinInc) {2472SmallString<128> P(D.ResourceDir);2473llvm::sys::path::append(P, "include");2474addSystemInclude(DriverArgs, CC1Args, P);2475}24762477if (NoStdInc || NoStdlibInc)2478return;24792480// Check for configure-time C include directories.2481llvm::StringRef CIncludeDirs(C_INCLUDE_DIRS);2482if (!CIncludeDirs.empty()) {2483llvm::SmallVector<llvm::StringRef, 5> dirs;2484CIncludeDirs.split(dirs, ":");2485for (llvm::StringRef dir : dirs) {2486llvm::StringRef Prefix =2487llvm::sys::path::is_absolute(dir) ? "" : llvm::StringRef(Sysroot);2488addExternCSystemInclude(DriverArgs, CC1Args, Prefix + dir);2489}2490} else {2491// Otherwise, add <sysroot>/usr/include.2492SmallString<128> P(Sysroot);2493llvm::sys::path::append(P, "usr", "include");2494addExternCSystemInclude(DriverArgs, CC1Args, P.str());2495}2496}24972498bool DarwinClang::AddGnuCPlusPlusIncludePaths(const llvm::opt::ArgList &DriverArgs,2499llvm::opt::ArgStringList &CC1Args,2500llvm::SmallString<128> Base,2501llvm::StringRef Version,2502llvm::StringRef ArchDir,2503llvm::StringRef BitDir) const {2504llvm::sys::path::append(Base, Version);25052506// Add the base dir2507addSystemInclude(DriverArgs, CC1Args, Base);25082509// Add the multilib dirs2510{2511llvm::SmallString<128> P = Base;2512if (!ArchDir.empty())2513llvm::sys::path::append(P, ArchDir);2514if (!BitDir.empty())2515llvm::sys::path::append(P, BitDir);2516addSystemInclude(DriverArgs, CC1Args, P);2517}25182519// Add the backward dir2520{2521llvm::SmallString<128> P = Base;2522llvm::sys::path::append(P, "backward");2523addSystemInclude(DriverArgs, CC1Args, P);2524}25252526return getVFS().exists(Base);2527}25282529void DarwinClang::AddClangCXXStdlibIncludeArgs(2530const llvm::opt::ArgList &DriverArgs,2531llvm::opt::ArgStringList &CC1Args) const {2532// The implementation from a base class will pass through the -stdlib to2533// CC1Args.2534// FIXME: this should not be necessary, remove usages in the frontend2535// (e.g. HeaderSearchOptions::UseLibcxx) and don't pipe -stdlib.2536// Also check whether this is used for setting library search paths.2537ToolChain::AddClangCXXStdlibIncludeArgs(DriverArgs, CC1Args);25382539if (DriverArgs.hasArg(options::OPT_nostdinc, options::OPT_nostdlibinc,2540options::OPT_nostdincxx))2541return;25422543llvm::SmallString<128> Sysroot = GetEffectiveSysroot(DriverArgs);25442545switch (GetCXXStdlibType(DriverArgs)) {2546case ToolChain::CST_Libcxx: {2547// On Darwin, libc++ can be installed in one of the following places:2548// 1. Alongside the compiler in <clang-executable-folder>/../include/c++/v12549// 2. In a SDK (or a custom sysroot) in <sysroot>/usr/include/c++/v12550//2551// The precedence of paths is as listed above, i.e. we take the first path2552// that exists. Note that we never include libc++ twice -- we take the first2553// path that exists and don't send the other paths to CC1 (otherwise2554// include_next could break).25552556// Check for (1)2557// Get from '<install>/bin' to '<install>/include/c++/v1'.2558// Note that InstallBin can be relative, so we use '..' instead of2559// parent_path.2560llvm::SmallString<128> InstallBin(getDriver().Dir); // <install>/bin2561llvm::sys::path::append(InstallBin, "..", "include", "c++", "v1");2562if (getVFS().exists(InstallBin)) {2563addSystemInclude(DriverArgs, CC1Args, InstallBin);2564return;2565} else if (DriverArgs.hasArg(options::OPT_v)) {2566llvm::errs() << "ignoring nonexistent directory \"" << InstallBin2567<< "\"\n";2568}25692570// Otherwise, check for (2)2571llvm::SmallString<128> SysrootUsr = Sysroot;2572llvm::sys::path::append(SysrootUsr, "usr", "include", "c++", "v1");2573if (getVFS().exists(SysrootUsr)) {2574addSystemInclude(DriverArgs, CC1Args, SysrootUsr);2575return;2576} else if (DriverArgs.hasArg(options::OPT_v)) {2577llvm::errs() << "ignoring nonexistent directory \"" << SysrootUsr2578<< "\"\n";2579}25802581// Otherwise, don't add any path.2582break;2583}25842585case ToolChain::CST_Libstdcxx:2586llvm::SmallString<128> UsrIncludeCxx = Sysroot;2587llvm::sys::path::append(UsrIncludeCxx, "usr", "include", "c++");25882589llvm::Triple::ArchType arch = getTriple().getArch();2590bool IsBaseFound = true;2591switch (arch) {2592default: break;25932594case llvm::Triple::x86:2595case llvm::Triple::x86_64:2596IsBaseFound = AddGnuCPlusPlusIncludePaths(DriverArgs, CC1Args, UsrIncludeCxx,2597"4.2.1",2598"i686-apple-darwin10",2599arch == llvm::Triple::x86_64 ? "x86_64" : "");2600IsBaseFound |= AddGnuCPlusPlusIncludePaths(DriverArgs, CC1Args, UsrIncludeCxx,2601"4.0.0", "i686-apple-darwin8",2602"");2603break;26042605case llvm::Triple::arm:2606case llvm::Triple::thumb:2607IsBaseFound = AddGnuCPlusPlusIncludePaths(DriverArgs, CC1Args, UsrIncludeCxx,2608"4.2.1",2609"arm-apple-darwin10",2610"v7");2611IsBaseFound |= AddGnuCPlusPlusIncludePaths(DriverArgs, CC1Args, UsrIncludeCxx,2612"4.2.1",2613"arm-apple-darwin10",2614"v6");2615break;26162617case llvm::Triple::aarch64:2618IsBaseFound = AddGnuCPlusPlusIncludePaths(DriverArgs, CC1Args, UsrIncludeCxx,2619"4.2.1",2620"arm64-apple-darwin10",2621"");2622break;2623}26242625if (!IsBaseFound) {2626getDriver().Diag(diag::warn_drv_libstdcxx_not_found);2627}26282629break;2630}2631}26322633void DarwinClang::AddCXXStdlibLibArgs(const ArgList &Args,2634ArgStringList &CmdArgs) const {2635CXXStdlibType Type = GetCXXStdlibType(Args);26362637switch (Type) {2638case ToolChain::CST_Libcxx:2639CmdArgs.push_back("-lc++");2640if (Args.hasArg(options::OPT_fexperimental_library))2641CmdArgs.push_back("-lc++experimental");2642break;26432644case ToolChain::CST_Libstdcxx:2645// Unfortunately, -lstdc++ doesn't always exist in the standard search path;2646// it was previously found in the gcc lib dir. However, for all the Darwin2647// platforms we care about it was -lstdc++.6, so we search for that2648// explicitly if we can't see an obvious -lstdc++ candidate.26492650// Check in the sysroot first.2651if (const Arg *A = Args.getLastArg(options::OPT_isysroot)) {2652SmallString<128> P(A->getValue());2653llvm::sys::path::append(P, "usr", "lib", "libstdc++.dylib");26542655if (!getVFS().exists(P)) {2656llvm::sys::path::remove_filename(P);2657llvm::sys::path::append(P, "libstdc++.6.dylib");2658if (getVFS().exists(P)) {2659CmdArgs.push_back(Args.MakeArgString(P));2660return;2661}2662}2663}26642665// Otherwise, look in the root.2666// FIXME: This should be removed someday when we don't have to care about2667// 10.6 and earlier, where /usr/lib/libstdc++.dylib does not exist.2668if (!getVFS().exists("/usr/lib/libstdc++.dylib") &&2669getVFS().exists("/usr/lib/libstdc++.6.dylib")) {2670CmdArgs.push_back("/usr/lib/libstdc++.6.dylib");2671return;2672}26732674// Otherwise, let the linker search.2675CmdArgs.push_back("-lstdc++");2676break;2677}2678}26792680void DarwinClang::AddCCKextLibArgs(const ArgList &Args,2681ArgStringList &CmdArgs) const {2682// For Darwin platforms, use the compiler-rt-based support library2683// instead of the gcc-provided one (which is also incidentally2684// only present in the gcc lib dir, which makes it hard to find).26852686SmallString<128> P(getDriver().ResourceDir);2687llvm::sys::path::append(P, "lib", "darwin");26882689// Use the newer cc_kext for iOS ARM after 6.0.2690if (isTargetWatchOS()) {2691llvm::sys::path::append(P, "libclang_rt.cc_kext_watchos.a");2692} else if (isTargetTvOS()) {2693llvm::sys::path::append(P, "libclang_rt.cc_kext_tvos.a");2694} else if (isTargetIPhoneOS()) {2695llvm::sys::path::append(P, "libclang_rt.cc_kext_ios.a");2696} else if (isTargetDriverKit()) {2697// DriverKit doesn't want extra runtime support.2698} else if (isTargetXROSDevice()) {2699llvm::sys::path::append(2700P, llvm::Twine("libclang_rt.cc_kext_") +2701llvm::Triple::getOSTypeName(llvm::Triple::XROS) + ".a");2702} else {2703llvm::sys::path::append(P, "libclang_rt.cc_kext.a");2704}27052706// For now, allow missing resource libraries to support developers who may2707// not have compiler-rt checked out or integrated into their build.2708if (getVFS().exists(P))2709CmdArgs.push_back(Args.MakeArgString(P));2710}27112712DerivedArgList *MachO::TranslateArgs(const DerivedArgList &Args,2713StringRef BoundArch,2714Action::OffloadKind) const {2715DerivedArgList *DAL = new DerivedArgList(Args.getBaseArgs());2716const OptTable &Opts = getDriver().getOpts();27172718// FIXME: We really want to get out of the tool chain level argument2719// translation business, as it makes the driver functionality much2720// more opaque. For now, we follow gcc closely solely for the2721// purpose of easily achieving feature parity & testability. Once we2722// have something that works, we should reevaluate each translation2723// and try to push it down into tool specific logic.27242725for (Arg *A : Args) {2726if (A->getOption().matches(options::OPT_Xarch__)) {2727// Skip this argument unless the architecture matches either the toolchain2728// triple arch, or the arch being bound.2729StringRef XarchArch = A->getValue(0);2730if (!(XarchArch == getArchName() ||2731(!BoundArch.empty() && XarchArch == BoundArch)))2732continue;27332734Arg *OriginalArg = A;2735TranslateXarchArgs(Args, A, DAL);27362737// Linker input arguments require custom handling. The problem is that we2738// have already constructed the phase actions, so we can not treat them as2739// "input arguments".2740if (A->getOption().hasFlag(options::LinkerInput)) {2741// Convert the argument into individual Zlinker_input_args.2742for (const char *Value : A->getValues()) {2743DAL->AddSeparateArg(2744OriginalArg, Opts.getOption(options::OPT_Zlinker_input), Value);2745}2746continue;2747}2748}27492750// Sob. These is strictly gcc compatible for the time being. Apple2751// gcc translates options twice, which means that self-expanding2752// options add duplicates.2753switch ((options::ID)A->getOption().getID()) {2754default:2755DAL->append(A);2756break;27572758case options::OPT_mkernel:2759case options::OPT_fapple_kext:2760DAL->append(A);2761DAL->AddFlagArg(A, Opts.getOption(options::OPT_static));2762break;27632764case options::OPT_dependency_file:2765DAL->AddSeparateArg(A, Opts.getOption(options::OPT_MF), A->getValue());2766break;27672768case options::OPT_gfull:2769DAL->AddFlagArg(A, Opts.getOption(options::OPT_g_Flag));2770DAL->AddFlagArg(2771A, Opts.getOption(options::OPT_fno_eliminate_unused_debug_symbols));2772break;27732774case options::OPT_gused:2775DAL->AddFlagArg(A, Opts.getOption(options::OPT_g_Flag));2776DAL->AddFlagArg(2777A, Opts.getOption(options::OPT_feliminate_unused_debug_symbols));2778break;27792780case options::OPT_shared:2781DAL->AddFlagArg(A, Opts.getOption(options::OPT_dynamiclib));2782break;27832784case options::OPT_fconstant_cfstrings:2785DAL->AddFlagArg(A, Opts.getOption(options::OPT_mconstant_cfstrings));2786break;27872788case options::OPT_fno_constant_cfstrings:2789DAL->AddFlagArg(A, Opts.getOption(options::OPT_mno_constant_cfstrings));2790break;27912792case options::OPT_Wnonportable_cfstrings:2793DAL->AddFlagArg(A,2794Opts.getOption(options::OPT_mwarn_nonportable_cfstrings));2795break;27962797case options::OPT_Wno_nonportable_cfstrings:2798DAL->AddFlagArg(2799A, Opts.getOption(options::OPT_mno_warn_nonportable_cfstrings));2800break;2801}2802}28032804// Add the arch options based on the particular spelling of -arch, to match2805// how the driver works.2806if (!BoundArch.empty()) {2807StringRef Name = BoundArch;2808const Option MCpu = Opts.getOption(options::OPT_mcpu_EQ);2809const Option MArch = Opts.getOption(clang::driver::options::OPT_march_EQ);28102811// This code must be kept in sync with LLVM's getArchTypeForDarwinArch,2812// which defines the list of which architectures we accept.2813if (Name == "ppc")2814;2815else if (Name == "ppc601")2816DAL->AddJoinedArg(nullptr, MCpu, "601");2817else if (Name == "ppc603")2818DAL->AddJoinedArg(nullptr, MCpu, "603");2819else if (Name == "ppc604")2820DAL->AddJoinedArg(nullptr, MCpu, "604");2821else if (Name == "ppc604e")2822DAL->AddJoinedArg(nullptr, MCpu, "604e");2823else if (Name == "ppc750")2824DAL->AddJoinedArg(nullptr, MCpu, "750");2825else if (Name == "ppc7400")2826DAL->AddJoinedArg(nullptr, MCpu, "7400");2827else if (Name == "ppc7450")2828DAL->AddJoinedArg(nullptr, MCpu, "7450");2829else if (Name == "ppc970")2830DAL->AddJoinedArg(nullptr, MCpu, "970");28312832else if (Name == "ppc64" || Name == "ppc64le")2833DAL->AddFlagArg(nullptr, Opts.getOption(options::OPT_m64));28342835else if (Name == "i386")2836;2837else if (Name == "i486")2838DAL->AddJoinedArg(nullptr, MArch, "i486");2839else if (Name == "i586")2840DAL->AddJoinedArg(nullptr, MArch, "i586");2841else if (Name == "i686")2842DAL->AddJoinedArg(nullptr, MArch, "i686");2843else if (Name == "pentium")2844DAL->AddJoinedArg(nullptr, MArch, "pentium");2845else if (Name == "pentium2")2846DAL->AddJoinedArg(nullptr, MArch, "pentium2");2847else if (Name == "pentpro")2848DAL->AddJoinedArg(nullptr, MArch, "pentiumpro");2849else if (Name == "pentIIm3")2850DAL->AddJoinedArg(nullptr, MArch, "pentium2");28512852else if (Name == "x86_64" || Name == "x86_64h")2853DAL->AddFlagArg(nullptr, Opts.getOption(options::OPT_m64));28542855else if (Name == "arm")2856DAL->AddJoinedArg(nullptr, MArch, "armv4t");2857else if (Name == "armv4t")2858DAL->AddJoinedArg(nullptr, MArch, "armv4t");2859else if (Name == "armv5")2860DAL->AddJoinedArg(nullptr, MArch, "armv5tej");2861else if (Name == "xscale")2862DAL->AddJoinedArg(nullptr, MArch, "xscale");2863else if (Name == "armv6")2864DAL->AddJoinedArg(nullptr, MArch, "armv6k");2865else if (Name == "armv6m")2866DAL->AddJoinedArg(nullptr, MArch, "armv6m");2867else if (Name == "armv7")2868DAL->AddJoinedArg(nullptr, MArch, "armv7a");2869else if (Name == "armv7em")2870DAL->AddJoinedArg(nullptr, MArch, "armv7em");2871else if (Name == "armv7k")2872DAL->AddJoinedArg(nullptr, MArch, "armv7k");2873else if (Name == "armv7m")2874DAL->AddJoinedArg(nullptr, MArch, "armv7m");2875else if (Name == "armv7s")2876DAL->AddJoinedArg(nullptr, MArch, "armv7s");2877}28782879return DAL;2880}28812882void MachO::AddLinkRuntimeLibArgs(const ArgList &Args,2883ArgStringList &CmdArgs,2884bool ForceLinkBuiltinRT) const {2885// Embedded targets are simple at the moment, not supporting sanitizers and2886// with different libraries for each member of the product { static, PIC } x2887// { hard-float, soft-float }2888llvm::SmallString<32> CompilerRT = StringRef("");2889CompilerRT +=2890(tools::arm::getARMFloatABI(*this, Args) == tools::arm::FloatABI::Hard)2891? "hard"2892: "soft";2893CompilerRT += Args.hasArg(options::OPT_fPIC) ? "_pic" : "_static";28942895AddLinkRuntimeLib(Args, CmdArgs, CompilerRT, RLO_IsEmbedded);2896}28972898bool Darwin::isAlignedAllocationUnavailable() const {2899llvm::Triple::OSType OS;29002901if (isTargetMacCatalyst())2902return TargetVersion < alignedAllocMinVersion(llvm::Triple::MacOSX);2903switch (TargetPlatform) {2904case MacOS: // Earlier than 10.13.2905OS = llvm::Triple::MacOSX;2906break;2907case IPhoneOS:2908OS = llvm::Triple::IOS;2909break;2910case TvOS: // Earlier than 11.0.2911OS = llvm::Triple::TvOS;2912break;2913case WatchOS: // Earlier than 4.0.2914OS = llvm::Triple::WatchOS;2915break;2916case XROS: // Always available.2917return false;2918case DriverKit: // Always available.2919return false;2920}29212922return TargetVersion < alignedAllocMinVersion(OS);2923}29242925static bool sdkSupportsBuiltinModules(2926const Darwin::DarwinPlatformKind &TargetPlatform,2927const Darwin::DarwinEnvironmentKind &TargetEnvironment,2928const std::optional<DarwinSDKInfo> &SDKInfo) {2929if (TargetEnvironment == Darwin::NativeEnvironment ||2930TargetEnvironment == Darwin::Simulator ||2931TargetEnvironment == Darwin::MacCatalyst) {2932// Standard xnu/Mach/Darwin based environments2933// depend on the SDK version.2934} else {2935// All other environments support builtin modules from the start.2936return true;2937}29382939if (!SDKInfo)2940// If there is no SDK info, assume this is building against a2941// pre-SDK version of macOS (i.e. before Mac OS X 10.4). Those2942// don't support modules anyway, but the headers definitely2943// don't support builtin modules either. It might also be some2944// kind of degenerate build environment, err on the side of2945// the old behavior which is to not use builtin modules.2946return false;29472948VersionTuple SDKVersion = SDKInfo->getVersion();2949switch (TargetPlatform) {2950// Existing SDKs added support for builtin modules in the fall2951// 2024 major releases.2952case Darwin::MacOS:2953return SDKVersion >= VersionTuple(15U);2954case Darwin::IPhoneOS:2955switch (TargetEnvironment) {2956case Darwin::MacCatalyst:2957// Mac Catalyst uses `-target arm64-apple-ios18.0-macabi` so the platform2958// is iOS, but it builds with the macOS SDK, so it's the macOS SDK version2959// that's relevant.2960return SDKVersion >= VersionTuple(15U);2961default:2962return SDKVersion >= VersionTuple(18U);2963}2964case Darwin::TvOS:2965return SDKVersion >= VersionTuple(18U);2966case Darwin::WatchOS:2967return SDKVersion >= VersionTuple(11U);2968case Darwin::XROS:2969return SDKVersion >= VersionTuple(2U);29702971// New SDKs support builtin modules from the start.2972default:2973return true;2974}2975}29762977static inline llvm::VersionTuple2978sizedDeallocMinVersion(llvm::Triple::OSType OS) {2979switch (OS) {2980default:2981break;2982case llvm::Triple::Darwin:2983case llvm::Triple::MacOSX: // Earliest supporting version is 10.12.2984return llvm::VersionTuple(10U, 12U);2985case llvm::Triple::IOS:2986case llvm::Triple::TvOS: // Earliest supporting version is 10.0.0.2987return llvm::VersionTuple(10U);2988case llvm::Triple::WatchOS: // Earliest supporting version is 3.0.0.2989return llvm::VersionTuple(3U);2990}29912992llvm_unreachable("Unexpected OS");2993}29942995bool Darwin::isSizedDeallocationUnavailable() const {2996llvm::Triple::OSType OS;29972998if (isTargetMacCatalyst())2999return TargetVersion < sizedDeallocMinVersion(llvm::Triple::MacOSX);3000switch (TargetPlatform) {3001case MacOS: // Earlier than 10.12.3002OS = llvm::Triple::MacOSX;3003break;3004case IPhoneOS:3005OS = llvm::Triple::IOS;3006break;3007case TvOS: // Earlier than 10.0.3008OS = llvm::Triple::TvOS;3009break;3010case WatchOS: // Earlier than 3.0.3011OS = llvm::Triple::WatchOS;3012break;3013case DriverKit:3014case XROS:3015// Always available.3016return false;3017}30183019return TargetVersion < sizedDeallocMinVersion(OS);3020}30213022void Darwin::addClangTargetOptions(3023const llvm::opt::ArgList &DriverArgs, llvm::opt::ArgStringList &CC1Args,3024Action::OffloadKind DeviceOffloadKind) const {3025// Pass "-faligned-alloc-unavailable" only when the user hasn't manually3026// enabled or disabled aligned allocations.3027if (!DriverArgs.hasArgNoClaim(options::OPT_faligned_allocation,3028options::OPT_fno_aligned_allocation) &&3029isAlignedAllocationUnavailable())3030CC1Args.push_back("-faligned-alloc-unavailable");30313032// Pass "-fno-sized-deallocation" only when the user hasn't manually enabled3033// or disabled sized deallocations.3034if (!DriverArgs.hasArgNoClaim(options::OPT_fsized_deallocation,3035options::OPT_fno_sized_deallocation) &&3036isSizedDeallocationUnavailable())3037CC1Args.push_back("-fno-sized-deallocation");30383039addClangCC1ASTargetOptions(DriverArgs, CC1Args);30403041// Enable compatibility mode for NSItemProviderCompletionHandler in3042// Foundation/NSItemProvider.h.3043CC1Args.push_back("-fcompatibility-qualified-id-block-type-checking");30443045// Give static local variables in inline functions hidden visibility when3046// -fvisibility-inlines-hidden is enabled.3047if (!DriverArgs.getLastArgNoClaim(3048options::OPT_fvisibility_inlines_hidden_static_local_var,3049options::OPT_fno_visibility_inlines_hidden_static_local_var))3050CC1Args.push_back("-fvisibility-inlines-hidden-static-local-var");30513052// Earlier versions of the darwin SDK have the C standard library headers3053// all together in the Darwin module. That leads to module cycles with3054// the _Builtin_ modules. e.g. <inttypes.h> on darwin includes <stdint.h>.3055// The builtin <stdint.h> include-nexts <stdint.h>. When both of those3056// darwin headers are in the Darwin module, there's a module cycle Darwin ->3057// _Builtin_stdint -> Darwin (i.e. inttypes.h (darwin) -> stdint.h (builtin) ->3058// stdint.h (darwin)). This is fixed in later versions of the darwin SDK,3059// but until then, the builtin headers need to join the system modules.3060// i.e. when the builtin stdint.h is in the Darwin module too, the cycle3061// goes away. Note that -fbuiltin-headers-in-system-modules does nothing3062// to fix the same problem with C++ headers, and is generally fragile.3063if (!sdkSupportsBuiltinModules(TargetPlatform, TargetEnvironment, SDKInfo))3064CC1Args.push_back("-fbuiltin-headers-in-system-modules");30653066if (!DriverArgs.hasArgNoClaim(options::OPT_fdefine_target_os_macros,3067options::OPT_fno_define_target_os_macros))3068CC1Args.push_back("-fdefine-target-os-macros");3069}30703071void Darwin::addClangCC1ASTargetOptions(3072const llvm::opt::ArgList &Args, llvm::opt::ArgStringList &CC1ASArgs) const {3073if (TargetVariantTriple) {3074CC1ASArgs.push_back("-darwin-target-variant-triple");3075CC1ASArgs.push_back(Args.MakeArgString(TargetVariantTriple->getTriple()));3076}30773078if (SDKInfo) {3079/// Pass the SDK version to the compiler when the SDK information is3080/// available.3081auto EmitTargetSDKVersionArg = [&](const VersionTuple &V) {3082std::string Arg;3083llvm::raw_string_ostream OS(Arg);3084OS << "-target-sdk-version=" << V;3085CC1ASArgs.push_back(Args.MakeArgString(Arg));3086};30873088if (isTargetMacCatalyst()) {3089if (const auto *MacOStoMacCatalystMapping = SDKInfo->getVersionMapping(3090DarwinSDKInfo::OSEnvPair::macOStoMacCatalystPair())) {3091std::optional<VersionTuple> SDKVersion = MacOStoMacCatalystMapping->map(3092SDKInfo->getVersion(), minimumMacCatalystDeploymentTarget(),3093std::nullopt);3094EmitTargetSDKVersionArg(3095SDKVersion ? *SDKVersion : minimumMacCatalystDeploymentTarget());3096}3097} else {3098EmitTargetSDKVersionArg(SDKInfo->getVersion());3099}31003101/// Pass the target variant SDK version to the compiler when the SDK3102/// information is available and is required for target variant.3103if (TargetVariantTriple) {3104if (isTargetMacCatalyst()) {3105std::string Arg;3106llvm::raw_string_ostream OS(Arg);3107OS << "-darwin-target-variant-sdk-version=" << SDKInfo->getVersion();3108CC1ASArgs.push_back(Args.MakeArgString(Arg));3109} else if (const auto *MacOStoMacCatalystMapping =3110SDKInfo->getVersionMapping(3111DarwinSDKInfo::OSEnvPair::macOStoMacCatalystPair())) {3112if (std::optional<VersionTuple> SDKVersion =3113MacOStoMacCatalystMapping->map(3114SDKInfo->getVersion(), minimumMacCatalystDeploymentTarget(),3115std::nullopt)) {3116std::string Arg;3117llvm::raw_string_ostream OS(Arg);3118OS << "-darwin-target-variant-sdk-version=" << *SDKVersion;3119CC1ASArgs.push_back(Args.MakeArgString(Arg));3120}3121}3122}3123}3124}31253126DerivedArgList *3127Darwin::TranslateArgs(const DerivedArgList &Args, StringRef BoundArch,3128Action::OffloadKind DeviceOffloadKind) const {3129// First get the generic Apple args, before moving onto Darwin-specific ones.3130DerivedArgList *DAL =3131MachO::TranslateArgs(Args, BoundArch, DeviceOffloadKind);31323133// If no architecture is bound, none of the translations here are relevant.3134if (BoundArch.empty())3135return DAL;31363137// Add an explicit version min argument for the deployment target. We do this3138// after argument translation because -Xarch_ arguments may add a version min3139// argument.3140AddDeploymentTarget(*DAL);31413142// For iOS 6, undo the translation to add -static for -mkernel/-fapple-kext.3143// FIXME: It would be far better to avoid inserting those -static arguments,3144// but we can't check the deployment target in the translation code until3145// it is set here.3146if (isTargetWatchOSBased() || isTargetDriverKit() || isTargetXROS() ||3147(isTargetIOSBased() && !isIPhoneOSVersionLT(6, 0))) {3148for (ArgList::iterator it = DAL->begin(), ie = DAL->end(); it != ie; ) {3149Arg *A = *it;3150++it;3151if (A->getOption().getID() != options::OPT_mkernel &&3152A->getOption().getID() != options::OPT_fapple_kext)3153continue;3154assert(it != ie && "unexpected argument translation");3155A = *it;3156assert(A->getOption().getID() == options::OPT_static &&3157"missing expected -static argument");3158*it = nullptr;3159++it;3160}3161}31623163auto Arch = tools::darwin::getArchTypeForMachOArchName(BoundArch);3164if ((Arch == llvm::Triple::arm || Arch == llvm::Triple::thumb)) {3165if (Args.hasFlag(options::OPT_fomit_frame_pointer,3166options::OPT_fno_omit_frame_pointer, false))3167getDriver().Diag(clang::diag::warn_drv_unsupported_opt_for_target)3168<< "-fomit-frame-pointer" << BoundArch;3169}31703171return DAL;3172}31733174ToolChain::UnwindTableLevel MachO::getDefaultUnwindTableLevel(const ArgList &Args) const {3175// Unwind tables are not emitted if -fno-exceptions is supplied (except when3176// targeting x86_64).3177if (getArch() == llvm::Triple::x86_64 ||3178(GetExceptionModel(Args) != llvm::ExceptionHandling::SjLj &&3179Args.hasFlag(options::OPT_fexceptions, options::OPT_fno_exceptions,3180true)))3181return (getArch() == llvm::Triple::aarch64 ||3182getArch() == llvm::Triple::aarch64_32)3183? UnwindTableLevel::Synchronous3184: UnwindTableLevel::Asynchronous;31853186return UnwindTableLevel::None;3187}31883189bool MachO::UseDwarfDebugFlags() const {3190if (const char *S = ::getenv("RC_DEBUG_OPTIONS"))3191return S[0] != '\0';3192return false;3193}31943195std::string MachO::GetGlobalDebugPathRemapping() const {3196if (const char *S = ::getenv("RC_DEBUG_PREFIX_MAP"))3197return S;3198return {};3199}32003201llvm::ExceptionHandling Darwin::GetExceptionModel(const ArgList &Args) const {3202// Darwin uses SjLj exceptions on ARM.3203if (getTriple().getArch() != llvm::Triple::arm &&3204getTriple().getArch() != llvm::Triple::thumb)3205return llvm::ExceptionHandling::None;32063207// Only watchOS uses the new DWARF/Compact unwinding method.3208llvm::Triple Triple(ComputeLLVMTriple(Args));3209if (Triple.isWatchABI())3210return llvm::ExceptionHandling::DwarfCFI;32113212return llvm::ExceptionHandling::SjLj;3213}32143215bool Darwin::SupportsEmbeddedBitcode() const {3216assert(TargetInitialized && "Target not initialized!");3217if (isTargetIPhoneOS() && isIPhoneOSVersionLT(6, 0))3218return false;3219return true;3220}32213222bool MachO::isPICDefault() const { return true; }32233224bool MachO::isPIEDefault(const llvm::opt::ArgList &Args) const { return false; }32253226bool MachO::isPICDefaultForced() const {3227return (getArch() == llvm::Triple::x86_64 ||3228getArch() == llvm::Triple::aarch64);3229}32303231bool MachO::SupportsProfiling() const {3232// Profiling instrumentation is only supported on x86.3233return getTriple().isX86();3234}32353236void Darwin::addMinVersionArgs(const ArgList &Args,3237ArgStringList &CmdArgs) const {3238VersionTuple TargetVersion = getTripleTargetVersion();32393240assert(!isTargetXROS() && "xrOS always uses -platform-version");32413242if (isTargetWatchOS())3243CmdArgs.push_back("-watchos_version_min");3244else if (isTargetWatchOSSimulator())3245CmdArgs.push_back("-watchos_simulator_version_min");3246else if (isTargetTvOS())3247CmdArgs.push_back("-tvos_version_min");3248else if (isTargetTvOSSimulator())3249CmdArgs.push_back("-tvos_simulator_version_min");3250else if (isTargetDriverKit())3251CmdArgs.push_back("-driverkit_version_min");3252else if (isTargetIOSSimulator())3253CmdArgs.push_back("-ios_simulator_version_min");3254else if (isTargetIOSBased())3255CmdArgs.push_back("-iphoneos_version_min");3256else if (isTargetMacCatalyst())3257CmdArgs.push_back("-maccatalyst_version_min");3258else {3259assert(isTargetMacOS() && "unexpected target");3260CmdArgs.push_back("-macosx_version_min");3261}32623263VersionTuple MinTgtVers = getEffectiveTriple().getMinimumSupportedOSVersion();3264if (!MinTgtVers.empty() && MinTgtVers > TargetVersion)3265TargetVersion = MinTgtVers;3266CmdArgs.push_back(Args.MakeArgString(TargetVersion.getAsString()));3267if (TargetVariantTriple) {3268assert(isTargetMacOSBased() && "unexpected target");3269VersionTuple VariantTargetVersion;3270if (TargetVariantTriple->isMacOSX()) {3271CmdArgs.push_back("-macosx_version_min");3272TargetVariantTriple->getMacOSXVersion(VariantTargetVersion);3273} else {3274assert(TargetVariantTriple->isiOS() &&3275TargetVariantTriple->isMacCatalystEnvironment() &&3276"unexpected target variant triple");3277CmdArgs.push_back("-maccatalyst_version_min");3278VariantTargetVersion = TargetVariantTriple->getiOSVersion();3279}3280VersionTuple MinTgtVers =3281TargetVariantTriple->getMinimumSupportedOSVersion();3282if (MinTgtVers.getMajor() && MinTgtVers > VariantTargetVersion)3283VariantTargetVersion = MinTgtVers;3284CmdArgs.push_back(Args.MakeArgString(VariantTargetVersion.getAsString()));3285}3286}32873288static const char *getPlatformName(Darwin::DarwinPlatformKind Platform,3289Darwin::DarwinEnvironmentKind Environment) {3290switch (Platform) {3291case Darwin::MacOS:3292return "macos";3293case Darwin::IPhoneOS:3294if (Environment == Darwin::MacCatalyst)3295return "mac catalyst";3296return "ios";3297case Darwin::TvOS:3298return "tvos";3299case Darwin::WatchOS:3300return "watchos";3301case Darwin::XROS:3302return "xros";3303case Darwin::DriverKit:3304return "driverkit";3305}3306llvm_unreachable("invalid platform");3307}33083309void Darwin::addPlatformVersionArgs(const llvm::opt::ArgList &Args,3310llvm::opt::ArgStringList &CmdArgs) const {3311auto EmitPlatformVersionArg =3312[&](const VersionTuple &TV, Darwin::DarwinPlatformKind TargetPlatform,3313Darwin::DarwinEnvironmentKind TargetEnvironment,3314const llvm::Triple &TT) {3315// -platform_version <platform> <target_version> <sdk_version>3316// Both the target and SDK version support only up to 3 components.3317CmdArgs.push_back("-platform_version");3318std::string PlatformName =3319getPlatformName(TargetPlatform, TargetEnvironment);3320if (TargetEnvironment == Darwin::Simulator)3321PlatformName += "-simulator";3322CmdArgs.push_back(Args.MakeArgString(PlatformName));3323VersionTuple TargetVersion = TV.withoutBuild();3324if ((TargetPlatform == Darwin::IPhoneOS ||3325TargetPlatform == Darwin::TvOS) &&3326getTriple().getArchName() == "arm64e" &&3327TargetVersion.getMajor() < 14) {3328// arm64e slice is supported on iOS/tvOS 14+ only.3329TargetVersion = VersionTuple(14, 0);3330}3331VersionTuple MinTgtVers = TT.getMinimumSupportedOSVersion();3332if (!MinTgtVers.empty() && MinTgtVers > TargetVersion)3333TargetVersion = MinTgtVers;3334CmdArgs.push_back(Args.MakeArgString(TargetVersion.getAsString()));33353336if (TargetPlatform == IPhoneOS && TargetEnvironment == MacCatalyst) {3337// Mac Catalyst programs must use the appropriate iOS SDK version3338// that corresponds to the macOS SDK version used for the compilation.3339std::optional<VersionTuple> iOSSDKVersion;3340if (SDKInfo) {3341if (const auto *MacOStoMacCatalystMapping =3342SDKInfo->getVersionMapping(3343DarwinSDKInfo::OSEnvPair::macOStoMacCatalystPair())) {3344iOSSDKVersion = MacOStoMacCatalystMapping->map(3345SDKInfo->getVersion().withoutBuild(),3346minimumMacCatalystDeploymentTarget(), std::nullopt);3347}3348}3349CmdArgs.push_back(Args.MakeArgString(3350(iOSSDKVersion ? *iOSSDKVersion3351: minimumMacCatalystDeploymentTarget())3352.getAsString()));3353return;3354}33553356if (SDKInfo) {3357VersionTuple SDKVersion = SDKInfo->getVersion().withoutBuild();3358if (!SDKVersion.getMinor())3359SDKVersion = VersionTuple(SDKVersion.getMajor(), 0);3360CmdArgs.push_back(Args.MakeArgString(SDKVersion.getAsString()));3361} else {3362// Use an SDK version that's matching the deployment target if the SDK3363// version is missing. This is preferred over an empty SDK version3364// (0.0.0) as the system's runtime might expect the linked binary to3365// contain a valid SDK version in order for the binary to work3366// correctly. It's reasonable to use the deployment target version as3367// a proxy for the SDK version because older SDKs don't guarantee3368// support for deployment targets newer than the SDK versions, so that3369// rules out using some predetermined older SDK version, which leaves3370// the deployment target version as the only reasonable choice.3371CmdArgs.push_back(Args.MakeArgString(TargetVersion.getAsString()));3372}3373};3374EmitPlatformVersionArg(getTripleTargetVersion(), TargetPlatform,3375TargetEnvironment, getEffectiveTriple());3376if (!TargetVariantTriple)3377return;3378Darwin::DarwinPlatformKind Platform;3379Darwin::DarwinEnvironmentKind Environment;3380VersionTuple TargetVariantVersion;3381if (TargetVariantTriple->isMacOSX()) {3382TargetVariantTriple->getMacOSXVersion(TargetVariantVersion);3383Platform = Darwin::MacOS;3384Environment = Darwin::NativeEnvironment;3385} else {3386assert(TargetVariantTriple->isiOS() &&3387TargetVariantTriple->isMacCatalystEnvironment() &&3388"unexpected target variant triple");3389TargetVariantVersion = TargetVariantTriple->getiOSVersion();3390Platform = Darwin::IPhoneOS;3391Environment = Darwin::MacCatalyst;3392}3393EmitPlatformVersionArg(TargetVariantVersion, Platform, Environment,3394*TargetVariantTriple);3395}33963397// Add additional link args for the -dynamiclib option.3398static void addDynamicLibLinkArgs(const Darwin &D, const ArgList &Args,3399ArgStringList &CmdArgs) {3400// Derived from darwin_dylib1 spec.3401if (D.isTargetIPhoneOS()) {3402if (D.isIPhoneOSVersionLT(3, 1))3403CmdArgs.push_back("-ldylib1.o");3404return;3405}34063407if (!D.isTargetMacOS())3408return;3409if (D.isMacosxVersionLT(10, 5))3410CmdArgs.push_back("-ldylib1.o");3411else if (D.isMacosxVersionLT(10, 6))3412CmdArgs.push_back("-ldylib1.10.5.o");3413}34143415// Add additional link args for the -bundle option.3416static void addBundleLinkArgs(const Darwin &D, const ArgList &Args,3417ArgStringList &CmdArgs) {3418if (Args.hasArg(options::OPT_static))3419return;3420// Derived from darwin_bundle1 spec.3421if ((D.isTargetIPhoneOS() && D.isIPhoneOSVersionLT(3, 1)) ||3422(D.isTargetMacOS() && D.isMacosxVersionLT(10, 6)))3423CmdArgs.push_back("-lbundle1.o");3424}34253426// Add additional link args for the -pg option.3427static void addPgProfilingLinkArgs(const Darwin &D, const ArgList &Args,3428ArgStringList &CmdArgs) {3429if (D.isTargetMacOS() && D.isMacosxVersionLT(10, 9)) {3430if (Args.hasArg(options::OPT_static) || Args.hasArg(options::OPT_object) ||3431Args.hasArg(options::OPT_preload)) {3432CmdArgs.push_back("-lgcrt0.o");3433} else {3434CmdArgs.push_back("-lgcrt1.o");34353436// darwin_crt2 spec is empty.3437}3438// By default on OS X 10.8 and later, we don't link with a crt1.o3439// file and the linker knows to use _main as the entry point. But,3440// when compiling with -pg, we need to link with the gcrt1.o file,3441// so pass the -no_new_main option to tell the linker to use the3442// "start" symbol as the entry point.3443if (!D.isMacosxVersionLT(10, 8))3444CmdArgs.push_back("-no_new_main");3445} else {3446D.getDriver().Diag(diag::err_drv_clang_unsupported_opt_pg_darwin)3447<< D.isTargetMacOSBased();3448}3449}34503451static void addDefaultCRTLinkArgs(const Darwin &D, const ArgList &Args,3452ArgStringList &CmdArgs) {3453// Derived from darwin_crt1 spec.3454if (D.isTargetIPhoneOS()) {3455if (D.getArch() == llvm::Triple::aarch64)3456; // iOS does not need any crt1 files for arm643457else if (D.isIPhoneOSVersionLT(3, 1))3458CmdArgs.push_back("-lcrt1.o");3459else if (D.isIPhoneOSVersionLT(6, 0))3460CmdArgs.push_back("-lcrt1.3.1.o");3461return;3462}34633464if (!D.isTargetMacOS())3465return;3466if (D.isMacosxVersionLT(10, 5))3467CmdArgs.push_back("-lcrt1.o");3468else if (D.isMacosxVersionLT(10, 6))3469CmdArgs.push_back("-lcrt1.10.5.o");3470else if (D.isMacosxVersionLT(10, 8))3471CmdArgs.push_back("-lcrt1.10.6.o");3472// darwin_crt2 spec is empty.3473}34743475void Darwin::addStartObjectFileArgs(const ArgList &Args,3476ArgStringList &CmdArgs) const {3477// Derived from startfile spec.3478if (Args.hasArg(options::OPT_dynamiclib))3479addDynamicLibLinkArgs(*this, Args, CmdArgs);3480else if (Args.hasArg(options::OPT_bundle))3481addBundleLinkArgs(*this, Args, CmdArgs);3482else if (Args.hasArg(options::OPT_pg) && SupportsProfiling())3483addPgProfilingLinkArgs(*this, Args, CmdArgs);3484else if (Args.hasArg(options::OPT_static) ||3485Args.hasArg(options::OPT_object) ||3486Args.hasArg(options::OPT_preload))3487CmdArgs.push_back("-lcrt0.o");3488else3489addDefaultCRTLinkArgs(*this, Args, CmdArgs);34903491if (isTargetMacOS() && Args.hasArg(options::OPT_shared_libgcc) &&3492isMacosxVersionLT(10, 5)) {3493const char *Str = Args.MakeArgString(GetFilePath("crt3.o"));3494CmdArgs.push_back(Str);3495}3496}34973498void Darwin::CheckObjCARC() const {3499if (isTargetIOSBased() || isTargetWatchOSBased() || isTargetXROS() ||3500(isTargetMacOSBased() && !isMacosxVersionLT(10, 6)))3501return;3502getDriver().Diag(diag::err_arc_unsupported_on_toolchain);3503}35043505SanitizerMask Darwin::getSupportedSanitizers() const {3506const bool IsX86_64 = getTriple().getArch() == llvm::Triple::x86_64;3507const bool IsAArch64 = getTriple().getArch() == llvm::Triple::aarch64;3508SanitizerMask Res = ToolChain::getSupportedSanitizers();3509Res |= SanitizerKind::Address;3510Res |= SanitizerKind::PointerCompare;3511Res |= SanitizerKind::PointerSubtract;3512Res |= SanitizerKind::Leak;3513Res |= SanitizerKind::Fuzzer;3514Res |= SanitizerKind::FuzzerNoLink;3515Res |= SanitizerKind::ObjCCast;35163517// Prior to 10.9, macOS shipped a version of the C++ standard library without3518// C++11 support. The same is true of iOS prior to version 5. These OS'es are3519// incompatible with -fsanitize=vptr.3520if (!(isTargetMacOSBased() && isMacosxVersionLT(10, 9)) &&3521!(isTargetIPhoneOS() && isIPhoneOSVersionLT(5, 0)))3522Res |= SanitizerKind::Vptr;35233524if ((IsX86_64 || IsAArch64) &&3525(isTargetMacOSBased() || isTargetIOSSimulator() ||3526isTargetTvOSSimulator() || isTargetWatchOSSimulator())) {3527Res |= SanitizerKind::Thread;3528}35293530if (IsX86_64)3531Res |= SanitizerKind::NumericalStability;35323533return Res;3534}35353536void Darwin::printVerboseInfo(raw_ostream &OS) const {3537CudaInstallation->print(OS);3538RocmInstallation->print(OS);3539}354035413542