//===--- Darwin.cpp - Darwin Tool and ToolChain Implementations -*- C++ -*-===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//

#include "Darwin.h"
#include "Arch/AArch64.h"
#include "Arch/ARM.h"
#include "CommonArgs.h"
#include "clang/Basic/AlignedAllocation.h"
#include "clang/Basic/ObjCRuntime.h"
#include "clang/Config/config.h"
#include "clang/Driver/Compilation.h"
#include "clang/Driver/Driver.h"
#include "clang/Driver/DriverDiagnostic.h"
#include "clang/Driver/Options.h"
#include "clang/Driver/SanitizerArgs.h"
#include "llvm/ADT/StringSwitch.h"
#include "llvm/Option/ArgList.h"
#include "llvm/ProfileData/InstrProf.h"
#include "llvm/Support/Path.h"
#include "llvm/Support/ScopedPrinter.h"
#include "llvm/Support/TargetParser.h"
#include "llvm/Support/Threading.h"
#include "llvm/Support/VirtualFileSystem.h"
#include <cstdlib> // ::getenv

using namespace clang::driver;
using namespace clang::driver::tools;
using namespace clang::driver::toolchains;
using namespace clang;
using namespace llvm::opt;

static VersionTuple minimumMacCatalystDeploymentTarget() {
  return VersionTuple(13, 1);
}

llvm::Triple::ArchType darwin::getArchTypeForMachOArchName(StringRef Str) {
  // See arch(3) and llvm-gcc's driver-driver.c. We don't implement support for
  // archs which Darwin doesn't use.

  // The matching this routine does is fairly pointless, since it is neither the
  // complete architecture list, nor a reasonable subset. The problem is that
  // historically the driver driver accepts this and also ties its -march=
  // handling to the architecture name, so we need to be careful before removing
  // support for it.

  // This code must be kept in sync with Clang's Darwin specific argument
  // translation.

  return llvm::StringSwitch<llvm::Triple::ArchType>(Str)
      .Cases("ppc", "ppc601", "ppc603", "ppc604", "ppc604e", llvm::Triple::ppc)
      .Cases("ppc750", "ppc7400", "ppc7450", "ppc970", llvm::Triple::ppc)
      .Case("ppc64", llvm::Triple::ppc64)
      .Cases("i386", "i486", "i486SX", "i586", "i686", llvm::Triple::x86)
      .Cases("pentium", "pentpro", "pentIIm3", "pentIIm5", "pentium4",
             llvm::Triple::x86)
      .Cases("x86_64", "x86_64h", llvm::Triple::x86_64)
      // This is derived from the driver driver.
      .Cases("arm", "armv4t", "armv5", "armv6", "armv6m", llvm::Triple::arm)
      .Cases("armv7", "armv7em", "armv7k", "armv7m", llvm::Triple::arm)
      .Cases("armv7s", "xscale", llvm::Triple::arm)
      .Cases("arm64", "arm64e", llvm::Triple::aarch64)
      .Case("arm64_32", llvm::Triple::aarch64_32)
      .Case("r600", llvm::Triple::r600)
      .Case("amdgcn", llvm::Triple::amdgcn)
      .Case("nvptx", llvm::Triple::nvptx)
      .Case("nvptx64", llvm::Triple::nvptx64)
      .Case("amdil", llvm::Triple::amdil)
      .Case("spir", llvm::Triple::spir)
      .Default(llvm::Triple::UnknownArch);
}

void darwin::setTripleTypeForMachOArchName(llvm::Triple &T, StringRef Str) {
  const llvm::Triple::ArchType Arch = getArchTypeForMachOArchName(Str);
  llvm::ARM::ArchKind ArchKind = llvm::ARM::parseArch(Str);
  T.setArch(Arch);
  if (Arch != llvm::Triple::UnknownArch)
    T.setArchName(Str);

  if (ArchKind == llvm::ARM::ArchKind::ARMV6M ||
      ArchKind == llvm::ARM::ArchKind::ARMV7M ||
      ArchKind == llvm::ARM::ArchKind::ARMV7EM) {
    T.setOS(llvm::Triple::UnknownOS);
    T.setObjectFormat(llvm::Triple::MachO);
  }
}

void darwin::Assembler::ConstructJob(Compilation &C, const JobAction &JA,
                                     const InputInfo &Output,
                                     const InputInfoList &Inputs,
                                     const ArgList &Args,
                                     const char *LinkingOutput) const {
  const llvm::Triple &T(getToolChain().getTriple());

  ArgStringList CmdArgs;

  assert(Inputs.size() == 1 && "Unexpected number of inputs.");
  const InputInfo &Input = Inputs[0];

  // Determine the original source input.
  const Action *SourceAction = &JA;
  while (SourceAction->getKind() != Action::InputClass) {
    assert(!SourceAction->getInputs().empty() && "unexpected root action!");
    SourceAction = SourceAction->getInputs()[0];
  }

  // If -fno-integrated-as is used add -Q to the darwin assembler driver to make
  // sure it runs its system assembler not clang's integrated assembler.
  // Applicable to darwin11+ and Xcode 4+.  darwin<10 lacked integrated-as.
  // FIXME: at run-time detect assembler capabilities or rely on version
  // information forwarded by -target-assembler-version.
  if (Args.hasArg(options::OPT_fno_integrated_as)) {
    if (!(T.isMacOSX() && T.isMacOSXVersionLT(10, 7)))
      CmdArgs.push_back("-Q");
  }

  // Forward -g, assuming we are dealing with an actual assembly file.
  if (SourceAction->getType() == types::TY_Asm ||
      SourceAction->getType() == types::TY_PP_Asm) {
    if (Args.hasArg(options::OPT_gstabs))
      CmdArgs.push_back("--gstabs");
    else if (Args.hasArg(options::OPT_g_Group))
      CmdArgs.push_back("-g");
  }

  // Derived from asm spec.
  AddMachOArch(Args, CmdArgs);

  // Use -force_cpusubtype_ALL on x86 by default.
  if (T.isX86() || Args.hasArg(options::OPT_force__cpusubtype__ALL))
    CmdArgs.push_back("-force_cpusubtype_ALL");

  if (getToolChain().getArch() != llvm::Triple::x86_64 &&
      (((Args.hasArg(options::OPT_mkernel) ||
         Args.hasArg(options::OPT_fapple_kext)) &&
        getMachOToolChain().isKernelStatic()) ||
       Args.hasArg(options::OPT_static)))
    CmdArgs.push_back("-static");

  Args.AddAllArgValues(CmdArgs, options::OPT_Wa_COMMA, options::OPT_Xassembler);

  assert(Output.isFilename() && "Unexpected lipo output.");
  CmdArgs.push_back("-o");
  CmdArgs.push_back(Output.getFilename());

  assert(Input.isFilename() && "Invalid input.");
  CmdArgs.push_back(Input.getFilename());

  // asm_final spec is empty.

  const char *Exec = Args.MakeArgString(getToolChain().GetProgramPath("as"));
  C.addCommand(std::make_unique<Command>(JA, *this, ResponseFileSupport::None(),
                                         Exec, CmdArgs, Inputs, Output));
}

void darwin::MachOTool::anchor() {}

void darwin::MachOTool::AddMachOArch(const ArgList &Args,
                                     ArgStringList &CmdArgs) const {
  StringRef ArchName = getMachOToolChain().getMachOArchName(Args);

  // Derived from darwin_arch spec.
  CmdArgs.push_back("-arch");
  CmdArgs.push_back(Args.MakeArgString(ArchName));

  // FIXME: Is this needed anymore?
  if (ArchName == "arm")
    CmdArgs.push_back("-force_cpusubtype_ALL");
}

bool darwin::Linker::NeedsTempPath(const InputInfoList &Inputs) const {
  // We only need to generate a temp path for LTO if we aren't compiling object
  // files. When compiling source files, we run 'dsymutil' after linking. We
  // don't run 'dsymutil' when compiling object files.
  for (const auto &Input : Inputs)
    if (Input.getType() != types::TY_Object)
      return true;

  return false;
}

/// Pass -no_deduplicate to ld64 under certain conditions:
///
/// - Either -O0 or -O1 is explicitly specified
/// - No -O option is specified *and* this is a compile+link (implicit -O0)
///
/// Also do *not* add -no_deduplicate when no -O option is specified and this
/// is just a link (we can't imply -O0)
static bool shouldLinkerNotDedup(bool IsLinkerOnlyAction, const ArgList &Args) {
  if (Arg *A = Args.getLastArg(options::OPT_O_Group)) {
    if (A->getOption().matches(options::OPT_O0))
      return true;
    if (A->getOption().matches(options::OPT_O))
      return llvm::StringSwitch<bool>(A->getValue())
                    .Case("1", true)
                    .Default(false);
    return false; // OPT_Ofast & OPT_O4
  }

  if (!IsLinkerOnlyAction) // Implicit -O0 for compile+linker only.
    return true;
  return false;
}

void darwin::Linker::AddLinkArgs(Compilation &C, const ArgList &Args,
                                 ArgStringList &CmdArgs,
                                 const InputInfoList &Inputs,
                                 unsigned Version[5], bool LinkerIsLLD,
                                 bool LinkerIsLLDDarwinNew) const {
  const Driver &D = getToolChain().getDriver();
  const toolchains::MachO &MachOTC = getMachOToolChain();

  // Newer linkers support -demangle. Pass it if supported and not disabled by
  // the user.
  if ((Version[0] >= 100 || LinkerIsLLD) &&
      !Args.hasArg(options::OPT_Z_Xlinker__no_demangle))
    CmdArgs.push_back("-demangle");

  // FIXME: Pass most of the flags below that check Version if LinkerIsLLD too.

  if (Args.hasArg(options::OPT_rdynamic) && Version[0] >= 137)
    CmdArgs.push_back("-export_dynamic");

  // If we are using App Extension restrictions, pass a flag to the linker
  // telling it that the compiled code has been audited.
  if (Args.hasFlag(options::OPT_fapplication_extension,
                   options::OPT_fno_application_extension, false))
    CmdArgs.push_back("-application_extension");

  if (D.isUsingLTO() && Version[0] >= 116 && NeedsTempPath(Inputs)) {
    std::string TmpPathName;
    if (D.getLTOMode() == LTOK_Full) {
      // If we are using full LTO, then automatically create a temporary file
      // path for the linker to use, so that it's lifetime will extend past a
      // possible dsymutil step.
      TmpPathName =
          D.GetTemporaryPath("cc", types::getTypeTempSuffix(types::TY_Object));
    } else if (D.getLTOMode() == LTOK_Thin)
      // If we are using thin LTO, then create a directory instead.
      TmpPathName = D.GetTemporaryDirectory("thinlto");

    if (!TmpPathName.empty()) {
      auto *TmpPath = C.getArgs().MakeArgString(TmpPathName);
      C.addTempFile(TmpPath);
      CmdArgs.push_back("-object_path_lto");
      CmdArgs.push_back(TmpPath);
    }
  }

  // Use -lto_library option to specify the libLTO.dylib path. Try to find
  // it in clang installed libraries. ld64 will only look at this argument
  // when it actually uses LTO, so libLTO.dylib only needs to exist at link
  // time if ld64 decides that it needs to use LTO.
  // Since this is passed unconditionally, ld64 will never look for libLTO.dylib
  // next to it. That's ok since ld64 using a libLTO.dylib not matching the
  // clang version won't work anyways.
  // lld is built at the same revision as clang and statically links in
  // LLVM libraries, so it doesn't need libLTO.dylib.
  if (Version[0] >= 133 && !LinkerIsLLD) {
    // Search for libLTO in <InstalledDir>/../lib/libLTO.dylib
    StringRef P = llvm::sys::path::parent_path(D.Dir);
    SmallString<128> LibLTOPath(P);
    llvm::sys::path::append(LibLTOPath, "lib");
    llvm::sys::path::append(LibLTOPath, "libLTO.dylib");
    CmdArgs.push_back("-lto_library");
    CmdArgs.push_back(C.getArgs().MakeArgString(LibLTOPath));
  }

  // ld64 version 262 and above run the deduplicate pass by default.
  if (Version[0] >= 262 && shouldLinkerNotDedup(C.getJobs().empty(), Args))
    CmdArgs.push_back("-no_deduplicate");

  // Derived from the "link" spec.
  Args.AddAllArgs(CmdArgs, options::OPT_static);
  if (!Args.hasArg(options::OPT_static))
    CmdArgs.push_back("-dynamic");
  if (Args.hasArg(options::OPT_fgnu_runtime)) {
    // FIXME: gcc replaces -lobjc in forward args with -lobjc-gnu
    // here. How do we wish to handle such things?
  }

  if (!Args.hasArg(options::OPT_dynamiclib)) {
    AddMachOArch(Args, CmdArgs);
    // FIXME: Why do this only on this path?
    Args.AddLastArg(CmdArgs, options::OPT_force__cpusubtype__ALL);

    Args.AddLastArg(CmdArgs, options::OPT_bundle);
    Args.AddAllArgs(CmdArgs, options::OPT_bundle__loader);
    Args.AddAllArgs(CmdArgs, options::OPT_client__name);

    Arg *A;
    if ((A = Args.getLastArg(options::OPT_compatibility__version)) ||
        (A = Args.getLastArg(options::OPT_current__version)) ||
        (A = Args.getLastArg(options::OPT_install__name)))
      D.Diag(diag::err_drv_argument_only_allowed_with) << A->getAsString(Args)
                                                       << "-dynamiclib";

    Args.AddLastArg(CmdArgs, options::OPT_force__flat__namespace);
    Args.AddLastArg(CmdArgs, options::OPT_keep__private__externs);
    Args.AddLastArg(CmdArgs, options::OPT_private__bundle);
  } else {
    CmdArgs.push_back("-dylib");

    Arg *A;
    if ((A = Args.getLastArg(options::OPT_bundle)) ||
        (A = Args.getLastArg(options::OPT_bundle__loader)) ||
        (A = Args.getLastArg(options::OPT_client__name)) ||
        (A = Args.getLastArg(options::OPT_force__flat__namespace)) ||
        (A = Args.getLastArg(options::OPT_keep__private__externs)) ||
        (A = Args.getLastArg(options::OPT_private__bundle)))
      D.Diag(diag::err_drv_argument_not_allowed_with) << A->getAsString(Args)
                                                      << "-dynamiclib";

    Args.AddAllArgsTranslated(CmdArgs, options::OPT_compatibility__version,
                              "-dylib_compatibility_version");
    Args.AddAllArgsTranslated(CmdArgs, options::OPT_current__version,
                              "-dylib_current_version");

    AddMachOArch(Args, CmdArgs);

    Args.AddAllArgsTranslated(CmdArgs, options::OPT_install__name,
                              "-dylib_install_name");
  }

  Args.AddLastArg(CmdArgs, options::OPT_all__load);
  Args.AddAllArgs(CmdArgs, options::OPT_allowable__client);
  Args.AddLastArg(CmdArgs, options::OPT_bind__at__load);
  if (MachOTC.isTargetIOSBased())
    Args.AddLastArg(CmdArgs, options::OPT_arch__errors__fatal);
  Args.AddLastArg(CmdArgs, options::OPT_dead__strip);
  Args.AddLastArg(CmdArgs, options::OPT_no__dead__strip__inits__and__terms);
  Args.AddAllArgs(CmdArgs, options::OPT_dylib__file);
  Args.AddLastArg(CmdArgs, options::OPT_dynamic);
  Args.AddAllArgs(CmdArgs, options::OPT_exported__symbols__list);
  Args.AddLastArg(CmdArgs, options::OPT_flat__namespace);
  Args.AddAllArgs(CmdArgs, options::OPT_force__load);
  Args.AddAllArgs(CmdArgs, options::OPT_headerpad__max__install__names);
  Args.AddAllArgs(CmdArgs, options::OPT_image__base);
  Args.AddAllArgs(CmdArgs, options::OPT_init);

  // Add the deployment target.
  if (Version[0] >= 520 || LinkerIsLLDDarwinNew)
    MachOTC.addPlatformVersionArgs(Args, CmdArgs);
  else
    MachOTC.addMinVersionArgs(Args, CmdArgs);

  Args.AddLastArg(CmdArgs, options::OPT_nomultidefs);
  Args.AddLastArg(CmdArgs, options::OPT_multi__module);
  Args.AddLastArg(CmdArgs, options::OPT_single__module);
  Args.AddAllArgs(CmdArgs, options::OPT_multiply__defined);
  Args.AddAllArgs(CmdArgs, options::OPT_multiply__defined__unused);

  if (const Arg *A =
          Args.getLastArg(options::OPT_fpie, options::OPT_fPIE,
                          options::OPT_fno_pie, options::OPT_fno_PIE)) {
    if (A->getOption().matches(options::OPT_fpie) ||
        A->getOption().matches(options::OPT_fPIE))
      CmdArgs.push_back("-pie");
    else
      CmdArgs.push_back("-no_pie");
  }

  // for embed-bitcode, use -bitcode_bundle in linker command
  if (C.getDriver().embedBitcodeEnabled()) {
    // Check if the toolchain supports bitcode build flow.
    if (MachOTC.SupportsEmbeddedBitcode()) {
      CmdArgs.push_back("-bitcode_bundle");
      if (C.getDriver().embedBitcodeMarkerOnly() && Version[0] >= 278) {
        CmdArgs.push_back("-bitcode_process_mode");
        CmdArgs.push_back("marker");
      }
    } else
      D.Diag(diag::err_drv_bitcode_unsupported_on_toolchain);
  }

  // If GlobalISel is enabled, pass it through to LLVM.
  if (Arg *A = Args.getLastArg(options::OPT_fglobal_isel,
                               options::OPT_fno_global_isel)) {
    if (A->getOption().matches(options::OPT_fglobal_isel)) {
      CmdArgs.push_back("-mllvm");
      CmdArgs.push_back("-global-isel");
      // Disable abort and fall back to SDAG silently.
      CmdArgs.push_back("-mllvm");
      CmdArgs.push_back("-global-isel-abort=0");
    }
  }

  Args.AddLastArg(CmdArgs, options::OPT_prebind);
  Args.AddLastArg(CmdArgs, options::OPT_noprebind);
  Args.AddLastArg(CmdArgs, options::OPT_nofixprebinding);
  Args.AddLastArg(CmdArgs, options::OPT_prebind__all__twolevel__modules);
  Args.AddLastArg(CmdArgs, options::OPT_read__only__relocs);
  Args.AddAllArgs(CmdArgs, options::OPT_sectcreate);
  Args.AddAllArgs(CmdArgs, options::OPT_sectorder);
  Args.AddAllArgs(CmdArgs, options::OPT_seg1addr);
  Args.AddAllArgs(CmdArgs, options::OPT_segprot);
  Args.AddAllArgs(CmdArgs, options::OPT_segaddr);
  Args.AddAllArgs(CmdArgs, options::OPT_segs__read__only__addr);
  Args.AddAllArgs(CmdArgs, options::OPT_segs__read__write__addr);
  Args.AddAllArgs(CmdArgs, options::OPT_seg__addr__table);
  Args.AddAllArgs(CmdArgs, options::OPT_seg__addr__table__filename);
  Args.AddAllArgs(CmdArgs, options::OPT_sub__library);
  Args.AddAllArgs(CmdArgs, options::OPT_sub__umbrella);

  // Give --sysroot= preference, over the Apple specific behavior to also use
  // --isysroot as the syslibroot.
  StringRef sysroot = C.getSysRoot();
  if (sysroot != "") {
    CmdArgs.push_back("-syslibroot");
    CmdArgs.push_back(C.getArgs().MakeArgString(sysroot));
  } else if (const Arg *A = Args.getLastArg(options::OPT_isysroot)) {
    CmdArgs.push_back("-syslibroot");
    CmdArgs.push_back(A->getValue());
  }

  Args.AddLastArg(CmdArgs, options::OPT_twolevel__namespace);
  Args.AddLastArg(CmdArgs, options::OPT_twolevel__namespace__hints);
  Args.AddAllArgs(CmdArgs, options::OPT_umbrella);
  Args.AddAllArgs(CmdArgs, options::OPT_undefined);
  Args.AddAllArgs(CmdArgs, options::OPT_unexported__symbols__list);
  Args.AddAllArgs(CmdArgs, options::OPT_weak__reference__mismatches);
  Args.AddLastArg(CmdArgs, options::OPT_X_Flag);
  Args.AddAllArgs(CmdArgs, options::OPT_y);
  Args.AddLastArg(CmdArgs, options::OPT_w);
  Args.AddAllArgs(CmdArgs, options::OPT_pagezero__size);
  Args.AddAllArgs(CmdArgs, options::OPT_segs__read__);
  Args.AddLastArg(CmdArgs, options::OPT_seglinkedit);
  Args.AddLastArg(CmdArgs, options::OPT_noseglinkedit);
  Args.AddAllArgs(CmdArgs, options::OPT_sectalign);
  Args.AddAllArgs(CmdArgs, options::OPT_sectobjectsymbols);
  Args.AddAllArgs(CmdArgs, options::OPT_segcreate);
  Args.AddLastArg(CmdArgs, options::OPT_why_load);
  Args.AddLastArg(CmdArgs, options::OPT_whatsloaded);
  Args.AddAllArgs(CmdArgs, options::OPT_dylinker__install__name);
  Args.AddLastArg(CmdArgs, options::OPT_dylinker);
  Args.AddLastArg(CmdArgs, options::OPT_Mach);
}

/// Determine whether we are linking the ObjC runtime.
static bool isObjCRuntimeLinked(const ArgList &Args) {
  if (isObjCAutoRefCount(Args)) {
    Args.ClaimAllArgs(options::OPT_fobjc_link_runtime);
    return true;
  }
  return Args.hasArg(options::OPT_fobjc_link_runtime);
}

static bool checkRemarksOptions(const Driver &D, const ArgList &Args,
                                const llvm::Triple &Triple) {
  // When enabling remarks, we need to error if:
  // * The remark file is specified but we're targeting multiple architectures,
  // which means more than one remark file is being generated.
  bool hasMultipleInvocations =
      Args.getAllArgValues(options::OPT_arch).size() > 1;
  bool hasExplicitOutputFile =
      Args.getLastArg(options::OPT_foptimization_record_file_EQ);
  if (hasMultipleInvocations && hasExplicitOutputFile) {
    D.Diag(diag::err_drv_invalid_output_with_multiple_archs)
        << "-foptimization-record-file";
    return false;
  }
  return true;
}

static void renderRemarksOptions(const ArgList &Args, ArgStringList &CmdArgs,
                                 const llvm::Triple &Triple,
                                 const InputInfo &Output, const JobAction &JA) {
  StringRef Format = "yaml";
  if (const Arg *A = Args.getLastArg(options::OPT_fsave_optimization_record_EQ))
    Format = A->getValue();

  CmdArgs.push_back("-mllvm");
  CmdArgs.push_back("-lto-pass-remarks-output");
  CmdArgs.push_back("-mllvm");

  const Arg *A = Args.getLastArg(options::OPT_foptimization_record_file_EQ);
  if (A) {
    CmdArgs.push_back(A->getValue());
  } else {
    assert(Output.isFilename() && "Unexpected ld output.");
    SmallString<128> F;
    F = Output.getFilename();
    F += ".opt.";
    F += Format;

    CmdArgs.push_back(Args.MakeArgString(F));
  }

  if (const Arg *A =
          Args.getLastArg(options::OPT_foptimization_record_passes_EQ)) {
    CmdArgs.push_back("-mllvm");
    std::string Passes =
        std::string("-lto-pass-remarks-filter=") + A->getValue();
    CmdArgs.push_back(Args.MakeArgString(Passes));
  }

  if (!Format.empty()) {
    CmdArgs.push_back("-mllvm");
    Twine FormatArg = Twine("-lto-pass-remarks-format=") + Format;
    CmdArgs.push_back(Args.MakeArgString(FormatArg));
  }

  if (getLastProfileUseArg(Args)) {
    CmdArgs.push_back("-mllvm");
    CmdArgs.push_back("-lto-pass-remarks-with-hotness");

    if (const Arg *A =
            Args.getLastArg(options::OPT_fdiagnostics_hotness_threshold_EQ)) {
      CmdArgs.push_back("-mllvm");
      std::string Opt =
          std::string("-lto-pass-remarks-hotness-threshold=") + A->getValue();
      CmdArgs.push_back(Args.MakeArgString(Opt));
    }
  }
}

void darwin::Linker::ConstructJob(Compilation &C, const JobAction &JA,
                                  const InputInfo &Output,
                                  const InputInfoList &Inputs,
                                  const ArgList &Args,
                                  const char *LinkingOutput) const {
  assert(Output.getType() == types::TY_Image && "Invalid linker output type.");

  // If the number of arguments surpasses the system limits, we will encode the
  // input files in a separate file, shortening the command line. To this end,
  // build a list of input file names that can be passed via a file with the
  // -filelist linker option.
  llvm::opt::ArgStringList InputFileList;

  // The logic here is derived from gcc's behavior; most of which
  // comes from specs (starting with link_command). Consult gcc for
  // more information.
  ArgStringList CmdArgs;

  /// Hack(tm) to ignore linking errors when we are doing ARC migration.
  if (Args.hasArg(options::OPT_ccc_arcmt_check,
                  options::OPT_ccc_arcmt_migrate)) {
    for (const auto &Arg : Args)
      Arg->claim();
    const char *Exec =
        Args.MakeArgString(getToolChain().GetProgramPath("touch"));
    CmdArgs.push_back(Output.getFilename());
    C.addCommand(std::make_unique<Command>(
        JA, *this, ResponseFileSupport::None(), Exec, CmdArgs, None, Output));
    return;
  }

  unsigned Version[5] = {0, 0, 0, 0, 0};
  if (Arg *A = Args.getLastArg(options::OPT_mlinker_version_EQ)) {
    if (!Driver::GetReleaseVersion(A->getValue(), Version))
      getToolChain().getDriver().Diag(diag::err_drv_invalid_version_number)
          << A->getAsString(Args);
  }

  bool LinkerIsLLD, LinkerIsLLDDarwinNew;
  const char *Exec = Args.MakeArgString(
      getToolChain().GetLinkerPath(&LinkerIsLLD, &LinkerIsLLDDarwinNew));

  // I'm not sure why this particular decomposition exists in gcc, but
  // we follow suite for ease of comparison.
  AddLinkArgs(C, Args, CmdArgs, Inputs, Version, LinkerIsLLD,
              LinkerIsLLDDarwinNew);

  if (willEmitRemarks(Args) &&
      checkRemarksOptions(getToolChain().getDriver(), Args,
                          getToolChain().getTriple()))
    renderRemarksOptions(Args, CmdArgs, getToolChain().getTriple(), Output, JA);

  // Propagate the -moutline flag to the linker in LTO.
  if (Arg *A =
          Args.getLastArg(options::OPT_moutline, options::OPT_mno_outline)) {
    if (A->getOption().matches(options::OPT_moutline)) {
      if (getMachOToolChain().getMachOArchName(Args) == "arm64") {
        CmdArgs.push_back("-mllvm");
        CmdArgs.push_back("-enable-machine-outliner");

        // Outline from linkonceodr functions by default in LTO.
        CmdArgs.push_back("-mllvm");
        CmdArgs.push_back("-enable-linkonceodr-outlining");
      }
    } else {
      // Disable all outlining behaviour if we have mno-outline. We need to do
      // this explicitly, because targets which support default outlining will
      // try to do work if we don't.
      CmdArgs.push_back("-mllvm");
      CmdArgs.push_back("-enable-machine-outliner=never");
    }
  }

  // Setup statistics file output.
  SmallString<128> StatsFile =
      getStatsFileName(Args, Output, Inputs[0], getToolChain().getDriver());
  if (!StatsFile.empty()) {
    CmdArgs.push_back("-mllvm");
    CmdArgs.push_back(Args.MakeArgString("-lto-stats-file=" + StatsFile.str()));
  }

  // It seems that the 'e' option is completely ignored for dynamic executables
  // (the default), and with static executables, the last one wins, as expected.
  Args.AddAllArgs(CmdArgs, {options::OPT_d_Flag, options::OPT_s, options::OPT_t,
                            options::OPT_Z_Flag, options::OPT_u_Group,
                            options::OPT_e, options::OPT_r});

  // Forward -ObjC when either -ObjC or -ObjC++ is used, to force loading
  // members of static archive libraries which implement Objective-C classes or
  // categories.
  if (Args.hasArg(options::OPT_ObjC) || Args.hasArg(options::OPT_ObjCXX))
    CmdArgs.push_back("-ObjC");

  CmdArgs.push_back("-o");
  CmdArgs.push_back(Output.getFilename());

  if (!Args.hasArg(options::OPT_nostdlib, options::OPT_nostartfiles))
    getMachOToolChain().addStartObjectFileArgs(Args, CmdArgs);

  Args.AddAllArgs(CmdArgs, options::OPT_L);

  AddLinkerInputs(getToolChain(), Inputs, Args, CmdArgs, JA);
  // Build the input file for -filelist (list of linker input files) in case we
  // need it later
  for (const auto &II : Inputs) {
    if (!II.isFilename()) {
      // This is a linker input argument.
      // We cannot mix input arguments and file names in a -filelist input, thus
      // we prematurely stop our list (remaining files shall be passed as
      // arguments).
      if (InputFileList.size() > 0)
        break;

      continue;
    }

    InputFileList.push_back(II.getFilename());
  }

  if (!Args.hasArg(options::OPT_nostdlib, options::OPT_nodefaultlibs))
    addOpenMPRuntime(CmdArgs, getToolChain(), Args);

  if (isObjCRuntimeLinked(Args) &&
      !Args.hasArg(options::OPT_nostdlib, options::OPT_nodefaultlibs)) {
    // We use arclite library for both ARC and subscripting support.
    getMachOToolChain().AddLinkARCArgs(Args, CmdArgs);

    CmdArgs.push_back("-framework");
    CmdArgs.push_back("Foundation");
    // Link libobj.
    CmdArgs.push_back("-lobjc");
  }

  if (LinkingOutput) {
    CmdArgs.push_back("-arch_multiple");
    CmdArgs.push_back("-final_output");
    CmdArgs.push_back(LinkingOutput);
  }

  if (Args.hasArg(options::OPT_fnested_functions))
    CmdArgs.push_back("-allow_stack_execute");

  getMachOToolChain().addProfileRTLibs(Args, CmdArgs);

  StringRef Parallelism = getLTOParallelism(Args, getToolChain().getDriver());
  if (!Parallelism.empty()) {
    CmdArgs.push_back("-mllvm");
    unsigned NumThreads =
        llvm::get_threadpool_strategy(Parallelism)->compute_thread_count();
    CmdArgs.push_back(Args.MakeArgString("-threads=" + Twine(NumThreads)));
  }

  if (getToolChain().ShouldLinkCXXStdlib(Args))
    getToolChain().AddCXXStdlibLibArgs(Args, CmdArgs);

  bool NoStdOrDefaultLibs =
      Args.hasArg(options::OPT_nostdlib, options::OPT_nodefaultlibs);
  bool ForceLinkBuiltins = Args.hasArg(options::OPT_fapple_link_rtlib);
  if (!NoStdOrDefaultLibs || ForceLinkBuiltins) {
    // link_ssp spec is empty.

    // If we have both -nostdlib/nodefaultlibs and -fapple-link-rtlib then
    // we just want to link the builtins, not the other libs like libSystem.
    if (NoStdOrDefaultLibs && ForceLinkBuiltins) {
      getMachOToolChain().AddLinkRuntimeLib(Args, CmdArgs, "builtins");
    } else {
      // Let the tool chain choose which runtime library to link.
      getMachOToolChain().AddLinkRuntimeLibArgs(Args, CmdArgs,
                                                ForceLinkBuiltins);

      // No need to do anything for pthreads. Claim argument to avoid warning.
      Args.ClaimAllArgs(options::OPT_pthread);
      Args.ClaimAllArgs(options::OPT_pthreads);
    }
  }

  if (!Args.hasArg(options::OPT_nostdlib, options::OPT_nostartfiles)) {
    // endfile_spec is empty.
  }

  Args.AddAllArgs(CmdArgs, options::OPT_T_Group);
  Args.AddAllArgs(CmdArgs, options::OPT_F);

  // -iframework should be forwarded as -F.
  for (const Arg *A : Args.filtered(options::OPT_iframework))
    CmdArgs.push_back(Args.MakeArgString(std::string("-F") + A->getValue()));

  if (!Args.hasArg(options::OPT_nostdlib, options::OPT_nodefaultlibs)) {
    if (Arg *A = Args.getLastArg(options::OPT_fveclib)) {
      if (A->getValue() == StringRef("Accelerate")) {
        CmdArgs.push_back("-framework");
        CmdArgs.push_back("Accelerate");
      }
    }
  }

  ResponseFileSupport ResponseSupport;
  if (Version[0] >= 705 || LinkerIsLLDDarwinNew) {
    ResponseSupport = ResponseFileSupport::AtFileUTF8();
  } else {
    // For older versions of the linker, use the legacy filelist method instead.
    ResponseSupport = {ResponseFileSupport::RF_FileList, llvm::sys::WEM_UTF8,
                       "-filelist"};
  }

  std::unique_ptr<Command> Cmd = std::make_unique<Command>(
      JA, *this, ResponseSupport, Exec, CmdArgs, Inputs, Output);
  Cmd->setInputFileList(std::move(InputFileList));
  C.addCommand(std::move(Cmd));
}

void darwin::StaticLibTool::ConstructJob(Compilation &C, const JobAction &JA,
                                         const InputInfo &Output,
                                         const InputInfoList &Inputs,
                                         const ArgList &Args,
                                         const char *LinkingOutput) const {
  const Driver &D = getToolChain().getDriver();

  // Silence warning for "clang -g foo.o -o foo"
  Args.ClaimAllArgs(options::OPT_g_Group);
  // and "clang -emit-llvm foo.o -o foo"
  Args.ClaimAllArgs(options::OPT_emit_llvm);
  // and for "clang -w foo.o -o foo". Other warning options are already
  // handled somewhere else.
  Args.ClaimAllArgs(options::OPT_w);
  // Silence warnings when linking C code with a C++ '-stdlib' argument.
  Args.ClaimAllArgs(options::OPT_stdlib_EQ);

  // libtool <options> <output_file> <input_files>
  ArgStringList CmdArgs;
  // Create and insert file members with a deterministic index.
  CmdArgs.push_back("-static");
  CmdArgs.push_back("-D");
  CmdArgs.push_back("-no_warning_for_no_symbols");
  CmdArgs.push_back("-o");
  CmdArgs.push_back(Output.getFilename());

  for (const auto &II : Inputs) {
    if (II.isFilename()) {
      CmdArgs.push_back(II.getFilename());
    }
  }

  // Delete old output archive file if it already exists before generating a new
  // archive file.
  const auto *OutputFileName = Output.getFilename();
  if (Output.isFilename() && llvm::sys::fs::exists(OutputFileName)) {
    if (std::error_code EC = llvm::sys::fs::remove(OutputFileName)) {
      D.Diag(diag::err_drv_unable_to_remove_file) << EC.message();
      return;
    }
  }

  const char *Exec = Args.MakeArgString(getToolChain().GetStaticLibToolPath());
  C.addCommand(std::make_unique<Command>(JA, *this,
                                         ResponseFileSupport::AtFileUTF8(),
                                         Exec, CmdArgs, Inputs, Output));
}

void darwin::Lipo::ConstructJob(Compilation &C, const JobAction &JA,
                                const InputInfo &Output,
                                const InputInfoList &Inputs,
                                const ArgList &Args,
                                const char *LinkingOutput) const {
  ArgStringList CmdArgs;

  CmdArgs.push_back("-create");
  assert(Output.isFilename() && "Unexpected lipo output.");

  CmdArgs.push_back("-output");
  CmdArgs.push_back(Output.getFilename());

  for (const auto &II : Inputs) {
    assert(II.isFilename() && "Unexpected lipo input.");
    CmdArgs.push_back(II.getFilename());
  }

  const char *Exec = Args.MakeArgString(getToolChain().GetProgramPath("lipo"));
  C.addCommand(std::make_unique<Command>(JA, *this, ResponseFileSupport::None(),
                                         Exec, CmdArgs, Inputs, Output));
}

void darwin::Dsymutil::ConstructJob(Compilation &C, const JobAction &JA,
                                    const InputInfo &Output,
                                    const InputInfoList &Inputs,
                                    const ArgList &Args,
                                    const char *LinkingOutput) const {
  ArgStringList CmdArgs;

  CmdArgs.push_back("-o");
  CmdArgs.push_back(Output.getFilename());

  assert(Inputs.size() == 1 && "Unable to handle multiple inputs.");
  const InputInfo &Input = Inputs[0];
  assert(Input.isFilename() && "Unexpected dsymutil input.");
  CmdArgs.push_back(Input.getFilename());

  const char *Exec =
      Args.MakeArgString(getToolChain().GetProgramPath("dsymutil"));
  C.addCommand(std::make_unique<Command>(JA, *this, ResponseFileSupport::None(),
                                         Exec, CmdArgs, Inputs, Output));
}

void darwin::VerifyDebug::ConstructJob(Compilation &C, const JobAction &JA,
                                       const InputInfo &Output,
                                       const InputInfoList &Inputs,
                                       const ArgList &Args,
                                       const char *LinkingOutput) const {
  ArgStringList CmdArgs;
  CmdArgs.push_back("--verify");
  CmdArgs.push_back("--debug-info");
  CmdArgs.push_back("--eh-frame");
  CmdArgs.push_back("--quiet");

  assert(Inputs.size() == 1 && "Unable to handle multiple inputs.");
  const InputInfo &Input = Inputs[0];
  assert(Input.isFilename() && "Unexpected verify input");

  // Grabbing the output of the earlier dsymutil run.
  CmdArgs.push_back(Input.getFilename());

  const char *Exec =
      Args.MakeArgString(getToolChain().GetProgramPath("dwarfdump"));
  C.addCommand(std::make_unique<Command>(JA, *this, ResponseFileSupport::None(),
                                         Exec, CmdArgs, Inputs, Output));
}

MachO::MachO(const Driver &D, const llvm::Triple &Triple, const ArgList &Args)
    : ToolChain(D, Triple, Args) {
  // We expect 'as', 'ld', etc. to be adjacent to our install dir.
  getProgramPaths().push_back(getDriver().getInstalledDir());
  if (getDriver().getInstalledDir() != getDriver().Dir)
    getProgramPaths().push_back(getDriver().Dir);
}

/// Darwin - Darwin tool chain for i386 and x86_64.
Darwin::Darwin(const Driver &D, const llvm::Triple &Triple, const ArgList &Args)
    : MachO(D, Triple, Args), TargetInitialized(false),
      CudaInstallation(D, Triple, Args), RocmInstallation(D, Triple, Args) {}

types::ID MachO::LookupTypeForExtension(StringRef Ext) const {
  types::ID Ty = ToolChain::LookupTypeForExtension(Ext);

  // Darwin always preprocesses assembly files (unless -x is used explicitly).
  if (Ty == types::TY_PP_Asm)
    return types::TY_Asm;

  return Ty;
}

bool MachO::HasNativeLLVMSupport() const { return true; }

ToolChain::CXXStdlibType Darwin::GetDefaultCXXStdlibType() const {
  // Default to use libc++ on OS X 10.9+ and iOS 7+.
  if ((isTargetMacOSBased() && !isMacosxVersionLT(10, 9)) ||
      (isTargetIOSBased() && !isIPhoneOSVersionLT(7, 0)) ||
      isTargetWatchOSBased())
    return ToolChain::CST_Libcxx;

  return ToolChain::CST_Libstdcxx;
}

/// Darwin provides an ARC runtime starting in MacOS X 10.7 and iOS 5.0.
ObjCRuntime Darwin::getDefaultObjCRuntime(bool isNonFragile) const {
  if (isTargetWatchOSBased())
    return ObjCRuntime(ObjCRuntime::WatchOS, TargetVersion);
  if (isTargetIOSBased())
    return ObjCRuntime(ObjCRuntime::iOS, TargetVersion);
  if (isNonFragile)
    return ObjCRuntime(ObjCRuntime::MacOSX, TargetVersion);
  return ObjCRuntime(ObjCRuntime::FragileMacOSX, TargetVersion);
}

/// Darwin provides a blocks runtime starting in MacOS X 10.6 and iOS 3.2.
bool Darwin::hasBlocksRuntime() const {
  if (isTargetWatchOSBased())
    return true;
  else if (isTargetIOSBased())
    return !isIPhoneOSVersionLT(3, 2);
  else {
    assert(isTargetMacOSBased() && "unexpected darwin target");
    return !isMacosxVersionLT(10, 6);
  }
}

void Darwin::AddCudaIncludeArgs(const ArgList &DriverArgs,
                                ArgStringList &CC1Args) const {
  CudaInstallation.AddCudaIncludeArgs(DriverArgs, CC1Args);
}

void Darwin::AddHIPIncludeArgs(const ArgList &DriverArgs,
                               ArgStringList &CC1Args) const {
  RocmInstallation.AddHIPIncludeArgs(DriverArgs, CC1Args);
}

// This is just a MachO name translation routine and there's no
// way to join this into ARMTargetParser without breaking all
// other assumptions. Maybe MachO should consider standardising
// their nomenclature.
static const char *ArmMachOArchName(StringRef Arch) {
  return llvm::StringSwitch<const char *>(Arch)
      .Case("armv6k", "armv6")
      .Case("armv6m", "armv6m")
      .Case("armv5tej", "armv5")
      .Case("xscale", "xscale")
      .Case("armv4t", "armv4t")
      .Case("armv7", "armv7")
      .Cases("armv7a", "armv7-a", "armv7")
      .Cases("armv7r", "armv7-r", "armv7")
      .Cases("armv7em", "armv7e-m", "armv7em")
      .Cases("armv7k", "armv7-k", "armv7k")
      .Cases("armv7m", "armv7-m", "armv7m")
      .Cases("armv7s", "armv7-s", "armv7s")
      .Default(nullptr);
}

static const char *ArmMachOArchNameCPU(StringRef CPU) {
  llvm::ARM::ArchKind ArchKind = llvm::ARM::parseCPUArch(CPU);
  if (ArchKind == llvm::ARM::ArchKind::INVALID)
    return nullptr;
  StringRef Arch = llvm::ARM::getArchName(ArchKind);

  // FIXME: Make sure this MachO triple mangling is really necessary.
  // ARMv5* normalises to ARMv5.
  if (Arch.startswith("armv5"))
    Arch = Arch.substr(0, 5);
  // ARMv6*, except ARMv6M, normalises to ARMv6.
  else if (Arch.startswith("armv6") && !Arch.endswith("6m"))
    Arch = Arch.substr(0, 5);
  // ARMv7A normalises to ARMv7.
  else if (Arch.endswith("v7a"))
    Arch = Arch.substr(0, 5);
  return Arch.data();
}

StringRef MachO::getMachOArchName(const ArgList &Args) const {
  switch (getTriple().getArch()) {
  default:
    return getDefaultUniversalArchName();

  case llvm::Triple::aarch64_32:
    return "arm64_32";

  case llvm::Triple::aarch64: {
    if (getTriple().isArm64e())
      return "arm64e";
    return "arm64";
  }

  case llvm::Triple::thumb:
  case llvm::Triple::arm:
    if (const Arg *A = Args.getLastArg(clang::driver::options::OPT_march_EQ))
      if (const char *Arch = ArmMachOArchName(A->getValue()))
        return Arch;

    if (const Arg *A = Args.getLastArg(options::OPT_mcpu_EQ))
      if (const char *Arch = ArmMachOArchNameCPU(A->getValue()))
        return Arch;

    return "arm";
  }
}

Darwin::~Darwin() {}

MachO::~MachO() {}

std::string Darwin::ComputeEffectiveClangTriple(const ArgList &Args,
                                                types::ID InputType) const {
  llvm::Triple Triple(ComputeLLVMTriple(Args, InputType));

  // If the target isn't initialized (e.g., an unknown Darwin platform, return
  // the default triple).
  if (!isTargetInitialized())
    return Triple.getTriple();

  SmallString<16> Str;
  if (isTargetWatchOSBased())
    Str += "watchos";
  else if (isTargetTvOSBased())
    Str += "tvos";
  else if (isTargetIOSBased() || isTargetMacCatalyst())
    Str += "ios";
  else
    Str += "macosx";
  Str += getTripleTargetVersion().getAsString();
  Triple.setOSName(Str);

  return Triple.getTriple();
}

Tool *MachO::getTool(Action::ActionClass AC) const {
  switch (AC) {
  case Action::LipoJobClass:
    if (!Lipo)
      Lipo.reset(new tools::darwin::Lipo(*this));
    return Lipo.get();
  case Action::DsymutilJobClass:
    if (!Dsymutil)
      Dsymutil.reset(new tools::darwin::Dsymutil(*this));
    return Dsymutil.get();
  case Action::VerifyDebugInfoJobClass:
    if (!VerifyDebug)
      VerifyDebug.reset(new tools::darwin::VerifyDebug(*this));
    return VerifyDebug.get();
  default:
    return ToolChain::getTool(AC);
  }
}

Tool *MachO::buildLinker() const { return new tools::darwin::Linker(*this); }

Tool *MachO::buildStaticLibTool() const {
  return new tools::darwin::StaticLibTool(*this);
}

Tool *MachO::buildAssembler() const {
  return new tools::darwin::Assembler(*this);
}

DarwinClang::DarwinClang(const Driver &D, const llvm::Triple &Triple,
                         const ArgList &Args)
    : Darwin(D, Triple, Args) {}

void DarwinClang::addClangWarningOptions(ArgStringList &CC1Args) const {
  // Always error about undefined 'TARGET_OS_*' macros.
  CC1Args.push_back("-Wundef-prefix=TARGET_OS_");
  CC1Args.push_back("-Werror=undef-prefix");

  // For modern targets, promote certain warnings to errors.
  if (isTargetWatchOSBased() || getTriple().isArch64Bit()) {
    // Always enable -Wdeprecated-objc-isa-usage and promote it
    // to an error.
    CC1Args.push_back("-Wdeprecated-objc-isa-usage");
    CC1Args.push_back("-Werror=deprecated-objc-isa-usage");

    // For iOS and watchOS, also error about implicit function declarations,
    // as that can impact calling conventions.
    if (!isTargetMacOS())
      CC1Args.push_back("-Werror=implicit-function-declaration");
  }
}

/// Take a path that speculatively points into Xcode and return the
/// `XCODE/Contents/Developer` path if it is an Xcode path, or an empty path
/// otherwise.
static StringRef getXcodeDeveloperPath(StringRef PathIntoXcode) {
  static constexpr llvm::StringLiteral XcodeAppSuffix(
      ".app/Contents/Developer");
  size_t Index = PathIntoXcode.find(XcodeAppSuffix);
  if (Index == StringRef::npos)
    return "";
  return PathIntoXcode.take_front(Index + XcodeAppSuffix.size());
}

void DarwinClang::AddLinkARCArgs(const ArgList &Args,
                                 ArgStringList &CmdArgs) const {
  // Avoid linking compatibility stubs on i386 mac.
  if (isTargetMacOSBased() && getArch() == llvm::Triple::x86)
    return;
  if (isTargetAppleSiliconMac())
    return;
  // ARC runtime is supported everywhere on arm64e.
  if (getTriple().isArm64e())
    return;

  ObjCRuntime runtime = getDefaultObjCRuntime(/*nonfragile*/ true);

  if ((runtime.hasNativeARC() || !isObjCAutoRefCount(Args)) &&
      runtime.hasSubscripting())
    return;

  SmallString<128> P(getDriver().ClangExecutable);
  llvm::sys::path::remove_filename(P); // 'clang'
  llvm::sys::path::remove_filename(P); // 'bin'

  // 'libarclite' usually lives in the same toolchain as 'clang'. However, the
  // Swift open source toolchains for macOS distribute Clang without libarclite.
  // In that case, to allow the linker to find 'libarclite', we point to the
  // 'libarclite' in the XcodeDefault toolchain instead.
  if (getXcodeDeveloperPath(P).empty()) {
    if (const Arg *A = Args.getLastArg(options::OPT_isysroot)) {
      // Try to infer the path to 'libarclite' in the toolchain from the
      // specified SDK path.
      StringRef XcodePathForSDK = getXcodeDeveloperPath(A->getValue());
      if (!XcodePathForSDK.empty()) {
        P = XcodePathForSDK;
        llvm::sys::path::append(P, "Toolchains/XcodeDefault.xctoolchain/usr");
      }
    }
  }

  CmdArgs.push_back("-force_load");
  llvm::sys::path::append(P, "lib", "arc", "libarclite_");
  // Mash in the platform.
  if (isTargetWatchOSSimulator())
    P += "watchsimulator";
  else if (isTargetWatchOS())
    P += "watchos";
  else if (isTargetTvOSSimulator())
    P += "appletvsimulator";
  else if (isTargetTvOS())
    P += "appletvos";
  else if (isTargetIOSSimulator())
    P += "iphonesimulator";
  else if (isTargetIPhoneOS())
    P += "iphoneos";
  else
    P += "macosx";
  P += ".a";

  CmdArgs.push_back(Args.MakeArgString(P));
}

unsigned DarwinClang::GetDefaultDwarfVersion() const {
  // Default to use DWARF 2 on OS X 10.10 / iOS 8 and lower.
  if ((isTargetMacOSBased() && isMacosxVersionLT(10, 11)) ||
      (isTargetIOSBased() && isIPhoneOSVersionLT(9)))
    return 2;
  return 4;
}

void MachO::AddLinkRuntimeLib(const ArgList &Args, ArgStringList &CmdArgs,
                              StringRef Component, RuntimeLinkOptions Opts,
                              bool IsShared) const {
  SmallString<64> DarwinLibName = StringRef("libclang_rt.");
  // an Darwin the builtins compomnent is not in the library name
  if (Component != "builtins") {
    DarwinLibName += Component;
    if (!(Opts & RLO_IsEmbedded))
      DarwinLibName += "_";
  }

  DarwinLibName += getOSLibraryNameSuffix();
  DarwinLibName += IsShared ? "_dynamic.dylib" : ".a";
  SmallString<128> Dir(getDriver().ResourceDir);
  llvm::sys::path::append(
      Dir, "lib", (Opts & RLO_IsEmbedded) ? "macho_embedded" : "darwin");

  SmallString<128> P(Dir);
  llvm::sys::path::append(P, DarwinLibName);

  // For now, allow missing resource libraries to support developers who may
  // not have compiler-rt checked out or integrated into their build (unless
  // we explicitly force linking with this library).
  if ((Opts & RLO_AlwaysLink) || getVFS().exists(P)) {
    const char *LibArg = Args.MakeArgString(P);
    CmdArgs.push_back(LibArg);
  }

  // Adding the rpaths might negatively interact when other rpaths are involved,
  // so we should make sure we add the rpaths last, after all user-specified
  // rpaths. This is currently true from this place, but we need to be
  // careful if this function is ever called before user's rpaths are emitted.
  if (Opts & RLO_AddRPath) {
    assert(DarwinLibName.endswith(".dylib") && "must be a dynamic library");

    // Add @executable_path to rpath to support having the dylib copied with
    // the executable.
    CmdArgs.push_back("-rpath");
    CmdArgs.push_back("@executable_path");

    // Add the path to the resource dir to rpath to support using the dylib
    // from the default location without copying.
    CmdArgs.push_back("-rpath");
    CmdArgs.push_back(Args.MakeArgString(Dir));
  }
}

StringRef Darwin::getPlatformFamily() const {
  switch (TargetPlatform) {
    case DarwinPlatformKind::MacOS:
      return "MacOSX";
    case DarwinPlatformKind::IPhoneOS:
      if (TargetEnvironment == MacCatalyst)
        return "MacOSX";
      return "iPhone";
    case DarwinPlatformKind::TvOS:
      return "AppleTV";
    case DarwinPlatformKind::WatchOS:
      return "Watch";
  }
  llvm_unreachable("Unsupported platform");
}

StringRef Darwin::getSDKName(StringRef isysroot) {
  // Assume SDK has path: SOME_PATH/SDKs/PlatformXX.YY.sdk
  auto BeginSDK = llvm::sys::path::rbegin(isysroot);
  auto EndSDK = llvm::sys::path::rend(isysroot);
  for (auto IT = BeginSDK; IT != EndSDK; ++IT) {
    StringRef SDK = *IT;
    if (SDK.endswith(".sdk"))
      return SDK.slice(0, SDK.size() - 4);
  }
  return "";
}

StringRef Darwin::getOSLibraryNameSuffix(bool IgnoreSim) const {
  switch (TargetPlatform) {
  case DarwinPlatformKind::MacOS:
    return "osx";
  case DarwinPlatformKind::IPhoneOS:
    if (TargetEnvironment == MacCatalyst)
      return "osx";
    return TargetEnvironment == NativeEnvironment || IgnoreSim ? "ios"
                                                               : "iossim";
  case DarwinPlatformKind::TvOS:
    return TargetEnvironment == NativeEnvironment || IgnoreSim ? "tvos"
                                                               : "tvossim";
  case DarwinPlatformKind::WatchOS:
    return TargetEnvironment == NativeEnvironment || IgnoreSim ? "watchos"
                                                               : "watchossim";
  }
  llvm_unreachable("Unsupported platform");
}

/// Check if the link command contains a symbol export directive.
static bool hasExportSymbolDirective(const ArgList &Args) {
  for (Arg *A : Args) {
    if (A->getOption().matches(options::OPT_exported__symbols__list))
      return true;
    if (!A->getOption().matches(options::OPT_Wl_COMMA) &&
        !A->getOption().matches(options::OPT_Xlinker))
      continue;
    if (A->containsValue("-exported_symbols_list") ||
        A->containsValue("-exported_symbol"))
      return true;
  }
  return false;
}

/// Add an export directive for \p Symbol to the link command.
static void addExportedSymbol(ArgStringList &CmdArgs, const char *Symbol) {
  CmdArgs.push_back("-exported_symbol");
  CmdArgs.push_back(Symbol);
}

/// Add a sectalign directive for \p Segment and \p Section to the maximum
/// expected page size for Darwin.
///
/// On iPhone 6+ the max supported page size is 16K. On macOS, the max is 4K.
/// Use a common alignment constant (16K) for now, and reduce the alignment on
/// macOS if it proves important.
static void addSectalignToPage(const ArgList &Args, ArgStringList &CmdArgs,
                               StringRef Segment, StringRef Section) {
  for (const char *A : {"-sectalign", Args.MakeArgString(Segment),
                        Args.MakeArgString(Section), "0x4000"})
    CmdArgs.push_back(A);
}

void Darwin::addProfileRTLibs(const ArgList &Args,
                              ArgStringList &CmdArgs) const {
  if (!needsProfileRT(Args) && !needsGCovInstrumentation(Args))
    return;

  AddLinkRuntimeLib(Args, CmdArgs, "profile",
                    RuntimeLinkOptions(RLO_AlwaysLink));

  bool ForGCOV = needsGCovInstrumentation(Args);

  // If we have a symbol export directive and we're linking in the profile
  // runtime, automatically export symbols necessary to implement some of the
  // runtime's functionality.
  if (hasExportSymbolDirective(Args)) {
    if (ForGCOV) {
      addExportedSymbol(CmdArgs, "___gcov_dump");
      addExportedSymbol(CmdArgs, "___gcov_reset");
      addExportedSymbol(CmdArgs, "_writeout_fn_list");
      addExportedSymbol(CmdArgs, "_reset_fn_list");
    } else {
      addExportedSymbol(CmdArgs, "___llvm_profile_filename");
      addExportedSymbol(CmdArgs, "___llvm_profile_raw_version");
    }
    addExportedSymbol(CmdArgs, "_lprofDirMode");
  }

  // Align __llvm_prf_{cnts,data} sections to the maximum expected page
  // alignment. This allows profile counters to be mmap()'d to disk. Note that
  // it's not enough to just page-align __llvm_prf_cnts: the following section
  // must also be page-aligned so that its data is not clobbered by mmap().
  //
  // The section alignment is only needed when continuous profile sync is
  // enabled, but this is expected to be the default in Xcode. Specifying the
  // extra alignment also allows the same binary to be used with/without sync
  // enabled.
  if (!ForGCOV) {
    for (auto IPSK : {llvm::IPSK_cnts, llvm::IPSK_data}) {
      addSectalignToPage(
          Args, CmdArgs, "__DATA",
          llvm::getInstrProfSectionName(IPSK, llvm::Triple::MachO,
                                        /*AddSegmentInfo=*/false));
    }
  }
}

void DarwinClang::AddLinkSanitizerLibArgs(const ArgList &Args,
                                          ArgStringList &CmdArgs,
                                          StringRef Sanitizer,
                                          bool Shared) const {
  auto RLO = RuntimeLinkOptions(RLO_AlwaysLink | (Shared ? RLO_AddRPath : 0U));
  AddLinkRuntimeLib(Args, CmdArgs, Sanitizer, RLO, Shared);
}

ToolChain::RuntimeLibType DarwinClang::GetRuntimeLibType(
    const ArgList &Args) const {
  if (Arg* A = Args.getLastArg(options::OPT_rtlib_EQ)) {
    StringRef Value = A->getValue();
    if (Value != "compiler-rt")
      getDriver().Diag(clang::diag::err_drv_unsupported_rtlib_for_platform)
          << Value << "darwin";
  }

  return ToolChain::RLT_CompilerRT;
}

void DarwinClang::AddLinkRuntimeLibArgs(const ArgList &Args,
                                        ArgStringList &CmdArgs,
                                        bool ForceLinkBuiltinRT) const {
  // Call once to ensure diagnostic is printed if wrong value was specified
  GetRuntimeLibType(Args);

  // Darwin doesn't support real static executables, don't link any runtime
  // libraries with -static.
  if (Args.hasArg(options::OPT_static) ||
      Args.hasArg(options::OPT_fapple_kext) ||
      Args.hasArg(options::OPT_mkernel)) {
    if (ForceLinkBuiltinRT)
      AddLinkRuntimeLib(Args, CmdArgs, "builtins");
    return;
  }

  // Reject -static-libgcc for now, we can deal with this when and if someone
  // cares. This is useful in situations where someone wants to statically link
  // something like libstdc++, and needs its runtime support routines.
  if (const Arg *A = Args.getLastArg(options::OPT_static_libgcc)) {
    getDriver().Diag(diag::err_drv_unsupported_opt) << A->getAsString(Args);
    return;
  }

  const SanitizerArgs &Sanitize = getSanitizerArgs(Args);
  if (Sanitize.needsAsanRt())
    AddLinkSanitizerLibArgs(Args, CmdArgs, "asan");
  if (Sanitize.needsLsanRt())
    AddLinkSanitizerLibArgs(Args, CmdArgs, "lsan");
  if (Sanitize.needsUbsanRt())
    AddLinkSanitizerLibArgs(Args, CmdArgs,
                            Sanitize.requiresMinimalRuntime() ? "ubsan_minimal"
                                                              : "ubsan",
                            Sanitize.needsSharedRt());
  if (Sanitize.needsTsanRt())
    AddLinkSanitizerLibArgs(Args, CmdArgs, "tsan");
  if (Sanitize.needsFuzzer() && !Args.hasArg(options::OPT_dynamiclib)) {
    AddLinkSanitizerLibArgs(Args, CmdArgs, "fuzzer", /*shared=*/false);

    // Libfuzzer is written in C++ and requires libcxx.
    AddCXXStdlibLibArgs(Args, CmdArgs);
  }
  if (Sanitize.needsStatsRt()) {
    AddLinkRuntimeLib(Args, CmdArgs, "stats_client", RLO_AlwaysLink);
    AddLinkSanitizerLibArgs(Args, CmdArgs, "stats");
  }

  const XRayArgs &XRay = getXRayArgs();
  if (XRay.needsXRayRt()) {
    AddLinkRuntimeLib(Args, CmdArgs, "xray");
    AddLinkRuntimeLib(Args, CmdArgs, "xray-basic");
    AddLinkRuntimeLib(Args, CmdArgs, "xray-fdr");
  }

  // Otherwise link libSystem, then the dynamic runtime library, and finally any
  // target specific static runtime library.
  CmdArgs.push_back("-lSystem");

  // Select the dynamic runtime library and the target specific static library.
  if (isTargetIOSBased()) {
    // If we are compiling as iOS / simulator, don't attempt to link libgcc_s.1,
    // it never went into the SDK.
    // Linking against libgcc_s.1 isn't needed for iOS 5.0+
    if (isIPhoneOSVersionLT(5, 0) && !isTargetIOSSimulator() &&
        getTriple().getArch() != llvm::Triple::aarch64)
      CmdArgs.push_back("-lgcc_s.1");
  }
  AddLinkRuntimeLib(Args, CmdArgs, "builtins");
}

/// Returns the most appropriate macOS target version for the current process.
///
/// If the macOS SDK version is the same or earlier than the system version,
/// then the SDK version is returned. Otherwise the system version is returned.
static std::string getSystemOrSDKMacOSVersion(StringRef MacOSSDKVersion) {
  unsigned Major, Minor, Micro;
  llvm::Triple SystemTriple(llvm::sys::getProcessTriple());
  if (!SystemTriple.isMacOSX())
    return std::string(MacOSSDKVersion);
  VersionTuple SystemVersion;
  SystemTriple.getMacOSXVersion(SystemVersion);
  bool HadExtra;
  if (!Driver::GetReleaseVersion(MacOSSDKVersion, Major, Minor, Micro,
                                 HadExtra))
    return std::string(MacOSSDKVersion);
  VersionTuple SDKVersion(Major, Minor, Micro);
  if (SDKVersion > SystemVersion)
    return SystemVersion.getAsString();
  return std::string(MacOSSDKVersion);
}

namespace {

/// The Darwin OS that was selected or inferred from arguments / environment.
struct DarwinPlatform {
  enum SourceKind {
    /// The OS was specified using the -target argument.
    TargetArg,
    /// The OS was specified using the -mtargetos= argument.
    MTargetOSArg,
    /// The OS was specified using the -m<os>-version-min argument.
    OSVersionArg,
    /// The OS was specified using the OS_DEPLOYMENT_TARGET environment.
    DeploymentTargetEnv,
    /// The OS was inferred from the SDK.
    InferredFromSDK,
    /// The OS was inferred from the -arch.
    InferredFromArch
  };

  using DarwinPlatformKind = Darwin::DarwinPlatformKind;
  using DarwinEnvironmentKind = Darwin::DarwinEnvironmentKind;

  DarwinPlatformKind getPlatform() const { return Platform; }

  DarwinEnvironmentKind getEnvironment() const { return Environment; }

  void setEnvironment(DarwinEnvironmentKind Kind) {
    Environment = Kind;
    InferSimulatorFromArch = false;
  }

  StringRef getOSVersion() const {
    if (Kind == OSVersionArg)
      return Argument->getValue();
    return OSVersion;
  }

  void setOSVersion(StringRef S) {
    assert(Kind == TargetArg && "Unexpected kind!");
    OSVersion = std::string(S);
  }

  bool hasOSVersion() const { return HasOSVersion; }

  VersionTuple getNativeTargetVersion() const {
    assert(Environment == DarwinEnvironmentKind::MacCatalyst &&
           "native target version is specified only for Mac Catalyst");
    return NativeTargetVersion;
  }

  /// Returns true if the target OS was explicitly specified.
  bool isExplicitlySpecified() const { return Kind <= DeploymentTargetEnv; }

  /// Returns true if the simulator environment can be inferred from the arch.
  bool canInferSimulatorFromArch() const { return InferSimulatorFromArch; }

  /// Adds the -m<os>-version-min argument to the compiler invocation.
  void addOSVersionMinArgument(DerivedArgList &Args, const OptTable &Opts) {
    if (Argument)
      return;
    assert(Kind != TargetArg && Kind != MTargetOSArg && Kind != OSVersionArg &&
           "Invalid kind");
    options::ID Opt;
    switch (Platform) {
    case DarwinPlatformKind::MacOS:
      Opt = options::OPT_mmacosx_version_min_EQ;
      break;
    case DarwinPlatformKind::IPhoneOS:
      Opt = options::OPT_miphoneos_version_min_EQ;
      break;
    case DarwinPlatformKind::TvOS:
      Opt = options::OPT_mtvos_version_min_EQ;
      break;
    case DarwinPlatformKind::WatchOS:
      Opt = options::OPT_mwatchos_version_min_EQ;
      break;
    }
    Argument = Args.MakeJoinedArg(nullptr, Opts.getOption(Opt), OSVersion);
    Args.append(Argument);
  }

  /// Returns the OS version with the argument / environment variable that
  /// specified it.
  std::string getAsString(DerivedArgList &Args, const OptTable &Opts) {
    switch (Kind) {
    case TargetArg:
    case MTargetOSArg:
    case OSVersionArg:
    case InferredFromSDK:
    case InferredFromArch:
      assert(Argument && "OS version argument not yet inferred");
      return Argument->getAsString(Args);
    case DeploymentTargetEnv:
      return (llvm::Twine(EnvVarName) + "=" + OSVersion).str();
    }
    llvm_unreachable("Unsupported Darwin Source Kind");
  }

  void setEnvironment(llvm::Triple::EnvironmentType EnvType,
                      const VersionTuple &OSVersion,
                      const Optional<DarwinSDKInfo> &SDKInfo) {
    switch (EnvType) {
    case llvm::Triple::Simulator:
      Environment = DarwinEnvironmentKind::Simulator;
      break;
    case llvm::Triple::MacABI: {
      Environment = DarwinEnvironmentKind::MacCatalyst;
      // The minimum native macOS target for MacCatalyst is macOS 10.15.
      NativeTargetVersion = VersionTuple(10, 15);
      if (HasOSVersion && SDKInfo) {
        if (const auto *MacCatalystToMacOSMapping = SDKInfo->getVersionMapping(
                DarwinSDKInfo::OSEnvPair::macCatalystToMacOSPair())) {
          if (auto MacOSVersion = MacCatalystToMacOSMapping->map(
                  OSVersion, NativeTargetVersion, None)) {
            NativeTargetVersion = *MacOSVersion;
          }
        }
      }
      break;
    }
    default:
      break;
    }
  }

  static DarwinPlatform
  createFromTarget(const llvm::Triple &TT, StringRef OSVersion, Arg *A,
                   const Optional<DarwinSDKInfo> &SDKInfo) {
    DarwinPlatform Result(TargetArg, getPlatformFromOS(TT.getOS()), OSVersion,
                          A);
    VersionTuple OsVersion = TT.getOSVersion();
    if (OsVersion.getMajor() == 0)
      Result.HasOSVersion = false;
    Result.setEnvironment(TT.getEnvironment(), OsVersion, SDKInfo);
    return Result;
  }
  static DarwinPlatform
  createFromMTargetOS(llvm::Triple::OSType OS, VersionTuple OSVersion,
                      llvm::Triple::EnvironmentType Environment, Arg *A,
                      const Optional<DarwinSDKInfo> &SDKInfo) {
    DarwinPlatform Result(MTargetOSArg, getPlatformFromOS(OS),
                          OSVersion.getAsString(), A);
    Result.InferSimulatorFromArch = false;
    Result.setEnvironment(Environment, OSVersion, SDKInfo);
    return Result;
  }
  static DarwinPlatform createOSVersionArg(DarwinPlatformKind Platform,
                                           Arg *A) {
    return DarwinPlatform(OSVersionArg, Platform, A);
  }
  static DarwinPlatform createDeploymentTargetEnv(DarwinPlatformKind Platform,
                                                  StringRef EnvVarName,
                                                  StringRef Value) {
    DarwinPlatform Result(DeploymentTargetEnv, Platform, Value);
    Result.EnvVarName = EnvVarName;
    return Result;
  }
  static DarwinPlatform createFromSDK(DarwinPlatformKind Platform,
                                      StringRef Value,
                                      bool IsSimulator = false) {
    DarwinPlatform Result(InferredFromSDK, Platform, Value);
    if (IsSimulator)
      Result.Environment = DarwinEnvironmentKind::Simulator;
    Result.InferSimulatorFromArch = false;
    return Result;
  }
  static DarwinPlatform createFromArch(llvm::Triple::OSType OS,
                                       StringRef Value) {
    return DarwinPlatform(InferredFromArch, getPlatformFromOS(OS), Value);
  }

  /// Constructs an inferred SDKInfo value based on the version inferred from
  /// the SDK path itself. Only works for values that were created by inferring
  /// the platform from the SDKPath.
  DarwinSDKInfo inferSDKInfo() {
    assert(Kind == InferredFromSDK && "can infer SDK info only");
    llvm::VersionTuple Version;
    bool IsValid = !Version.tryParse(OSVersion);
    (void)IsValid;
    assert(IsValid && "invalid SDK version");
    return DarwinSDKInfo(
        Version,
        /*MaximumDeploymentTarget=*/VersionTuple(Version.getMajor(), 0, 99));
  }

private:
  DarwinPlatform(SourceKind Kind, DarwinPlatformKind Platform, Arg *Argument)
      : Kind(Kind), Platform(Platform), Argument(Argument) {}
  DarwinPlatform(SourceKind Kind, DarwinPlatformKind Platform, StringRef Value,
                 Arg *Argument = nullptr)
      : Kind(Kind), Platform(Platform), OSVersion(Value), Argument(Argument) {}

  static DarwinPlatformKind getPlatformFromOS(llvm::Triple::OSType OS) {
    switch (OS) {
    case llvm::Triple::Darwin:
    case llvm::Triple::MacOSX:
      return DarwinPlatformKind::MacOS;
    case llvm::Triple::IOS:
      return DarwinPlatformKind::IPhoneOS;
    case llvm::Triple::TvOS:
      return DarwinPlatformKind::TvOS;
    case llvm::Triple::WatchOS:
      return DarwinPlatformKind::WatchOS;
    default:
      llvm_unreachable("Unable to infer Darwin variant");
    }
  }

  SourceKind Kind;
  DarwinPlatformKind Platform;
  DarwinEnvironmentKind Environment = DarwinEnvironmentKind::NativeEnvironment;
  VersionTuple NativeTargetVersion;
  std::string OSVersion;
  bool HasOSVersion = true, InferSimulatorFromArch = true;
  Arg *Argument;
  StringRef EnvVarName;
};

/// Returns the deployment target that's specified using the -m<os>-version-min
/// argument.
Optional<DarwinPlatform>
getDeploymentTargetFromOSVersionArg(DerivedArgList &Args,
                                    const Driver &TheDriver) {
  Arg *OSXVersion = Args.getLastArg(options::OPT_mmacosx_version_min_EQ);
  Arg *iOSVersion = Args.getLastArg(options::OPT_miphoneos_version_min_EQ,
                                    options::OPT_mios_simulator_version_min_EQ);
  Arg *TvOSVersion =
      Args.getLastArg(options::OPT_mtvos_version_min_EQ,
                      options::OPT_mtvos_simulator_version_min_EQ);
  Arg *WatchOSVersion =
      Args.getLastArg(options::OPT_mwatchos_version_min_EQ,
                      options::OPT_mwatchos_simulator_version_min_EQ);
  if (OSXVersion) {
    if (iOSVersion || TvOSVersion || WatchOSVersion) {
      TheDriver.Diag(diag::err_drv_argument_not_allowed_with)
          << OSXVersion->getAsString(Args)
          << (iOSVersion ? iOSVersion
                         : TvOSVersion ? TvOSVersion : WatchOSVersion)
                 ->getAsString(Args);
    }
    return DarwinPlatform::createOSVersionArg(Darwin::MacOS, OSXVersion);
  } else if (iOSVersion) {
    if (TvOSVersion || WatchOSVersion) {
      TheDriver.Diag(diag::err_drv_argument_not_allowed_with)
          << iOSVersion->getAsString(Args)
          << (TvOSVersion ? TvOSVersion : WatchOSVersion)->getAsString(Args);
    }
    return DarwinPlatform::createOSVersionArg(Darwin::IPhoneOS, iOSVersion);
  } else if (TvOSVersion) {
    if (WatchOSVersion) {
      TheDriver.Diag(diag::err_drv_argument_not_allowed_with)
          << TvOSVersion->getAsString(Args)
          << WatchOSVersion->getAsString(Args);
    }
    return DarwinPlatform::createOSVersionArg(Darwin::TvOS, TvOSVersion);
  } else if (WatchOSVersion)
    return DarwinPlatform::createOSVersionArg(Darwin::WatchOS, WatchOSVersion);
  return None;
}

/// Returns the deployment target that's specified using the
/// OS_DEPLOYMENT_TARGET environment variable.
Optional<DarwinPlatform>
getDeploymentTargetFromEnvironmentVariables(const Driver &TheDriver,
                                            const llvm::Triple &Triple) {
  std::string Targets[Darwin::LastDarwinPlatform + 1];
  const char *EnvVars[] = {
      "MACOSX_DEPLOYMENT_TARGET",
      "IPHONEOS_DEPLOYMENT_TARGET",
      "TVOS_DEPLOYMENT_TARGET",
      "WATCHOS_DEPLOYMENT_TARGET",
  };
  static_assert(llvm::array_lengthof(EnvVars) == Darwin::LastDarwinPlatform + 1,
                "Missing platform");
  for (const auto &I : llvm::enumerate(llvm::makeArrayRef(EnvVars))) {
    if (char *Env = ::getenv(I.value()))
      Targets[I.index()] = Env;
  }

  // Allow conflicts among OSX and iOS for historical reasons, but choose the
  // default platform.
  if (!Targets[Darwin::MacOS].empty() &&
      (!Targets[Darwin::IPhoneOS].empty() ||
       !Targets[Darwin::WatchOS].empty() || !Targets[Darwin::TvOS].empty())) {
    if (Triple.getArch() == llvm::Triple::arm ||
        Triple.getArch() == llvm::Triple::aarch64 ||
        Triple.getArch() == llvm::Triple::thumb)
      Targets[Darwin::MacOS] = "";
    else
      Targets[Darwin::IPhoneOS] = Targets[Darwin::WatchOS] =
          Targets[Darwin::TvOS] = "";
  } else {
    // Don't allow conflicts in any other platform.
    unsigned FirstTarget = llvm::array_lengthof(Targets);
    for (unsigned I = 0; I != llvm::array_lengthof(Targets); ++I) {
      if (Targets[I].empty())
        continue;
      if (FirstTarget == llvm::array_lengthof(Targets))
        FirstTarget = I;
      else
        TheDriver.Diag(diag::err_drv_conflicting_deployment_targets)
            << Targets[FirstTarget] << Targets[I];
    }
  }

  for (const auto &Target : llvm::enumerate(llvm::makeArrayRef(Targets))) {
    if (!Target.value().empty())
      return DarwinPlatform::createDeploymentTargetEnv(
          (Darwin::DarwinPlatformKind)Target.index(), EnvVars[Target.index()],
          Target.value());
  }
  return None;
}

/// Returns the SDK name without the optional prefix that ends with a '.' or an
/// empty string otherwise.
static StringRef dropSDKNamePrefix(StringRef SDKName) {
  size_t PrefixPos = SDKName.find('.');
  if (PrefixPos == StringRef::npos)
    return "";
  return SDKName.substr(PrefixPos + 1);
}

/// Tries to infer the deployment target from the SDK specified by -isysroot
/// (or SDKROOT). Uses the version specified in the SDKSettings.json file if
/// it's available.
Optional<DarwinPlatform>
inferDeploymentTargetFromSDK(DerivedArgList &Args,
                             const Optional<DarwinSDKInfo> &SDKInfo) {
  const Arg *A = Args.getLastArg(options::OPT_isysroot);
  if (!A)
    return None;
  StringRef isysroot = A->getValue();
  StringRef SDK = Darwin::getSDKName(isysroot);
  if (!SDK.size())
    return None;

  std::string Version;
  if (SDKInfo) {
    // Get the version from the SDKSettings.json if it's available.
    Version = SDKInfo->getVersion().getAsString();
  } else {
    // Slice the version number out.
    // Version number is between the first and the last number.
    size_t StartVer = SDK.find_first_of("0123456789");
    size_t EndVer = SDK.find_last_of("0123456789");
    if (StartVer != StringRef::npos && EndVer > StartVer)
      Version = std::string(SDK.slice(StartVer, EndVer + 1));
  }
  if (Version.empty())
    return None;

  auto CreatePlatformFromSDKName =
      [&](StringRef SDK) -> Optional<DarwinPlatform> {
    if (SDK.startswith("iPhoneOS") || SDK.startswith("iPhoneSimulator"))
      return DarwinPlatform::createFromSDK(
          Darwin::IPhoneOS, Version,
          /*IsSimulator=*/SDK.startswith("iPhoneSimulator"));
    else if (SDK.startswith("MacOSX"))
      return DarwinPlatform::createFromSDK(Darwin::MacOS,
                                           getSystemOrSDKMacOSVersion(Version));
    else if (SDK.startswith("WatchOS") || SDK.startswith("WatchSimulator"))
      return DarwinPlatform::createFromSDK(
          Darwin::WatchOS, Version,
          /*IsSimulator=*/SDK.startswith("WatchSimulator"));
    else if (SDK.startswith("AppleTVOS") || SDK.startswith("AppleTVSimulator"))
      return DarwinPlatform::createFromSDK(
          Darwin::TvOS, Version,
          /*IsSimulator=*/SDK.startswith("AppleTVSimulator"));
    return None;
  };
  if (auto Result = CreatePlatformFromSDKName(SDK))
    return Result;
  // The SDK can be an SDK variant with a name like `<prefix>.<platform>`.
  return CreatePlatformFromSDKName(dropSDKNamePrefix(SDK));
}

std::string getOSVersion(llvm::Triple::OSType OS, const llvm::Triple &Triple,
                         const Driver &TheDriver) {
  VersionTuple OsVersion;
  llvm::Triple SystemTriple(llvm::sys::getProcessTriple());
  switch (OS) {
  case llvm::Triple::Darwin:
  case llvm::Triple::MacOSX:
    // If there is no version specified on triple, and both host and target are
    // macos, use the host triple to infer OS version.
    if (Triple.isMacOSX() && SystemTriple.isMacOSX() &&
        !Triple.getOSMajorVersion())
      SystemTriple.getMacOSXVersion(OsVersion);
    else if (!Triple.getMacOSXVersion(OsVersion))
      TheDriver.Diag(diag::err_drv_invalid_darwin_version)
          << Triple.getOSName();
    break;
  case llvm::Triple::IOS:
    if (Triple.isMacCatalystEnvironment() && !Triple.getOSMajorVersion()) {
      OsVersion = VersionTuple(13, 1);
    } else
      OsVersion = Triple.getiOSVersion();
    break;
  case llvm::Triple::TvOS:
    OsVersion = Triple.getOSVersion();
    break;
  case llvm::Triple::WatchOS:
    OsVersion = Triple.getWatchOSVersion();
    break;
  default:
    llvm_unreachable("Unexpected OS type");
    break;
  }

  std::string OSVersion;
  llvm::raw_string_ostream(OSVersion)
      << OsVersion.getMajor() << '.' << OsVersion.getMinor().getValueOr(0)
      << '.' << OsVersion.getSubminor().getValueOr(0);
  return OSVersion;
}

/// Tries to infer the target OS from the -arch.
Optional<DarwinPlatform>
inferDeploymentTargetFromArch(DerivedArgList &Args, const Darwin &Toolchain,
                              const llvm::Triple &Triple,
                              const Driver &TheDriver) {
  llvm::Triple::OSType OSTy = llvm::Triple::UnknownOS;

  StringRef MachOArchName = Toolchain.getMachOArchName(Args);
  if (MachOArchName == "arm64" || MachOArchName == "arm64e") {
#if __arm64__
    // A clang running on an Apple Silicon mac defaults
    // to building for mac when building for arm64 rather than
    // defaulting to iOS.
    OSTy = llvm::Triple::MacOSX;
#else
    OSTy = llvm::Triple::IOS;
#endif
  } else if (MachOArchName == "armv7" || MachOArchName == "armv7s")
    OSTy = llvm::Triple::IOS;
  else if (MachOArchName == "armv7k" || MachOArchName == "arm64_32")
    OSTy = llvm::Triple::WatchOS;
  else if (MachOArchName != "armv6m" && MachOArchName != "armv7m" &&
           MachOArchName != "armv7em")
    OSTy = llvm::Triple::MacOSX;

  if (OSTy == llvm::Triple::UnknownOS)
    return None;
  return DarwinPlatform::createFromArch(OSTy,
                                        getOSVersion(OSTy, Triple, TheDriver));
}

/// Returns the deployment target that's specified using the -target option.
Optional<DarwinPlatform> getDeploymentTargetFromTargetArg(
    DerivedArgList &Args, const llvm::Triple &Triple, const Driver &TheDriver,
    const Optional<DarwinSDKInfo> &SDKInfo) {
  if (!Args.hasArg(options::OPT_target))
    return None;
  if (Triple.getOS() == llvm::Triple::Darwin ||
      Triple.getOS() == llvm::Triple::UnknownOS)
    return None;
  std::string OSVersion = getOSVersion(Triple.getOS(), Triple, TheDriver);
  return DarwinPlatform::createFromTarget(
      Triple, OSVersion, Args.getLastArg(options::OPT_target), SDKInfo);
}

/// Returns the deployment target that's specified using the -mtargetos option.
Optional<DarwinPlatform>
getDeploymentTargetFromMTargetOSArg(DerivedArgList &Args,
                                    const Driver &TheDriver,
                                    const Optional<DarwinSDKInfo> &SDKInfo) {
  auto *A = Args.getLastArg(options::OPT_mtargetos_EQ);
  if (!A)
    return None;
  llvm::Triple TT(llvm::Twine("unknown-apple-") + A->getValue());
  switch (TT.getOS()) {
  case llvm::Triple::MacOSX:
  case llvm::Triple::IOS:
  case llvm::Triple::TvOS:
  case llvm::Triple::WatchOS:
    break;
  default:
    TheDriver.Diag(diag::err_drv_invalid_os_in_arg)
        << TT.getOSName() << A->getAsString(Args);
    return None;
  }

  VersionTuple Version = TT.getOSVersion();
  if (!Version.getMajor()) {
    TheDriver.Diag(diag::err_drv_invalid_version_number)
        << A->getAsString(Args);
    return None;
  }
  return DarwinPlatform::createFromMTargetOS(TT.getOS(), Version,
                                             TT.getEnvironment(), A, SDKInfo);
}

Optional<DarwinSDKInfo> parseSDKSettings(llvm::vfs::FileSystem &VFS,
                                         const ArgList &Args,
                                         const Driver &TheDriver) {
  const Arg *A = Args.getLastArg(options::OPT_isysroot);
  if (!A)
    return None;
  StringRef isysroot = A->getValue();
  auto SDKInfoOrErr = parseDarwinSDKInfo(VFS, isysroot);
  if (!SDKInfoOrErr) {
    llvm::consumeError(SDKInfoOrErr.takeError());
    TheDriver.Diag(diag::warn_drv_darwin_sdk_invalid_settings);
    return None;
  }
  return *SDKInfoOrErr;
}

} // namespace

void Darwin::AddDeploymentTarget(DerivedArgList &Args) const {
  const OptTable &Opts = getDriver().getOpts();

  // Support allowing the SDKROOT environment variable used by xcrun and other
  // Xcode tools to define the default sysroot, by making it the default for
  // isysroot.
  if (const Arg *A = Args.getLastArg(options::OPT_isysroot)) {
    // Warn if the path does not exist.
    if (!getVFS().exists(A->getValue()))
      getDriver().Diag(clang::diag::warn_missing_sysroot) << A->getValue();
  } else {
    if (char *env = ::getenv("SDKROOT")) {
      // We only use this value as the default if it is an absolute path,
      // exists, and it is not the root path.
      if (llvm::sys::path::is_absolute(env) && getVFS().exists(env) &&
          StringRef(env) != "/") {
        Args.append(Args.MakeSeparateArg(
            nullptr, Opts.getOption(options::OPT_isysroot), env));
      }
    }
  }

  // Read the SDKSettings.json file for more information, like the SDK version
  // that we can pass down to the compiler.
  SDKInfo = parseSDKSettings(getVFS(), Args, getDriver());

  // The OS and the version can be specified using the -target argument.
  Optional<DarwinPlatform> OSTarget =
      getDeploymentTargetFromTargetArg(Args, getTriple(), getDriver(), SDKInfo);
  if (OSTarget) {
    // Disallow mixing -target and -mtargetos=.
    if (const auto *MTargetOSArg = Args.getLastArg(options::OPT_mtargetos_EQ)) {
      std::string TargetArgStr = OSTarget->getAsString(Args, Opts);
      std::string MTargetOSArgStr = MTargetOSArg->getAsString(Args);
      getDriver().Diag(diag::err_drv_cannot_mix_options)
          << TargetArgStr << MTargetOSArgStr;
    }
    Optional<DarwinPlatform> OSVersionArgTarget =
        getDeploymentTargetFromOSVersionArg(Args, getDriver());
    if (OSVersionArgTarget) {
      unsigned TargetMajor, TargetMinor, TargetMicro;
      bool TargetExtra;
      unsigned ArgMajor, ArgMinor, ArgMicro;
      bool ArgExtra;
      if (OSTarget->getPlatform() != OSVersionArgTarget->getPlatform() ||
          (Driver::GetReleaseVersion(OSTarget->getOSVersion(), TargetMajor,
                                     TargetMinor, TargetMicro, TargetExtra) &&
           Driver::GetReleaseVersion(OSVersionArgTarget->getOSVersion(),
                                     ArgMajor, ArgMinor, ArgMicro, ArgExtra) &&
           (VersionTuple(TargetMajor, TargetMinor, TargetMicro) !=
                VersionTuple(ArgMajor, ArgMinor, ArgMicro) ||
            TargetExtra != ArgExtra))) {
        // Select the OS version from the -m<os>-version-min argument when
        // the -target does not include an OS version.
        if (OSTarget->getPlatform() == OSVersionArgTarget->getPlatform() &&
            !OSTarget->hasOSVersion()) {
          OSTarget->setOSVersion(OSVersionArgTarget->getOSVersion());
        } else {
          // Warn about -m<os>-version-min that doesn't match the OS version
          // that's specified in the target.
          std::string OSVersionArg =
              OSVersionArgTarget->getAsString(Args, Opts);
          std::string TargetArg = OSTarget->getAsString(Args, Opts);
          getDriver().Diag(clang::diag::warn_drv_overriding_flag_option)
              << OSVersionArg << TargetArg;
        }
      }
    }
  } else if ((OSTarget = getDeploymentTargetFromMTargetOSArg(Args, getDriver(),
                                                             SDKInfo))) {
    // The OS target can be specified using the -mtargetos= argument.
    // Disallow mixing -mtargetos= and -m<os>version-min=.
    Optional<DarwinPlatform> OSVersionArgTarget =
        getDeploymentTargetFromOSVersionArg(Args, getDriver());
    if (OSVersionArgTarget) {
      std::string MTargetOSArgStr = OSTarget->getAsString(Args, Opts);
      std::string OSVersionArgStr = OSVersionArgTarget->getAsString(Args, Opts);
      getDriver().Diag(diag::err_drv_cannot_mix_options)
          << MTargetOSArgStr << OSVersionArgStr;
    }
  } else {
    // The OS target can be specified using the -m<os>version-min argument.
    OSTarget = getDeploymentTargetFromOSVersionArg(Args, getDriver());
    // If no deployment target was specified on the command line, check for
    // environment defines.
    if (!OSTarget) {
      OSTarget =
          getDeploymentTargetFromEnvironmentVariables(getDriver(), getTriple());
      if (OSTarget) {
        // Don't infer simulator from the arch when the SDK is also specified.
        Optional<DarwinPlatform> SDKTarget =
            inferDeploymentTargetFromSDK(Args, SDKInfo);
        if (SDKTarget)
          OSTarget->setEnvironment(SDKTarget->getEnvironment());
      }
    }
    // If there is no command-line argument to specify the Target version and
    // no environment variable defined, see if we can set the default based
    // on -isysroot using SDKSettings.json if it exists.
    if (!OSTarget) {
      OSTarget = inferDeploymentTargetFromSDK(Args, SDKInfo);
      /// If the target was successfully constructed from the SDK path, try to
      /// infer the SDK info if the SDK doesn't have it.
      if (OSTarget && !SDKInfo)
        SDKInfo = OSTarget->inferSDKInfo();
    }
    // If no OS targets have been specified, try to guess platform from -target
    // or arch name and compute the version from the triple.
    if (!OSTarget)
      OSTarget =
          inferDeploymentTargetFromArch(Args, *this, getTriple(), getDriver());
  }

  assert(OSTarget && "Unable to infer Darwin variant");
  OSTarget->addOSVersionMinArgument(Args, Opts);
  DarwinPlatformKind Platform = OSTarget->getPlatform();

  unsigned Major, Minor, Micro;
  bool HadExtra;
  // Set the tool chain target information.
  if (Platform == MacOS) {
    if (!Driver::GetReleaseVersion(OSTarget->getOSVersion(), Major, Minor,
                                   Micro, HadExtra) ||
        HadExtra || Major < 10 || Major >= 100 || Minor >= 100 || Micro >= 100)
      getDriver().Diag(diag::err_drv_invalid_version_number)
          << OSTarget->getAsString(Args, Opts);
  } else if (Platform == IPhoneOS) {
    if (!Driver::GetReleaseVersion(OSTarget->getOSVersion(), Major, Minor,
                                   Micro, HadExtra) ||
        HadExtra || Major >= 100 || Minor >= 100 || Micro >= 100)
      getDriver().Diag(diag::err_drv_invalid_version_number)
          << OSTarget->getAsString(Args, Opts);
    ;
    if (OSTarget->getEnvironment() == MacCatalyst &&
        (Major < 13 || (Major == 13 && Minor < 1))) {
      getDriver().Diag(diag::err_drv_invalid_version_number)
          << OSTarget->getAsString(Args, Opts);
      Major = 13;
      Minor = 1;
      Micro = 0;
    }
    // For 32-bit targets, the deployment target for iOS has to be earlier than
    // iOS 11.
    if (getTriple().isArch32Bit() && Major >= 11) {
      // If the deployment target is explicitly specified, print a diagnostic.
      if (OSTarget->isExplicitlySpecified()) {
        if (OSTarget->getEnvironment() == MacCatalyst)
          getDriver().Diag(diag::err_invalid_macos_32bit_deployment_target);
        else
          getDriver().Diag(diag::warn_invalid_ios_deployment_target)
              << OSTarget->getAsString(Args, Opts);
        // Otherwise, set it to 10.99.99.
      } else {
        Major = 10;
        Minor = 99;
        Micro = 99;
      }
    }
  } else if (Platform == TvOS) {
    if (!Driver::GetReleaseVersion(OSTarget->getOSVersion(), Major, Minor,
                                   Micro, HadExtra) ||
        HadExtra || Major >= 100 || Minor >= 100 || Micro >= 100)
      getDriver().Diag(diag::err_drv_invalid_version_number)
          << OSTarget->getAsString(Args, Opts);
  } else if (Platform == WatchOS) {
    if (!Driver::GetReleaseVersion(OSTarget->getOSVersion(), Major, Minor,
                                   Micro, HadExtra) ||
        HadExtra || Major >= 10 || Minor >= 100 || Micro >= 100)
      getDriver().Diag(diag::err_drv_invalid_version_number)
          << OSTarget->getAsString(Args, Opts);
  } else
    llvm_unreachable("unknown kind of Darwin platform");

  DarwinEnvironmentKind Environment = OSTarget->getEnvironment();
  // Recognize iOS targets with an x86 architecture as the iOS simulator.
  if (Environment == NativeEnvironment && Platform != MacOS &&
      OSTarget->canInferSimulatorFromArch() && getTriple().isX86())
    Environment = Simulator;

  VersionTuple NativeTargetVersion;
  if (Environment == MacCatalyst)
    NativeTargetVersion = OSTarget->getNativeTargetVersion();
  setTarget(Platform, Environment, Major, Minor, Micro, NativeTargetVersion);

  if (const Arg *A = Args.getLastArg(options::OPT_isysroot)) {
    StringRef SDK = getSDKName(A->getValue());
    if (SDK.size() > 0) {
      size_t StartVer = SDK.find_first_of("0123456789");
      StringRef SDKName = SDK.slice(0, StartVer);
      if (!SDKName.startswith(getPlatformFamily()) &&
          !dropSDKNamePrefix(SDKName).startswith(getPlatformFamily()))
        getDriver().Diag(diag::warn_incompatible_sysroot)
            << SDKName << getPlatformFamily();
    }
  }
}

// Returns the effective header sysroot path to use. This comes either from
// -isysroot or --sysroot.
llvm::StringRef DarwinClang::GetHeaderSysroot(const llvm::opt::ArgList &DriverArgs) const {
  if(DriverArgs.hasArg(options::OPT_isysroot))
    return DriverArgs.getLastArgValue(options::OPT_isysroot);
  if (!getDriver().SysRoot.empty())
    return getDriver().SysRoot;
  return "/";
}

void DarwinClang::AddClangSystemIncludeArgs(const llvm::opt::ArgList &DriverArgs,
                                            llvm::opt::ArgStringList &CC1Args) const {
  const Driver &D = getDriver();

  llvm::StringRef Sysroot = GetHeaderSysroot(DriverArgs);

  bool NoStdInc = DriverArgs.hasArg(options::OPT_nostdinc);
  bool NoStdlibInc = DriverArgs.hasArg(options::OPT_nostdlibinc);
  bool NoBuiltinInc = DriverArgs.hasFlag(
      options::OPT_nobuiltininc, options::OPT_ibuiltininc, /*Default=*/false);
  bool ForceBuiltinInc = DriverArgs.hasFlag(
      options::OPT_ibuiltininc, options::OPT_nobuiltininc, /*Default=*/false);

  // Add <sysroot>/usr/local/include
  if (!NoStdInc && !NoStdlibInc) {
      SmallString<128> P(Sysroot);
      llvm::sys::path::append(P, "usr", "local", "include");
      addSystemInclude(DriverArgs, CC1Args, P);
  }

  // Add the Clang builtin headers (<resource>/include)
  if (!(NoStdInc && !ForceBuiltinInc) && !NoBuiltinInc) {
    SmallString<128> P(D.ResourceDir);
    llvm::sys::path::append(P, "include");
    addSystemInclude(DriverArgs, CC1Args, P);
  }

  if (NoStdInc || NoStdlibInc)
    return;

  // Check for configure-time C include directories.
  llvm::StringRef CIncludeDirs(C_INCLUDE_DIRS);
  if (!CIncludeDirs.empty()) {
    llvm::SmallVector<llvm::StringRef, 5> dirs;
    CIncludeDirs.split(dirs, ":");
    for (llvm::StringRef dir : dirs) {
      llvm::StringRef Prefix =
          llvm::sys::path::is_absolute(dir) ? "" : llvm::StringRef(Sysroot);
      addExternCSystemInclude(DriverArgs, CC1Args, Prefix + dir);
    }
  } else {
    // Otherwise, add <sysroot>/usr/include.
    SmallString<128> P(Sysroot);
    llvm::sys::path::append(P, "usr", "include");
    addExternCSystemInclude(DriverArgs, CC1Args, P.str());
  }
}

bool DarwinClang::AddGnuCPlusPlusIncludePaths(const llvm::opt::ArgList &DriverArgs,
                                              llvm::opt::ArgStringList &CC1Args,
                                              llvm::SmallString<128> Base,
                                              llvm::StringRef Version,
                                              llvm::StringRef ArchDir,
                                              llvm::StringRef BitDir) const {
  llvm::sys::path::append(Base, Version);

  // Add the base dir
  addSystemInclude(DriverArgs, CC1Args, Base);

  // Add the multilib dirs
  {
    llvm::SmallString<128> P = Base;
    if (!ArchDir.empty())
      llvm::sys::path::append(P, ArchDir);
    if (!BitDir.empty())
      llvm::sys::path::append(P, BitDir);
    addSystemInclude(DriverArgs, CC1Args, P);
  }

  // Add the backward dir
  {
    llvm::SmallString<128> P = Base;
    llvm::sys::path::append(P, "backward");
    addSystemInclude(DriverArgs, CC1Args, P);
  }

  return getVFS().exists(Base);
}

void DarwinClang::AddClangCXXStdlibIncludeArgs(
    const llvm::opt::ArgList &DriverArgs,
    llvm::opt::ArgStringList &CC1Args) const {
  // The implementation from a base class will pass through the -stdlib to
  // CC1Args.
  // FIXME: this should not be necessary, remove usages in the frontend
  //        (e.g. HeaderSearchOptions::UseLibcxx) and don't pipe -stdlib.
  //        Also check whether this is used for setting library search paths.
  ToolChain::AddClangCXXStdlibIncludeArgs(DriverArgs, CC1Args);

  if (DriverArgs.hasArg(options::OPT_nostdlibinc) ||
      DriverArgs.hasArg(options::OPT_nostdincxx))
    return;

  llvm::StringRef Sysroot = GetHeaderSysroot(DriverArgs);

  switch (GetCXXStdlibType(DriverArgs)) {
  case ToolChain::CST_Libcxx: {
    // On Darwin, libc++ can be installed in one of the following two places:
    // 1. Alongside the compiler in         <install>/include/c++/v1
    // 2. In a SDK (or a custom sysroot) in <sysroot>/usr/include/c++/v1
    //
    // The precendence of paths is as listed above, i.e. we take the first path
    // that exists. Also note that we never include libc++ twice -- we take the
    // first path that exists and don't send the other paths to CC1 (otherwise
    // include_next could break).

    // Check for (1)
    // Get from '<install>/bin' to '<install>/include/c++/v1'.
    // Note that InstallBin can be relative, so we use '..' instead of
    // parent_path.
    llvm::SmallString<128> InstallBin =
        llvm::StringRef(getDriver().getInstalledDir()); // <install>/bin
    llvm::sys::path::append(InstallBin, "..", "include", "c++", "v1");
    if (getVFS().exists(InstallBin)) {
      addSystemInclude(DriverArgs, CC1Args, InstallBin);
      return;
    } else if (DriverArgs.hasArg(options::OPT_v)) {
      llvm::errs() << "ignoring nonexistent directory \"" << InstallBin
                   << "\"\n";
    }

    // Otherwise, check for (2)
    llvm::SmallString<128> SysrootUsr = Sysroot;
    llvm::sys::path::append(SysrootUsr, "usr", "include", "c++", "v1");
    if (getVFS().exists(SysrootUsr)) {
      addSystemInclude(DriverArgs, CC1Args, SysrootUsr);
      return;
    } else if (DriverArgs.hasArg(options::OPT_v)) {
      llvm::errs() << "ignoring nonexistent directory \"" << SysrootUsr
                   << "\"\n";
    }

    // Otherwise, don't add any path.
    break;
  }

  case ToolChain::CST_Libstdcxx:
    llvm::SmallString<128> UsrIncludeCxx = Sysroot;
    llvm::sys::path::append(UsrIncludeCxx, "usr", "include", "c++");

    llvm::Triple::ArchType arch = getTriple().getArch();
    bool IsBaseFound = true;
    switch (arch) {
    default: break;

    case llvm::Triple::ppc:
    case llvm::Triple::ppc64:
      IsBaseFound = AddGnuCPlusPlusIncludePaths(DriverArgs, CC1Args, UsrIncludeCxx,
                                                "4.2.1",
                                                "powerpc-apple-darwin10",
                                                arch == llvm::Triple::ppc64 ? "ppc64" : "");
      IsBaseFound |= AddGnuCPlusPlusIncludePaths(DriverArgs, CC1Args, UsrIncludeCxx,
                                                "4.0.0", "powerpc-apple-darwin10",
                                                 arch == llvm::Triple::ppc64 ? "ppc64" : "");
      break;

    case llvm::Triple::x86:
    case llvm::Triple::x86_64:
      IsBaseFound = AddGnuCPlusPlusIncludePaths(DriverArgs, CC1Args, UsrIncludeCxx,
                                                "4.2.1",
                                                "i686-apple-darwin10",
                                                arch == llvm::Triple::x86_64 ? "x86_64" : "");
      IsBaseFound |= AddGnuCPlusPlusIncludePaths(DriverArgs, CC1Args, UsrIncludeCxx,
                                                "4.0.0", "i686-apple-darwin8",
                                                 "");
      break;

    case llvm::Triple::arm:
    case llvm::Triple::thumb:
      IsBaseFound = AddGnuCPlusPlusIncludePaths(DriverArgs, CC1Args, UsrIncludeCxx,
                                                "4.2.1",
                                                "arm-apple-darwin10",
                                                "v7");
      IsBaseFound |= AddGnuCPlusPlusIncludePaths(DriverArgs, CC1Args, UsrIncludeCxx,
                                                "4.2.1",
                                                "arm-apple-darwin10",
                                                 "v6");
      break;

    case llvm::Triple::aarch64:
      IsBaseFound = AddGnuCPlusPlusIncludePaths(DriverArgs, CC1Args, UsrIncludeCxx,
                                                "4.2.1",
                                                "arm64-apple-darwin10",
                                                "");
      break;
    }

    if (!IsBaseFound) {
      getDriver().Diag(diag::warn_drv_libstdcxx_not_found);
    }

    break;
  }
}
void DarwinClang::AddCXXStdlibLibArgs(const ArgList &Args,
                                      ArgStringList &CmdArgs) const {
  CXXStdlibType Type = GetCXXStdlibType(Args);

  switch (Type) {
  case ToolChain::CST_Libcxx:
    CmdArgs.push_back("-lc++");
    break;

  case ToolChain::CST_Libstdcxx:
    // Unfortunately, -lstdc++ doesn't always exist in the standard search path;
    // it was previously found in the gcc lib dir. However, for all the Darwin
    // platforms we care about it was -lstdc++.6, so we search for that
    // explicitly if we can't see an obvious -lstdc++ candidate.

    // Check in the sysroot first.
    if (const Arg *A = Args.getLastArg(options::OPT_isysroot)) {
      SmallString<128> P(A->getValue());
      llvm::sys::path::append(P, "usr", "lib", "libstdc++.dylib");

      if (!getVFS().exists(P)) {
        llvm::sys::path::remove_filename(P);
        llvm::sys::path::append(P, "libstdc++.6.dylib");
        if (getVFS().exists(P)) {
          CmdArgs.push_back(Args.MakeArgString(P));
          return;
        }
      }
    }

    // Otherwise, look in the root.
    // FIXME: This should be removed someday when we don't have to care about
    // 10.6 and earlier, where /usr/lib/libstdc++.dylib does not exist.
    if (!getVFS().exists("/usr/lib/libstdc++.dylib") &&
        getVFS().exists("/usr/lib/libstdc++.6.dylib")) {
      CmdArgs.push_back("/usr/lib/libstdc++.6.dylib");
      return;
    }

    // Otherwise, let the linker search.
    CmdArgs.push_back("-lstdc++");
    break;
  }
}

void DarwinClang::AddCCKextLibArgs(const ArgList &Args,
                                   ArgStringList &CmdArgs) const {
  // For Darwin platforms, use the compiler-rt-based support library
  // instead of the gcc-provided one (which is also incidentally
  // only present in the gcc lib dir, which makes it hard to find).

  SmallString<128> P(getDriver().ResourceDir);
  llvm::sys::path::append(P, "lib", "darwin");

  // Use the newer cc_kext for iOS ARM after 6.0.
  if (isTargetWatchOS()) {
    llvm::sys::path::append(P, "libclang_rt.cc_kext_watchos.a");
  } else if (isTargetTvOS()) {
    llvm::sys::path::append(P, "libclang_rt.cc_kext_tvos.a");
  } else if (isTargetIPhoneOS()) {
    llvm::sys::path::append(P, "libclang_rt.cc_kext_ios.a");
  } else {
    llvm::sys::path::append(P, "libclang_rt.cc_kext.a");
  }

  // For now, allow missing resource libraries to support developers who may
  // not have compiler-rt checked out or integrated into their build.
  if (getVFS().exists(P))
    CmdArgs.push_back(Args.MakeArgString(P));
}

DerivedArgList *MachO::TranslateArgs(const DerivedArgList &Args,
                                     StringRef BoundArch,
                                     Action::OffloadKind) const {
  DerivedArgList *DAL = new DerivedArgList(Args.getBaseArgs());
  const OptTable &Opts = getDriver().getOpts();

  // FIXME: We really want to get out of the tool chain level argument
  // translation business, as it makes the driver functionality much
  // more opaque. For now, we follow gcc closely solely for the
  // purpose of easily achieving feature parity & testability. Once we
  // have something that works, we should reevaluate each translation
  // and try to push it down into tool specific logic.

  for (Arg *A : Args) {
    if (A->getOption().matches(options::OPT_Xarch__)) {
      // Skip this argument unless the architecture matches either the toolchain
      // triple arch, or the arch being bound.
      llvm::Triple::ArchType XarchArch =
          tools::darwin::getArchTypeForMachOArchName(A->getValue(0));
      if (!(XarchArch == getArch() ||
            (!BoundArch.empty() &&
             XarchArch ==
                 tools::darwin::getArchTypeForMachOArchName(BoundArch))))
        continue;

      Arg *OriginalArg = A;
      TranslateXarchArgs(Args, A, DAL);

      // Linker input arguments require custom handling. The problem is that we
      // have already constructed the phase actions, so we can not treat them as
      // "input arguments".
      if (A->getOption().hasFlag(options::LinkerInput)) {
        // Convert the argument into individual Zlinker_input_args.
        for (const char *Value : A->getValues()) {
          DAL->AddSeparateArg(
              OriginalArg, Opts.getOption(options::OPT_Zlinker_input), Value);
        }
        continue;
      }
    }

    // Sob. These is strictly gcc compatible for the time being. Apple
    // gcc translates options twice, which means that self-expanding
    // options add duplicates.
    switch ((options::ID)A->getOption().getID()) {
    default:
      DAL->append(A);
      break;

    case options::OPT_mkernel:
    case options::OPT_fapple_kext:
      DAL->append(A);
      DAL->AddFlagArg(A, Opts.getOption(options::OPT_static));
      break;

    case options::OPT_dependency_file:
      DAL->AddSeparateArg(A, Opts.getOption(options::OPT_MF), A->getValue());
      break;

    case options::OPT_gfull:
      DAL->AddFlagArg(A, Opts.getOption(options::OPT_g_Flag));
      DAL->AddFlagArg(
          A, Opts.getOption(options::OPT_fno_eliminate_unused_debug_symbols));
      break;

    case options::OPT_gused:
      DAL->AddFlagArg(A, Opts.getOption(options::OPT_g_Flag));
      DAL->AddFlagArg(
          A, Opts.getOption(options::OPT_feliminate_unused_debug_symbols));
      break;

    case options::OPT_shared:
      DAL->AddFlagArg(A, Opts.getOption(options::OPT_dynamiclib));
      break;

    case options::OPT_fconstant_cfstrings:
      DAL->AddFlagArg(A, Opts.getOption(options::OPT_mconstant_cfstrings));
      break;

    case options::OPT_fno_constant_cfstrings:
      DAL->AddFlagArg(A, Opts.getOption(options::OPT_mno_constant_cfstrings));
      break;

    case options::OPT_Wnonportable_cfstrings:
      DAL->AddFlagArg(A,
                      Opts.getOption(options::OPT_mwarn_nonportable_cfstrings));
      break;

    case options::OPT_Wno_nonportable_cfstrings:
      DAL->AddFlagArg(
          A, Opts.getOption(options::OPT_mno_warn_nonportable_cfstrings));
      break;

    case options::OPT_fpascal_strings:
      DAL->AddFlagArg(A, Opts.getOption(options::OPT_mpascal_strings));
      break;

    case options::OPT_fno_pascal_strings:
      DAL->AddFlagArg(A, Opts.getOption(options::OPT_mno_pascal_strings));
      break;
    }
  }

  // Add the arch options based on the particular spelling of -arch, to match
  // how the driver driver works.
  if (!BoundArch.empty()) {
    StringRef Name = BoundArch;
    const Option MCpu = Opts.getOption(options::OPT_mcpu_EQ);
    const Option MArch = Opts.getOption(clang::driver::options::OPT_march_EQ);

    // This code must be kept in sync with LLVM's getArchTypeForDarwinArch,
    // which defines the list of which architectures we accept.
    if (Name == "ppc")
      ;
    else if (Name == "ppc601")
      DAL->AddJoinedArg(nullptr, MCpu, "601");
    else if (Name == "ppc603")
      DAL->AddJoinedArg(nullptr, MCpu, "603");
    else if (Name == "ppc604")
      DAL->AddJoinedArg(nullptr, MCpu, "604");
    else if (Name == "ppc604e")
      DAL->AddJoinedArg(nullptr, MCpu, "604e");
    else if (Name == "ppc750")
      DAL->AddJoinedArg(nullptr, MCpu, "750");
    else if (Name == "ppc7400")
      DAL->AddJoinedArg(nullptr, MCpu, "7400");
    else if (Name == "ppc7450")
      DAL->AddJoinedArg(nullptr, MCpu, "7450");
    else if (Name == "ppc970")
      DAL->AddJoinedArg(nullptr, MCpu, "970");

    else if (Name == "ppc64" || Name == "ppc64le")
      DAL->AddFlagArg(nullptr, Opts.getOption(options::OPT_m64));

    else if (Name == "i386")
      ;
    else if (Name == "i486")
      DAL->AddJoinedArg(nullptr, MArch, "i486");
    else if (Name == "i586")
      DAL->AddJoinedArg(nullptr, MArch, "i586");
    else if (Name == "i686")
      DAL->AddJoinedArg(nullptr, MArch, "i686");
    else if (Name == "pentium")
      DAL->AddJoinedArg(nullptr, MArch, "pentium");
    else if (Name == "pentium2")
      DAL->AddJoinedArg(nullptr, MArch, "pentium2");
    else if (Name == "pentpro")
      DAL->AddJoinedArg(nullptr, MArch, "pentiumpro");
    else if (Name == "pentIIm3")
      DAL->AddJoinedArg(nullptr, MArch, "pentium2");

    else if (Name == "x86_64" || Name == "x86_64h")
      DAL->AddFlagArg(nullptr, Opts.getOption(options::OPT_m64));

    else if (Name == "arm")
      DAL->AddJoinedArg(nullptr, MArch, "armv4t");
    else if (Name == "armv4t")
      DAL->AddJoinedArg(nullptr, MArch, "armv4t");
    else if (Name == "armv5")
      DAL->AddJoinedArg(nullptr, MArch, "armv5tej");
    else if (Name == "xscale")
      DAL->AddJoinedArg(nullptr, MArch, "xscale");
    else if (Name == "armv6")
      DAL->AddJoinedArg(nullptr, MArch, "armv6k");
    else if (Name == "armv6m")
      DAL->AddJoinedArg(nullptr, MArch, "armv6m");
    else if (Name == "armv7")
      DAL->AddJoinedArg(nullptr, MArch, "armv7a");
    else if (Name == "armv7em")
      DAL->AddJoinedArg(nullptr, MArch, "armv7em");
    else if (Name == "armv7k")
      DAL->AddJoinedArg(nullptr, MArch, "armv7k");
    else if (Name == "armv7m")
      DAL->AddJoinedArg(nullptr, MArch, "armv7m");
    else if (Name == "armv7s")
      DAL->AddJoinedArg(nullptr, MArch, "armv7s");
  }

  return DAL;
}

void MachO::AddLinkRuntimeLibArgs(const ArgList &Args,
                                  ArgStringList &CmdArgs,
                                  bool ForceLinkBuiltinRT) const {
  // Embedded targets are simple at the moment, not supporting sanitizers and
  // with different libraries for each member of the product { static, PIC } x
  // { hard-float, soft-float }
  llvm::SmallString<32> CompilerRT = StringRef("");
  CompilerRT +=
      (tools::arm::getARMFloatABI(*this, Args) == tools::arm::FloatABI::Hard)
          ? "hard"
          : "soft";
  CompilerRT += Args.hasArg(options::OPT_fPIC) ? "_pic" : "_static";

  AddLinkRuntimeLib(Args, CmdArgs, CompilerRT, RLO_IsEmbedded);
}

bool Darwin::isAlignedAllocationUnavailable() const {
  llvm::Triple::OSType OS;

  if (isTargetMacCatalyst())
    return TargetVersion < alignedAllocMinVersion(llvm::Triple::MacOSX);
  switch (TargetPlatform) {
  case MacOS: // Earlier than 10.13.
    OS = llvm::Triple::MacOSX;
    break;
  case IPhoneOS:
    OS = llvm::Triple::IOS;
    break;
  case TvOS: // Earlier than 11.0.
    OS = llvm::Triple::TvOS;
    break;
  case WatchOS: // Earlier than 4.0.
    OS = llvm::Triple::WatchOS;
    break;
  }

  return TargetVersion < alignedAllocMinVersion(OS);
}

void Darwin::addClangTargetOptions(const llvm::opt::ArgList &DriverArgs,
                                   llvm::opt::ArgStringList &CC1Args,
                                   Action::OffloadKind DeviceOffloadKind) const {
  // Pass "-faligned-alloc-unavailable" only when the user hasn't manually
  // enabled or disabled aligned allocations.
  if (!DriverArgs.hasArgNoClaim(options::OPT_faligned_allocation,
                                options::OPT_fno_aligned_allocation) &&
      isAlignedAllocationUnavailable())
    CC1Args.push_back("-faligned-alloc-unavailable");

  if (SDKInfo) {
    /// Pass the SDK version to the compiler when the SDK information is
    /// available.
    auto EmitTargetSDKVersionArg = [&](const VersionTuple &V) {
      std::string Arg;
      llvm::raw_string_ostream OS(Arg);
      OS << "-target-sdk-version=" << V;
      CC1Args.push_back(DriverArgs.MakeArgString(OS.str()));
    };

    if (isTargetMacCatalyst()) {
      if (const auto *MacOStoMacCatalystMapping = SDKInfo->getVersionMapping(
              DarwinSDKInfo::OSEnvPair::macOStoMacCatalystPair())) {
        Optional<VersionTuple> SDKVersion = MacOStoMacCatalystMapping->map(
            SDKInfo->getVersion(), minimumMacCatalystDeploymentTarget(), None);
        EmitTargetSDKVersionArg(
            SDKVersion ? *SDKVersion : minimumMacCatalystDeploymentTarget());
      }
    } else {
      EmitTargetSDKVersionArg(SDKInfo->getVersion());
    }
  }

  // Enable compatibility mode for NSItemProviderCompletionHandler in
  // Foundation/NSItemProvider.h.
  CC1Args.push_back("-fcompatibility-qualified-id-block-type-checking");

  // Give static local variables in inline functions hidden visibility when
  // -fvisibility-inlines-hidden is enabled.
  if (!DriverArgs.getLastArgNoClaim(
          options::OPT_fvisibility_inlines_hidden_static_local_var,
          options::OPT_fno_visibility_inlines_hidden_static_local_var))
    CC1Args.push_back("-fvisibility-inlines-hidden-static-local-var");
}

DerivedArgList *
Darwin::TranslateArgs(const DerivedArgList &Args, StringRef BoundArch,
                      Action::OffloadKind DeviceOffloadKind) const {
  // First get the generic Apple args, before moving onto Darwin-specific ones.
  DerivedArgList *DAL =
      MachO::TranslateArgs(Args, BoundArch, DeviceOffloadKind);
  const OptTable &Opts = getDriver().getOpts();

  // If no architecture is bound, none of the translations here are relevant.
  if (BoundArch.empty())
    return DAL;

  // Add an explicit version min argument for the deployment target. We do this
  // after argument translation because -Xarch_ arguments may add a version min
  // argument.
  AddDeploymentTarget(*DAL);

  // For iOS 6, undo the translation to add -static for -mkernel/-fapple-kext.
  // FIXME: It would be far better to avoid inserting those -static arguments,
  // but we can't check the deployment target in the translation code until
  // it is set here.
  if (isTargetWatchOSBased() ||
      (isTargetIOSBased() && !isIPhoneOSVersionLT(6, 0))) {
    for (ArgList::iterator it = DAL->begin(), ie = DAL->end(); it != ie; ) {
      Arg *A = *it;
      ++it;
      if (A->getOption().getID() != options::OPT_mkernel &&
          A->getOption().getID() != options::OPT_fapple_kext)
        continue;
      assert(it != ie && "unexpected argument translation");
      A = *it;
      assert(A->getOption().getID() == options::OPT_static &&
             "missing expected -static argument");
      *it = nullptr;
      ++it;
    }
  }

  if (!Args.getLastArg(options::OPT_stdlib_EQ) &&
      GetCXXStdlibType(Args) == ToolChain::CST_Libcxx)
    DAL->AddJoinedArg(nullptr, Opts.getOption(options::OPT_stdlib_EQ),
                      "libc++");

  // Validate the C++ standard library choice.
  CXXStdlibType Type = GetCXXStdlibType(*DAL);
  if (Type == ToolChain::CST_Libcxx) {
    // Check whether the target provides libc++.
    StringRef where;

    // Complain about targeting iOS < 5.0 in any way.
    if (isTargetIOSBased() && isIPhoneOSVersionLT(5, 0))
      where = "iOS 5.0";

    if (where != StringRef()) {
      getDriver().Diag(clang::diag::err_drv_invalid_libcxx_deployment) << where;
    }
  }

  auto Arch = tools::darwin::getArchTypeForMachOArchName(BoundArch);
  if ((Arch == llvm::Triple::arm || Arch == llvm::Triple::thumb)) {
    if (Args.hasFlag(options::OPT_fomit_frame_pointer,
                     options::OPT_fno_omit_frame_pointer, false))
      getDriver().Diag(clang::diag::warn_drv_unsupported_opt_for_target)
          << "-fomit-frame-pointer" << BoundArch;
  }

  return DAL;
}

bool MachO::IsUnwindTablesDefault(const ArgList &Args) const {
  // Unwind tables are not emitted if -fno-exceptions is supplied (except when
  // targeting x86_64).
  return getArch() == llvm::Triple::x86_64 ||
         (GetExceptionModel(Args) != llvm::ExceptionHandling::SjLj &&
          Args.hasFlag(options::OPT_fexceptions, options::OPT_fno_exceptions,
                       true));
}

bool MachO::UseDwarfDebugFlags() const {
  if (const char *S = ::getenv("RC_DEBUG_OPTIONS"))
    return S[0] != '\0';
  return false;
}

llvm::ExceptionHandling Darwin::GetExceptionModel(const ArgList &Args) const {
  // Darwin uses SjLj exceptions on ARM.
  if (getTriple().getArch() != llvm::Triple::arm &&
      getTriple().getArch() != llvm::Triple::thumb)
    return llvm::ExceptionHandling::None;

  // Only watchOS uses the new DWARF/Compact unwinding method.
  llvm::Triple Triple(ComputeLLVMTriple(Args));
  if (Triple.isWatchABI())
    return llvm::ExceptionHandling::DwarfCFI;

  return llvm::ExceptionHandling::SjLj;
}

bool Darwin::SupportsEmbeddedBitcode() const {
  assert(TargetInitialized && "Target not initialized!");
  if (isTargetIPhoneOS() && isIPhoneOSVersionLT(6, 0))
    return false;
  return true;
}

bool MachO::isPICDefault() const { return true; }

bool MachO::isPIEDefault(const llvm::opt::ArgList &Args) const { return false; }

bool MachO::isPICDefaultForced() const {
  return (getArch() == llvm::Triple::x86_64 ||
          getArch() == llvm::Triple::aarch64);
}

bool MachO::SupportsProfiling() const {
  // Profiling instrumentation is only supported on x86.
  return getTriple().isX86();
}

void Darwin::addMinVersionArgs(const ArgList &Args,
                               ArgStringList &CmdArgs) const {
  VersionTuple TargetVersion = getTripleTargetVersion();

  if (isTargetWatchOS())
    CmdArgs.push_back("-watchos_version_min");
  else if (isTargetWatchOSSimulator())
    CmdArgs.push_back("-watchos_simulator_version_min");
  else if (isTargetTvOS())
    CmdArgs.push_back("-tvos_version_min");
  else if (isTargetTvOSSimulator())
    CmdArgs.push_back("-tvos_simulator_version_min");
  else if (isTargetIOSSimulator())
    CmdArgs.push_back("-ios_simulator_version_min");
  else if (isTargetIOSBased())
    CmdArgs.push_back("-iphoneos_version_min");
  else if (isTargetMacCatalyst())
    CmdArgs.push_back("-maccatalyst_version_min");
  else {
    assert(isTargetMacOS() && "unexpected target");
    CmdArgs.push_back("-macosx_version_min");
  }

  VersionTuple MinTgtVers = getEffectiveTriple().getMinimumSupportedOSVersion();
  if (!MinTgtVers.empty() && MinTgtVers > TargetVersion)
    TargetVersion = MinTgtVers;
  CmdArgs.push_back(Args.MakeArgString(TargetVersion.getAsString()));
}

static const char *getPlatformName(Darwin::DarwinPlatformKind Platform,
                                   Darwin::DarwinEnvironmentKind Environment) {
  switch (Platform) {
  case Darwin::MacOS:
    return "macos";
  case Darwin::IPhoneOS:
    if (Environment == Darwin::MacCatalyst)
      return "mac catalyst";
    return "ios";
  case Darwin::TvOS:
    return "tvos";
  case Darwin::WatchOS:
    return "watchos";
  }
  llvm_unreachable("invalid platform");
}

void Darwin::addPlatformVersionArgs(const llvm::opt::ArgList &Args,
                                    llvm::opt::ArgStringList &CmdArgs) const {
  // -platform_version <platform> <target_version> <sdk_version>
  // Both the target and SDK version support only up to 3 components.
  CmdArgs.push_back("-platform_version");
  std::string PlatformName = getPlatformName(TargetPlatform, TargetEnvironment);
  if (TargetEnvironment == Darwin::Simulator)
    PlatformName += "-simulator";
  CmdArgs.push_back(Args.MakeArgString(PlatformName));
  VersionTuple TargetVersion = getTripleTargetVersion().withoutBuild();
  VersionTuple MinTgtVers = getEffectiveTriple().getMinimumSupportedOSVersion();
  if (!MinTgtVers.empty() && MinTgtVers > TargetVersion)
    TargetVersion = MinTgtVers;
  CmdArgs.push_back(Args.MakeArgString(TargetVersion.getAsString()));

  if (isTargetMacCatalyst()) {
    // Mac Catalyst programs must use the appropriate iOS SDK version
    // that corresponds to the macOS SDK version used for the compilation.
    Optional<VersionTuple> iOSSDKVersion;
    if (SDKInfo) {
      if (const auto *MacOStoMacCatalystMapping = SDKInfo->getVersionMapping(
              DarwinSDKInfo::OSEnvPair::macOStoMacCatalystPair())) {
        iOSSDKVersion = MacOStoMacCatalystMapping->map(
            SDKInfo->getVersion().withoutBuild(),
            minimumMacCatalystDeploymentTarget(), None);
      }
    }
    CmdArgs.push_back(Args.MakeArgString(
        (iOSSDKVersion ? *iOSSDKVersion : minimumMacCatalystDeploymentTarget())
            .getAsString()));
    return;
  }

  if (SDKInfo) {
    VersionTuple SDKVersion = SDKInfo->getVersion().withoutBuild();
    CmdArgs.push_back(Args.MakeArgString(SDKVersion.getAsString()));
  } else {
    // Use an SDK version that's matching the deployment target if the SDK
    // version is missing. This is preferred over an empty SDK version (0.0.0)
    // as the system's runtime might expect the linked binary to contain a
    // valid SDK version in order for the binary to work correctly. It's
    // reasonable to use the deployment target version as a proxy for the
    // SDK version because older SDKs don't guarantee support for deployment
    // targets newer than the SDK versions, so that rules out using some
    // predetermined older SDK version, which leaves the deployment target
    // version as the only reasonable choice.
    CmdArgs.push_back(Args.MakeArgString(TargetVersion.getAsString()));
  }
}

// Add additional link args for the -dynamiclib option.
static void addDynamicLibLinkArgs(const Darwin &D, const ArgList &Args,
                                  ArgStringList &CmdArgs) {
  // Derived from darwin_dylib1 spec.
  if (D.isTargetIPhoneOS()) {
    if (D.isIPhoneOSVersionLT(3, 1))
      CmdArgs.push_back("-ldylib1.o");
    return;
  }

  if (!D.isTargetMacOS())
    return;
  if (D.isMacosxVersionLT(10, 5))
    CmdArgs.push_back("-ldylib1.o");
  else if (D.isMacosxVersionLT(10, 6))
    CmdArgs.push_back("-ldylib1.10.5.o");
}

// Add additional link args for the -bundle option.
static void addBundleLinkArgs(const Darwin &D, const ArgList &Args,
                              ArgStringList &CmdArgs) {
  if (Args.hasArg(options::OPT_static))
    return;
  // Derived from darwin_bundle1 spec.
  if ((D.isTargetIPhoneOS() && D.isIPhoneOSVersionLT(3, 1)) ||
      (D.isTargetMacOS() && D.isMacosxVersionLT(10, 6)))
    CmdArgs.push_back("-lbundle1.o");
}

// Add additional link args for the -pg option.
static void addPgProfilingLinkArgs(const Darwin &D, const ArgList &Args,
                                   ArgStringList &CmdArgs) {
  if (D.isTargetMacOS() && D.isMacosxVersionLT(10, 9)) {
    if (Args.hasArg(options::OPT_static) || Args.hasArg(options::OPT_object) ||
        Args.hasArg(options::OPT_preload)) {
      CmdArgs.push_back("-lgcrt0.o");
    } else {
      CmdArgs.push_back("-lgcrt1.o");

      // darwin_crt2 spec is empty.
    }
    // By default on OS X 10.8 and later, we don't link with a crt1.o
    // file and the linker knows to use _main as the entry point.  But,
    // when compiling with -pg, we need to link with the gcrt1.o file,
    // so pass the -no_new_main option to tell the linker to use the
    // "start" symbol as the entry point.
    if (!D.isMacosxVersionLT(10, 8))
      CmdArgs.push_back("-no_new_main");
  } else {
    D.getDriver().Diag(diag::err_drv_clang_unsupported_opt_pg_darwin)
        << D.isTargetMacOSBased();
  }
}

static void addDefaultCRTLinkArgs(const Darwin &D, const ArgList &Args,
                                  ArgStringList &CmdArgs) {
  // Derived from darwin_crt1 spec.
  if (D.isTargetIPhoneOS()) {
    if (D.getArch() == llvm::Triple::aarch64)
      ; // iOS does not need any crt1 files for arm64
    else if (D.isIPhoneOSVersionLT(3, 1))
      CmdArgs.push_back("-lcrt1.o");
    else if (D.isIPhoneOSVersionLT(6, 0))
      CmdArgs.push_back("-lcrt1.3.1.o");
    return;
  }

  if (!D.isTargetMacOS())
    return;
  if (D.isMacosxVersionLT(10, 5))
    CmdArgs.push_back("-lcrt1.o");
  else if (D.isMacosxVersionLT(10, 6))
    CmdArgs.push_back("-lcrt1.10.5.o");
  else if (D.isMacosxVersionLT(10, 8))
    CmdArgs.push_back("-lcrt1.10.6.o");
  // darwin_crt2 spec is empty.
}

void Darwin::addStartObjectFileArgs(const ArgList &Args,
                                    ArgStringList &CmdArgs) const {
  // Derived from startfile spec.
  if (Args.hasArg(options::OPT_dynamiclib))
    addDynamicLibLinkArgs(*this, Args, CmdArgs);
  else if (Args.hasArg(options::OPT_bundle))
    addBundleLinkArgs(*this, Args, CmdArgs);
  else if (Args.hasArg(options::OPT_pg) && SupportsProfiling())
    addPgProfilingLinkArgs(*this, Args, CmdArgs);
  else if (Args.hasArg(options::OPT_static) ||
           Args.hasArg(options::OPT_object) ||
           Args.hasArg(options::OPT_preload))
    CmdArgs.push_back("-lcrt0.o");
  else
    addDefaultCRTLinkArgs(*this, Args, CmdArgs);

  if (isTargetMacOS() && Args.hasArg(options::OPT_shared_libgcc) &&
      isMacosxVersionLT(10, 5)) {
    const char *Str = Args.MakeArgString(GetFilePath("crt3.o"));
    CmdArgs.push_back(Str);
  }
}

void Darwin::CheckObjCARC() const {
  if (isTargetIOSBased() || isTargetWatchOSBased() ||
      (isTargetMacOSBased() && !isMacosxVersionLT(10, 6)))
    return;
  getDriver().Diag(diag::err_arc_unsupported_on_toolchain);
}

SanitizerMask Darwin::getSupportedSanitizers() const {
  const bool IsX86_64 = getTriple().getArch() == llvm::Triple::x86_64;
  const bool IsAArch64 = getTriple().getArch() == llvm::Triple::aarch64;
  SanitizerMask Res = ToolChain::getSupportedSanitizers();
  Res |= SanitizerKind::Address;
  Res |= SanitizerKind::PointerCompare;
  Res |= SanitizerKind::PointerSubtract;
  Res |= SanitizerKind::Leak;
  Res |= SanitizerKind::Fuzzer;
  Res |= SanitizerKind::FuzzerNoLink;
  Res |= SanitizerKind::Function;
  Res |= SanitizerKind::ObjCCast;

  // Prior to 10.9, macOS shipped a version of the C++ standard library without
  // C++11 support. The same is true of iOS prior to version 5. These OS'es are
  // incompatible with -fsanitize=vptr.
  if (!(isTargetMacOSBased() && isMacosxVersionLT(10, 9)) &&
      !(isTargetIPhoneOS() && isIPhoneOSVersionLT(5, 0)))
    Res |= SanitizerKind::Vptr;

  if ((IsX86_64 || IsAArch64) && isTargetMacOSBased()) {
    Res |= SanitizerKind::Thread;
  } else if (isTargetIOSSimulator() || isTargetTvOSSimulator()) {
    if (IsX86_64)
      Res |= SanitizerKind::Thread;
  }
  return Res;
}

void Darwin::printVerboseInfo(raw_ostream &OS) const {
  CudaInstallation.print(OS);
  RocmInstallation.print(OS);
}
