10b57cec5SDimitry Andric //===--- Darwin.cpp - Darwin Tool and ToolChain Implementations -*- C++ -*-===// 20b57cec5SDimitry Andric // 30b57cec5SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 40b57cec5SDimitry Andric // See https://llvm.org/LICENSE.txt for license information. 50b57cec5SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 60b57cec5SDimitry Andric // 70b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 80b57cec5SDimitry Andric 90b57cec5SDimitry Andric #include "Darwin.h" 10e8d8bef9SDimitry Andric #include "Arch/AArch64.h" 110b57cec5SDimitry Andric #include "Arch/ARM.h" 120b57cec5SDimitry Andric #include "CommonArgs.h" 130b57cec5SDimitry Andric #include "clang/Basic/AlignedAllocation.h" 140b57cec5SDimitry Andric #include "clang/Basic/ObjCRuntime.h" 150b57cec5SDimitry Andric #include "clang/Config/config.h" 160b57cec5SDimitry Andric #include "clang/Driver/Compilation.h" 170b57cec5SDimitry Andric #include "clang/Driver/Driver.h" 180b57cec5SDimitry Andric #include "clang/Driver/DriverDiagnostic.h" 190b57cec5SDimitry Andric #include "clang/Driver/Options.h" 200b57cec5SDimitry Andric #include "clang/Driver/SanitizerArgs.h" 210b57cec5SDimitry Andric #include "llvm/ADT/StringSwitch.h" 220b57cec5SDimitry Andric #include "llvm/Option/ArgList.h" 23480093f4SDimitry Andric #include "llvm/ProfileData/InstrProf.h" 240b57cec5SDimitry Andric #include "llvm/Support/Path.h" 250b57cec5SDimitry Andric #include "llvm/Support/ScopedPrinter.h" 265ffd83dbSDimitry Andric #include "llvm/Support/Threading.h" 270b57cec5SDimitry Andric #include "llvm/Support/VirtualFileSystem.h" 2806c3fb27SDimitry Andric #include "llvm/TargetParser/TargetParser.h" 2906c3fb27SDimitry Andric #include "llvm/TargetParser/Triple.h" 300b57cec5SDimitry Andric #include <cstdlib> // ::getenv 310b57cec5SDimitry Andric 320b57cec5SDimitry Andric using namespace clang::driver; 330b57cec5SDimitry Andric using namespace clang::driver::tools; 340b57cec5SDimitry Andric using namespace clang::driver::toolchains; 350b57cec5SDimitry Andric using namespace clang; 360b57cec5SDimitry Andric using namespace llvm::opt; 370b57cec5SDimitry Andric 38349cc55cSDimitry Andric static VersionTuple minimumMacCatalystDeploymentTarget() { 39fe6060f1SDimitry Andric return VersionTuple(13, 1); 40fe6060f1SDimitry Andric } 41fe6060f1SDimitry Andric 420b57cec5SDimitry Andric llvm::Triple::ArchType darwin::getArchTypeForMachOArchName(StringRef Str) { 430b57cec5SDimitry Andric // See arch(3) and llvm-gcc's driver-driver.c. We don't implement support for 440b57cec5SDimitry Andric // archs which Darwin doesn't use. 450b57cec5SDimitry Andric 460b57cec5SDimitry Andric // The matching this routine does is fairly pointless, since it is neither the 470b57cec5SDimitry Andric // complete architecture list, nor a reasonable subset. The problem is that 48bdd1243dSDimitry Andric // historically the driver accepts this and also ties its -march= 490b57cec5SDimitry Andric // handling to the architecture name, so we need to be careful before removing 500b57cec5SDimitry Andric // support for it. 510b57cec5SDimitry Andric 520b57cec5SDimitry Andric // This code must be kept in sync with Clang's Darwin specific argument 530b57cec5SDimitry Andric // translation. 540b57cec5SDimitry Andric 550b57cec5SDimitry Andric return llvm::StringSwitch<llvm::Triple::ArchType>(Str) 560b57cec5SDimitry Andric .Cases("i386", "i486", "i486SX", "i586", "i686", llvm::Triple::x86) 570b57cec5SDimitry Andric .Cases("pentium", "pentpro", "pentIIm3", "pentIIm5", "pentium4", 580b57cec5SDimitry Andric llvm::Triple::x86) 590b57cec5SDimitry Andric .Cases("x86_64", "x86_64h", llvm::Triple::x86_64) 60bdd1243dSDimitry Andric // This is derived from the driver. 610b57cec5SDimitry Andric .Cases("arm", "armv4t", "armv5", "armv6", "armv6m", llvm::Triple::arm) 620b57cec5SDimitry Andric .Cases("armv7", "armv7em", "armv7k", "armv7m", llvm::Triple::arm) 630b57cec5SDimitry Andric .Cases("armv7s", "xscale", llvm::Triple::arm) 64e8d8bef9SDimitry Andric .Cases("arm64", "arm64e", llvm::Triple::aarch64) 65480093f4SDimitry Andric .Case("arm64_32", llvm::Triple::aarch64_32) 660b57cec5SDimitry Andric .Case("r600", llvm::Triple::r600) 670b57cec5SDimitry Andric .Case("amdgcn", llvm::Triple::amdgcn) 680b57cec5SDimitry Andric .Case("nvptx", llvm::Triple::nvptx) 690b57cec5SDimitry Andric .Case("nvptx64", llvm::Triple::nvptx64) 700b57cec5SDimitry Andric .Case("amdil", llvm::Triple::amdil) 710b57cec5SDimitry Andric .Case("spir", llvm::Triple::spir) 720b57cec5SDimitry Andric .Default(llvm::Triple::UnknownArch); 730b57cec5SDimitry Andric } 740b57cec5SDimitry Andric 7506c3fb27SDimitry Andric void darwin::setTripleTypeForMachOArchName(llvm::Triple &T, StringRef Str, 7606c3fb27SDimitry Andric const ArgList &Args) { 770b57cec5SDimitry Andric const llvm::Triple::ArchType Arch = getArchTypeForMachOArchName(Str); 780b57cec5SDimitry Andric llvm::ARM::ArchKind ArchKind = llvm::ARM::parseArch(Str); 790b57cec5SDimitry Andric T.setArch(Arch); 80fe6060f1SDimitry Andric if (Arch != llvm::Triple::UnknownArch) 810b57cec5SDimitry Andric T.setArchName(Str); 82fe6060f1SDimitry Andric 83fe6060f1SDimitry Andric if (ArchKind == llvm::ARM::ArchKind::ARMV6M || 840b57cec5SDimitry Andric ArchKind == llvm::ARM::ArchKind::ARMV7M || 850b57cec5SDimitry Andric ArchKind == llvm::ARM::ArchKind::ARMV7EM) { 8606c3fb27SDimitry Andric // Don't reject these -version-min= if we have the appropriate triple. 8706c3fb27SDimitry Andric if (T.getOS() == llvm::Triple::IOS) 8806c3fb27SDimitry Andric for (Arg *A : Args.filtered(options::OPT_mios_version_min_EQ)) 8906c3fb27SDimitry Andric A->ignoreTargetSpecific(); 9006c3fb27SDimitry Andric if (T.getOS() == llvm::Triple::WatchOS) 9106c3fb27SDimitry Andric for (Arg *A : Args.filtered(options::OPT_mwatchos_version_min_EQ)) 9206c3fb27SDimitry Andric A->ignoreTargetSpecific(); 9306c3fb27SDimitry Andric if (T.getOS() == llvm::Triple::TvOS) 9406c3fb27SDimitry Andric for (Arg *A : Args.filtered(options::OPT_mtvos_version_min_EQ)) 9506c3fb27SDimitry Andric A->ignoreTargetSpecific(); 9606c3fb27SDimitry Andric 970b57cec5SDimitry Andric T.setOS(llvm::Triple::UnknownOS); 980b57cec5SDimitry Andric T.setObjectFormat(llvm::Triple::MachO); 990b57cec5SDimitry Andric } 1000b57cec5SDimitry Andric } 1010b57cec5SDimitry Andric 1020b57cec5SDimitry Andric void darwin::Assembler::ConstructJob(Compilation &C, const JobAction &JA, 1030b57cec5SDimitry Andric const InputInfo &Output, 1040b57cec5SDimitry Andric const InputInfoList &Inputs, 1050b57cec5SDimitry Andric const ArgList &Args, 1060b57cec5SDimitry Andric const char *LinkingOutput) const { 107349cc55cSDimitry Andric const llvm::Triple &T(getToolChain().getTriple()); 108349cc55cSDimitry Andric 1090b57cec5SDimitry Andric ArgStringList CmdArgs; 1100b57cec5SDimitry Andric 1110b57cec5SDimitry Andric assert(Inputs.size() == 1 && "Unexpected number of inputs."); 1120b57cec5SDimitry Andric const InputInfo &Input = Inputs[0]; 1130b57cec5SDimitry Andric 1140b57cec5SDimitry Andric // Determine the original source input. 1150b57cec5SDimitry Andric const Action *SourceAction = &JA; 1160b57cec5SDimitry Andric while (SourceAction->getKind() != Action::InputClass) { 1170b57cec5SDimitry Andric assert(!SourceAction->getInputs().empty() && "unexpected root action!"); 1180b57cec5SDimitry Andric SourceAction = SourceAction->getInputs()[0]; 1190b57cec5SDimitry Andric } 1200b57cec5SDimitry Andric 1210b57cec5SDimitry Andric // If -fno-integrated-as is used add -Q to the darwin assembler driver to make 1220b57cec5SDimitry Andric // sure it runs its system assembler not clang's integrated assembler. 1230b57cec5SDimitry Andric // Applicable to darwin11+ and Xcode 4+. darwin<10 lacked integrated-as. 1240b57cec5SDimitry Andric // FIXME: at run-time detect assembler capabilities or rely on version 1250b57cec5SDimitry Andric // information forwarded by -target-assembler-version. 1260b57cec5SDimitry Andric if (Args.hasArg(options::OPT_fno_integrated_as)) { 1270b57cec5SDimitry Andric if (!(T.isMacOSX() && T.isMacOSXVersionLT(10, 7))) 1280b57cec5SDimitry Andric CmdArgs.push_back("-Q"); 1290b57cec5SDimitry Andric } 1300b57cec5SDimitry Andric 1310b57cec5SDimitry Andric // Forward -g, assuming we are dealing with an actual assembly file. 1320b57cec5SDimitry Andric if (SourceAction->getType() == types::TY_Asm || 1330b57cec5SDimitry Andric SourceAction->getType() == types::TY_PP_Asm) { 1340b57cec5SDimitry Andric if (Args.hasArg(options::OPT_gstabs)) 1350b57cec5SDimitry Andric CmdArgs.push_back("--gstabs"); 1360b57cec5SDimitry Andric else if (Args.hasArg(options::OPT_g_Group)) 1370b57cec5SDimitry Andric CmdArgs.push_back("-g"); 1380b57cec5SDimitry Andric } 1390b57cec5SDimitry Andric 1400b57cec5SDimitry Andric // Derived from asm spec. 1410b57cec5SDimitry Andric AddMachOArch(Args, CmdArgs); 1420b57cec5SDimitry Andric 1430b57cec5SDimitry Andric // Use -force_cpusubtype_ALL on x86 by default. 144349cc55cSDimitry Andric if (T.isX86() || Args.hasArg(options::OPT_force__cpusubtype__ALL)) 1450b57cec5SDimitry Andric CmdArgs.push_back("-force_cpusubtype_ALL"); 1460b57cec5SDimitry Andric 1470b57cec5SDimitry Andric if (getToolChain().getArch() != llvm::Triple::x86_64 && 1480b57cec5SDimitry Andric (((Args.hasArg(options::OPT_mkernel) || 1490b57cec5SDimitry Andric Args.hasArg(options::OPT_fapple_kext)) && 1500b57cec5SDimitry Andric getMachOToolChain().isKernelStatic()) || 1510b57cec5SDimitry Andric Args.hasArg(options::OPT_static))) 1520b57cec5SDimitry Andric CmdArgs.push_back("-static"); 1530b57cec5SDimitry Andric 1540b57cec5SDimitry Andric Args.AddAllArgValues(CmdArgs, options::OPT_Wa_COMMA, options::OPT_Xassembler); 1550b57cec5SDimitry Andric 1560b57cec5SDimitry Andric assert(Output.isFilename() && "Unexpected lipo output."); 1570b57cec5SDimitry Andric CmdArgs.push_back("-o"); 1580b57cec5SDimitry Andric CmdArgs.push_back(Output.getFilename()); 1590b57cec5SDimitry Andric 1600b57cec5SDimitry Andric assert(Input.isFilename() && "Invalid input."); 1610b57cec5SDimitry Andric CmdArgs.push_back(Input.getFilename()); 1620b57cec5SDimitry Andric 1630b57cec5SDimitry Andric // asm_final spec is empty. 1640b57cec5SDimitry Andric 1650b57cec5SDimitry Andric const char *Exec = Args.MakeArgString(getToolChain().GetProgramPath("as")); 1665ffd83dbSDimitry Andric C.addCommand(std::make_unique<Command>(JA, *this, ResponseFileSupport::None(), 167e8d8bef9SDimitry Andric Exec, CmdArgs, Inputs, Output)); 1680b57cec5SDimitry Andric } 1690b57cec5SDimitry Andric 1700b57cec5SDimitry Andric void darwin::MachOTool::anchor() {} 1710b57cec5SDimitry Andric 1720b57cec5SDimitry Andric void darwin::MachOTool::AddMachOArch(const ArgList &Args, 1730b57cec5SDimitry Andric ArgStringList &CmdArgs) const { 1740b57cec5SDimitry Andric StringRef ArchName = getMachOToolChain().getMachOArchName(Args); 1750b57cec5SDimitry Andric 1760b57cec5SDimitry Andric // Derived from darwin_arch spec. 1770b57cec5SDimitry Andric CmdArgs.push_back("-arch"); 1780b57cec5SDimitry Andric CmdArgs.push_back(Args.MakeArgString(ArchName)); 1790b57cec5SDimitry Andric 1800b57cec5SDimitry Andric // FIXME: Is this needed anymore? 1810b57cec5SDimitry Andric if (ArchName == "arm") 1820b57cec5SDimitry Andric CmdArgs.push_back("-force_cpusubtype_ALL"); 1830b57cec5SDimitry Andric } 1840b57cec5SDimitry Andric 1850b57cec5SDimitry Andric bool darwin::Linker::NeedsTempPath(const InputInfoList &Inputs) const { 1860b57cec5SDimitry Andric // We only need to generate a temp path for LTO if we aren't compiling object 1870b57cec5SDimitry Andric // files. When compiling source files, we run 'dsymutil' after linking. We 1880b57cec5SDimitry Andric // don't run 'dsymutil' when compiling object files. 1890b57cec5SDimitry Andric for (const auto &Input : Inputs) 1900b57cec5SDimitry Andric if (Input.getType() != types::TY_Object) 1910b57cec5SDimitry Andric return true; 1920b57cec5SDimitry Andric 1930b57cec5SDimitry Andric return false; 1940b57cec5SDimitry Andric } 1950b57cec5SDimitry Andric 1960b57cec5SDimitry Andric /// Pass -no_deduplicate to ld64 under certain conditions: 1970b57cec5SDimitry Andric /// 1980b57cec5SDimitry Andric /// - Either -O0 or -O1 is explicitly specified 1990b57cec5SDimitry Andric /// - No -O option is specified *and* this is a compile+link (implicit -O0) 2000b57cec5SDimitry Andric /// 2010b57cec5SDimitry Andric /// Also do *not* add -no_deduplicate when no -O option is specified and this 2020b57cec5SDimitry Andric /// is just a link (we can't imply -O0) 2030b57cec5SDimitry Andric static bool shouldLinkerNotDedup(bool IsLinkerOnlyAction, const ArgList &Args) { 2040b57cec5SDimitry Andric if (Arg *A = Args.getLastArg(options::OPT_O_Group)) { 2050b57cec5SDimitry Andric if (A->getOption().matches(options::OPT_O0)) 2060b57cec5SDimitry Andric return true; 2070b57cec5SDimitry Andric if (A->getOption().matches(options::OPT_O)) 2080b57cec5SDimitry Andric return llvm::StringSwitch<bool>(A->getValue()) 2090b57cec5SDimitry Andric .Case("1", true) 2100b57cec5SDimitry Andric .Default(false); 2110b57cec5SDimitry Andric return false; // OPT_Ofast & OPT_O4 2120b57cec5SDimitry Andric } 2130b57cec5SDimitry Andric 2140b57cec5SDimitry Andric if (!IsLinkerOnlyAction) // Implicit -O0 for compile+linker only. 2150b57cec5SDimitry Andric return true; 2160b57cec5SDimitry Andric return false; 2170b57cec5SDimitry Andric } 2180b57cec5SDimitry Andric 2190b57cec5SDimitry Andric void darwin::Linker::AddLinkArgs(Compilation &C, const ArgList &Args, 2200b57cec5SDimitry Andric ArgStringList &CmdArgs, 2215ffd83dbSDimitry Andric const InputInfoList &Inputs, 2227a6dacacSDimitry Andric VersionTuple Version, bool LinkerIsLLD, 2237a6dacacSDimitry Andric bool UsePlatformVersion) const { 2240b57cec5SDimitry Andric const Driver &D = getToolChain().getDriver(); 2250b57cec5SDimitry Andric const toolchains::MachO &MachOTC = getMachOToolChain(); 2260b57cec5SDimitry Andric 2270b57cec5SDimitry Andric // Newer linkers support -demangle. Pass it if supported and not disabled by 2280b57cec5SDimitry Andric // the user. 22981ad6265SDimitry Andric if ((Version >= VersionTuple(100) || LinkerIsLLD) && 230e8d8bef9SDimitry Andric !Args.hasArg(options::OPT_Z_Xlinker__no_demangle)) 2310b57cec5SDimitry Andric CmdArgs.push_back("-demangle"); 2320b57cec5SDimitry Andric 23381ad6265SDimitry Andric if (Args.hasArg(options::OPT_rdynamic) && 23481ad6265SDimitry Andric (Version >= VersionTuple(137) || LinkerIsLLD)) 2350b57cec5SDimitry Andric CmdArgs.push_back("-export_dynamic"); 2360b57cec5SDimitry Andric 2370b57cec5SDimitry Andric // If we are using App Extension restrictions, pass a flag to the linker 2380b57cec5SDimitry Andric // telling it that the compiled code has been audited. 2390b57cec5SDimitry Andric if (Args.hasFlag(options::OPT_fapplication_extension, 2400b57cec5SDimitry Andric options::OPT_fno_application_extension, false)) 2410b57cec5SDimitry Andric CmdArgs.push_back("-application_extension"); 2420b57cec5SDimitry Andric 24381ad6265SDimitry Andric if (D.isUsingLTO() && (Version >= VersionTuple(116) || LinkerIsLLD) && 24481ad6265SDimitry Andric NeedsTempPath(Inputs)) { 2450b57cec5SDimitry Andric std::string TmpPathName; 2460b57cec5SDimitry Andric if (D.getLTOMode() == LTOK_Full) { 2470b57cec5SDimitry Andric // If we are using full LTO, then automatically create a temporary file 2480b57cec5SDimitry Andric // path for the linker to use, so that it's lifetime will extend past a 2490b57cec5SDimitry Andric // possible dsymutil step. 2500b57cec5SDimitry Andric TmpPathName = 2510b57cec5SDimitry Andric D.GetTemporaryPath("cc", types::getTypeTempSuffix(types::TY_Object)); 2520b57cec5SDimitry Andric } else if (D.getLTOMode() == LTOK_Thin) 2530b57cec5SDimitry Andric // If we are using thin LTO, then create a directory instead. 2540b57cec5SDimitry Andric TmpPathName = D.GetTemporaryDirectory("thinlto"); 2550b57cec5SDimitry Andric 2560b57cec5SDimitry Andric if (!TmpPathName.empty()) { 2570b57cec5SDimitry Andric auto *TmpPath = C.getArgs().MakeArgString(TmpPathName); 2580b57cec5SDimitry Andric C.addTempFile(TmpPath); 2590b57cec5SDimitry Andric CmdArgs.push_back("-object_path_lto"); 2600b57cec5SDimitry Andric CmdArgs.push_back(TmpPath); 2610b57cec5SDimitry Andric } 2620b57cec5SDimitry Andric } 2630b57cec5SDimitry Andric 2640b57cec5SDimitry Andric // Use -lto_library option to specify the libLTO.dylib path. Try to find 2650b57cec5SDimitry Andric // it in clang installed libraries. ld64 will only look at this argument 2660b57cec5SDimitry Andric // when it actually uses LTO, so libLTO.dylib only needs to exist at link 2670b57cec5SDimitry Andric // time if ld64 decides that it needs to use LTO. 2680b57cec5SDimitry Andric // Since this is passed unconditionally, ld64 will never look for libLTO.dylib 2690b57cec5SDimitry Andric // next to it. That's ok since ld64 using a libLTO.dylib not matching the 2700b57cec5SDimitry Andric // clang version won't work anyways. 271e8d8bef9SDimitry Andric // lld is built at the same revision as clang and statically links in 272e8d8bef9SDimitry Andric // LLVM libraries, so it doesn't need libLTO.dylib. 27381ad6265SDimitry Andric if (Version >= VersionTuple(133) && !LinkerIsLLD) { 2740b57cec5SDimitry Andric // Search for libLTO in <InstalledDir>/../lib/libLTO.dylib 2750b57cec5SDimitry Andric StringRef P = llvm::sys::path::parent_path(D.Dir); 2760b57cec5SDimitry Andric SmallString<128> LibLTOPath(P); 2770b57cec5SDimitry Andric llvm::sys::path::append(LibLTOPath, "lib"); 2780b57cec5SDimitry Andric llvm::sys::path::append(LibLTOPath, "libLTO.dylib"); 2790b57cec5SDimitry Andric CmdArgs.push_back("-lto_library"); 2800b57cec5SDimitry Andric CmdArgs.push_back(C.getArgs().MakeArgString(LibLTOPath)); 2810b57cec5SDimitry Andric } 2820b57cec5SDimitry Andric 28381ad6265SDimitry Andric // ld64 version 262 and above runs the deduplicate pass by default. 28481ad6265SDimitry Andric // FIXME: lld doesn't dedup by default. Should we pass `--icf=safe` 28581ad6265SDimitry Andric // if `!shouldLinkerNotDedup()` if LinkerIsLLD here? 28681ad6265SDimitry Andric if (Version >= VersionTuple(262) && 28781ad6265SDimitry Andric shouldLinkerNotDedup(C.getJobs().empty(), Args)) 2880b57cec5SDimitry Andric CmdArgs.push_back("-no_deduplicate"); 2890b57cec5SDimitry Andric 2900b57cec5SDimitry Andric // Derived from the "link" spec. 2910b57cec5SDimitry Andric Args.AddAllArgs(CmdArgs, options::OPT_static); 2920b57cec5SDimitry Andric if (!Args.hasArg(options::OPT_static)) 2930b57cec5SDimitry Andric CmdArgs.push_back("-dynamic"); 2940b57cec5SDimitry Andric if (Args.hasArg(options::OPT_fgnu_runtime)) { 2950b57cec5SDimitry Andric // FIXME: gcc replaces -lobjc in forward args with -lobjc-gnu 2960b57cec5SDimitry Andric // here. How do we wish to handle such things? 2970b57cec5SDimitry Andric } 2980b57cec5SDimitry Andric 2990b57cec5SDimitry Andric if (!Args.hasArg(options::OPT_dynamiclib)) { 3000b57cec5SDimitry Andric AddMachOArch(Args, CmdArgs); 3010b57cec5SDimitry Andric // FIXME: Why do this only on this path? 3020b57cec5SDimitry Andric Args.AddLastArg(CmdArgs, options::OPT_force__cpusubtype__ALL); 3030b57cec5SDimitry Andric 3040b57cec5SDimitry Andric Args.AddLastArg(CmdArgs, options::OPT_bundle); 3050b57cec5SDimitry Andric Args.AddAllArgs(CmdArgs, options::OPT_bundle__loader); 3060b57cec5SDimitry Andric Args.AddAllArgs(CmdArgs, options::OPT_client__name); 3070b57cec5SDimitry Andric 3080b57cec5SDimitry Andric Arg *A; 3090b57cec5SDimitry Andric if ((A = Args.getLastArg(options::OPT_compatibility__version)) || 3100b57cec5SDimitry Andric (A = Args.getLastArg(options::OPT_current__version)) || 3110b57cec5SDimitry Andric (A = Args.getLastArg(options::OPT_install__name))) 3120b57cec5SDimitry Andric D.Diag(diag::err_drv_argument_only_allowed_with) << A->getAsString(Args) 3130b57cec5SDimitry Andric << "-dynamiclib"; 3140b57cec5SDimitry Andric 3150b57cec5SDimitry Andric Args.AddLastArg(CmdArgs, options::OPT_force__flat__namespace); 3160b57cec5SDimitry Andric Args.AddLastArg(CmdArgs, options::OPT_keep__private__externs); 3170b57cec5SDimitry Andric Args.AddLastArg(CmdArgs, options::OPT_private__bundle); 3180b57cec5SDimitry Andric } else { 3190b57cec5SDimitry Andric CmdArgs.push_back("-dylib"); 3200b57cec5SDimitry Andric 3210b57cec5SDimitry Andric Arg *A; 3220b57cec5SDimitry Andric if ((A = Args.getLastArg(options::OPT_bundle)) || 3230b57cec5SDimitry Andric (A = Args.getLastArg(options::OPT_bundle__loader)) || 3240b57cec5SDimitry Andric (A = Args.getLastArg(options::OPT_client__name)) || 3250b57cec5SDimitry Andric (A = Args.getLastArg(options::OPT_force__flat__namespace)) || 3260b57cec5SDimitry Andric (A = Args.getLastArg(options::OPT_keep__private__externs)) || 3270b57cec5SDimitry Andric (A = Args.getLastArg(options::OPT_private__bundle))) 3280b57cec5SDimitry Andric D.Diag(diag::err_drv_argument_not_allowed_with) << A->getAsString(Args) 3290b57cec5SDimitry Andric << "-dynamiclib"; 3300b57cec5SDimitry Andric 3310b57cec5SDimitry Andric Args.AddAllArgsTranslated(CmdArgs, options::OPT_compatibility__version, 3320b57cec5SDimitry Andric "-dylib_compatibility_version"); 3330b57cec5SDimitry Andric Args.AddAllArgsTranslated(CmdArgs, options::OPT_current__version, 3340b57cec5SDimitry Andric "-dylib_current_version"); 3350b57cec5SDimitry Andric 3360b57cec5SDimitry Andric AddMachOArch(Args, CmdArgs); 3370b57cec5SDimitry Andric 3380b57cec5SDimitry Andric Args.AddAllArgsTranslated(CmdArgs, options::OPT_install__name, 3390b57cec5SDimitry Andric "-dylib_install_name"); 3400b57cec5SDimitry Andric } 3410b57cec5SDimitry Andric 3420b57cec5SDimitry Andric Args.AddLastArg(CmdArgs, options::OPT_all__load); 3430b57cec5SDimitry Andric Args.AddAllArgs(CmdArgs, options::OPT_allowable__client); 3440b57cec5SDimitry Andric Args.AddLastArg(CmdArgs, options::OPT_bind__at__load); 3450b57cec5SDimitry Andric if (MachOTC.isTargetIOSBased()) 3460b57cec5SDimitry Andric Args.AddLastArg(CmdArgs, options::OPT_arch__errors__fatal); 3470b57cec5SDimitry Andric Args.AddLastArg(CmdArgs, options::OPT_dead__strip); 3480b57cec5SDimitry Andric Args.AddLastArg(CmdArgs, options::OPT_no__dead__strip__inits__and__terms); 3490b57cec5SDimitry Andric Args.AddAllArgs(CmdArgs, options::OPT_dylib__file); 3500b57cec5SDimitry Andric Args.AddLastArg(CmdArgs, options::OPT_dynamic); 3510b57cec5SDimitry Andric Args.AddAllArgs(CmdArgs, options::OPT_exported__symbols__list); 3520b57cec5SDimitry Andric Args.AddLastArg(CmdArgs, options::OPT_flat__namespace); 3530b57cec5SDimitry Andric Args.AddAllArgs(CmdArgs, options::OPT_force__load); 3540b57cec5SDimitry Andric Args.AddAllArgs(CmdArgs, options::OPT_headerpad__max__install__names); 3550b57cec5SDimitry Andric Args.AddAllArgs(CmdArgs, options::OPT_image__base); 3560b57cec5SDimitry Andric Args.AddAllArgs(CmdArgs, options::OPT_init); 3570b57cec5SDimitry Andric 3580b57cec5SDimitry Andric // Add the deployment target. 3597a6dacacSDimitry Andric if (Version >= VersionTuple(520) || LinkerIsLLD || UsePlatformVersion) 360480093f4SDimitry Andric MachOTC.addPlatformVersionArgs(Args, CmdArgs); 361480093f4SDimitry Andric else 3620b57cec5SDimitry Andric MachOTC.addMinVersionArgs(Args, CmdArgs); 3630b57cec5SDimitry Andric 3640b57cec5SDimitry Andric Args.AddLastArg(CmdArgs, options::OPT_nomultidefs); 3650b57cec5SDimitry Andric Args.AddLastArg(CmdArgs, options::OPT_multi__module); 3660b57cec5SDimitry Andric Args.AddLastArg(CmdArgs, options::OPT_single__module); 3670b57cec5SDimitry Andric Args.AddAllArgs(CmdArgs, options::OPT_multiply__defined); 3680b57cec5SDimitry Andric Args.AddAllArgs(CmdArgs, options::OPT_multiply__defined__unused); 3690b57cec5SDimitry Andric 3700b57cec5SDimitry Andric if (const Arg *A = 3710b57cec5SDimitry Andric Args.getLastArg(options::OPT_fpie, options::OPT_fPIE, 3720b57cec5SDimitry Andric options::OPT_fno_pie, options::OPT_fno_PIE)) { 3730b57cec5SDimitry Andric if (A->getOption().matches(options::OPT_fpie) || 3740b57cec5SDimitry Andric A->getOption().matches(options::OPT_fPIE)) 3750b57cec5SDimitry Andric CmdArgs.push_back("-pie"); 3760b57cec5SDimitry Andric else 3770b57cec5SDimitry Andric CmdArgs.push_back("-no_pie"); 3780b57cec5SDimitry Andric } 3790b57cec5SDimitry Andric 3800b57cec5SDimitry Andric // for embed-bitcode, use -bitcode_bundle in linker command 3810b57cec5SDimitry Andric if (C.getDriver().embedBitcodeEnabled()) { 3820b57cec5SDimitry Andric // Check if the toolchain supports bitcode build flow. 3830b57cec5SDimitry Andric if (MachOTC.SupportsEmbeddedBitcode()) { 3840b57cec5SDimitry Andric CmdArgs.push_back("-bitcode_bundle"); 38581ad6265SDimitry Andric // FIXME: Pass this if LinkerIsLLD too, once it implements this flag. 38681ad6265SDimitry Andric if (C.getDriver().embedBitcodeMarkerOnly() && 38781ad6265SDimitry Andric Version >= VersionTuple(278)) { 3880b57cec5SDimitry Andric CmdArgs.push_back("-bitcode_process_mode"); 3890b57cec5SDimitry Andric CmdArgs.push_back("marker"); 3900b57cec5SDimitry Andric } 3910b57cec5SDimitry Andric } else 3920b57cec5SDimitry Andric D.Diag(diag::err_drv_bitcode_unsupported_on_toolchain); 3930b57cec5SDimitry Andric } 3940b57cec5SDimitry Andric 395fe6060f1SDimitry Andric // If GlobalISel is enabled, pass it through to LLVM. 396fe6060f1SDimitry Andric if (Arg *A = Args.getLastArg(options::OPT_fglobal_isel, 397fe6060f1SDimitry Andric options::OPT_fno_global_isel)) { 398fe6060f1SDimitry Andric if (A->getOption().matches(options::OPT_fglobal_isel)) { 399fe6060f1SDimitry Andric CmdArgs.push_back("-mllvm"); 400fe6060f1SDimitry Andric CmdArgs.push_back("-global-isel"); 401fe6060f1SDimitry Andric // Disable abort and fall back to SDAG silently. 402fe6060f1SDimitry Andric CmdArgs.push_back("-mllvm"); 403fe6060f1SDimitry Andric CmdArgs.push_back("-global-isel-abort=0"); 404fe6060f1SDimitry Andric } 405fe6060f1SDimitry Andric } 406fe6060f1SDimitry Andric 40706c3fb27SDimitry Andric if (Args.hasArg(options::OPT_mkernel) || 40806c3fb27SDimitry Andric Args.hasArg(options::OPT_fapple_kext) || 40906c3fb27SDimitry Andric Args.hasArg(options::OPT_ffreestanding)) { 41006c3fb27SDimitry Andric CmdArgs.push_back("-mllvm"); 41106c3fb27SDimitry Andric CmdArgs.push_back("-disable-atexit-based-global-dtor-lowering"); 41206c3fb27SDimitry Andric } 41306c3fb27SDimitry Andric 4140b57cec5SDimitry Andric Args.AddLastArg(CmdArgs, options::OPT_prebind); 4150b57cec5SDimitry Andric Args.AddLastArg(CmdArgs, options::OPT_noprebind); 4160b57cec5SDimitry Andric Args.AddLastArg(CmdArgs, options::OPT_nofixprebinding); 4170b57cec5SDimitry Andric Args.AddLastArg(CmdArgs, options::OPT_prebind__all__twolevel__modules); 4180b57cec5SDimitry Andric Args.AddLastArg(CmdArgs, options::OPT_read__only__relocs); 4190b57cec5SDimitry Andric Args.AddAllArgs(CmdArgs, options::OPT_sectcreate); 4200b57cec5SDimitry Andric Args.AddAllArgs(CmdArgs, options::OPT_sectorder); 4210b57cec5SDimitry Andric Args.AddAllArgs(CmdArgs, options::OPT_seg1addr); 4220b57cec5SDimitry Andric Args.AddAllArgs(CmdArgs, options::OPT_segprot); 4230b57cec5SDimitry Andric Args.AddAllArgs(CmdArgs, options::OPT_segaddr); 4240b57cec5SDimitry Andric Args.AddAllArgs(CmdArgs, options::OPT_segs__read__only__addr); 4250b57cec5SDimitry Andric Args.AddAllArgs(CmdArgs, options::OPT_segs__read__write__addr); 4260b57cec5SDimitry Andric Args.AddAllArgs(CmdArgs, options::OPT_seg__addr__table); 4270b57cec5SDimitry Andric Args.AddAllArgs(CmdArgs, options::OPT_seg__addr__table__filename); 4280b57cec5SDimitry Andric Args.AddAllArgs(CmdArgs, options::OPT_sub__library); 4290b57cec5SDimitry Andric Args.AddAllArgs(CmdArgs, options::OPT_sub__umbrella); 4300b57cec5SDimitry Andric 4310b57cec5SDimitry Andric // Give --sysroot= preference, over the Apple specific behavior to also use 4320b57cec5SDimitry Andric // --isysroot as the syslibroot. 4330b57cec5SDimitry Andric StringRef sysroot = C.getSysRoot(); 4340b57cec5SDimitry Andric if (sysroot != "") { 4350b57cec5SDimitry Andric CmdArgs.push_back("-syslibroot"); 4360b57cec5SDimitry Andric CmdArgs.push_back(C.getArgs().MakeArgString(sysroot)); 4370b57cec5SDimitry Andric } else if (const Arg *A = Args.getLastArg(options::OPT_isysroot)) { 4380b57cec5SDimitry Andric CmdArgs.push_back("-syslibroot"); 4390b57cec5SDimitry Andric CmdArgs.push_back(A->getValue()); 4400b57cec5SDimitry Andric } 4410b57cec5SDimitry Andric 4420b57cec5SDimitry Andric Args.AddLastArg(CmdArgs, options::OPT_twolevel__namespace); 4430b57cec5SDimitry Andric Args.AddLastArg(CmdArgs, options::OPT_twolevel__namespace__hints); 4440b57cec5SDimitry Andric Args.AddAllArgs(CmdArgs, options::OPT_umbrella); 4450b57cec5SDimitry Andric Args.AddAllArgs(CmdArgs, options::OPT_undefined); 4460b57cec5SDimitry Andric Args.AddAllArgs(CmdArgs, options::OPT_unexported__symbols__list); 4470b57cec5SDimitry Andric Args.AddAllArgs(CmdArgs, options::OPT_weak__reference__mismatches); 4480b57cec5SDimitry Andric Args.AddLastArg(CmdArgs, options::OPT_X_Flag); 4490b57cec5SDimitry Andric Args.AddAllArgs(CmdArgs, options::OPT_y); 4500b57cec5SDimitry Andric Args.AddLastArg(CmdArgs, options::OPT_w); 4510b57cec5SDimitry Andric Args.AddAllArgs(CmdArgs, options::OPT_pagezero__size); 4520b57cec5SDimitry Andric Args.AddAllArgs(CmdArgs, options::OPT_segs__read__); 4530b57cec5SDimitry Andric Args.AddLastArg(CmdArgs, options::OPT_seglinkedit); 4540b57cec5SDimitry Andric Args.AddLastArg(CmdArgs, options::OPT_noseglinkedit); 4550b57cec5SDimitry Andric Args.AddAllArgs(CmdArgs, options::OPT_sectalign); 4560b57cec5SDimitry Andric Args.AddAllArgs(CmdArgs, options::OPT_sectobjectsymbols); 4570b57cec5SDimitry Andric Args.AddAllArgs(CmdArgs, options::OPT_segcreate); 458fe6060f1SDimitry Andric Args.AddLastArg(CmdArgs, options::OPT_why_load); 4590b57cec5SDimitry Andric Args.AddLastArg(CmdArgs, options::OPT_whatsloaded); 4600b57cec5SDimitry Andric Args.AddAllArgs(CmdArgs, options::OPT_dylinker__install__name); 4610b57cec5SDimitry Andric Args.AddLastArg(CmdArgs, options::OPT_dylinker); 4620b57cec5SDimitry Andric Args.AddLastArg(CmdArgs, options::OPT_Mach); 46306c3fb27SDimitry Andric 46406c3fb27SDimitry Andric if (LinkerIsLLD) { 46506c3fb27SDimitry Andric if (auto *CSPGOGenerateArg = getLastCSProfileGenerateArg(Args)) { 46606c3fb27SDimitry Andric SmallString<128> Path(CSPGOGenerateArg->getNumValues() == 0 46706c3fb27SDimitry Andric ? "" 46806c3fb27SDimitry Andric : CSPGOGenerateArg->getValue()); 46906c3fb27SDimitry Andric llvm::sys::path::append(Path, "default_%m.profraw"); 47006c3fb27SDimitry Andric CmdArgs.push_back("--cs-profile-generate"); 47106c3fb27SDimitry Andric CmdArgs.push_back(Args.MakeArgString(Twine("--cs-profile-path=") + Path)); 47206c3fb27SDimitry Andric } else if (auto *ProfileUseArg = getLastProfileUseArg(Args)) { 47306c3fb27SDimitry Andric SmallString<128> Path( 47406c3fb27SDimitry Andric ProfileUseArg->getNumValues() == 0 ? "" : ProfileUseArg->getValue()); 47506c3fb27SDimitry Andric if (Path.empty() || llvm::sys::fs::is_directory(Path)) 47606c3fb27SDimitry Andric llvm::sys::path::append(Path, "default.profdata"); 47706c3fb27SDimitry Andric CmdArgs.push_back(Args.MakeArgString(Twine("--cs-profile-path=") + Path)); 47806c3fb27SDimitry Andric } 47906c3fb27SDimitry Andric } 4800b57cec5SDimitry Andric } 4810b57cec5SDimitry Andric 4820b57cec5SDimitry Andric /// Determine whether we are linking the ObjC runtime. 4830b57cec5SDimitry Andric static bool isObjCRuntimeLinked(const ArgList &Args) { 4840b57cec5SDimitry Andric if (isObjCAutoRefCount(Args)) { 4850b57cec5SDimitry Andric Args.ClaimAllArgs(options::OPT_fobjc_link_runtime); 4860b57cec5SDimitry Andric return true; 4870b57cec5SDimitry Andric } 4880b57cec5SDimitry Andric return Args.hasArg(options::OPT_fobjc_link_runtime); 4890b57cec5SDimitry Andric } 4900b57cec5SDimitry Andric 4915ffd83dbSDimitry Andric static bool checkRemarksOptions(const Driver &D, const ArgList &Args, 4925ffd83dbSDimitry Andric const llvm::Triple &Triple) { 4935ffd83dbSDimitry Andric // When enabling remarks, we need to error if: 4945ffd83dbSDimitry Andric // * The remark file is specified but we're targeting multiple architectures, 4955ffd83dbSDimitry Andric // which means more than one remark file is being generated. 4965ffd83dbSDimitry Andric bool hasMultipleInvocations = 4975ffd83dbSDimitry Andric Args.getAllArgValues(options::OPT_arch).size() > 1; 4985ffd83dbSDimitry Andric bool hasExplicitOutputFile = 4995ffd83dbSDimitry Andric Args.getLastArg(options::OPT_foptimization_record_file_EQ); 5005ffd83dbSDimitry Andric if (hasMultipleInvocations && hasExplicitOutputFile) { 5015ffd83dbSDimitry Andric D.Diag(diag::err_drv_invalid_output_with_multiple_archs) 5025ffd83dbSDimitry Andric << "-foptimization-record-file"; 5035ffd83dbSDimitry Andric return false; 5045ffd83dbSDimitry Andric } 5055ffd83dbSDimitry Andric return true; 5065ffd83dbSDimitry Andric } 5075ffd83dbSDimitry Andric 5085ffd83dbSDimitry Andric static void renderRemarksOptions(const ArgList &Args, ArgStringList &CmdArgs, 5095ffd83dbSDimitry Andric const llvm::Triple &Triple, 5105ffd83dbSDimitry Andric const InputInfo &Output, const JobAction &JA) { 5115ffd83dbSDimitry Andric StringRef Format = "yaml"; 5125ffd83dbSDimitry Andric if (const Arg *A = Args.getLastArg(options::OPT_fsave_optimization_record_EQ)) 5135ffd83dbSDimitry Andric Format = A->getValue(); 5145ffd83dbSDimitry Andric 5155ffd83dbSDimitry Andric CmdArgs.push_back("-mllvm"); 5165ffd83dbSDimitry Andric CmdArgs.push_back("-lto-pass-remarks-output"); 5175ffd83dbSDimitry Andric CmdArgs.push_back("-mllvm"); 5185ffd83dbSDimitry Andric 5195ffd83dbSDimitry Andric const Arg *A = Args.getLastArg(options::OPT_foptimization_record_file_EQ); 5205ffd83dbSDimitry Andric if (A) { 5215ffd83dbSDimitry Andric CmdArgs.push_back(A->getValue()); 5225ffd83dbSDimitry Andric } else { 5235ffd83dbSDimitry Andric assert(Output.isFilename() && "Unexpected ld output."); 5245ffd83dbSDimitry Andric SmallString<128> F; 5255ffd83dbSDimitry Andric F = Output.getFilename(); 5265ffd83dbSDimitry Andric F += ".opt."; 5275ffd83dbSDimitry Andric F += Format; 5285ffd83dbSDimitry Andric 5295ffd83dbSDimitry Andric CmdArgs.push_back(Args.MakeArgString(F)); 5305ffd83dbSDimitry Andric } 5315ffd83dbSDimitry Andric 5325ffd83dbSDimitry Andric if (const Arg *A = 5335ffd83dbSDimitry Andric Args.getLastArg(options::OPT_foptimization_record_passes_EQ)) { 5345ffd83dbSDimitry Andric CmdArgs.push_back("-mllvm"); 5355ffd83dbSDimitry Andric std::string Passes = 5365ffd83dbSDimitry Andric std::string("-lto-pass-remarks-filter=") + A->getValue(); 5375ffd83dbSDimitry Andric CmdArgs.push_back(Args.MakeArgString(Passes)); 5385ffd83dbSDimitry Andric } 5395ffd83dbSDimitry Andric 5405ffd83dbSDimitry Andric if (!Format.empty()) { 5415ffd83dbSDimitry Andric CmdArgs.push_back("-mllvm"); 5425ffd83dbSDimitry Andric Twine FormatArg = Twine("-lto-pass-remarks-format=") + Format; 5435ffd83dbSDimitry Andric CmdArgs.push_back(Args.MakeArgString(FormatArg)); 5445ffd83dbSDimitry Andric } 5455ffd83dbSDimitry Andric 5465ffd83dbSDimitry Andric if (getLastProfileUseArg(Args)) { 5475ffd83dbSDimitry Andric CmdArgs.push_back("-mllvm"); 5485ffd83dbSDimitry Andric CmdArgs.push_back("-lto-pass-remarks-with-hotness"); 5495ffd83dbSDimitry Andric 5505ffd83dbSDimitry Andric if (const Arg *A = 5515ffd83dbSDimitry Andric Args.getLastArg(options::OPT_fdiagnostics_hotness_threshold_EQ)) { 5525ffd83dbSDimitry Andric CmdArgs.push_back("-mllvm"); 5535ffd83dbSDimitry Andric std::string Opt = 5545ffd83dbSDimitry Andric std::string("-lto-pass-remarks-hotness-threshold=") + A->getValue(); 5555ffd83dbSDimitry Andric CmdArgs.push_back(Args.MakeArgString(Opt)); 5565ffd83dbSDimitry Andric } 5575ffd83dbSDimitry Andric } 5585ffd83dbSDimitry Andric } 5595ffd83dbSDimitry Andric 560bdd1243dSDimitry Andric static void AppendPlatformPrefix(SmallString<128> &Path, const llvm::Triple &T); 561bdd1243dSDimitry Andric 5620b57cec5SDimitry Andric void darwin::Linker::ConstructJob(Compilation &C, const JobAction &JA, 5630b57cec5SDimitry Andric const InputInfo &Output, 5640b57cec5SDimitry Andric const InputInfoList &Inputs, 5650b57cec5SDimitry Andric const ArgList &Args, 5660b57cec5SDimitry Andric const char *LinkingOutput) const { 5670b57cec5SDimitry Andric assert(Output.getType() == types::TY_Image && "Invalid linker output type."); 5680b57cec5SDimitry Andric 5690b57cec5SDimitry Andric // If the number of arguments surpasses the system limits, we will encode the 5700b57cec5SDimitry Andric // input files in a separate file, shortening the command line. To this end, 5710b57cec5SDimitry Andric // build a list of input file names that can be passed via a file with the 5720b57cec5SDimitry Andric // -filelist linker option. 5730b57cec5SDimitry Andric llvm::opt::ArgStringList InputFileList; 5740b57cec5SDimitry Andric 5750b57cec5SDimitry Andric // The logic here is derived from gcc's behavior; most of which 5760b57cec5SDimitry Andric // comes from specs (starting with link_command). Consult gcc for 5770b57cec5SDimitry Andric // more information. 5780b57cec5SDimitry Andric ArgStringList CmdArgs; 5790b57cec5SDimitry Andric 5800b57cec5SDimitry Andric /// Hack(tm) to ignore linking errors when we are doing ARC migration. 5810b57cec5SDimitry Andric if (Args.hasArg(options::OPT_ccc_arcmt_check, 5820b57cec5SDimitry Andric options::OPT_ccc_arcmt_migrate)) { 5830b57cec5SDimitry Andric for (const auto &Arg : Args) 5840b57cec5SDimitry Andric Arg->claim(); 5850b57cec5SDimitry Andric const char *Exec = 5860b57cec5SDimitry Andric Args.MakeArgString(getToolChain().GetProgramPath("touch")); 5870b57cec5SDimitry Andric CmdArgs.push_back(Output.getFilename()); 588bdd1243dSDimitry Andric C.addCommand(std::make_unique<Command>(JA, *this, 589bdd1243dSDimitry Andric ResponseFileSupport::None(), Exec, 590bdd1243dSDimitry Andric CmdArgs, std::nullopt, Output)); 5910b57cec5SDimitry Andric return; 5920b57cec5SDimitry Andric } 5930b57cec5SDimitry Andric 59481ad6265SDimitry Andric VersionTuple Version = getMachOToolChain().getLinkerVersion(Args); 5955ffd83dbSDimitry Andric 5960eae32dcSDimitry Andric bool LinkerIsLLD; 5970eae32dcSDimitry Andric const char *Exec = 5980eae32dcSDimitry Andric Args.MakeArgString(getToolChain().GetLinkerPath(&LinkerIsLLD)); 599e8d8bef9SDimitry Andric 6007a6dacacSDimitry Andric // xrOS always uses -platform-version. 6017a6dacacSDimitry Andric bool UsePlatformVersion = getToolChain().getTriple().isXROS(); 6027a6dacacSDimitry Andric 6030b57cec5SDimitry Andric // I'm not sure why this particular decomposition exists in gcc, but 6040b57cec5SDimitry Andric // we follow suite for ease of comparison. 6057a6dacacSDimitry Andric AddLinkArgs(C, Args, CmdArgs, Inputs, Version, LinkerIsLLD, 6067a6dacacSDimitry Andric UsePlatformVersion); 6070b57cec5SDimitry Andric 6085ffd83dbSDimitry Andric if (willEmitRemarks(Args) && 6095ffd83dbSDimitry Andric checkRemarksOptions(getToolChain().getDriver(), Args, 6105ffd83dbSDimitry Andric getToolChain().getTriple())) 6115ffd83dbSDimitry Andric renderRemarksOptions(Args, CmdArgs, getToolChain().getTriple(), Output, JA); 6120b57cec5SDimitry Andric 6130b57cec5SDimitry Andric // Propagate the -moutline flag to the linker in LTO. 6140b57cec5SDimitry Andric if (Arg *A = 6150b57cec5SDimitry Andric Args.getLastArg(options::OPT_moutline, options::OPT_mno_outline)) { 6160b57cec5SDimitry Andric if (A->getOption().matches(options::OPT_moutline)) { 6170b57cec5SDimitry Andric if (getMachOToolChain().getMachOArchName(Args) == "arm64") { 6180b57cec5SDimitry Andric CmdArgs.push_back("-mllvm"); 6190b57cec5SDimitry Andric CmdArgs.push_back("-enable-machine-outliner"); 6200b57cec5SDimitry Andric } 6210b57cec5SDimitry Andric } else { 6220b57cec5SDimitry Andric // Disable all outlining behaviour if we have mno-outline. We need to do 6230b57cec5SDimitry Andric // this explicitly, because targets which support default outlining will 6240b57cec5SDimitry Andric // try to do work if we don't. 6250b57cec5SDimitry Andric CmdArgs.push_back("-mllvm"); 6260b57cec5SDimitry Andric CmdArgs.push_back("-enable-machine-outliner=never"); 6270b57cec5SDimitry Andric } 6280b57cec5SDimitry Andric } 6290b57cec5SDimitry Andric 6305f757f3fSDimitry Andric // Outline from linkonceodr functions by default in LTO, whenever the outliner 6315f757f3fSDimitry Andric // is enabled. Note that the target may enable the machine outliner 6325f757f3fSDimitry Andric // independently of -moutline. 6335f757f3fSDimitry Andric CmdArgs.push_back("-mllvm"); 6345f757f3fSDimitry Andric CmdArgs.push_back("-enable-linkonceodr-outlining"); 6355f757f3fSDimitry Andric 6360b57cec5SDimitry Andric // Setup statistics file output. 6370b57cec5SDimitry Andric SmallString<128> StatsFile = 6380b57cec5SDimitry Andric getStatsFileName(Args, Output, Inputs[0], getToolChain().getDriver()); 6390b57cec5SDimitry Andric if (!StatsFile.empty()) { 6400b57cec5SDimitry Andric CmdArgs.push_back("-mllvm"); 6410b57cec5SDimitry Andric CmdArgs.push_back(Args.MakeArgString("-lto-stats-file=" + StatsFile.str())); 6420b57cec5SDimitry Andric } 6430b57cec5SDimitry Andric 6440b57cec5SDimitry Andric // It seems that the 'e' option is completely ignored for dynamic executables 6450b57cec5SDimitry Andric // (the default), and with static executables, the last one wins, as expected. 6460fca6ea1SDimitry Andric Args.addAllArgs(CmdArgs, {options::OPT_d_Flag, options::OPT_s, options::OPT_t, 6470fca6ea1SDimitry Andric options::OPT_Z_Flag, options::OPT_u_Group}); 6480b57cec5SDimitry Andric 6490b57cec5SDimitry Andric // Forward -ObjC when either -ObjC or -ObjC++ is used, to force loading 6500b57cec5SDimitry Andric // members of static archive libraries which implement Objective-C classes or 6510b57cec5SDimitry Andric // categories. 6520b57cec5SDimitry Andric if (Args.hasArg(options::OPT_ObjC) || Args.hasArg(options::OPT_ObjCXX)) 6530b57cec5SDimitry Andric CmdArgs.push_back("-ObjC"); 6540b57cec5SDimitry Andric 6550b57cec5SDimitry Andric CmdArgs.push_back("-o"); 6560b57cec5SDimitry Andric CmdArgs.push_back(Output.getFilename()); 6570b57cec5SDimitry Andric 6580b57cec5SDimitry Andric if (!Args.hasArg(options::OPT_nostdlib, options::OPT_nostartfiles)) 6590b57cec5SDimitry Andric getMachOToolChain().addStartObjectFileArgs(Args, CmdArgs); 6600b57cec5SDimitry Andric 6610b57cec5SDimitry Andric Args.AddAllArgs(CmdArgs, options::OPT_L); 6620b57cec5SDimitry Andric 6630b57cec5SDimitry Andric AddLinkerInputs(getToolChain(), Inputs, Args, CmdArgs, JA); 6640b57cec5SDimitry Andric // Build the input file for -filelist (list of linker input files) in case we 6650b57cec5SDimitry Andric // need it later 6660b57cec5SDimitry Andric for (const auto &II : Inputs) { 6670b57cec5SDimitry Andric if (!II.isFilename()) { 6680b57cec5SDimitry Andric // This is a linker input argument. 6690b57cec5SDimitry Andric // We cannot mix input arguments and file names in a -filelist input, thus 6700b57cec5SDimitry Andric // we prematurely stop our list (remaining files shall be passed as 6710b57cec5SDimitry Andric // arguments). 6720b57cec5SDimitry Andric if (InputFileList.size() > 0) 6730b57cec5SDimitry Andric break; 6740b57cec5SDimitry Andric 6750b57cec5SDimitry Andric continue; 6760b57cec5SDimitry Andric } 6770b57cec5SDimitry Andric 6780b57cec5SDimitry Andric InputFileList.push_back(II.getFilename()); 6790b57cec5SDimitry Andric } 6800b57cec5SDimitry Andric 68181ad6265SDimitry Andric // Additional linker set-up and flags for Fortran. This is required in order 68281ad6265SDimitry Andric // to generate executables. 68381ad6265SDimitry Andric if (getToolChain().getDriver().IsFlangMode()) { 68481ad6265SDimitry Andric addFortranRuntimeLibraryPath(getToolChain(), Args, CmdArgs); 6855f757f3fSDimitry Andric addFortranRuntimeLibs(getToolChain(), Args, CmdArgs); 68681ad6265SDimitry Andric } 68781ad6265SDimitry Andric 6880b57cec5SDimitry Andric if (!Args.hasArg(options::OPT_nostdlib, options::OPT_nodefaultlibs)) 6890fca6ea1SDimitry Andric addOpenMPRuntime(C, CmdArgs, getToolChain(), Args); 6900b57cec5SDimitry Andric 6910b57cec5SDimitry Andric if (isObjCRuntimeLinked(Args) && 6920b57cec5SDimitry Andric !Args.hasArg(options::OPT_nostdlib, options::OPT_nodefaultlibs)) { 6930b57cec5SDimitry Andric // We use arclite library for both ARC and subscripting support. 6940b57cec5SDimitry Andric getMachOToolChain().AddLinkARCArgs(Args, CmdArgs); 6950b57cec5SDimitry Andric 6960b57cec5SDimitry Andric CmdArgs.push_back("-framework"); 6970b57cec5SDimitry Andric CmdArgs.push_back("Foundation"); 6980b57cec5SDimitry Andric // Link libobj. 6990b57cec5SDimitry Andric CmdArgs.push_back("-lobjc"); 7000b57cec5SDimitry Andric } 7010b57cec5SDimitry Andric 7020b57cec5SDimitry Andric if (LinkingOutput) { 7030b57cec5SDimitry Andric CmdArgs.push_back("-arch_multiple"); 7040b57cec5SDimitry Andric CmdArgs.push_back("-final_output"); 7050b57cec5SDimitry Andric CmdArgs.push_back(LinkingOutput); 7060b57cec5SDimitry Andric } 7070b57cec5SDimitry Andric 7080b57cec5SDimitry Andric if (Args.hasArg(options::OPT_fnested_functions)) 7090b57cec5SDimitry Andric CmdArgs.push_back("-allow_stack_execute"); 7100b57cec5SDimitry Andric 7110b57cec5SDimitry Andric getMachOToolChain().addProfileRTLibs(Args, CmdArgs); 7120b57cec5SDimitry Andric 7135ffd83dbSDimitry Andric StringRef Parallelism = getLTOParallelism(Args, getToolChain().getDriver()); 7145ffd83dbSDimitry Andric if (!Parallelism.empty()) { 7150b57cec5SDimitry Andric CmdArgs.push_back("-mllvm"); 7165ffd83dbSDimitry Andric unsigned NumThreads = 7175ffd83dbSDimitry Andric llvm::get_threadpool_strategy(Parallelism)->compute_thread_count(); 7185ffd83dbSDimitry Andric CmdArgs.push_back(Args.MakeArgString("-threads=" + Twine(NumThreads))); 7190b57cec5SDimitry Andric } 7200b57cec5SDimitry Andric 7210b57cec5SDimitry Andric if (getToolChain().ShouldLinkCXXStdlib(Args)) 7220b57cec5SDimitry Andric getToolChain().AddCXXStdlibLibArgs(Args, CmdArgs); 7230b57cec5SDimitry Andric 7240b57cec5SDimitry Andric bool NoStdOrDefaultLibs = 7250b57cec5SDimitry Andric Args.hasArg(options::OPT_nostdlib, options::OPT_nodefaultlibs); 7260b57cec5SDimitry Andric bool ForceLinkBuiltins = Args.hasArg(options::OPT_fapple_link_rtlib); 7270b57cec5SDimitry Andric if (!NoStdOrDefaultLibs || ForceLinkBuiltins) { 7280b57cec5SDimitry Andric // link_ssp spec is empty. 7290b57cec5SDimitry Andric 7300b57cec5SDimitry Andric // If we have both -nostdlib/nodefaultlibs and -fapple-link-rtlib then 7310b57cec5SDimitry Andric // we just want to link the builtins, not the other libs like libSystem. 7320b57cec5SDimitry Andric if (NoStdOrDefaultLibs && ForceLinkBuiltins) { 7330b57cec5SDimitry Andric getMachOToolChain().AddLinkRuntimeLib(Args, CmdArgs, "builtins"); 7340b57cec5SDimitry Andric } else { 7350b57cec5SDimitry Andric // Let the tool chain choose which runtime library to link. 7360b57cec5SDimitry Andric getMachOToolChain().AddLinkRuntimeLibArgs(Args, CmdArgs, 7370b57cec5SDimitry Andric ForceLinkBuiltins); 7380b57cec5SDimitry Andric 7390b57cec5SDimitry Andric // No need to do anything for pthreads. Claim argument to avoid warning. 7400b57cec5SDimitry Andric Args.ClaimAllArgs(options::OPT_pthread); 7410b57cec5SDimitry Andric Args.ClaimAllArgs(options::OPT_pthreads); 7420b57cec5SDimitry Andric } 7430b57cec5SDimitry Andric } 7440b57cec5SDimitry Andric 7450b57cec5SDimitry Andric if (!Args.hasArg(options::OPT_nostdlib, options::OPT_nostartfiles)) { 7460b57cec5SDimitry Andric // endfile_spec is empty. 7470b57cec5SDimitry Andric } 7480b57cec5SDimitry Andric 7490b57cec5SDimitry Andric Args.AddAllArgs(CmdArgs, options::OPT_T_Group); 7500b57cec5SDimitry Andric Args.AddAllArgs(CmdArgs, options::OPT_F); 7510b57cec5SDimitry Andric 7520b57cec5SDimitry Andric // -iframework should be forwarded as -F. 7530b57cec5SDimitry Andric for (const Arg *A : Args.filtered(options::OPT_iframework)) 7540b57cec5SDimitry Andric CmdArgs.push_back(Args.MakeArgString(std::string("-F") + A->getValue())); 7550b57cec5SDimitry Andric 7560b57cec5SDimitry Andric if (!Args.hasArg(options::OPT_nostdlib, options::OPT_nodefaultlibs)) { 7570b57cec5SDimitry Andric if (Arg *A = Args.getLastArg(options::OPT_fveclib)) { 7580b57cec5SDimitry Andric if (A->getValue() == StringRef("Accelerate")) { 7590b57cec5SDimitry Andric CmdArgs.push_back("-framework"); 7600b57cec5SDimitry Andric CmdArgs.push_back("Accelerate"); 7610b57cec5SDimitry Andric } 7620b57cec5SDimitry Andric } 7630b57cec5SDimitry Andric } 7640b57cec5SDimitry Andric 765bdd1243dSDimitry Andric // Add non-standard, platform-specific search paths, e.g., for DriverKit: 766bdd1243dSDimitry Andric // -L<sysroot>/System/DriverKit/usr/lib 767bdd1243dSDimitry Andric // -F<sysroot>/System/DriverKit/System/Library/Framework 768bdd1243dSDimitry Andric { 769bdd1243dSDimitry Andric bool NonStandardSearchPath = false; 770bdd1243dSDimitry Andric const auto &Triple = getToolChain().getTriple(); 771bdd1243dSDimitry Andric if (Triple.isDriverKit()) { 77281ad6265SDimitry Andric // ld64 fixed the implicit -F and -L paths in ld64-605.1+. 773bdd1243dSDimitry Andric NonStandardSearchPath = 774bdd1243dSDimitry Andric Version.getMajor() < 605 || 775bdd1243dSDimitry Andric (Version.getMajor() == 605 && Version.getMinor().value_or(0) < 1); 776bdd1243dSDimitry Andric } 77781ad6265SDimitry Andric 778bdd1243dSDimitry Andric if (NonStandardSearchPath) { 779bdd1243dSDimitry Andric if (auto *Sysroot = Args.getLastArg(options::OPT_isysroot)) { 780bdd1243dSDimitry Andric auto AddSearchPath = [&](StringRef Flag, StringRef SearchPath) { 781bdd1243dSDimitry Andric SmallString<128> P(Sysroot->getValue()); 782bdd1243dSDimitry Andric AppendPlatformPrefix(P, Triple); 783bdd1243dSDimitry Andric llvm::sys::path::append(P, SearchPath); 784bdd1243dSDimitry Andric if (getToolChain().getVFS().exists(P)) { 785bdd1243dSDimitry Andric CmdArgs.push_back(Args.MakeArgString(Flag + P)); 786bdd1243dSDimitry Andric } 787bdd1243dSDimitry Andric }; 788bdd1243dSDimitry Andric AddSearchPath("-L", "/usr/lib"); 789bdd1243dSDimitry Andric AddSearchPath("-F", "/System/Library/Frameworks"); 79081ad6265SDimitry Andric } 79181ad6265SDimitry Andric } 79281ad6265SDimitry Andric } 79381ad6265SDimitry Andric 794e8d8bef9SDimitry Andric ResponseFileSupport ResponseSupport; 79581ad6265SDimitry Andric if (Version >= VersionTuple(705) || LinkerIsLLD) { 796e8d8bef9SDimitry Andric ResponseSupport = ResponseFileSupport::AtFileUTF8(); 797e8d8bef9SDimitry Andric } else { 7985ffd83dbSDimitry Andric // For older versions of the linker, use the legacy filelist method instead. 7995ffd83dbSDimitry Andric ResponseSupport = {ResponseFileSupport::RF_FileList, llvm::sys::WEM_UTF8, 8005ffd83dbSDimitry Andric "-filelist"}; 8015ffd83dbSDimitry Andric } 8025ffd83dbSDimitry Andric 8035ffd83dbSDimitry Andric std::unique_ptr<Command> Cmd = std::make_unique<Command>( 804e8d8bef9SDimitry Andric JA, *this, ResponseSupport, Exec, CmdArgs, Inputs, Output); 8050b57cec5SDimitry Andric Cmd->setInputFileList(std::move(InputFileList)); 8060b57cec5SDimitry Andric C.addCommand(std::move(Cmd)); 8070b57cec5SDimitry Andric } 8080b57cec5SDimitry Andric 809349cc55cSDimitry Andric void darwin::StaticLibTool::ConstructJob(Compilation &C, const JobAction &JA, 810349cc55cSDimitry Andric const InputInfo &Output, 811349cc55cSDimitry Andric const InputInfoList &Inputs, 812349cc55cSDimitry Andric const ArgList &Args, 813349cc55cSDimitry Andric const char *LinkingOutput) const { 814349cc55cSDimitry Andric const Driver &D = getToolChain().getDriver(); 815349cc55cSDimitry Andric 816349cc55cSDimitry Andric // Silence warning for "clang -g foo.o -o foo" 817349cc55cSDimitry Andric Args.ClaimAllArgs(options::OPT_g_Group); 818349cc55cSDimitry Andric // and "clang -emit-llvm foo.o -o foo" 819349cc55cSDimitry Andric Args.ClaimAllArgs(options::OPT_emit_llvm); 820349cc55cSDimitry Andric // and for "clang -w foo.o -o foo". Other warning options are already 821349cc55cSDimitry Andric // handled somewhere else. 822349cc55cSDimitry Andric Args.ClaimAllArgs(options::OPT_w); 823349cc55cSDimitry Andric // Silence warnings when linking C code with a C++ '-stdlib' argument. 824349cc55cSDimitry Andric Args.ClaimAllArgs(options::OPT_stdlib_EQ); 825349cc55cSDimitry Andric 826349cc55cSDimitry Andric // libtool <options> <output_file> <input_files> 827349cc55cSDimitry Andric ArgStringList CmdArgs; 828349cc55cSDimitry Andric // Create and insert file members with a deterministic index. 829349cc55cSDimitry Andric CmdArgs.push_back("-static"); 830349cc55cSDimitry Andric CmdArgs.push_back("-D"); 831349cc55cSDimitry Andric CmdArgs.push_back("-no_warning_for_no_symbols"); 832349cc55cSDimitry Andric CmdArgs.push_back("-o"); 833349cc55cSDimitry Andric CmdArgs.push_back(Output.getFilename()); 834349cc55cSDimitry Andric 835349cc55cSDimitry Andric for (const auto &II : Inputs) { 836349cc55cSDimitry Andric if (II.isFilename()) { 837349cc55cSDimitry Andric CmdArgs.push_back(II.getFilename()); 838349cc55cSDimitry Andric } 839349cc55cSDimitry Andric } 840349cc55cSDimitry Andric 841349cc55cSDimitry Andric // Delete old output archive file if it already exists before generating a new 842349cc55cSDimitry Andric // archive file. 843349cc55cSDimitry Andric const auto *OutputFileName = Output.getFilename(); 844349cc55cSDimitry Andric if (Output.isFilename() && llvm::sys::fs::exists(OutputFileName)) { 845349cc55cSDimitry Andric if (std::error_code EC = llvm::sys::fs::remove(OutputFileName)) { 846349cc55cSDimitry Andric D.Diag(diag::err_drv_unable_to_remove_file) << EC.message(); 847349cc55cSDimitry Andric return; 848349cc55cSDimitry Andric } 849349cc55cSDimitry Andric } 850349cc55cSDimitry Andric 851349cc55cSDimitry Andric const char *Exec = Args.MakeArgString(getToolChain().GetStaticLibToolPath()); 852349cc55cSDimitry Andric C.addCommand(std::make_unique<Command>(JA, *this, 853349cc55cSDimitry Andric ResponseFileSupport::AtFileUTF8(), 854349cc55cSDimitry Andric Exec, CmdArgs, Inputs, Output)); 855349cc55cSDimitry Andric } 856349cc55cSDimitry Andric 8570b57cec5SDimitry Andric void darwin::Lipo::ConstructJob(Compilation &C, const JobAction &JA, 8580b57cec5SDimitry Andric const InputInfo &Output, 8590b57cec5SDimitry Andric const InputInfoList &Inputs, 8600b57cec5SDimitry Andric const ArgList &Args, 8610b57cec5SDimitry Andric const char *LinkingOutput) const { 8620b57cec5SDimitry Andric ArgStringList CmdArgs; 8630b57cec5SDimitry Andric 8640b57cec5SDimitry Andric CmdArgs.push_back("-create"); 8650b57cec5SDimitry Andric assert(Output.isFilename() && "Unexpected lipo output."); 8660b57cec5SDimitry Andric 8670b57cec5SDimitry Andric CmdArgs.push_back("-output"); 8680b57cec5SDimitry Andric CmdArgs.push_back(Output.getFilename()); 8690b57cec5SDimitry Andric 8700b57cec5SDimitry Andric for (const auto &II : Inputs) { 8710b57cec5SDimitry Andric assert(II.isFilename() && "Unexpected lipo input."); 8720b57cec5SDimitry Andric CmdArgs.push_back(II.getFilename()); 8730b57cec5SDimitry Andric } 8740b57cec5SDimitry Andric 8750b57cec5SDimitry Andric const char *Exec = Args.MakeArgString(getToolChain().GetProgramPath("lipo")); 8765ffd83dbSDimitry Andric C.addCommand(std::make_unique<Command>(JA, *this, ResponseFileSupport::None(), 877e8d8bef9SDimitry Andric Exec, CmdArgs, Inputs, Output)); 8780b57cec5SDimitry Andric } 8790b57cec5SDimitry Andric 8800b57cec5SDimitry Andric void darwin::Dsymutil::ConstructJob(Compilation &C, const JobAction &JA, 8810b57cec5SDimitry Andric const InputInfo &Output, 8820b57cec5SDimitry Andric const InputInfoList &Inputs, 8830b57cec5SDimitry Andric const ArgList &Args, 8840b57cec5SDimitry Andric const char *LinkingOutput) const { 8850b57cec5SDimitry Andric ArgStringList CmdArgs; 8860b57cec5SDimitry Andric 8870b57cec5SDimitry Andric CmdArgs.push_back("-o"); 8880b57cec5SDimitry Andric CmdArgs.push_back(Output.getFilename()); 8890b57cec5SDimitry Andric 8900b57cec5SDimitry Andric assert(Inputs.size() == 1 && "Unable to handle multiple inputs."); 8910b57cec5SDimitry Andric const InputInfo &Input = Inputs[0]; 8920b57cec5SDimitry Andric assert(Input.isFilename() && "Unexpected dsymutil input."); 8930b57cec5SDimitry Andric CmdArgs.push_back(Input.getFilename()); 8940b57cec5SDimitry Andric 8950b57cec5SDimitry Andric const char *Exec = 8960b57cec5SDimitry Andric Args.MakeArgString(getToolChain().GetProgramPath("dsymutil")); 8975ffd83dbSDimitry Andric C.addCommand(std::make_unique<Command>(JA, *this, ResponseFileSupport::None(), 898e8d8bef9SDimitry Andric Exec, CmdArgs, Inputs, Output)); 8990b57cec5SDimitry Andric } 9000b57cec5SDimitry Andric 9010b57cec5SDimitry Andric void darwin::VerifyDebug::ConstructJob(Compilation &C, const JobAction &JA, 9020b57cec5SDimitry Andric const InputInfo &Output, 9030b57cec5SDimitry Andric const InputInfoList &Inputs, 9040b57cec5SDimitry Andric const ArgList &Args, 9050b57cec5SDimitry Andric const char *LinkingOutput) const { 9060b57cec5SDimitry Andric ArgStringList CmdArgs; 9070b57cec5SDimitry Andric CmdArgs.push_back("--verify"); 9080b57cec5SDimitry Andric CmdArgs.push_back("--debug-info"); 9090b57cec5SDimitry Andric CmdArgs.push_back("--eh-frame"); 9100b57cec5SDimitry Andric CmdArgs.push_back("--quiet"); 9110b57cec5SDimitry Andric 9120b57cec5SDimitry Andric assert(Inputs.size() == 1 && "Unable to handle multiple inputs."); 9130b57cec5SDimitry Andric const InputInfo &Input = Inputs[0]; 9140b57cec5SDimitry Andric assert(Input.isFilename() && "Unexpected verify input"); 9150b57cec5SDimitry Andric 9160b57cec5SDimitry Andric // Grabbing the output of the earlier dsymutil run. 9170b57cec5SDimitry Andric CmdArgs.push_back(Input.getFilename()); 9180b57cec5SDimitry Andric 9190b57cec5SDimitry Andric const char *Exec = 9200b57cec5SDimitry Andric Args.MakeArgString(getToolChain().GetProgramPath("dwarfdump")); 9215ffd83dbSDimitry Andric C.addCommand(std::make_unique<Command>(JA, *this, ResponseFileSupport::None(), 922e8d8bef9SDimitry Andric Exec, CmdArgs, Inputs, Output)); 9230b57cec5SDimitry Andric } 9240b57cec5SDimitry Andric 9250b57cec5SDimitry Andric MachO::MachO(const Driver &D, const llvm::Triple &Triple, const ArgList &Args) 9260b57cec5SDimitry Andric : ToolChain(D, Triple, Args) { 9270b57cec5SDimitry Andric // We expect 'as', 'ld', etc. to be adjacent to our install dir. 9280b57cec5SDimitry Andric getProgramPaths().push_back(getDriver().Dir); 9290b57cec5SDimitry Andric } 9300b57cec5SDimitry Andric 9310b57cec5SDimitry Andric /// Darwin - Darwin tool chain for i386 and x86_64. 9320b57cec5SDimitry Andric Darwin::Darwin(const Driver &D, const llvm::Triple &Triple, const ArgList &Args) 9330b57cec5SDimitry Andric : MachO(D, Triple, Args), TargetInitialized(false), 9345ffd83dbSDimitry Andric CudaInstallation(D, Triple, Args), RocmInstallation(D, Triple, Args) {} 9350b57cec5SDimitry Andric 9360b57cec5SDimitry Andric types::ID MachO::LookupTypeForExtension(StringRef Ext) const { 937480093f4SDimitry Andric types::ID Ty = ToolChain::LookupTypeForExtension(Ext); 9380b57cec5SDimitry Andric 9390b57cec5SDimitry Andric // Darwin always preprocesses assembly files (unless -x is used explicitly). 9400b57cec5SDimitry Andric if (Ty == types::TY_PP_Asm) 9410b57cec5SDimitry Andric return types::TY_Asm; 9420b57cec5SDimitry Andric 9430b57cec5SDimitry Andric return Ty; 9440b57cec5SDimitry Andric } 9450b57cec5SDimitry Andric 9460b57cec5SDimitry Andric bool MachO::HasNativeLLVMSupport() const { return true; } 9470b57cec5SDimitry Andric 9480b57cec5SDimitry Andric ToolChain::CXXStdlibType Darwin::GetDefaultCXXStdlibType() const { 949bdd1243dSDimitry Andric // Always use libc++ by default 95081ad6265SDimitry Andric return ToolChain::CST_Libcxx; 9510b57cec5SDimitry Andric } 9520b57cec5SDimitry Andric 9530b57cec5SDimitry Andric /// Darwin provides an ARC runtime starting in MacOS X 10.7 and iOS 5.0. 9540b57cec5SDimitry Andric ObjCRuntime Darwin::getDefaultObjCRuntime(bool isNonFragile) const { 9550b57cec5SDimitry Andric if (isTargetWatchOSBased()) 9560b57cec5SDimitry Andric return ObjCRuntime(ObjCRuntime::WatchOS, TargetVersion); 9570b57cec5SDimitry Andric if (isTargetIOSBased()) 9580b57cec5SDimitry Andric return ObjCRuntime(ObjCRuntime::iOS, TargetVersion); 9597a6dacacSDimitry Andric if (isTargetXROS()) { 9607a6dacacSDimitry Andric // XROS uses the iOS runtime. 9617a6dacacSDimitry Andric auto T = llvm::Triple(Twine("arm64-apple-") + 9627a6dacacSDimitry Andric llvm::Triple::getOSTypeName(llvm::Triple::XROS) + 9637a6dacacSDimitry Andric TargetVersion.getAsString()); 9647a6dacacSDimitry Andric return ObjCRuntime(ObjCRuntime::iOS, T.getiOSVersion()); 9657a6dacacSDimitry Andric } 9660b57cec5SDimitry Andric if (isNonFragile) 9670b57cec5SDimitry Andric return ObjCRuntime(ObjCRuntime::MacOSX, TargetVersion); 9680b57cec5SDimitry Andric return ObjCRuntime(ObjCRuntime::FragileMacOSX, TargetVersion); 9690b57cec5SDimitry Andric } 9700b57cec5SDimitry Andric 9710b57cec5SDimitry Andric /// Darwin provides a blocks runtime starting in MacOS X 10.6 and iOS 3.2. 9720b57cec5SDimitry Andric bool Darwin::hasBlocksRuntime() const { 9737a6dacacSDimitry Andric if (isTargetWatchOSBased() || isTargetDriverKit() || isTargetXROS()) 9740b57cec5SDimitry Andric return true; 9750b57cec5SDimitry Andric else if (isTargetIOSBased()) 9760b57cec5SDimitry Andric return !isIPhoneOSVersionLT(3, 2); 9770b57cec5SDimitry Andric else { 978fe6060f1SDimitry Andric assert(isTargetMacOSBased() && "unexpected darwin target"); 9790b57cec5SDimitry Andric return !isMacosxVersionLT(10, 6); 9800b57cec5SDimitry Andric } 9810b57cec5SDimitry Andric } 9820b57cec5SDimitry Andric 9830b57cec5SDimitry Andric void Darwin::AddCudaIncludeArgs(const ArgList &DriverArgs, 9840b57cec5SDimitry Andric ArgStringList &CC1Args) const { 9857a6dacacSDimitry Andric CudaInstallation->AddCudaIncludeArgs(DriverArgs, CC1Args); 9860b57cec5SDimitry Andric } 9870b57cec5SDimitry Andric 9885ffd83dbSDimitry Andric void Darwin::AddHIPIncludeArgs(const ArgList &DriverArgs, 9895ffd83dbSDimitry Andric ArgStringList &CC1Args) const { 9907a6dacacSDimitry Andric RocmInstallation->AddHIPIncludeArgs(DriverArgs, CC1Args); 9915ffd83dbSDimitry Andric } 9925ffd83dbSDimitry Andric 9930b57cec5SDimitry Andric // This is just a MachO name translation routine and there's no 9940b57cec5SDimitry Andric // way to join this into ARMTargetParser without breaking all 9950b57cec5SDimitry Andric // other assumptions. Maybe MachO should consider standardising 9960b57cec5SDimitry Andric // their nomenclature. 9970b57cec5SDimitry Andric static const char *ArmMachOArchName(StringRef Arch) { 9980b57cec5SDimitry Andric return llvm::StringSwitch<const char *>(Arch) 9990b57cec5SDimitry Andric .Case("armv6k", "armv6") 10000b57cec5SDimitry Andric .Case("armv6m", "armv6m") 10010b57cec5SDimitry Andric .Case("armv5tej", "armv5") 10020b57cec5SDimitry Andric .Case("xscale", "xscale") 10030b57cec5SDimitry Andric .Case("armv4t", "armv4t") 10040b57cec5SDimitry Andric .Case("armv7", "armv7") 10050b57cec5SDimitry Andric .Cases("armv7a", "armv7-a", "armv7") 10060b57cec5SDimitry Andric .Cases("armv7r", "armv7-r", "armv7") 10070b57cec5SDimitry Andric .Cases("armv7em", "armv7e-m", "armv7em") 10080b57cec5SDimitry Andric .Cases("armv7k", "armv7-k", "armv7k") 10090b57cec5SDimitry Andric .Cases("armv7m", "armv7-m", "armv7m") 10100b57cec5SDimitry Andric .Cases("armv7s", "armv7-s", "armv7s") 10110b57cec5SDimitry Andric .Default(nullptr); 10120b57cec5SDimitry Andric } 10130b57cec5SDimitry Andric 10140b57cec5SDimitry Andric static const char *ArmMachOArchNameCPU(StringRef CPU) { 10150b57cec5SDimitry Andric llvm::ARM::ArchKind ArchKind = llvm::ARM::parseCPUArch(CPU); 10160b57cec5SDimitry Andric if (ArchKind == llvm::ARM::ArchKind::INVALID) 10170b57cec5SDimitry Andric return nullptr; 10180b57cec5SDimitry Andric StringRef Arch = llvm::ARM::getArchName(ArchKind); 10190b57cec5SDimitry Andric 10200b57cec5SDimitry Andric // FIXME: Make sure this MachO triple mangling is really necessary. 10210b57cec5SDimitry Andric // ARMv5* normalises to ARMv5. 10225f757f3fSDimitry Andric if (Arch.starts_with("armv5")) 10230b57cec5SDimitry Andric Arch = Arch.substr(0, 5); 10240b57cec5SDimitry Andric // ARMv6*, except ARMv6M, normalises to ARMv6. 10255f757f3fSDimitry Andric else if (Arch.starts_with("armv6") && !Arch.ends_with("6m")) 10260b57cec5SDimitry Andric Arch = Arch.substr(0, 5); 10270b57cec5SDimitry Andric // ARMv7A normalises to ARMv7. 10285f757f3fSDimitry Andric else if (Arch.ends_with("v7a")) 10290b57cec5SDimitry Andric Arch = Arch.substr(0, 5); 10300b57cec5SDimitry Andric return Arch.data(); 10310b57cec5SDimitry Andric } 10320b57cec5SDimitry Andric 10330b57cec5SDimitry Andric StringRef MachO::getMachOArchName(const ArgList &Args) const { 10340b57cec5SDimitry Andric switch (getTriple().getArch()) { 10350b57cec5SDimitry Andric default: 10360b57cec5SDimitry Andric return getDefaultUniversalArchName(); 10370b57cec5SDimitry Andric 1038480093f4SDimitry Andric case llvm::Triple::aarch64_32: 1039480093f4SDimitry Andric return "arm64_32"; 1040480093f4SDimitry Andric 1041e8d8bef9SDimitry Andric case llvm::Triple::aarch64: { 1042e8d8bef9SDimitry Andric if (getTriple().isArm64e()) 1043e8d8bef9SDimitry Andric return "arm64e"; 10440b57cec5SDimitry Andric return "arm64"; 1045e8d8bef9SDimitry Andric } 10460b57cec5SDimitry Andric 10470b57cec5SDimitry Andric case llvm::Triple::thumb: 10480b57cec5SDimitry Andric case llvm::Triple::arm: 10490b57cec5SDimitry Andric if (const Arg *A = Args.getLastArg(clang::driver::options::OPT_march_EQ)) 10500b57cec5SDimitry Andric if (const char *Arch = ArmMachOArchName(A->getValue())) 10510b57cec5SDimitry Andric return Arch; 10520b57cec5SDimitry Andric 10530b57cec5SDimitry Andric if (const Arg *A = Args.getLastArg(options::OPT_mcpu_EQ)) 10540b57cec5SDimitry Andric if (const char *Arch = ArmMachOArchNameCPU(A->getValue())) 10550b57cec5SDimitry Andric return Arch; 10560b57cec5SDimitry Andric 10570b57cec5SDimitry Andric return "arm"; 10580b57cec5SDimitry Andric } 10590b57cec5SDimitry Andric } 10600b57cec5SDimitry Andric 106181ad6265SDimitry Andric VersionTuple MachO::getLinkerVersion(const llvm::opt::ArgList &Args) const { 106281ad6265SDimitry Andric if (LinkerVersion) { 106381ad6265SDimitry Andric #ifndef NDEBUG 106481ad6265SDimitry Andric VersionTuple NewLinkerVersion; 106581ad6265SDimitry Andric if (Arg *A = Args.getLastArg(options::OPT_mlinker_version_EQ)) 106681ad6265SDimitry Andric (void)NewLinkerVersion.tryParse(A->getValue()); 106781ad6265SDimitry Andric assert(NewLinkerVersion == LinkerVersion); 106881ad6265SDimitry Andric #endif 106981ad6265SDimitry Andric return *LinkerVersion; 107081ad6265SDimitry Andric } 107181ad6265SDimitry Andric 107281ad6265SDimitry Andric VersionTuple NewLinkerVersion; 107381ad6265SDimitry Andric if (Arg *A = Args.getLastArg(options::OPT_mlinker_version_EQ)) 107481ad6265SDimitry Andric if (NewLinkerVersion.tryParse(A->getValue())) 107581ad6265SDimitry Andric getDriver().Diag(diag::err_drv_invalid_version_number) 107681ad6265SDimitry Andric << A->getAsString(Args); 107781ad6265SDimitry Andric 107881ad6265SDimitry Andric LinkerVersion = NewLinkerVersion; 107981ad6265SDimitry Andric return *LinkerVersion; 108081ad6265SDimitry Andric } 108181ad6265SDimitry Andric 10820b57cec5SDimitry Andric Darwin::~Darwin() {} 10830b57cec5SDimitry Andric 10840b57cec5SDimitry Andric MachO::~MachO() {} 10850b57cec5SDimitry Andric 10860b57cec5SDimitry Andric std::string Darwin::ComputeEffectiveClangTriple(const ArgList &Args, 10870b57cec5SDimitry Andric types::ID InputType) const { 10880b57cec5SDimitry Andric llvm::Triple Triple(ComputeLLVMTriple(Args, InputType)); 10890b57cec5SDimitry Andric 10900b57cec5SDimitry Andric // If the target isn't initialized (e.g., an unknown Darwin platform, return 10910b57cec5SDimitry Andric // the default triple). 10920b57cec5SDimitry Andric if (!isTargetInitialized()) 10930b57cec5SDimitry Andric return Triple.getTriple(); 10940b57cec5SDimitry Andric 10950b57cec5SDimitry Andric SmallString<16> Str; 10960b57cec5SDimitry Andric if (isTargetWatchOSBased()) 10970b57cec5SDimitry Andric Str += "watchos"; 10980b57cec5SDimitry Andric else if (isTargetTvOSBased()) 10990b57cec5SDimitry Andric Str += "tvos"; 110081ad6265SDimitry Andric else if (isTargetDriverKit()) 110181ad6265SDimitry Andric Str += "driverkit"; 1102fe6060f1SDimitry Andric else if (isTargetIOSBased() || isTargetMacCatalyst()) 11030b57cec5SDimitry Andric Str += "ios"; 11047a6dacacSDimitry Andric else if (isTargetXROS()) 11057a6dacacSDimitry Andric Str += llvm::Triple::getOSTypeName(llvm::Triple::XROS); 11060b57cec5SDimitry Andric else 11070b57cec5SDimitry Andric Str += "macosx"; 1108fe6060f1SDimitry Andric Str += getTripleTargetVersion().getAsString(); 11090b57cec5SDimitry Andric Triple.setOSName(Str); 11100b57cec5SDimitry Andric 11110b57cec5SDimitry Andric return Triple.getTriple(); 11120b57cec5SDimitry Andric } 11130b57cec5SDimitry Andric 11140b57cec5SDimitry Andric Tool *MachO::getTool(Action::ActionClass AC) const { 11150b57cec5SDimitry Andric switch (AC) { 11160b57cec5SDimitry Andric case Action::LipoJobClass: 11170b57cec5SDimitry Andric if (!Lipo) 11180b57cec5SDimitry Andric Lipo.reset(new tools::darwin::Lipo(*this)); 11190b57cec5SDimitry Andric return Lipo.get(); 11200b57cec5SDimitry Andric case Action::DsymutilJobClass: 11210b57cec5SDimitry Andric if (!Dsymutil) 11220b57cec5SDimitry Andric Dsymutil.reset(new tools::darwin::Dsymutil(*this)); 11230b57cec5SDimitry Andric return Dsymutil.get(); 11240b57cec5SDimitry Andric case Action::VerifyDebugInfoJobClass: 11250b57cec5SDimitry Andric if (!VerifyDebug) 11260b57cec5SDimitry Andric VerifyDebug.reset(new tools::darwin::VerifyDebug(*this)); 11270b57cec5SDimitry Andric return VerifyDebug.get(); 11280b57cec5SDimitry Andric default: 11290b57cec5SDimitry Andric return ToolChain::getTool(AC); 11300b57cec5SDimitry Andric } 11310b57cec5SDimitry Andric } 11320b57cec5SDimitry Andric 11330b57cec5SDimitry Andric Tool *MachO::buildLinker() const { return new tools::darwin::Linker(*this); } 11340b57cec5SDimitry Andric 1135349cc55cSDimitry Andric Tool *MachO::buildStaticLibTool() const { 1136349cc55cSDimitry Andric return new tools::darwin::StaticLibTool(*this); 1137349cc55cSDimitry Andric } 1138349cc55cSDimitry Andric 11390b57cec5SDimitry Andric Tool *MachO::buildAssembler() const { 11400b57cec5SDimitry Andric return new tools::darwin::Assembler(*this); 11410b57cec5SDimitry Andric } 11420b57cec5SDimitry Andric 11430b57cec5SDimitry Andric DarwinClang::DarwinClang(const Driver &D, const llvm::Triple &Triple, 11440b57cec5SDimitry Andric const ArgList &Args) 11450b57cec5SDimitry Andric : Darwin(D, Triple, Args) {} 11460b57cec5SDimitry Andric 11470b57cec5SDimitry Andric void DarwinClang::addClangWarningOptions(ArgStringList &CC1Args) const { 11485ffd83dbSDimitry Andric // Always error about undefined 'TARGET_OS_*' macros. 11495ffd83dbSDimitry Andric CC1Args.push_back("-Wundef-prefix=TARGET_OS_"); 11505ffd83dbSDimitry Andric CC1Args.push_back("-Werror=undef-prefix"); 11515ffd83dbSDimitry Andric 11520b57cec5SDimitry Andric // For modern targets, promote certain warnings to errors. 11530b57cec5SDimitry Andric if (isTargetWatchOSBased() || getTriple().isArch64Bit()) { 11540b57cec5SDimitry Andric // Always enable -Wdeprecated-objc-isa-usage and promote it 11550b57cec5SDimitry Andric // to an error. 11560b57cec5SDimitry Andric CC1Args.push_back("-Wdeprecated-objc-isa-usage"); 11570b57cec5SDimitry Andric CC1Args.push_back("-Werror=deprecated-objc-isa-usage"); 11580b57cec5SDimitry Andric 11590b57cec5SDimitry Andric // For iOS and watchOS, also error about implicit function declarations, 11600b57cec5SDimitry Andric // as that can impact calling conventions. 11610b57cec5SDimitry Andric if (!isTargetMacOS()) 11620b57cec5SDimitry Andric CC1Args.push_back("-Werror=implicit-function-declaration"); 11630b57cec5SDimitry Andric } 11640b57cec5SDimitry Andric } 11650b57cec5SDimitry Andric 11660b57cec5SDimitry Andric /// Take a path that speculatively points into Xcode and return the 11670b57cec5SDimitry Andric /// `XCODE/Contents/Developer` path if it is an Xcode path, or an empty path 11680b57cec5SDimitry Andric /// otherwise. 11690b57cec5SDimitry Andric static StringRef getXcodeDeveloperPath(StringRef PathIntoXcode) { 11700b57cec5SDimitry Andric static constexpr llvm::StringLiteral XcodeAppSuffix( 11710b57cec5SDimitry Andric ".app/Contents/Developer"); 11720b57cec5SDimitry Andric size_t Index = PathIntoXcode.find(XcodeAppSuffix); 11730b57cec5SDimitry Andric if (Index == StringRef::npos) 11740b57cec5SDimitry Andric return ""; 11750b57cec5SDimitry Andric return PathIntoXcode.take_front(Index + XcodeAppSuffix.size()); 11760b57cec5SDimitry Andric } 11770b57cec5SDimitry Andric 11780b57cec5SDimitry Andric void DarwinClang::AddLinkARCArgs(const ArgList &Args, 11790b57cec5SDimitry Andric ArgStringList &CmdArgs) const { 11800b57cec5SDimitry Andric // Avoid linking compatibility stubs on i386 mac. 1181fe6060f1SDimitry Andric if (isTargetMacOSBased() && getArch() == llvm::Triple::x86) 11820b57cec5SDimitry Andric return; 11835ffd83dbSDimitry Andric if (isTargetAppleSiliconMac()) 11845ffd83dbSDimitry Andric return; 1185e8d8bef9SDimitry Andric // ARC runtime is supported everywhere on arm64e. 1186e8d8bef9SDimitry Andric if (getTriple().isArm64e()) 1187e8d8bef9SDimitry Andric return; 11887a6dacacSDimitry Andric if (isTargetXROS()) 11897a6dacacSDimitry Andric return; 11900b57cec5SDimitry Andric 11910b57cec5SDimitry Andric ObjCRuntime runtime = getDefaultObjCRuntime(/*nonfragile*/ true); 11920b57cec5SDimitry Andric 11930b57cec5SDimitry Andric if ((runtime.hasNativeARC() || !isObjCAutoRefCount(Args)) && 11940b57cec5SDimitry Andric runtime.hasSubscripting()) 11950b57cec5SDimitry Andric return; 11960b57cec5SDimitry Andric 11970b57cec5SDimitry Andric SmallString<128> P(getDriver().ClangExecutable); 11980b57cec5SDimitry Andric llvm::sys::path::remove_filename(P); // 'clang' 11990b57cec5SDimitry Andric llvm::sys::path::remove_filename(P); // 'bin' 1200fcaf7f86SDimitry Andric llvm::sys::path::append(P, "lib", "arc"); 12010b57cec5SDimitry Andric 12020b57cec5SDimitry Andric // 'libarclite' usually lives in the same toolchain as 'clang'. However, the 12030b57cec5SDimitry Andric // Swift open source toolchains for macOS distribute Clang without libarclite. 12040b57cec5SDimitry Andric // In that case, to allow the linker to find 'libarclite', we point to the 12050b57cec5SDimitry Andric // 'libarclite' in the XcodeDefault toolchain instead. 1206fcaf7f86SDimitry Andric if (!getVFS().exists(P)) { 1207fcaf7f86SDimitry Andric auto updatePath = [&](const Arg *A) { 12080b57cec5SDimitry Andric // Try to infer the path to 'libarclite' in the toolchain from the 12090b57cec5SDimitry Andric // specified SDK path. 12100b57cec5SDimitry Andric StringRef XcodePathForSDK = getXcodeDeveloperPath(A->getValue()); 1211fcaf7f86SDimitry Andric if (XcodePathForSDK.empty()) 1212fcaf7f86SDimitry Andric return false; 1213fcaf7f86SDimitry Andric 12140b57cec5SDimitry Andric P = XcodePathForSDK; 1215fcaf7f86SDimitry Andric llvm::sys::path::append(P, "Toolchains/XcodeDefault.xctoolchain/usr", 1216fcaf7f86SDimitry Andric "lib", "arc"); 1217fcaf7f86SDimitry Andric return getVFS().exists(P); 1218fcaf7f86SDimitry Andric }; 1219fcaf7f86SDimitry Andric 1220fcaf7f86SDimitry Andric bool updated = false; 1221fcaf7f86SDimitry Andric if (const Arg *A = Args.getLastArg(options::OPT_isysroot)) 1222fcaf7f86SDimitry Andric updated = updatePath(A); 1223fcaf7f86SDimitry Andric 1224fcaf7f86SDimitry Andric if (!updated) { 1225fcaf7f86SDimitry Andric if (const Arg *A = Args.getLastArg(options::OPT__sysroot_EQ)) 1226fcaf7f86SDimitry Andric updatePath(A); 12270b57cec5SDimitry Andric } 12280b57cec5SDimitry Andric } 12290b57cec5SDimitry Andric 12300b57cec5SDimitry Andric CmdArgs.push_back("-force_load"); 1231fcaf7f86SDimitry Andric llvm::sys::path::append(P, "libarclite_"); 12320b57cec5SDimitry Andric // Mash in the platform. 12330b57cec5SDimitry Andric if (isTargetWatchOSSimulator()) 12340b57cec5SDimitry Andric P += "watchsimulator"; 12350b57cec5SDimitry Andric else if (isTargetWatchOS()) 12360b57cec5SDimitry Andric P += "watchos"; 12370b57cec5SDimitry Andric else if (isTargetTvOSSimulator()) 12380b57cec5SDimitry Andric P += "appletvsimulator"; 12390b57cec5SDimitry Andric else if (isTargetTvOS()) 12400b57cec5SDimitry Andric P += "appletvos"; 12410b57cec5SDimitry Andric else if (isTargetIOSSimulator()) 12420b57cec5SDimitry Andric P += "iphonesimulator"; 12430b57cec5SDimitry Andric else if (isTargetIPhoneOS()) 12440b57cec5SDimitry Andric P += "iphoneos"; 12450b57cec5SDimitry Andric else 12460b57cec5SDimitry Andric P += "macosx"; 12470b57cec5SDimitry Andric P += ".a"; 12480b57cec5SDimitry Andric 124906c3fb27SDimitry Andric if (!getVFS().exists(P)) 125006c3fb27SDimitry Andric getDriver().Diag(clang::diag::err_drv_darwin_sdk_missing_arclite) << P; 125106c3fb27SDimitry Andric 12520b57cec5SDimitry Andric CmdArgs.push_back(Args.MakeArgString(P)); 12530b57cec5SDimitry Andric } 12540b57cec5SDimitry Andric 12550b57cec5SDimitry Andric unsigned DarwinClang::GetDefaultDwarfVersion() const { 12560b57cec5SDimitry Andric // Default to use DWARF 2 on OS X 10.10 / iOS 8 and lower. 1257fe6060f1SDimitry Andric if ((isTargetMacOSBased() && isMacosxVersionLT(10, 11)) || 12580b57cec5SDimitry Andric (isTargetIOSBased() && isIPhoneOSVersionLT(9))) 12590b57cec5SDimitry Andric return 2; 12600fca6ea1SDimitry Andric // Default to use DWARF 4 on OS X 10.11 - macOS 14 / iOS 9 - iOS 17. 12610fca6ea1SDimitry Andric if ((isTargetMacOSBased() && isMacosxVersionLT(15)) || 12620fca6ea1SDimitry Andric (isTargetIOSBased() && isIPhoneOSVersionLT(18)) || 12630fca6ea1SDimitry Andric (isTargetWatchOSBased() && TargetVersion < llvm::VersionTuple(11)) || 12640fca6ea1SDimitry Andric (isTargetXROS() && TargetVersion < llvm::VersionTuple(2)) || 12650fca6ea1SDimitry Andric (isTargetDriverKit() && TargetVersion < llvm::VersionTuple(24)) || 12660fca6ea1SDimitry Andric (isTargetMacOSBased() && 12670fca6ea1SDimitry Andric TargetVersion.empty())) // apple-darwin, no version. 12680b57cec5SDimitry Andric return 4; 12690fca6ea1SDimitry Andric return 5; 12700b57cec5SDimitry Andric } 12710b57cec5SDimitry Andric 12720b57cec5SDimitry Andric void MachO::AddLinkRuntimeLib(const ArgList &Args, ArgStringList &CmdArgs, 12730b57cec5SDimitry Andric StringRef Component, RuntimeLinkOptions Opts, 12740b57cec5SDimitry Andric bool IsShared) const { 12750fca6ea1SDimitry Andric std::string P = getCompilerRT( 12760fca6ea1SDimitry Andric Args, Component, IsShared ? ToolChain::FT_Shared : ToolChain::FT_Static); 12770b57cec5SDimitry Andric 12780b57cec5SDimitry Andric // For now, allow missing resource libraries to support developers who may 12790b57cec5SDimitry Andric // not have compiler-rt checked out or integrated into their build (unless 12800b57cec5SDimitry Andric // we explicitly force linking with this library). 12810b57cec5SDimitry Andric if ((Opts & RLO_AlwaysLink) || getVFS().exists(P)) { 12820b57cec5SDimitry Andric const char *LibArg = Args.MakeArgString(P); 12830b57cec5SDimitry Andric CmdArgs.push_back(LibArg); 12840b57cec5SDimitry Andric } 12850b57cec5SDimitry Andric 12860b57cec5SDimitry Andric // Adding the rpaths might negatively interact when other rpaths are involved, 12870b57cec5SDimitry Andric // so we should make sure we add the rpaths last, after all user-specified 12880b57cec5SDimitry Andric // rpaths. This is currently true from this place, but we need to be 12890b57cec5SDimitry Andric // careful if this function is ever called before user's rpaths are emitted. 12900b57cec5SDimitry Andric if (Opts & RLO_AddRPath) { 12910fca6ea1SDimitry Andric assert(StringRef(P).ends_with(".dylib") && "must be a dynamic library"); 12920b57cec5SDimitry Andric 12930b57cec5SDimitry Andric // Add @executable_path to rpath to support having the dylib copied with 12940b57cec5SDimitry Andric // the executable. 12950b57cec5SDimitry Andric CmdArgs.push_back("-rpath"); 12960b57cec5SDimitry Andric CmdArgs.push_back("@executable_path"); 12970b57cec5SDimitry Andric 12980fca6ea1SDimitry Andric // Add the compiler-rt library's directory to rpath to support using the 12990fca6ea1SDimitry Andric // dylib from the default location without copying. 13000b57cec5SDimitry Andric CmdArgs.push_back("-rpath"); 13010fca6ea1SDimitry Andric CmdArgs.push_back(Args.MakeArgString(llvm::sys::path::parent_path(P))); 13020b57cec5SDimitry Andric } 13030b57cec5SDimitry Andric } 13040b57cec5SDimitry Andric 13050fca6ea1SDimitry Andric std::string MachO::getCompilerRT(const ArgList &, StringRef Component, 13060fca6ea1SDimitry Andric FileType Type) const { 13070fca6ea1SDimitry Andric assert(Type != ToolChain::FT_Object && 13080fca6ea1SDimitry Andric "it doesn't make sense to ask for the compiler-rt library name as an " 13090fca6ea1SDimitry Andric "object file"); 13100fca6ea1SDimitry Andric SmallString<64> MachOLibName = StringRef("libclang_rt"); 13110fca6ea1SDimitry Andric // On MachO, the builtins component is not in the library name 13120fca6ea1SDimitry Andric if (Component != "builtins") { 13130fca6ea1SDimitry Andric MachOLibName += '.'; 13140fca6ea1SDimitry Andric MachOLibName += Component; 13150fca6ea1SDimitry Andric } 13160fca6ea1SDimitry Andric MachOLibName += Type == ToolChain::FT_Shared ? "_dynamic.dylib" : ".a"; 13170fca6ea1SDimitry Andric 13180fca6ea1SDimitry Andric SmallString<128> FullPath(getDriver().ResourceDir); 13190fca6ea1SDimitry Andric llvm::sys::path::append(FullPath, "lib", "darwin", "macho_embedded", 13200fca6ea1SDimitry Andric MachOLibName); 13210fca6ea1SDimitry Andric return std::string(FullPath); 13220fca6ea1SDimitry Andric } 13230fca6ea1SDimitry Andric 13240fca6ea1SDimitry Andric std::string Darwin::getCompilerRT(const ArgList &, StringRef Component, 13250fca6ea1SDimitry Andric FileType Type) const { 13260fca6ea1SDimitry Andric assert(Type != ToolChain::FT_Object && 13270fca6ea1SDimitry Andric "it doesn't make sense to ask for the compiler-rt library name as an " 13280fca6ea1SDimitry Andric "object file"); 13290fca6ea1SDimitry Andric SmallString<64> DarwinLibName = StringRef("libclang_rt."); 13300fca6ea1SDimitry Andric // On Darwin, the builtins component is not in the library name 13310fca6ea1SDimitry Andric if (Component != "builtins") { 13320fca6ea1SDimitry Andric DarwinLibName += Component; 13330fca6ea1SDimitry Andric DarwinLibName += '_'; 13340fca6ea1SDimitry Andric } 13350fca6ea1SDimitry Andric DarwinLibName += getOSLibraryNameSuffix(); 13360fca6ea1SDimitry Andric DarwinLibName += Type == ToolChain::FT_Shared ? "_dynamic.dylib" : ".a"; 13370fca6ea1SDimitry Andric 13380fca6ea1SDimitry Andric SmallString<128> FullPath(getDriver().ResourceDir); 13390fca6ea1SDimitry Andric llvm::sys::path::append(FullPath, "lib", "darwin", DarwinLibName); 13400fca6ea1SDimitry Andric return std::string(FullPath); 13410fca6ea1SDimitry Andric } 13420fca6ea1SDimitry Andric 13430b57cec5SDimitry Andric StringRef Darwin::getPlatformFamily() const { 13440b57cec5SDimitry Andric switch (TargetPlatform) { 13450b57cec5SDimitry Andric case DarwinPlatformKind::MacOS: 13460b57cec5SDimitry Andric return "MacOSX"; 13470b57cec5SDimitry Andric case DarwinPlatformKind::IPhoneOS: 1348fe6060f1SDimitry Andric if (TargetEnvironment == MacCatalyst) 1349fe6060f1SDimitry Andric return "MacOSX"; 13500b57cec5SDimitry Andric return "iPhone"; 13510b57cec5SDimitry Andric case DarwinPlatformKind::TvOS: 13520b57cec5SDimitry Andric return "AppleTV"; 13530b57cec5SDimitry Andric case DarwinPlatformKind::WatchOS: 13540b57cec5SDimitry Andric return "Watch"; 135581ad6265SDimitry Andric case DarwinPlatformKind::DriverKit: 135681ad6265SDimitry Andric return "DriverKit"; 13577a6dacacSDimitry Andric case DarwinPlatformKind::XROS: 13587a6dacacSDimitry Andric return "XR"; 13590b57cec5SDimitry Andric } 13600b57cec5SDimitry Andric llvm_unreachable("Unsupported platform"); 13610b57cec5SDimitry Andric } 13620b57cec5SDimitry Andric 13630b57cec5SDimitry Andric StringRef Darwin::getSDKName(StringRef isysroot) { 13640b57cec5SDimitry Andric // Assume SDK has path: SOME_PATH/SDKs/PlatformXX.YY.sdk 13655ffd83dbSDimitry Andric auto BeginSDK = llvm::sys::path::rbegin(isysroot); 13665ffd83dbSDimitry Andric auto EndSDK = llvm::sys::path::rend(isysroot); 13670b57cec5SDimitry Andric for (auto IT = BeginSDK; IT != EndSDK; ++IT) { 13680b57cec5SDimitry Andric StringRef SDK = *IT; 13695f757f3fSDimitry Andric if (SDK.ends_with(".sdk")) 13700b57cec5SDimitry Andric return SDK.slice(0, SDK.size() - 4); 13710b57cec5SDimitry Andric } 13720b57cec5SDimitry Andric return ""; 13730b57cec5SDimitry Andric } 13740b57cec5SDimitry Andric 13750b57cec5SDimitry Andric StringRef Darwin::getOSLibraryNameSuffix(bool IgnoreSim) const { 13760b57cec5SDimitry Andric switch (TargetPlatform) { 13770b57cec5SDimitry Andric case DarwinPlatformKind::MacOS: 13780b57cec5SDimitry Andric return "osx"; 13790b57cec5SDimitry Andric case DarwinPlatformKind::IPhoneOS: 1380fe6060f1SDimitry Andric if (TargetEnvironment == MacCatalyst) 1381fe6060f1SDimitry Andric return "osx"; 13820b57cec5SDimitry Andric return TargetEnvironment == NativeEnvironment || IgnoreSim ? "ios" 13830b57cec5SDimitry Andric : "iossim"; 13840b57cec5SDimitry Andric case DarwinPlatformKind::TvOS: 13850b57cec5SDimitry Andric return TargetEnvironment == NativeEnvironment || IgnoreSim ? "tvos" 13860b57cec5SDimitry Andric : "tvossim"; 13870b57cec5SDimitry Andric case DarwinPlatformKind::WatchOS: 13880b57cec5SDimitry Andric return TargetEnvironment == NativeEnvironment || IgnoreSim ? "watchos" 13890b57cec5SDimitry Andric : "watchossim"; 13907a6dacacSDimitry Andric case DarwinPlatformKind::XROS: 13917a6dacacSDimitry Andric return TargetEnvironment == NativeEnvironment || IgnoreSim ? "xros" 13927a6dacacSDimitry Andric : "xrossim"; 139381ad6265SDimitry Andric case DarwinPlatformKind::DriverKit: 139481ad6265SDimitry Andric return "driverkit"; 13950b57cec5SDimitry Andric } 13960b57cec5SDimitry Andric llvm_unreachable("Unsupported platform"); 13970b57cec5SDimitry Andric } 13980b57cec5SDimitry Andric 13990b57cec5SDimitry Andric /// Check if the link command contains a symbol export directive. 14000b57cec5SDimitry Andric static bool hasExportSymbolDirective(const ArgList &Args) { 14010b57cec5SDimitry Andric for (Arg *A : Args) { 14020b57cec5SDimitry Andric if (A->getOption().matches(options::OPT_exported__symbols__list)) 14030b57cec5SDimitry Andric return true; 14040b57cec5SDimitry Andric if (!A->getOption().matches(options::OPT_Wl_COMMA) && 14050b57cec5SDimitry Andric !A->getOption().matches(options::OPT_Xlinker)) 14060b57cec5SDimitry Andric continue; 14070b57cec5SDimitry Andric if (A->containsValue("-exported_symbols_list") || 14080b57cec5SDimitry Andric A->containsValue("-exported_symbol")) 14090b57cec5SDimitry Andric return true; 14100b57cec5SDimitry Andric } 14110b57cec5SDimitry Andric return false; 14120b57cec5SDimitry Andric } 14130b57cec5SDimitry Andric 14140b57cec5SDimitry Andric /// Add an export directive for \p Symbol to the link command. 14150b57cec5SDimitry Andric static void addExportedSymbol(ArgStringList &CmdArgs, const char *Symbol) { 14160b57cec5SDimitry Andric CmdArgs.push_back("-exported_symbol"); 14170b57cec5SDimitry Andric CmdArgs.push_back(Symbol); 14180b57cec5SDimitry Andric } 14190b57cec5SDimitry Andric 1420480093f4SDimitry Andric /// Add a sectalign directive for \p Segment and \p Section to the maximum 1421480093f4SDimitry Andric /// expected page size for Darwin. 1422480093f4SDimitry Andric /// 1423480093f4SDimitry Andric /// On iPhone 6+ the max supported page size is 16K. On macOS, the max is 4K. 1424480093f4SDimitry Andric /// Use a common alignment constant (16K) for now, and reduce the alignment on 1425480093f4SDimitry Andric /// macOS if it proves important. 1426480093f4SDimitry Andric static void addSectalignToPage(const ArgList &Args, ArgStringList &CmdArgs, 1427480093f4SDimitry Andric StringRef Segment, StringRef Section) { 1428480093f4SDimitry Andric for (const char *A : {"-sectalign", Args.MakeArgString(Segment), 1429480093f4SDimitry Andric Args.MakeArgString(Section), "0x4000"}) 1430480093f4SDimitry Andric CmdArgs.push_back(A); 1431480093f4SDimitry Andric } 1432480093f4SDimitry Andric 14330b57cec5SDimitry Andric void Darwin::addProfileRTLibs(const ArgList &Args, 14340b57cec5SDimitry Andric ArgStringList &CmdArgs) const { 14355ffd83dbSDimitry Andric if (!needsProfileRT(Args) && !needsGCovInstrumentation(Args)) 14365ffd83dbSDimitry Andric return; 14370b57cec5SDimitry Andric 14380b57cec5SDimitry Andric AddLinkRuntimeLib(Args, CmdArgs, "profile", 1439fe6060f1SDimitry Andric RuntimeLinkOptions(RLO_AlwaysLink)); 14400b57cec5SDimitry Andric 1441480093f4SDimitry Andric bool ForGCOV = needsGCovInstrumentation(Args); 1442480093f4SDimitry Andric 14430b57cec5SDimitry Andric // If we have a symbol export directive and we're linking in the profile 14440b57cec5SDimitry Andric // runtime, automatically export symbols necessary to implement some of the 14450b57cec5SDimitry Andric // runtime's functionality. 1446bdd1243dSDimitry Andric if (hasExportSymbolDirective(Args) && ForGCOV) { 1447e8d8bef9SDimitry Andric addExportedSymbol(CmdArgs, "___gcov_dump"); 1448e8d8bef9SDimitry Andric addExportedSymbol(CmdArgs, "___gcov_reset"); 14490b57cec5SDimitry Andric addExportedSymbol(CmdArgs, "_writeout_fn_list"); 1450d65cd7a5SDimitry Andric addExportedSymbol(CmdArgs, "_reset_fn_list"); 14510b57cec5SDimitry Andric } 1452480093f4SDimitry Andric 14535f757f3fSDimitry Andric // Align __llvm_prf_{cnts,bits,data} sections to the maximum expected page 1454480093f4SDimitry Andric // alignment. This allows profile counters to be mmap()'d to disk. Note that 1455480093f4SDimitry Andric // it's not enough to just page-align __llvm_prf_cnts: the following section 1456480093f4SDimitry Andric // must also be page-aligned so that its data is not clobbered by mmap(). 1457480093f4SDimitry Andric // 1458480093f4SDimitry Andric // The section alignment is only needed when continuous profile sync is 1459480093f4SDimitry Andric // enabled, but this is expected to be the default in Xcode. Specifying the 1460480093f4SDimitry Andric // extra alignment also allows the same binary to be used with/without sync 1461480093f4SDimitry Andric // enabled. 1462480093f4SDimitry Andric if (!ForGCOV) { 14635f757f3fSDimitry Andric for (auto IPSK : {llvm::IPSK_cnts, llvm::IPSK_bitmap, llvm::IPSK_data}) { 1464480093f4SDimitry Andric addSectalignToPage( 1465480093f4SDimitry Andric Args, CmdArgs, "__DATA", 1466480093f4SDimitry Andric llvm::getInstrProfSectionName(IPSK, llvm::Triple::MachO, 1467480093f4SDimitry Andric /*AddSegmentInfo=*/false)); 1468480093f4SDimitry Andric } 1469480093f4SDimitry Andric } 14700b57cec5SDimitry Andric } 14710b57cec5SDimitry Andric 14720b57cec5SDimitry Andric void DarwinClang::AddLinkSanitizerLibArgs(const ArgList &Args, 14730b57cec5SDimitry Andric ArgStringList &CmdArgs, 14740b57cec5SDimitry Andric StringRef Sanitizer, 14750b57cec5SDimitry Andric bool Shared) const { 14760b57cec5SDimitry Andric auto RLO = RuntimeLinkOptions(RLO_AlwaysLink | (Shared ? RLO_AddRPath : 0U)); 14770b57cec5SDimitry Andric AddLinkRuntimeLib(Args, CmdArgs, Sanitizer, RLO, Shared); 14780b57cec5SDimitry Andric } 14790b57cec5SDimitry Andric 14800b57cec5SDimitry Andric ToolChain::RuntimeLibType DarwinClang::GetRuntimeLibType( 14810b57cec5SDimitry Andric const ArgList &Args) const { 14820b57cec5SDimitry Andric if (Arg* A = Args.getLastArg(options::OPT_rtlib_EQ)) { 14830b57cec5SDimitry Andric StringRef Value = A->getValue(); 1484bdd1243dSDimitry Andric if (Value != "compiler-rt" && Value != "platform") 14850b57cec5SDimitry Andric getDriver().Diag(clang::diag::err_drv_unsupported_rtlib_for_platform) 14860b57cec5SDimitry Andric << Value << "darwin"; 14870b57cec5SDimitry Andric } 14880b57cec5SDimitry Andric 14890b57cec5SDimitry Andric return ToolChain::RLT_CompilerRT; 14900b57cec5SDimitry Andric } 14910b57cec5SDimitry Andric 14920b57cec5SDimitry Andric void DarwinClang::AddLinkRuntimeLibArgs(const ArgList &Args, 14930b57cec5SDimitry Andric ArgStringList &CmdArgs, 14940b57cec5SDimitry Andric bool ForceLinkBuiltinRT) const { 14950b57cec5SDimitry Andric // Call once to ensure diagnostic is printed if wrong value was specified 14960b57cec5SDimitry Andric GetRuntimeLibType(Args); 14970b57cec5SDimitry Andric 14980b57cec5SDimitry Andric // Darwin doesn't support real static executables, don't link any runtime 14990b57cec5SDimitry Andric // libraries with -static. 15000b57cec5SDimitry Andric if (Args.hasArg(options::OPT_static) || 15010b57cec5SDimitry Andric Args.hasArg(options::OPT_fapple_kext) || 15020b57cec5SDimitry Andric Args.hasArg(options::OPT_mkernel)) { 15030b57cec5SDimitry Andric if (ForceLinkBuiltinRT) 15040b57cec5SDimitry Andric AddLinkRuntimeLib(Args, CmdArgs, "builtins"); 15050b57cec5SDimitry Andric return; 15060b57cec5SDimitry Andric } 15070b57cec5SDimitry Andric 15080b57cec5SDimitry Andric // Reject -static-libgcc for now, we can deal with this when and if someone 15090b57cec5SDimitry Andric // cares. This is useful in situations where someone wants to statically link 15100b57cec5SDimitry Andric // something like libstdc++, and needs its runtime support routines. 15110b57cec5SDimitry Andric if (const Arg *A = Args.getLastArg(options::OPT_static_libgcc)) { 15120b57cec5SDimitry Andric getDriver().Diag(diag::err_drv_unsupported_opt) << A->getAsString(Args); 15130b57cec5SDimitry Andric return; 15140b57cec5SDimitry Andric } 15150b57cec5SDimitry Andric 1516349cc55cSDimitry Andric const SanitizerArgs &Sanitize = getSanitizerArgs(Args); 1517bdd1243dSDimitry Andric 151806c3fb27SDimitry Andric if (!Sanitize.needsSharedRt()) { 151906c3fb27SDimitry Andric const char *sanitizer = nullptr; 152006c3fb27SDimitry Andric if (Sanitize.needsUbsanRt()) { 152106c3fb27SDimitry Andric sanitizer = "UndefinedBehaviorSanitizer"; 152206c3fb27SDimitry Andric } else if (Sanitize.needsAsanRt()) { 152306c3fb27SDimitry Andric sanitizer = "AddressSanitizer"; 152406c3fb27SDimitry Andric } else if (Sanitize.needsTsanRt()) { 152506c3fb27SDimitry Andric sanitizer = "ThreadSanitizer"; 152606c3fb27SDimitry Andric } 152706c3fb27SDimitry Andric if (sanitizer) { 152806c3fb27SDimitry Andric getDriver().Diag(diag::err_drv_unsupported_static_sanitizer_darwin) 152906c3fb27SDimitry Andric << sanitizer; 1530bdd1243dSDimitry Andric return; 1531bdd1243dSDimitry Andric } 153206c3fb27SDimitry Andric } 1533bdd1243dSDimitry Andric 153406c3fb27SDimitry Andric if (Sanitize.linkRuntimes()) { 153506c3fb27SDimitry Andric if (Sanitize.needsAsanRt()) { 15365f757f3fSDimitry Andric if (Sanitize.needsStableAbi()) { 15375f757f3fSDimitry Andric AddLinkSanitizerLibArgs(Args, CmdArgs, "asan_abi", /*shared=*/false); 15385f757f3fSDimitry Andric } else { 153906c3fb27SDimitry Andric assert(Sanitize.needsSharedRt() && 154006c3fb27SDimitry Andric "Static sanitizer runtimes not supported"); 15410b57cec5SDimitry Andric AddLinkSanitizerLibArgs(Args, CmdArgs, "asan"); 154206c3fb27SDimitry Andric } 15435f757f3fSDimitry Andric } 15440b57cec5SDimitry Andric if (Sanitize.needsLsanRt()) 15450b57cec5SDimitry Andric AddLinkSanitizerLibArgs(Args, CmdArgs, "lsan"); 1546bdd1243dSDimitry Andric if (Sanitize.needsUbsanRt()) { 154706c3fb27SDimitry Andric assert(Sanitize.needsSharedRt() && 154806c3fb27SDimitry Andric "Static sanitizer runtimes not supported"); 154906c3fb27SDimitry Andric AddLinkSanitizerLibArgs( 155006c3fb27SDimitry Andric Args, CmdArgs, 155106c3fb27SDimitry Andric Sanitize.requiresMinimalRuntime() ? "ubsan_minimal" : "ubsan"); 1552bdd1243dSDimitry Andric } 155306c3fb27SDimitry Andric if (Sanitize.needsTsanRt()) { 155406c3fb27SDimitry Andric assert(Sanitize.needsSharedRt() && 155506c3fb27SDimitry Andric "Static sanitizer runtimes not supported"); 15560b57cec5SDimitry Andric AddLinkSanitizerLibArgs(Args, CmdArgs, "tsan"); 155706c3fb27SDimitry Andric } 15580b57cec5SDimitry Andric if (Sanitize.needsFuzzer() && !Args.hasArg(options::OPT_dynamiclib)) { 15590b57cec5SDimitry Andric AddLinkSanitizerLibArgs(Args, CmdArgs, "fuzzer", /*shared=*/false); 15600b57cec5SDimitry Andric 15610b57cec5SDimitry Andric // Libfuzzer is written in C++ and requires libcxx. 15620b57cec5SDimitry Andric AddCXXStdlibLibArgs(Args, CmdArgs); 15630b57cec5SDimitry Andric } 15640b57cec5SDimitry Andric if (Sanitize.needsStatsRt()) { 15650b57cec5SDimitry Andric AddLinkRuntimeLib(Args, CmdArgs, "stats_client", RLO_AlwaysLink); 15660b57cec5SDimitry Andric AddLinkSanitizerLibArgs(Args, CmdArgs, "stats"); 15670b57cec5SDimitry Andric } 156806c3fb27SDimitry Andric } 15690b57cec5SDimitry Andric 15700b57cec5SDimitry Andric const XRayArgs &XRay = getXRayArgs(); 15710b57cec5SDimitry Andric if (XRay.needsXRayRt()) { 15720b57cec5SDimitry Andric AddLinkRuntimeLib(Args, CmdArgs, "xray"); 15730b57cec5SDimitry Andric AddLinkRuntimeLib(Args, CmdArgs, "xray-basic"); 15740b57cec5SDimitry Andric AddLinkRuntimeLib(Args, CmdArgs, "xray-fdr"); 15750b57cec5SDimitry Andric } 15760b57cec5SDimitry Andric 157781ad6265SDimitry Andric if (isTargetDriverKit() && !Args.hasArg(options::OPT_nodriverkitlib)) { 157881ad6265SDimitry Andric CmdArgs.push_back("-framework"); 157981ad6265SDimitry Andric CmdArgs.push_back("DriverKit"); 158081ad6265SDimitry Andric } 158181ad6265SDimitry Andric 15820b57cec5SDimitry Andric // Otherwise link libSystem, then the dynamic runtime library, and finally any 15830b57cec5SDimitry Andric // target specific static runtime library. 158481ad6265SDimitry Andric if (!isTargetDriverKit()) 15850b57cec5SDimitry Andric CmdArgs.push_back("-lSystem"); 15860b57cec5SDimitry Andric 15870b57cec5SDimitry Andric // Select the dynamic runtime library and the target specific static library. 15880b57cec5SDimitry Andric if (isTargetIOSBased()) { 15890b57cec5SDimitry Andric // If we are compiling as iOS / simulator, don't attempt to link libgcc_s.1, 15900b57cec5SDimitry Andric // it never went into the SDK. 15910b57cec5SDimitry Andric // Linking against libgcc_s.1 isn't needed for iOS 5.0+ 15920b57cec5SDimitry Andric if (isIPhoneOSVersionLT(5, 0) && !isTargetIOSSimulator() && 15930b57cec5SDimitry Andric getTriple().getArch() != llvm::Triple::aarch64) 15940b57cec5SDimitry Andric CmdArgs.push_back("-lgcc_s.1"); 15950b57cec5SDimitry Andric } 15960b57cec5SDimitry Andric AddLinkRuntimeLib(Args, CmdArgs, "builtins"); 15970b57cec5SDimitry Andric } 15980b57cec5SDimitry Andric 15990b57cec5SDimitry Andric /// Returns the most appropriate macOS target version for the current process. 16000b57cec5SDimitry Andric /// 16010b57cec5SDimitry Andric /// If the macOS SDK version is the same or earlier than the system version, 16020b57cec5SDimitry Andric /// then the SDK version is returned. Otherwise the system version is returned. 16030b57cec5SDimitry Andric static std::string getSystemOrSDKMacOSVersion(StringRef MacOSSDKVersion) { 16040b57cec5SDimitry Andric llvm::Triple SystemTriple(llvm::sys::getProcessTriple()); 16050b57cec5SDimitry Andric if (!SystemTriple.isMacOSX()) 16065ffd83dbSDimitry Andric return std::string(MacOSSDKVersion); 16070eae32dcSDimitry Andric VersionTuple SystemVersion; 16080eae32dcSDimitry Andric SystemTriple.getMacOSXVersion(SystemVersion); 1609bdd1243dSDimitry Andric 1610bdd1243dSDimitry Andric unsigned Major, Minor, Micro; 16110b57cec5SDimitry Andric bool HadExtra; 16120b57cec5SDimitry Andric if (!Driver::GetReleaseVersion(MacOSSDKVersion, Major, Minor, Micro, 16130b57cec5SDimitry Andric HadExtra)) 16145ffd83dbSDimitry Andric return std::string(MacOSSDKVersion); 16150b57cec5SDimitry Andric VersionTuple SDKVersion(Major, Minor, Micro); 1616bdd1243dSDimitry Andric 16170b57cec5SDimitry Andric if (SDKVersion > SystemVersion) 16180b57cec5SDimitry Andric return SystemVersion.getAsString(); 16195ffd83dbSDimitry Andric return std::string(MacOSSDKVersion); 16200b57cec5SDimitry Andric } 16210b57cec5SDimitry Andric 16220b57cec5SDimitry Andric namespace { 16230b57cec5SDimitry Andric 16240b57cec5SDimitry Andric /// The Darwin OS that was selected or inferred from arguments / environment. 16250b57cec5SDimitry Andric struct DarwinPlatform { 16260b57cec5SDimitry Andric enum SourceKind { 16270b57cec5SDimitry Andric /// The OS was specified using the -target argument. 16280b57cec5SDimitry Andric TargetArg, 1629349cc55cSDimitry Andric /// The OS was specified using the -mtargetos= argument. 1630349cc55cSDimitry Andric MTargetOSArg, 16310b57cec5SDimitry Andric /// The OS was specified using the -m<os>-version-min argument. 16320b57cec5SDimitry Andric OSVersionArg, 16330b57cec5SDimitry Andric /// The OS was specified using the OS_DEPLOYMENT_TARGET environment. 16340b57cec5SDimitry Andric DeploymentTargetEnv, 16350b57cec5SDimitry Andric /// The OS was inferred from the SDK. 16360b57cec5SDimitry Andric InferredFromSDK, 16370b57cec5SDimitry Andric /// The OS was inferred from the -arch. 16380b57cec5SDimitry Andric InferredFromArch 16390b57cec5SDimitry Andric }; 16400b57cec5SDimitry Andric 16410b57cec5SDimitry Andric using DarwinPlatformKind = Darwin::DarwinPlatformKind; 16420b57cec5SDimitry Andric using DarwinEnvironmentKind = Darwin::DarwinEnvironmentKind; 16430b57cec5SDimitry Andric 16440b57cec5SDimitry Andric DarwinPlatformKind getPlatform() const { return Platform; } 16450b57cec5SDimitry Andric 16460b57cec5SDimitry Andric DarwinEnvironmentKind getEnvironment() const { return Environment; } 16470b57cec5SDimitry Andric 16480b57cec5SDimitry Andric void setEnvironment(DarwinEnvironmentKind Kind) { 16490b57cec5SDimitry Andric Environment = Kind; 16500b57cec5SDimitry Andric InferSimulatorFromArch = false; 16510b57cec5SDimitry Andric } 16520b57cec5SDimitry Andric 16530b57cec5SDimitry Andric StringRef getOSVersion() const { 16540b57cec5SDimitry Andric if (Kind == OSVersionArg) 16550b57cec5SDimitry Andric return Argument->getValue(); 16560b57cec5SDimitry Andric return OSVersion; 16570b57cec5SDimitry Andric } 16580b57cec5SDimitry Andric 16590b57cec5SDimitry Andric void setOSVersion(StringRef S) { 16600b57cec5SDimitry Andric assert(Kind == TargetArg && "Unexpected kind!"); 16615ffd83dbSDimitry Andric OSVersion = std::string(S); 16620b57cec5SDimitry Andric } 16630b57cec5SDimitry Andric 16640b57cec5SDimitry Andric bool hasOSVersion() const { return HasOSVersion; } 16650b57cec5SDimitry Andric 1666fe6060f1SDimitry Andric VersionTuple getNativeTargetVersion() const { 1667fe6060f1SDimitry Andric assert(Environment == DarwinEnvironmentKind::MacCatalyst && 1668fe6060f1SDimitry Andric "native target version is specified only for Mac Catalyst"); 1669fe6060f1SDimitry Andric return NativeTargetVersion; 1670fe6060f1SDimitry Andric } 1671fe6060f1SDimitry Andric 16720b57cec5SDimitry Andric /// Returns true if the target OS was explicitly specified. 16730b57cec5SDimitry Andric bool isExplicitlySpecified() const { return Kind <= DeploymentTargetEnv; } 16740b57cec5SDimitry Andric 16750b57cec5SDimitry Andric /// Returns true if the simulator environment can be inferred from the arch. 16760b57cec5SDimitry Andric bool canInferSimulatorFromArch() const { return InferSimulatorFromArch; } 16770b57cec5SDimitry Andric 1678bdd1243dSDimitry Andric const std::optional<llvm::Triple> &getTargetVariantTriple() const { 167981ad6265SDimitry Andric return TargetVariantTriple; 168081ad6265SDimitry Andric } 168181ad6265SDimitry Andric 16820b57cec5SDimitry Andric /// Adds the -m<os>-version-min argument to the compiler invocation. 16830b57cec5SDimitry Andric void addOSVersionMinArgument(DerivedArgList &Args, const OptTable &Opts) { 16840b57cec5SDimitry Andric if (Argument) 16850b57cec5SDimitry Andric return; 1686349cc55cSDimitry Andric assert(Kind != TargetArg && Kind != MTargetOSArg && Kind != OSVersionArg && 1687349cc55cSDimitry Andric "Invalid kind"); 16880b57cec5SDimitry Andric options::ID Opt; 16890b57cec5SDimitry Andric switch (Platform) { 16900b57cec5SDimitry Andric case DarwinPlatformKind::MacOS: 1691753f127fSDimitry Andric Opt = options::OPT_mmacos_version_min_EQ; 16920b57cec5SDimitry Andric break; 16930b57cec5SDimitry Andric case DarwinPlatformKind::IPhoneOS: 1694753f127fSDimitry Andric Opt = options::OPT_mios_version_min_EQ; 16950b57cec5SDimitry Andric break; 16960b57cec5SDimitry Andric case DarwinPlatformKind::TvOS: 16970b57cec5SDimitry Andric Opt = options::OPT_mtvos_version_min_EQ; 16980b57cec5SDimitry Andric break; 16990b57cec5SDimitry Andric case DarwinPlatformKind::WatchOS: 17000b57cec5SDimitry Andric Opt = options::OPT_mwatchos_version_min_EQ; 17010b57cec5SDimitry Andric break; 17027a6dacacSDimitry Andric case DarwinPlatformKind::XROS: 17037a6dacacSDimitry Andric // xrOS always explicitly provides a version in the triple. 17047a6dacacSDimitry Andric return; 170581ad6265SDimitry Andric case DarwinPlatformKind::DriverKit: 170681ad6265SDimitry Andric // DriverKit always explicitly provides a version in the triple. 170781ad6265SDimitry Andric return; 17080b57cec5SDimitry Andric } 17090b57cec5SDimitry Andric Argument = Args.MakeJoinedArg(nullptr, Opts.getOption(Opt), OSVersion); 17100b57cec5SDimitry Andric Args.append(Argument); 17110b57cec5SDimitry Andric } 17120b57cec5SDimitry Andric 17130b57cec5SDimitry Andric /// Returns the OS version with the argument / environment variable that 17140b57cec5SDimitry Andric /// specified it. 17150b57cec5SDimitry Andric std::string getAsString(DerivedArgList &Args, const OptTable &Opts) { 17160b57cec5SDimitry Andric switch (Kind) { 17170b57cec5SDimitry Andric case TargetArg: 1718349cc55cSDimitry Andric case MTargetOSArg: 17190b57cec5SDimitry Andric case OSVersionArg: 17200b57cec5SDimitry Andric case InferredFromSDK: 17210b57cec5SDimitry Andric case InferredFromArch: 17220b57cec5SDimitry Andric assert(Argument && "OS version argument not yet inferred"); 17230b57cec5SDimitry Andric return Argument->getAsString(Args); 17240b57cec5SDimitry Andric case DeploymentTargetEnv: 17250b57cec5SDimitry Andric return (llvm::Twine(EnvVarName) + "=" + OSVersion).str(); 17260b57cec5SDimitry Andric } 17270b57cec5SDimitry Andric llvm_unreachable("Unsupported Darwin Source Kind"); 17280b57cec5SDimitry Andric } 17290b57cec5SDimitry Andric 1730349cc55cSDimitry Andric void setEnvironment(llvm::Triple::EnvironmentType EnvType, 1731349cc55cSDimitry Andric const VersionTuple &OSVersion, 1732bdd1243dSDimitry Andric const std::optional<DarwinSDKInfo> &SDKInfo) { 1733349cc55cSDimitry Andric switch (EnvType) { 1734349cc55cSDimitry Andric case llvm::Triple::Simulator: 1735349cc55cSDimitry Andric Environment = DarwinEnvironmentKind::Simulator; 1736349cc55cSDimitry Andric break; 1737349cc55cSDimitry Andric case llvm::Triple::MacABI: { 1738349cc55cSDimitry Andric Environment = DarwinEnvironmentKind::MacCatalyst; 1739349cc55cSDimitry Andric // The minimum native macOS target for MacCatalyst is macOS 10.15. 1740349cc55cSDimitry Andric NativeTargetVersion = VersionTuple(10, 15); 1741349cc55cSDimitry Andric if (HasOSVersion && SDKInfo) { 1742349cc55cSDimitry Andric if (const auto *MacCatalystToMacOSMapping = SDKInfo->getVersionMapping( 1743349cc55cSDimitry Andric DarwinSDKInfo::OSEnvPair::macCatalystToMacOSPair())) { 1744349cc55cSDimitry Andric if (auto MacOSVersion = MacCatalystToMacOSMapping->map( 1745bdd1243dSDimitry Andric OSVersion, NativeTargetVersion, std::nullopt)) { 1746349cc55cSDimitry Andric NativeTargetVersion = *MacOSVersion; 1747349cc55cSDimitry Andric } 1748349cc55cSDimitry Andric } 1749349cc55cSDimitry Andric } 175081ad6265SDimitry Andric // In a zippered build, we could be building for a macOS target that's 175181ad6265SDimitry Andric // lower than the version that's implied by the OS version. In that case 175281ad6265SDimitry Andric // we need to use the minimum version as the native target version. 175381ad6265SDimitry Andric if (TargetVariantTriple) { 175481ad6265SDimitry Andric auto TargetVariantVersion = TargetVariantTriple->getOSVersion(); 175581ad6265SDimitry Andric if (TargetVariantVersion.getMajor()) { 175681ad6265SDimitry Andric if (TargetVariantVersion < NativeTargetVersion) 175781ad6265SDimitry Andric NativeTargetVersion = TargetVariantVersion; 175881ad6265SDimitry Andric } 175981ad6265SDimitry Andric } 1760349cc55cSDimitry Andric break; 1761349cc55cSDimitry Andric } 1762349cc55cSDimitry Andric default: 1763349cc55cSDimitry Andric break; 1764349cc55cSDimitry Andric } 1765349cc55cSDimitry Andric } 1766349cc55cSDimitry Andric 1767fe6060f1SDimitry Andric static DarwinPlatform 1768fe6060f1SDimitry Andric createFromTarget(const llvm::Triple &TT, StringRef OSVersion, Arg *A, 1769bdd1243dSDimitry Andric std::optional<llvm::Triple> TargetVariantTriple, 1770bdd1243dSDimitry Andric const std::optional<DarwinSDKInfo> &SDKInfo) { 17710b57cec5SDimitry Andric DarwinPlatform Result(TargetArg, getPlatformFromOS(TT.getOS()), OSVersion, 17720b57cec5SDimitry Andric A); 17730eae32dcSDimitry Andric VersionTuple OsVersion = TT.getOSVersion(); 17740eae32dcSDimitry Andric if (OsVersion.getMajor() == 0) 17750b57cec5SDimitry Andric Result.HasOSVersion = false; 177681ad6265SDimitry Andric Result.TargetVariantTriple = TargetVariantTriple; 17770eae32dcSDimitry Andric Result.setEnvironment(TT.getEnvironment(), OsVersion, SDKInfo); 1778349cc55cSDimitry Andric return Result; 1779fe6060f1SDimitry Andric } 1780349cc55cSDimitry Andric static DarwinPlatform 1781349cc55cSDimitry Andric createFromMTargetOS(llvm::Triple::OSType OS, VersionTuple OSVersion, 1782349cc55cSDimitry Andric llvm::Triple::EnvironmentType Environment, Arg *A, 1783bdd1243dSDimitry Andric const std::optional<DarwinSDKInfo> &SDKInfo) { 1784349cc55cSDimitry Andric DarwinPlatform Result(MTargetOSArg, getPlatformFromOS(OS), 1785349cc55cSDimitry Andric OSVersion.getAsString(), A); 1786349cc55cSDimitry Andric Result.InferSimulatorFromArch = false; 1787349cc55cSDimitry Andric Result.setEnvironment(Environment, OSVersion, SDKInfo); 17880b57cec5SDimitry Andric return Result; 17890b57cec5SDimitry Andric } 1790bdd1243dSDimitry Andric static DarwinPlatform createOSVersionArg(DarwinPlatformKind Platform, Arg *A, 1791bdd1243dSDimitry Andric bool IsSimulator) { 1792bdd1243dSDimitry Andric DarwinPlatform Result{OSVersionArg, Platform, A}; 1793bdd1243dSDimitry Andric if (IsSimulator) 1794bdd1243dSDimitry Andric Result.Environment = DarwinEnvironmentKind::Simulator; 1795bdd1243dSDimitry Andric return Result; 17960b57cec5SDimitry Andric } 17970b57cec5SDimitry Andric static DarwinPlatform createDeploymentTargetEnv(DarwinPlatformKind Platform, 17980b57cec5SDimitry Andric StringRef EnvVarName, 17990b57cec5SDimitry Andric StringRef Value) { 18000b57cec5SDimitry Andric DarwinPlatform Result(DeploymentTargetEnv, Platform, Value); 18010b57cec5SDimitry Andric Result.EnvVarName = EnvVarName; 18020b57cec5SDimitry Andric return Result; 18030b57cec5SDimitry Andric } 18040b57cec5SDimitry Andric static DarwinPlatform createFromSDK(DarwinPlatformKind Platform, 18050b57cec5SDimitry Andric StringRef Value, 18060b57cec5SDimitry Andric bool IsSimulator = false) { 18070b57cec5SDimitry Andric DarwinPlatform Result(InferredFromSDK, Platform, Value); 18080b57cec5SDimitry Andric if (IsSimulator) 18090b57cec5SDimitry Andric Result.Environment = DarwinEnvironmentKind::Simulator; 18100b57cec5SDimitry Andric Result.InferSimulatorFromArch = false; 18110b57cec5SDimitry Andric return Result; 18120b57cec5SDimitry Andric } 18130b57cec5SDimitry Andric static DarwinPlatform createFromArch(llvm::Triple::OSType OS, 18140b57cec5SDimitry Andric StringRef Value) { 18150b57cec5SDimitry Andric return DarwinPlatform(InferredFromArch, getPlatformFromOS(OS), Value); 18160b57cec5SDimitry Andric } 18170b57cec5SDimitry Andric 18180b57cec5SDimitry Andric /// Constructs an inferred SDKInfo value based on the version inferred from 18190b57cec5SDimitry Andric /// the SDK path itself. Only works for values that were created by inferring 18200b57cec5SDimitry Andric /// the platform from the SDKPath. 18210b57cec5SDimitry Andric DarwinSDKInfo inferSDKInfo() { 18220b57cec5SDimitry Andric assert(Kind == InferredFromSDK && "can infer SDK info only"); 18230b57cec5SDimitry Andric llvm::VersionTuple Version; 18240b57cec5SDimitry Andric bool IsValid = !Version.tryParse(OSVersion); 18250b57cec5SDimitry Andric (void)IsValid; 18260b57cec5SDimitry Andric assert(IsValid && "invalid SDK version"); 1827fe6060f1SDimitry Andric return DarwinSDKInfo( 1828fe6060f1SDimitry Andric Version, 1829fe6060f1SDimitry Andric /*MaximumDeploymentTarget=*/VersionTuple(Version.getMajor(), 0, 99)); 18300b57cec5SDimitry Andric } 18310b57cec5SDimitry Andric 18320b57cec5SDimitry Andric private: 18330b57cec5SDimitry Andric DarwinPlatform(SourceKind Kind, DarwinPlatformKind Platform, Arg *Argument) 18340b57cec5SDimitry Andric : Kind(Kind), Platform(Platform), Argument(Argument) {} 18350b57cec5SDimitry Andric DarwinPlatform(SourceKind Kind, DarwinPlatformKind Platform, StringRef Value, 18360b57cec5SDimitry Andric Arg *Argument = nullptr) 18370b57cec5SDimitry Andric : Kind(Kind), Platform(Platform), OSVersion(Value), Argument(Argument) {} 18380b57cec5SDimitry Andric 18390b57cec5SDimitry Andric static DarwinPlatformKind getPlatformFromOS(llvm::Triple::OSType OS) { 18400b57cec5SDimitry Andric switch (OS) { 18410b57cec5SDimitry Andric case llvm::Triple::Darwin: 18420b57cec5SDimitry Andric case llvm::Triple::MacOSX: 18430b57cec5SDimitry Andric return DarwinPlatformKind::MacOS; 18440b57cec5SDimitry Andric case llvm::Triple::IOS: 18450b57cec5SDimitry Andric return DarwinPlatformKind::IPhoneOS; 18460b57cec5SDimitry Andric case llvm::Triple::TvOS: 18470b57cec5SDimitry Andric return DarwinPlatformKind::TvOS; 18480b57cec5SDimitry Andric case llvm::Triple::WatchOS: 18490b57cec5SDimitry Andric return DarwinPlatformKind::WatchOS; 18507a6dacacSDimitry Andric case llvm::Triple::XROS: 18517a6dacacSDimitry Andric return DarwinPlatformKind::XROS; 185281ad6265SDimitry Andric case llvm::Triple::DriverKit: 185381ad6265SDimitry Andric return DarwinPlatformKind::DriverKit; 18540b57cec5SDimitry Andric default: 18550b57cec5SDimitry Andric llvm_unreachable("Unable to infer Darwin variant"); 18560b57cec5SDimitry Andric } 18570b57cec5SDimitry Andric } 18580b57cec5SDimitry Andric 18590b57cec5SDimitry Andric SourceKind Kind; 18600b57cec5SDimitry Andric DarwinPlatformKind Platform; 18610b57cec5SDimitry Andric DarwinEnvironmentKind Environment = DarwinEnvironmentKind::NativeEnvironment; 1862fe6060f1SDimitry Andric VersionTuple NativeTargetVersion; 18630b57cec5SDimitry Andric std::string OSVersion; 18640b57cec5SDimitry Andric bool HasOSVersion = true, InferSimulatorFromArch = true; 18650b57cec5SDimitry Andric Arg *Argument; 18660b57cec5SDimitry Andric StringRef EnvVarName; 1867bdd1243dSDimitry Andric std::optional<llvm::Triple> TargetVariantTriple; 18680b57cec5SDimitry Andric }; 18690b57cec5SDimitry Andric 18700b57cec5SDimitry Andric /// Returns the deployment target that's specified using the -m<os>-version-min 18710b57cec5SDimitry Andric /// argument. 1872bdd1243dSDimitry Andric std::optional<DarwinPlatform> 18730b57cec5SDimitry Andric getDeploymentTargetFromOSVersionArg(DerivedArgList &Args, 18740b57cec5SDimitry Andric const Driver &TheDriver) { 1875753f127fSDimitry Andric Arg *macOSVersion = Args.getLastArg(options::OPT_mmacos_version_min_EQ); 1876753f127fSDimitry Andric Arg *iOSVersion = Args.getLastArg(options::OPT_mios_version_min_EQ, 18770b57cec5SDimitry Andric options::OPT_mios_simulator_version_min_EQ); 18780b57cec5SDimitry Andric Arg *TvOSVersion = 18790b57cec5SDimitry Andric Args.getLastArg(options::OPT_mtvos_version_min_EQ, 18800b57cec5SDimitry Andric options::OPT_mtvos_simulator_version_min_EQ); 18810b57cec5SDimitry Andric Arg *WatchOSVersion = 18820b57cec5SDimitry Andric Args.getLastArg(options::OPT_mwatchos_version_min_EQ, 18830b57cec5SDimitry Andric options::OPT_mwatchos_simulator_version_min_EQ); 1884753f127fSDimitry Andric if (macOSVersion) { 18850b57cec5SDimitry Andric if (iOSVersion || TvOSVersion || WatchOSVersion) { 18860b57cec5SDimitry Andric TheDriver.Diag(diag::err_drv_argument_not_allowed_with) 1887753f127fSDimitry Andric << macOSVersion->getAsString(Args) 18880b57cec5SDimitry Andric << (iOSVersion ? iOSVersion 18890b57cec5SDimitry Andric : TvOSVersion ? TvOSVersion : WatchOSVersion) 18900b57cec5SDimitry Andric ->getAsString(Args); 18910b57cec5SDimitry Andric } 1892bdd1243dSDimitry Andric return DarwinPlatform::createOSVersionArg(Darwin::MacOS, macOSVersion, 189306c3fb27SDimitry Andric /*IsSimulator=*/false); 18940b57cec5SDimitry Andric } else if (iOSVersion) { 18950b57cec5SDimitry Andric if (TvOSVersion || WatchOSVersion) { 18960b57cec5SDimitry Andric TheDriver.Diag(diag::err_drv_argument_not_allowed_with) 18970b57cec5SDimitry Andric << iOSVersion->getAsString(Args) 18980b57cec5SDimitry Andric << (TvOSVersion ? TvOSVersion : WatchOSVersion)->getAsString(Args); 18990b57cec5SDimitry Andric } 1900bdd1243dSDimitry Andric return DarwinPlatform::createOSVersionArg( 1901bdd1243dSDimitry Andric Darwin::IPhoneOS, iOSVersion, 1902bdd1243dSDimitry Andric iOSVersion->getOption().getID() == 1903bdd1243dSDimitry Andric options::OPT_mios_simulator_version_min_EQ); 19040b57cec5SDimitry Andric } else if (TvOSVersion) { 19050b57cec5SDimitry Andric if (WatchOSVersion) { 19060b57cec5SDimitry Andric TheDriver.Diag(diag::err_drv_argument_not_allowed_with) 19070b57cec5SDimitry Andric << TvOSVersion->getAsString(Args) 19080b57cec5SDimitry Andric << WatchOSVersion->getAsString(Args); 19090b57cec5SDimitry Andric } 1910bdd1243dSDimitry Andric return DarwinPlatform::createOSVersionArg( 1911bdd1243dSDimitry Andric Darwin::TvOS, TvOSVersion, 1912bdd1243dSDimitry Andric TvOSVersion->getOption().getID() == 1913bdd1243dSDimitry Andric options::OPT_mtvos_simulator_version_min_EQ); 19140b57cec5SDimitry Andric } else if (WatchOSVersion) 1915bdd1243dSDimitry Andric return DarwinPlatform::createOSVersionArg( 1916bdd1243dSDimitry Andric Darwin::WatchOS, WatchOSVersion, 1917bdd1243dSDimitry Andric WatchOSVersion->getOption().getID() == 1918bdd1243dSDimitry Andric options::OPT_mwatchos_simulator_version_min_EQ); 1919bdd1243dSDimitry Andric return std::nullopt; 19200b57cec5SDimitry Andric } 19210b57cec5SDimitry Andric 19220b57cec5SDimitry Andric /// Returns the deployment target that's specified using the 19230b57cec5SDimitry Andric /// OS_DEPLOYMENT_TARGET environment variable. 1924bdd1243dSDimitry Andric std::optional<DarwinPlatform> 19250b57cec5SDimitry Andric getDeploymentTargetFromEnvironmentVariables(const Driver &TheDriver, 19260b57cec5SDimitry Andric const llvm::Triple &Triple) { 19270b57cec5SDimitry Andric std::string Targets[Darwin::LastDarwinPlatform + 1]; 19280b57cec5SDimitry Andric const char *EnvVars[] = { 19290b57cec5SDimitry Andric "MACOSX_DEPLOYMENT_TARGET", 19300b57cec5SDimitry Andric "IPHONEOS_DEPLOYMENT_TARGET", 19310b57cec5SDimitry Andric "TVOS_DEPLOYMENT_TARGET", 19320b57cec5SDimitry Andric "WATCHOS_DEPLOYMENT_TARGET", 193381ad6265SDimitry Andric "DRIVERKIT_DEPLOYMENT_TARGET", 19340fca6ea1SDimitry Andric "XROS_DEPLOYMENT_TARGET" 19350b57cec5SDimitry Andric }; 1936bdd1243dSDimitry Andric static_assert(std::size(EnvVars) == Darwin::LastDarwinPlatform + 1, 19370b57cec5SDimitry Andric "Missing platform"); 1938bdd1243dSDimitry Andric for (const auto &I : llvm::enumerate(llvm::ArrayRef(EnvVars))) { 19390b57cec5SDimitry Andric if (char *Env = ::getenv(I.value())) 19400b57cec5SDimitry Andric Targets[I.index()] = Env; 19410b57cec5SDimitry Andric } 19420b57cec5SDimitry Andric 19430b57cec5SDimitry Andric // Allow conflicts among OSX and iOS for historical reasons, but choose the 19440b57cec5SDimitry Andric // default platform. 19450b57cec5SDimitry Andric if (!Targets[Darwin::MacOS].empty() && 19460b57cec5SDimitry Andric (!Targets[Darwin::IPhoneOS].empty() || 19470fca6ea1SDimitry Andric !Targets[Darwin::WatchOS].empty() || !Targets[Darwin::TvOS].empty() || 19480fca6ea1SDimitry Andric !Targets[Darwin::XROS].empty())) { 19490b57cec5SDimitry Andric if (Triple.getArch() == llvm::Triple::arm || 19500b57cec5SDimitry Andric Triple.getArch() == llvm::Triple::aarch64 || 19510b57cec5SDimitry Andric Triple.getArch() == llvm::Triple::thumb) 19520b57cec5SDimitry Andric Targets[Darwin::MacOS] = ""; 19530b57cec5SDimitry Andric else 19540b57cec5SDimitry Andric Targets[Darwin::IPhoneOS] = Targets[Darwin::WatchOS] = 19550fca6ea1SDimitry Andric Targets[Darwin::TvOS] = Targets[Darwin::XROS] = ""; 1956a7dea167SDimitry Andric } else { 1957a7dea167SDimitry Andric // Don't allow conflicts in any other platform. 1958bdd1243dSDimitry Andric unsigned FirstTarget = std::size(Targets); 1959bdd1243dSDimitry Andric for (unsigned I = 0; I != std::size(Targets); ++I) { 1960a7dea167SDimitry Andric if (Targets[I].empty()) 1961a7dea167SDimitry Andric continue; 1962bdd1243dSDimitry Andric if (FirstTarget == std::size(Targets)) 1963a7dea167SDimitry Andric FirstTarget = I; 1964a7dea167SDimitry Andric else 1965a7dea167SDimitry Andric TheDriver.Diag(diag::err_drv_conflicting_deployment_targets) 1966a7dea167SDimitry Andric << Targets[FirstTarget] << Targets[I]; 1967a7dea167SDimitry Andric } 19680b57cec5SDimitry Andric } 19690b57cec5SDimitry Andric 1970bdd1243dSDimitry Andric for (const auto &Target : llvm::enumerate(llvm::ArrayRef(Targets))) { 19710b57cec5SDimitry Andric if (!Target.value().empty()) 19720b57cec5SDimitry Andric return DarwinPlatform::createDeploymentTargetEnv( 19730b57cec5SDimitry Andric (Darwin::DarwinPlatformKind)Target.index(), EnvVars[Target.index()], 19740b57cec5SDimitry Andric Target.value()); 19750b57cec5SDimitry Andric } 1976bdd1243dSDimitry Andric return std::nullopt; 19770b57cec5SDimitry Andric } 19780b57cec5SDimitry Andric 1979fe6060f1SDimitry Andric /// Returns the SDK name without the optional prefix that ends with a '.' or an 1980fe6060f1SDimitry Andric /// empty string otherwise. 1981fe6060f1SDimitry Andric static StringRef dropSDKNamePrefix(StringRef SDKName) { 1982fe6060f1SDimitry Andric size_t PrefixPos = SDKName.find('.'); 1983fe6060f1SDimitry Andric if (PrefixPos == StringRef::npos) 1984fe6060f1SDimitry Andric return ""; 1985fe6060f1SDimitry Andric return SDKName.substr(PrefixPos + 1); 1986fe6060f1SDimitry Andric } 1987fe6060f1SDimitry Andric 19880b57cec5SDimitry Andric /// Tries to infer the deployment target from the SDK specified by -isysroot 19890b57cec5SDimitry Andric /// (or SDKROOT). Uses the version specified in the SDKSettings.json file if 19900b57cec5SDimitry Andric /// it's available. 1991bdd1243dSDimitry Andric std::optional<DarwinPlatform> 19920b57cec5SDimitry Andric inferDeploymentTargetFromSDK(DerivedArgList &Args, 1993bdd1243dSDimitry Andric const std::optional<DarwinSDKInfo> &SDKInfo) { 19940b57cec5SDimitry Andric const Arg *A = Args.getLastArg(options::OPT_isysroot); 19950b57cec5SDimitry Andric if (!A) 1996bdd1243dSDimitry Andric return std::nullopt; 19970b57cec5SDimitry Andric StringRef isysroot = A->getValue(); 19980b57cec5SDimitry Andric StringRef SDK = Darwin::getSDKName(isysroot); 19990b57cec5SDimitry Andric if (!SDK.size()) 2000bdd1243dSDimitry Andric return std::nullopt; 20010b57cec5SDimitry Andric 20020b57cec5SDimitry Andric std::string Version; 20030b57cec5SDimitry Andric if (SDKInfo) { 20040b57cec5SDimitry Andric // Get the version from the SDKSettings.json if it's available. 20050b57cec5SDimitry Andric Version = SDKInfo->getVersion().getAsString(); 20060b57cec5SDimitry Andric } else { 20070b57cec5SDimitry Andric // Slice the version number out. 20080b57cec5SDimitry Andric // Version number is between the first and the last number. 20090b57cec5SDimitry Andric size_t StartVer = SDK.find_first_of("0123456789"); 20100b57cec5SDimitry Andric size_t EndVer = SDK.find_last_of("0123456789"); 20110b57cec5SDimitry Andric if (StartVer != StringRef::npos && EndVer > StartVer) 20125ffd83dbSDimitry Andric Version = std::string(SDK.slice(StartVer, EndVer + 1)); 20130b57cec5SDimitry Andric } 20140b57cec5SDimitry Andric if (Version.empty()) 2015bdd1243dSDimitry Andric return std::nullopt; 20160b57cec5SDimitry Andric 2017fe6060f1SDimitry Andric auto CreatePlatformFromSDKName = 2018bdd1243dSDimitry Andric [&](StringRef SDK) -> std::optional<DarwinPlatform> { 20195f757f3fSDimitry Andric if (SDK.starts_with("iPhoneOS") || SDK.starts_with("iPhoneSimulator")) 20200b57cec5SDimitry Andric return DarwinPlatform::createFromSDK( 20210b57cec5SDimitry Andric Darwin::IPhoneOS, Version, 20225f757f3fSDimitry Andric /*IsSimulator=*/SDK.starts_with("iPhoneSimulator")); 20235f757f3fSDimitry Andric else if (SDK.starts_with("MacOSX")) 20240b57cec5SDimitry Andric return DarwinPlatform::createFromSDK(Darwin::MacOS, 20250b57cec5SDimitry Andric getSystemOrSDKMacOSVersion(Version)); 20265f757f3fSDimitry Andric else if (SDK.starts_with("WatchOS") || SDK.starts_with("WatchSimulator")) 20270b57cec5SDimitry Andric return DarwinPlatform::createFromSDK( 20280b57cec5SDimitry Andric Darwin::WatchOS, Version, 20295f757f3fSDimitry Andric /*IsSimulator=*/SDK.starts_with("WatchSimulator")); 20305f757f3fSDimitry Andric else if (SDK.starts_with("AppleTVOS") || 20315f757f3fSDimitry Andric SDK.starts_with("AppleTVSimulator")) 20320b57cec5SDimitry Andric return DarwinPlatform::createFromSDK( 20330b57cec5SDimitry Andric Darwin::TvOS, Version, 20345f757f3fSDimitry Andric /*IsSimulator=*/SDK.starts_with("AppleTVSimulator")); 20357a6dacacSDimitry Andric else if (SDK.starts_with("XR")) 20367a6dacacSDimitry Andric return DarwinPlatform::createFromSDK( 20377a6dacacSDimitry Andric Darwin::XROS, Version, 20387a6dacacSDimitry Andric /*IsSimulator=*/SDK.contains("Simulator")); 20395f757f3fSDimitry Andric else if (SDK.starts_with("DriverKit")) 204081ad6265SDimitry Andric return DarwinPlatform::createFromSDK(Darwin::DriverKit, Version); 2041bdd1243dSDimitry Andric return std::nullopt; 2042fe6060f1SDimitry Andric }; 2043fe6060f1SDimitry Andric if (auto Result = CreatePlatformFromSDKName(SDK)) 2044fe6060f1SDimitry Andric return Result; 2045fe6060f1SDimitry Andric // The SDK can be an SDK variant with a name like `<prefix>.<platform>`. 2046fe6060f1SDimitry Andric return CreatePlatformFromSDKName(dropSDKNamePrefix(SDK)); 20470b57cec5SDimitry Andric } 20480b57cec5SDimitry Andric 20490b57cec5SDimitry Andric std::string getOSVersion(llvm::Triple::OSType OS, const llvm::Triple &Triple, 20500b57cec5SDimitry Andric const Driver &TheDriver) { 20510eae32dcSDimitry Andric VersionTuple OsVersion; 20520b57cec5SDimitry Andric llvm::Triple SystemTriple(llvm::sys::getProcessTriple()); 20530b57cec5SDimitry Andric switch (OS) { 20540b57cec5SDimitry Andric case llvm::Triple::Darwin: 20550b57cec5SDimitry Andric case llvm::Triple::MacOSX: 20560b57cec5SDimitry Andric // If there is no version specified on triple, and both host and target are 20570b57cec5SDimitry Andric // macos, use the host triple to infer OS version. 20580b57cec5SDimitry Andric if (Triple.isMacOSX() && SystemTriple.isMacOSX() && 20590b57cec5SDimitry Andric !Triple.getOSMajorVersion()) 20600eae32dcSDimitry Andric SystemTriple.getMacOSXVersion(OsVersion); 20610eae32dcSDimitry Andric else if (!Triple.getMacOSXVersion(OsVersion)) 20620b57cec5SDimitry Andric TheDriver.Diag(diag::err_drv_invalid_darwin_version) 20630b57cec5SDimitry Andric << Triple.getOSName(); 20640b57cec5SDimitry Andric break; 20650b57cec5SDimitry Andric case llvm::Triple::IOS: 2066349cc55cSDimitry Andric if (Triple.isMacCatalystEnvironment() && !Triple.getOSMajorVersion()) { 20670eae32dcSDimitry Andric OsVersion = VersionTuple(13, 1); 2068349cc55cSDimitry Andric } else 20690eae32dcSDimitry Andric OsVersion = Triple.getiOSVersion(); 20700b57cec5SDimitry Andric break; 20710b57cec5SDimitry Andric case llvm::Triple::TvOS: 20720eae32dcSDimitry Andric OsVersion = Triple.getOSVersion(); 20730b57cec5SDimitry Andric break; 20740b57cec5SDimitry Andric case llvm::Triple::WatchOS: 20750eae32dcSDimitry Andric OsVersion = Triple.getWatchOSVersion(); 20760b57cec5SDimitry Andric break; 20777a6dacacSDimitry Andric case llvm::Triple::XROS: 20787a6dacacSDimitry Andric OsVersion = Triple.getOSVersion(); 20797a6dacacSDimitry Andric if (!OsVersion.getMajor()) 20807a6dacacSDimitry Andric OsVersion = OsVersion.withMajorReplaced(1); 20817a6dacacSDimitry Andric break; 208281ad6265SDimitry Andric case llvm::Triple::DriverKit: 208381ad6265SDimitry Andric OsVersion = Triple.getDriverKitVersion(); 208481ad6265SDimitry Andric break; 20850b57cec5SDimitry Andric default: 20860b57cec5SDimitry Andric llvm_unreachable("Unexpected OS type"); 20870b57cec5SDimitry Andric break; 20880b57cec5SDimitry Andric } 20890b57cec5SDimitry Andric 20900b57cec5SDimitry Andric std::string OSVersion; 20910eae32dcSDimitry Andric llvm::raw_string_ostream(OSVersion) 209281ad6265SDimitry Andric << OsVersion.getMajor() << '.' << OsVersion.getMinor().value_or(0) << '.' 209381ad6265SDimitry Andric << OsVersion.getSubminor().value_or(0); 20940b57cec5SDimitry Andric return OSVersion; 20950b57cec5SDimitry Andric } 20960b57cec5SDimitry Andric 20970b57cec5SDimitry Andric /// Tries to infer the target OS from the -arch. 2098bdd1243dSDimitry Andric std::optional<DarwinPlatform> 20990b57cec5SDimitry Andric inferDeploymentTargetFromArch(DerivedArgList &Args, const Darwin &Toolchain, 21000b57cec5SDimitry Andric const llvm::Triple &Triple, 21010b57cec5SDimitry Andric const Driver &TheDriver) { 21020b57cec5SDimitry Andric llvm::Triple::OSType OSTy = llvm::Triple::UnknownOS; 21030b57cec5SDimitry Andric 21040b57cec5SDimitry Andric StringRef MachOArchName = Toolchain.getMachOArchName(Args); 210581ad6265SDimitry Andric if (MachOArchName == "arm64" || MachOArchName == "arm64e") 21065ffd83dbSDimitry Andric OSTy = llvm::Triple::MacOSX; 210781ad6265SDimitry Andric else if (MachOArchName == "armv7" || MachOArchName == "armv7s") 21080b57cec5SDimitry Andric OSTy = llvm::Triple::IOS; 2109480093f4SDimitry Andric else if (MachOArchName == "armv7k" || MachOArchName == "arm64_32") 21100b57cec5SDimitry Andric OSTy = llvm::Triple::WatchOS; 21110b57cec5SDimitry Andric else if (MachOArchName != "armv6m" && MachOArchName != "armv7m" && 21120b57cec5SDimitry Andric MachOArchName != "armv7em") 21130b57cec5SDimitry Andric OSTy = llvm::Triple::MacOSX; 21140b57cec5SDimitry Andric if (OSTy == llvm::Triple::UnknownOS) 2115bdd1243dSDimitry Andric return std::nullopt; 21160b57cec5SDimitry Andric return DarwinPlatform::createFromArch(OSTy, 21170b57cec5SDimitry Andric getOSVersion(OSTy, Triple, TheDriver)); 21180b57cec5SDimitry Andric } 21190b57cec5SDimitry Andric 21200b57cec5SDimitry Andric /// Returns the deployment target that's specified using the -target option. 2121bdd1243dSDimitry Andric std::optional<DarwinPlatform> getDeploymentTargetFromTargetArg( 2122fe6060f1SDimitry Andric DerivedArgList &Args, const llvm::Triple &Triple, const Driver &TheDriver, 2123bdd1243dSDimitry Andric const std::optional<DarwinSDKInfo> &SDKInfo) { 21240b57cec5SDimitry Andric if (!Args.hasArg(options::OPT_target)) 2125bdd1243dSDimitry Andric return std::nullopt; 21260b57cec5SDimitry Andric if (Triple.getOS() == llvm::Triple::Darwin || 21270b57cec5SDimitry Andric Triple.getOS() == llvm::Triple::UnknownOS) 2128bdd1243dSDimitry Andric return std::nullopt; 21290b57cec5SDimitry Andric std::string OSVersion = getOSVersion(Triple.getOS(), Triple, TheDriver); 2130bdd1243dSDimitry Andric std::optional<llvm::Triple> TargetVariantTriple; 213181ad6265SDimitry Andric for (const Arg *A : Args.filtered(options::OPT_darwin_target_variant)) { 213281ad6265SDimitry Andric llvm::Triple TVT(A->getValue()); 213381ad6265SDimitry Andric // Find a matching <arch>-<vendor> target variant triple that can be used. 213481ad6265SDimitry Andric if ((Triple.getArch() == llvm::Triple::aarch64 || 213581ad6265SDimitry Andric TVT.getArchName() == Triple.getArchName()) && 213681ad6265SDimitry Andric TVT.getArch() == Triple.getArch() && 213781ad6265SDimitry Andric TVT.getSubArch() == Triple.getSubArch() && 213881ad6265SDimitry Andric TVT.getVendor() == Triple.getVendor()) { 213981ad6265SDimitry Andric if (TargetVariantTriple) 214081ad6265SDimitry Andric continue; 214181ad6265SDimitry Andric A->claim(); 214281ad6265SDimitry Andric // Accept a -target-variant triple when compiling code that may run on 21435f757f3fSDimitry Andric // macOS or Mac Catalyst. 214481ad6265SDimitry Andric if ((Triple.isMacOSX() && TVT.getOS() == llvm::Triple::IOS && 214581ad6265SDimitry Andric TVT.isMacCatalystEnvironment()) || 214681ad6265SDimitry Andric (TVT.isMacOSX() && Triple.getOS() == llvm::Triple::IOS && 214781ad6265SDimitry Andric Triple.isMacCatalystEnvironment())) { 214881ad6265SDimitry Andric TargetVariantTriple = TVT; 214981ad6265SDimitry Andric continue; 215081ad6265SDimitry Andric } 215181ad6265SDimitry Andric TheDriver.Diag(diag::err_drv_target_variant_invalid) 215281ad6265SDimitry Andric << A->getSpelling() << A->getValue(); 215381ad6265SDimitry Andric } 215481ad6265SDimitry Andric } 215581ad6265SDimitry Andric return DarwinPlatform::createFromTarget(Triple, OSVersion, 215681ad6265SDimitry Andric Args.getLastArg(options::OPT_target), 215781ad6265SDimitry Andric TargetVariantTriple, SDKInfo); 21580b57cec5SDimitry Andric } 21590b57cec5SDimitry Andric 2160349cc55cSDimitry Andric /// Returns the deployment target that's specified using the -mtargetos option. 2161bdd1243dSDimitry Andric std::optional<DarwinPlatform> getDeploymentTargetFromMTargetOSArg( 2162bdd1243dSDimitry Andric DerivedArgList &Args, const Driver &TheDriver, 2163bdd1243dSDimitry Andric const std::optional<DarwinSDKInfo> &SDKInfo) { 2164349cc55cSDimitry Andric auto *A = Args.getLastArg(options::OPT_mtargetos_EQ); 2165349cc55cSDimitry Andric if (!A) 2166bdd1243dSDimitry Andric return std::nullopt; 2167349cc55cSDimitry Andric llvm::Triple TT(llvm::Twine("unknown-apple-") + A->getValue()); 2168349cc55cSDimitry Andric switch (TT.getOS()) { 2169349cc55cSDimitry Andric case llvm::Triple::MacOSX: 2170349cc55cSDimitry Andric case llvm::Triple::IOS: 2171349cc55cSDimitry Andric case llvm::Triple::TvOS: 2172349cc55cSDimitry Andric case llvm::Triple::WatchOS: 21737a6dacacSDimitry Andric case llvm::Triple::XROS: 2174349cc55cSDimitry Andric break; 2175349cc55cSDimitry Andric default: 2176349cc55cSDimitry Andric TheDriver.Diag(diag::err_drv_invalid_os_in_arg) 2177349cc55cSDimitry Andric << TT.getOSName() << A->getAsString(Args); 2178bdd1243dSDimitry Andric return std::nullopt; 2179349cc55cSDimitry Andric } 2180349cc55cSDimitry Andric 21810eae32dcSDimitry Andric VersionTuple Version = TT.getOSVersion(); 21820eae32dcSDimitry Andric if (!Version.getMajor()) { 2183349cc55cSDimitry Andric TheDriver.Diag(diag::err_drv_invalid_version_number) 2184349cc55cSDimitry Andric << A->getAsString(Args); 2185bdd1243dSDimitry Andric return std::nullopt; 2186349cc55cSDimitry Andric } 21870eae32dcSDimitry Andric return DarwinPlatform::createFromMTargetOS(TT.getOS(), Version, 2188349cc55cSDimitry Andric TT.getEnvironment(), A, SDKInfo); 2189349cc55cSDimitry Andric } 2190349cc55cSDimitry Andric 2191bdd1243dSDimitry Andric std::optional<DarwinSDKInfo> parseSDKSettings(llvm::vfs::FileSystem &VFS, 21920b57cec5SDimitry Andric const ArgList &Args, 21930b57cec5SDimitry Andric const Driver &TheDriver) { 21940b57cec5SDimitry Andric const Arg *A = Args.getLastArg(options::OPT_isysroot); 21950b57cec5SDimitry Andric if (!A) 2196bdd1243dSDimitry Andric return std::nullopt; 21970b57cec5SDimitry Andric StringRef isysroot = A->getValue(); 2198fe6060f1SDimitry Andric auto SDKInfoOrErr = parseDarwinSDKInfo(VFS, isysroot); 21990b57cec5SDimitry Andric if (!SDKInfoOrErr) { 22000b57cec5SDimitry Andric llvm::consumeError(SDKInfoOrErr.takeError()); 22010b57cec5SDimitry Andric TheDriver.Diag(diag::warn_drv_darwin_sdk_invalid_settings); 2202bdd1243dSDimitry Andric return std::nullopt; 22030b57cec5SDimitry Andric } 22040b57cec5SDimitry Andric return *SDKInfoOrErr; 22050b57cec5SDimitry Andric } 22060b57cec5SDimitry Andric 22070b57cec5SDimitry Andric } // namespace 22080b57cec5SDimitry Andric 22090b57cec5SDimitry Andric void Darwin::AddDeploymentTarget(DerivedArgList &Args) const { 22100b57cec5SDimitry Andric const OptTable &Opts = getDriver().getOpts(); 22110b57cec5SDimitry Andric 22120b57cec5SDimitry Andric // Support allowing the SDKROOT environment variable used by xcrun and other 22130b57cec5SDimitry Andric // Xcode tools to define the default sysroot, by making it the default for 22140b57cec5SDimitry Andric // isysroot. 22150b57cec5SDimitry Andric if (const Arg *A = Args.getLastArg(options::OPT_isysroot)) { 22160b57cec5SDimitry Andric // Warn if the path does not exist. 22170b57cec5SDimitry Andric if (!getVFS().exists(A->getValue())) 22180b57cec5SDimitry Andric getDriver().Diag(clang::diag::warn_missing_sysroot) << A->getValue(); 22190b57cec5SDimitry Andric } else { 22200b57cec5SDimitry Andric if (char *env = ::getenv("SDKROOT")) { 22210b57cec5SDimitry Andric // We only use this value as the default if it is an absolute path, 22220b57cec5SDimitry Andric // exists, and it is not the root path. 22230b57cec5SDimitry Andric if (llvm::sys::path::is_absolute(env) && getVFS().exists(env) && 22240b57cec5SDimitry Andric StringRef(env) != "/") { 22250b57cec5SDimitry Andric Args.append(Args.MakeSeparateArg( 22260b57cec5SDimitry Andric nullptr, Opts.getOption(options::OPT_isysroot), env)); 22270b57cec5SDimitry Andric } 22280b57cec5SDimitry Andric } 22290b57cec5SDimitry Andric } 22300b57cec5SDimitry Andric 22310b57cec5SDimitry Andric // Read the SDKSettings.json file for more information, like the SDK version 22320b57cec5SDimitry Andric // that we can pass down to the compiler. 22330b57cec5SDimitry Andric SDKInfo = parseSDKSettings(getVFS(), Args, getDriver()); 22340b57cec5SDimitry Andric 22350b57cec5SDimitry Andric // The OS and the version can be specified using the -target argument. 2236bdd1243dSDimitry Andric std::optional<DarwinPlatform> OSTarget = 2237fe6060f1SDimitry Andric getDeploymentTargetFromTargetArg(Args, getTriple(), getDriver(), SDKInfo); 22380b57cec5SDimitry Andric if (OSTarget) { 2239349cc55cSDimitry Andric // Disallow mixing -target and -mtargetos=. 2240349cc55cSDimitry Andric if (const auto *MTargetOSArg = Args.getLastArg(options::OPT_mtargetos_EQ)) { 2241349cc55cSDimitry Andric std::string TargetArgStr = OSTarget->getAsString(Args, Opts); 2242349cc55cSDimitry Andric std::string MTargetOSArgStr = MTargetOSArg->getAsString(Args); 2243349cc55cSDimitry Andric getDriver().Diag(diag::err_drv_cannot_mix_options) 2244349cc55cSDimitry Andric << TargetArgStr << MTargetOSArgStr; 2245349cc55cSDimitry Andric } 2246bdd1243dSDimitry Andric std::optional<DarwinPlatform> OSVersionArgTarget = 22470b57cec5SDimitry Andric getDeploymentTargetFromOSVersionArg(Args, getDriver()); 22480b57cec5SDimitry Andric if (OSVersionArgTarget) { 22490b57cec5SDimitry Andric unsigned TargetMajor, TargetMinor, TargetMicro; 22500b57cec5SDimitry Andric bool TargetExtra; 22510b57cec5SDimitry Andric unsigned ArgMajor, ArgMinor, ArgMicro; 22520b57cec5SDimitry Andric bool ArgExtra; 22530b57cec5SDimitry Andric if (OSTarget->getPlatform() != OSVersionArgTarget->getPlatform() || 22540b57cec5SDimitry Andric (Driver::GetReleaseVersion(OSTarget->getOSVersion(), TargetMajor, 22550b57cec5SDimitry Andric TargetMinor, TargetMicro, TargetExtra) && 22560b57cec5SDimitry Andric Driver::GetReleaseVersion(OSVersionArgTarget->getOSVersion(), 22570b57cec5SDimitry Andric ArgMajor, ArgMinor, ArgMicro, ArgExtra) && 22580b57cec5SDimitry Andric (VersionTuple(TargetMajor, TargetMinor, TargetMicro) != 22590b57cec5SDimitry Andric VersionTuple(ArgMajor, ArgMinor, ArgMicro) || 22600b57cec5SDimitry Andric TargetExtra != ArgExtra))) { 22610b57cec5SDimitry Andric // Select the OS version from the -m<os>-version-min argument when 22620b57cec5SDimitry Andric // the -target does not include an OS version. 22630b57cec5SDimitry Andric if (OSTarget->getPlatform() == OSVersionArgTarget->getPlatform() && 22640b57cec5SDimitry Andric !OSTarget->hasOSVersion()) { 22650b57cec5SDimitry Andric OSTarget->setOSVersion(OSVersionArgTarget->getOSVersion()); 22660b57cec5SDimitry Andric } else { 22670b57cec5SDimitry Andric // Warn about -m<os>-version-min that doesn't match the OS version 22680b57cec5SDimitry Andric // that's specified in the target. 22690b57cec5SDimitry Andric std::string OSVersionArg = 22700b57cec5SDimitry Andric OSVersionArgTarget->getAsString(Args, Opts); 22710b57cec5SDimitry Andric std::string TargetArg = OSTarget->getAsString(Args, Opts); 22725f757f3fSDimitry Andric getDriver().Diag(clang::diag::warn_drv_overriding_option) 22730b57cec5SDimitry Andric << OSVersionArg << TargetArg; 22740b57cec5SDimitry Andric } 22750b57cec5SDimitry Andric } 22760b57cec5SDimitry Andric } 2277349cc55cSDimitry Andric } else if ((OSTarget = getDeploymentTargetFromMTargetOSArg(Args, getDriver(), 2278349cc55cSDimitry Andric SDKInfo))) { 2279349cc55cSDimitry Andric // The OS target can be specified using the -mtargetos= argument. 2280349cc55cSDimitry Andric // Disallow mixing -mtargetos= and -m<os>version-min=. 2281bdd1243dSDimitry Andric std::optional<DarwinPlatform> OSVersionArgTarget = 2282349cc55cSDimitry Andric getDeploymentTargetFromOSVersionArg(Args, getDriver()); 2283349cc55cSDimitry Andric if (OSVersionArgTarget) { 2284349cc55cSDimitry Andric std::string MTargetOSArgStr = OSTarget->getAsString(Args, Opts); 2285349cc55cSDimitry Andric std::string OSVersionArgStr = OSVersionArgTarget->getAsString(Args, Opts); 2286349cc55cSDimitry Andric getDriver().Diag(diag::err_drv_cannot_mix_options) 2287349cc55cSDimitry Andric << MTargetOSArgStr << OSVersionArgStr; 2288349cc55cSDimitry Andric } 22890b57cec5SDimitry Andric } else { 22900b57cec5SDimitry Andric // The OS target can be specified using the -m<os>version-min argument. 22910b57cec5SDimitry Andric OSTarget = getDeploymentTargetFromOSVersionArg(Args, getDriver()); 22920b57cec5SDimitry Andric // If no deployment target was specified on the command line, check for 22930b57cec5SDimitry Andric // environment defines. 22940b57cec5SDimitry Andric if (!OSTarget) { 22950b57cec5SDimitry Andric OSTarget = 22960b57cec5SDimitry Andric getDeploymentTargetFromEnvironmentVariables(getDriver(), getTriple()); 22970b57cec5SDimitry Andric if (OSTarget) { 22980b57cec5SDimitry Andric // Don't infer simulator from the arch when the SDK is also specified. 2299bdd1243dSDimitry Andric std::optional<DarwinPlatform> SDKTarget = 23000b57cec5SDimitry Andric inferDeploymentTargetFromSDK(Args, SDKInfo); 23010b57cec5SDimitry Andric if (SDKTarget) 23020b57cec5SDimitry Andric OSTarget->setEnvironment(SDKTarget->getEnvironment()); 23030b57cec5SDimitry Andric } 23040b57cec5SDimitry Andric } 23050b57cec5SDimitry Andric // If there is no command-line argument to specify the Target version and 23060b57cec5SDimitry Andric // no environment variable defined, see if we can set the default based 23070b57cec5SDimitry Andric // on -isysroot using SDKSettings.json if it exists. 23080b57cec5SDimitry Andric if (!OSTarget) { 23090b57cec5SDimitry Andric OSTarget = inferDeploymentTargetFromSDK(Args, SDKInfo); 23100b57cec5SDimitry Andric /// If the target was successfully constructed from the SDK path, try to 23110b57cec5SDimitry Andric /// infer the SDK info if the SDK doesn't have it. 23120b57cec5SDimitry Andric if (OSTarget && !SDKInfo) 23130b57cec5SDimitry Andric SDKInfo = OSTarget->inferSDKInfo(); 23140b57cec5SDimitry Andric } 23150b57cec5SDimitry Andric // If no OS targets have been specified, try to guess platform from -target 23160b57cec5SDimitry Andric // or arch name and compute the version from the triple. 23170b57cec5SDimitry Andric if (!OSTarget) 23180b57cec5SDimitry Andric OSTarget = 23190b57cec5SDimitry Andric inferDeploymentTargetFromArch(Args, *this, getTriple(), getDriver()); 23200b57cec5SDimitry Andric } 23210b57cec5SDimitry Andric 23220b57cec5SDimitry Andric assert(OSTarget && "Unable to infer Darwin variant"); 23230b57cec5SDimitry Andric OSTarget->addOSVersionMinArgument(Args, Opts); 23240b57cec5SDimitry Andric DarwinPlatformKind Platform = OSTarget->getPlatform(); 23250b57cec5SDimitry Andric 23260b57cec5SDimitry Andric unsigned Major, Minor, Micro; 23270b57cec5SDimitry Andric bool HadExtra; 2328bdd1243dSDimitry Andric // The major version should not be over this number. 2329bdd1243dSDimitry Andric const unsigned MajorVersionLimit = 1000; 23300b57cec5SDimitry Andric // Set the tool chain target information. 23310b57cec5SDimitry Andric if (Platform == MacOS) { 23320b57cec5SDimitry Andric if (!Driver::GetReleaseVersion(OSTarget->getOSVersion(), Major, Minor, 23330b57cec5SDimitry Andric Micro, HadExtra) || 2334bdd1243dSDimitry Andric HadExtra || Major < 10 || Major >= MajorVersionLimit || Minor >= 100 || 2335bdd1243dSDimitry Andric Micro >= 100) 23360b57cec5SDimitry Andric getDriver().Diag(diag::err_drv_invalid_version_number) 23370b57cec5SDimitry Andric << OSTarget->getAsString(Args, Opts); 23380b57cec5SDimitry Andric } else if (Platform == IPhoneOS) { 23390b57cec5SDimitry Andric if (!Driver::GetReleaseVersion(OSTarget->getOSVersion(), Major, Minor, 23400b57cec5SDimitry Andric Micro, HadExtra) || 2341bdd1243dSDimitry Andric HadExtra || Major >= MajorVersionLimit || Minor >= 100 || Micro >= 100) 23420b57cec5SDimitry Andric getDriver().Diag(diag::err_drv_invalid_version_number) 23430b57cec5SDimitry Andric << OSTarget->getAsString(Args, Opts); 23440b57cec5SDimitry Andric ; 2345fe6060f1SDimitry Andric if (OSTarget->getEnvironment() == MacCatalyst && 2346fe6060f1SDimitry Andric (Major < 13 || (Major == 13 && Minor < 1))) { 2347fe6060f1SDimitry Andric getDriver().Diag(diag::err_drv_invalid_version_number) 2348fe6060f1SDimitry Andric << OSTarget->getAsString(Args, Opts); 2349fe6060f1SDimitry Andric Major = 13; 2350fe6060f1SDimitry Andric Minor = 1; 2351fe6060f1SDimitry Andric Micro = 0; 2352fe6060f1SDimitry Andric } 23530b57cec5SDimitry Andric // For 32-bit targets, the deployment target for iOS has to be earlier than 23540b57cec5SDimitry Andric // iOS 11. 23550b57cec5SDimitry Andric if (getTriple().isArch32Bit() && Major >= 11) { 23560b57cec5SDimitry Andric // If the deployment target is explicitly specified, print a diagnostic. 23570b57cec5SDimitry Andric if (OSTarget->isExplicitlySpecified()) { 2358fe6060f1SDimitry Andric if (OSTarget->getEnvironment() == MacCatalyst) 2359fe6060f1SDimitry Andric getDriver().Diag(diag::err_invalid_macos_32bit_deployment_target); 2360fe6060f1SDimitry Andric else 23610b57cec5SDimitry Andric getDriver().Diag(diag::warn_invalid_ios_deployment_target) 23620b57cec5SDimitry Andric << OSTarget->getAsString(Args, Opts); 23630b57cec5SDimitry Andric // Otherwise, set it to 10.99.99. 23640b57cec5SDimitry Andric } else { 23650b57cec5SDimitry Andric Major = 10; 23660b57cec5SDimitry Andric Minor = 99; 23670b57cec5SDimitry Andric Micro = 99; 23680b57cec5SDimitry Andric } 23690b57cec5SDimitry Andric } 23700b57cec5SDimitry Andric } else if (Platform == TvOS) { 23710b57cec5SDimitry Andric if (!Driver::GetReleaseVersion(OSTarget->getOSVersion(), Major, Minor, 23720b57cec5SDimitry Andric Micro, HadExtra) || 2373bdd1243dSDimitry Andric HadExtra || Major >= MajorVersionLimit || Minor >= 100 || Micro >= 100) 23740b57cec5SDimitry Andric getDriver().Diag(diag::err_drv_invalid_version_number) 23750b57cec5SDimitry Andric << OSTarget->getAsString(Args, Opts); 23760b57cec5SDimitry Andric } else if (Platform == WatchOS) { 23770b57cec5SDimitry Andric if (!Driver::GetReleaseVersion(OSTarget->getOSVersion(), Major, Minor, 23780b57cec5SDimitry Andric Micro, HadExtra) || 2379bdd1243dSDimitry Andric HadExtra || Major >= MajorVersionLimit || Minor >= 100 || Micro >= 100) 23800b57cec5SDimitry Andric getDriver().Diag(diag::err_drv_invalid_version_number) 23810b57cec5SDimitry Andric << OSTarget->getAsString(Args, Opts); 238281ad6265SDimitry Andric } else if (Platform == DriverKit) { 238381ad6265SDimitry Andric if (!Driver::GetReleaseVersion(OSTarget->getOSVersion(), Major, Minor, 238481ad6265SDimitry Andric Micro, HadExtra) || 2385bdd1243dSDimitry Andric HadExtra || Major < 19 || Major >= MajorVersionLimit || Minor >= 100 || 2386bdd1243dSDimitry Andric Micro >= 100) 238781ad6265SDimitry Andric getDriver().Diag(diag::err_drv_invalid_version_number) 238881ad6265SDimitry Andric << OSTarget->getAsString(Args, Opts); 23897a6dacacSDimitry Andric } else if (Platform == XROS) { 23907a6dacacSDimitry Andric if (!Driver::GetReleaseVersion(OSTarget->getOSVersion(), Major, Minor, 23917a6dacacSDimitry Andric Micro, HadExtra) || 23927a6dacacSDimitry Andric HadExtra || Major < 1 || Major >= MajorVersionLimit || Minor >= 100 || 23937a6dacacSDimitry Andric Micro >= 100) 23947a6dacacSDimitry Andric getDriver().Diag(diag::err_drv_invalid_version_number) 23957a6dacacSDimitry Andric << OSTarget->getAsString(Args, Opts); 23960b57cec5SDimitry Andric } else 23970b57cec5SDimitry Andric llvm_unreachable("unknown kind of Darwin platform"); 23980b57cec5SDimitry Andric 23990b57cec5SDimitry Andric DarwinEnvironmentKind Environment = OSTarget->getEnvironment(); 24000b57cec5SDimitry Andric // Recognize iOS targets with an x86 architecture as the iOS simulator. 24010b57cec5SDimitry Andric if (Environment == NativeEnvironment && Platform != MacOS && 240281ad6265SDimitry Andric Platform != DriverKit && OSTarget->canInferSimulatorFromArch() && 240381ad6265SDimitry Andric getTriple().isX86()) 24040b57cec5SDimitry Andric Environment = Simulator; 24050b57cec5SDimitry Andric 2406fe6060f1SDimitry Andric VersionTuple NativeTargetVersion; 2407fe6060f1SDimitry Andric if (Environment == MacCatalyst) 2408fe6060f1SDimitry Andric NativeTargetVersion = OSTarget->getNativeTargetVersion(); 2409fe6060f1SDimitry Andric setTarget(Platform, Environment, Major, Minor, Micro, NativeTargetVersion); 241081ad6265SDimitry Andric TargetVariantTriple = OSTarget->getTargetVariantTriple(); 24110b57cec5SDimitry Andric 24120b57cec5SDimitry Andric if (const Arg *A = Args.getLastArg(options::OPT_isysroot)) { 24130b57cec5SDimitry Andric StringRef SDK = getSDKName(A->getValue()); 24140b57cec5SDimitry Andric if (SDK.size() > 0) { 24150b57cec5SDimitry Andric size_t StartVer = SDK.find_first_of("0123456789"); 24160b57cec5SDimitry Andric StringRef SDKName = SDK.slice(0, StartVer); 24175f757f3fSDimitry Andric if (!SDKName.starts_with(getPlatformFamily()) && 24185f757f3fSDimitry Andric !dropSDKNamePrefix(SDKName).starts_with(getPlatformFamily())) 24190b57cec5SDimitry Andric getDriver().Diag(diag::warn_incompatible_sysroot) 24200b57cec5SDimitry Andric << SDKName << getPlatformFamily(); 24210b57cec5SDimitry Andric } 24220b57cec5SDimitry Andric } 24230b57cec5SDimitry Andric } 24240b57cec5SDimitry Andric 2425bdd1243dSDimitry Andric // For certain platforms/environments almost all resources (e.g., headers) are 2426bdd1243dSDimitry Andric // located in sub-directories, e.g., for DriverKit they live in 2427bdd1243dSDimitry Andric // <SYSROOT>/System/DriverKit/usr/include (instead of <SYSROOT>/usr/include). 2428bdd1243dSDimitry Andric static void AppendPlatformPrefix(SmallString<128> &Path, 2429bdd1243dSDimitry Andric const llvm::Triple &T) { 2430bdd1243dSDimitry Andric if (T.isDriverKit()) { 2431bdd1243dSDimitry Andric llvm::sys::path::append(Path, "System", "DriverKit"); 2432bdd1243dSDimitry Andric } 2433bdd1243dSDimitry Andric } 2434bdd1243dSDimitry Andric 2435bdd1243dSDimitry Andric // Returns the effective sysroot from either -isysroot or --sysroot, plus the 2436bdd1243dSDimitry Andric // platform prefix (if any). 2437bdd1243dSDimitry Andric llvm::SmallString<128> 2438bdd1243dSDimitry Andric DarwinClang::GetEffectiveSysroot(const llvm::opt::ArgList &DriverArgs) const { 2439bdd1243dSDimitry Andric llvm::SmallString<128> Path("/"); 24400b57cec5SDimitry Andric if (DriverArgs.hasArg(options::OPT_isysroot)) 2441bdd1243dSDimitry Andric Path = DriverArgs.getLastArgValue(options::OPT_isysroot); 2442bdd1243dSDimitry Andric else if (!getDriver().SysRoot.empty()) 2443bdd1243dSDimitry Andric Path = getDriver().SysRoot; 2444bdd1243dSDimitry Andric 2445bdd1243dSDimitry Andric if (hasEffectiveTriple()) { 2446bdd1243dSDimitry Andric AppendPlatformPrefix(Path, getEffectiveTriple()); 2447bdd1243dSDimitry Andric } 2448bdd1243dSDimitry Andric return Path; 24490b57cec5SDimitry Andric } 24500b57cec5SDimitry Andric 24510b57cec5SDimitry Andric void DarwinClang::AddClangSystemIncludeArgs(const llvm::opt::ArgList &DriverArgs, 24520b57cec5SDimitry Andric llvm::opt::ArgStringList &CC1Args) const { 24530b57cec5SDimitry Andric const Driver &D = getDriver(); 24540b57cec5SDimitry Andric 2455bdd1243dSDimitry Andric llvm::SmallString<128> Sysroot = GetEffectiveSysroot(DriverArgs); 24560b57cec5SDimitry Andric 24570b57cec5SDimitry Andric bool NoStdInc = DriverArgs.hasArg(options::OPT_nostdinc); 24580b57cec5SDimitry Andric bool NoStdlibInc = DriverArgs.hasArg(options::OPT_nostdlibinc); 24595ffd83dbSDimitry Andric bool NoBuiltinInc = DriverArgs.hasFlag( 24605ffd83dbSDimitry Andric options::OPT_nobuiltininc, options::OPT_ibuiltininc, /*Default=*/false); 24615ffd83dbSDimitry Andric bool ForceBuiltinInc = DriverArgs.hasFlag( 24625ffd83dbSDimitry Andric options::OPT_ibuiltininc, options::OPT_nobuiltininc, /*Default=*/false); 24630b57cec5SDimitry Andric 24640b57cec5SDimitry Andric // Add <sysroot>/usr/local/include 24650b57cec5SDimitry Andric if (!NoStdInc && !NoStdlibInc) { 24660b57cec5SDimitry Andric SmallString<128> P(Sysroot); 24670b57cec5SDimitry Andric llvm::sys::path::append(P, "usr", "local", "include"); 24680b57cec5SDimitry Andric addSystemInclude(DriverArgs, CC1Args, P); 24690b57cec5SDimitry Andric } 24700b57cec5SDimitry Andric 24710b57cec5SDimitry Andric // Add the Clang builtin headers (<resource>/include) 24725ffd83dbSDimitry Andric if (!(NoStdInc && !ForceBuiltinInc) && !NoBuiltinInc) { 24730b57cec5SDimitry Andric SmallString<128> P(D.ResourceDir); 24740b57cec5SDimitry Andric llvm::sys::path::append(P, "include"); 24750b57cec5SDimitry Andric addSystemInclude(DriverArgs, CC1Args, P); 24760b57cec5SDimitry Andric } 24770b57cec5SDimitry Andric 24780b57cec5SDimitry Andric if (NoStdInc || NoStdlibInc) 24790b57cec5SDimitry Andric return; 24800b57cec5SDimitry Andric 24810b57cec5SDimitry Andric // Check for configure-time C include directories. 24820b57cec5SDimitry Andric llvm::StringRef CIncludeDirs(C_INCLUDE_DIRS); 24830b57cec5SDimitry Andric if (!CIncludeDirs.empty()) { 24840b57cec5SDimitry Andric llvm::SmallVector<llvm::StringRef, 5> dirs; 24850b57cec5SDimitry Andric CIncludeDirs.split(dirs, ":"); 24860b57cec5SDimitry Andric for (llvm::StringRef dir : dirs) { 24870b57cec5SDimitry Andric llvm::StringRef Prefix = 24885ffd83dbSDimitry Andric llvm::sys::path::is_absolute(dir) ? "" : llvm::StringRef(Sysroot); 24890b57cec5SDimitry Andric addExternCSystemInclude(DriverArgs, CC1Args, Prefix + dir); 24900b57cec5SDimitry Andric } 24910b57cec5SDimitry Andric } else { 24920b57cec5SDimitry Andric // Otherwise, add <sysroot>/usr/include. 24930b57cec5SDimitry Andric SmallString<128> P(Sysroot); 24940b57cec5SDimitry Andric llvm::sys::path::append(P, "usr", "include"); 24950b57cec5SDimitry Andric addExternCSystemInclude(DriverArgs, CC1Args, P.str()); 24960b57cec5SDimitry Andric } 24970b57cec5SDimitry Andric } 24980b57cec5SDimitry Andric 24990b57cec5SDimitry Andric bool DarwinClang::AddGnuCPlusPlusIncludePaths(const llvm::opt::ArgList &DriverArgs, 25000b57cec5SDimitry Andric llvm::opt::ArgStringList &CC1Args, 25010b57cec5SDimitry Andric llvm::SmallString<128> Base, 25020b57cec5SDimitry Andric llvm::StringRef Version, 25030b57cec5SDimitry Andric llvm::StringRef ArchDir, 25040b57cec5SDimitry Andric llvm::StringRef BitDir) const { 25050b57cec5SDimitry Andric llvm::sys::path::append(Base, Version); 25060b57cec5SDimitry Andric 25070b57cec5SDimitry Andric // Add the base dir 25080b57cec5SDimitry Andric addSystemInclude(DriverArgs, CC1Args, Base); 25090b57cec5SDimitry Andric 25100b57cec5SDimitry Andric // Add the multilib dirs 25110b57cec5SDimitry Andric { 25120b57cec5SDimitry Andric llvm::SmallString<128> P = Base; 25130b57cec5SDimitry Andric if (!ArchDir.empty()) 25140b57cec5SDimitry Andric llvm::sys::path::append(P, ArchDir); 25150b57cec5SDimitry Andric if (!BitDir.empty()) 25160b57cec5SDimitry Andric llvm::sys::path::append(P, BitDir); 25170b57cec5SDimitry Andric addSystemInclude(DriverArgs, CC1Args, P); 25180b57cec5SDimitry Andric } 25190b57cec5SDimitry Andric 25200b57cec5SDimitry Andric // Add the backward dir 25210b57cec5SDimitry Andric { 25220b57cec5SDimitry Andric llvm::SmallString<128> P = Base; 25230b57cec5SDimitry Andric llvm::sys::path::append(P, "backward"); 25240b57cec5SDimitry Andric addSystemInclude(DriverArgs, CC1Args, P); 25250b57cec5SDimitry Andric } 25260b57cec5SDimitry Andric 25270b57cec5SDimitry Andric return getVFS().exists(Base); 25280b57cec5SDimitry Andric } 25290b57cec5SDimitry Andric 25300b57cec5SDimitry Andric void DarwinClang::AddClangCXXStdlibIncludeArgs( 25310b57cec5SDimitry Andric const llvm::opt::ArgList &DriverArgs, 25320b57cec5SDimitry Andric llvm::opt::ArgStringList &CC1Args) const { 25330b57cec5SDimitry Andric // The implementation from a base class will pass through the -stdlib to 25340b57cec5SDimitry Andric // CC1Args. 25350b57cec5SDimitry Andric // FIXME: this should not be necessary, remove usages in the frontend 25360b57cec5SDimitry Andric // (e.g. HeaderSearchOptions::UseLibcxx) and don't pipe -stdlib. 25370b57cec5SDimitry Andric // Also check whether this is used for setting library search paths. 25380b57cec5SDimitry Andric ToolChain::AddClangCXXStdlibIncludeArgs(DriverArgs, CC1Args); 25390b57cec5SDimitry Andric 2540bdd1243dSDimitry Andric if (DriverArgs.hasArg(options::OPT_nostdinc, options::OPT_nostdlibinc, 2541bdd1243dSDimitry Andric options::OPT_nostdincxx)) 25420b57cec5SDimitry Andric return; 25430b57cec5SDimitry Andric 2544bdd1243dSDimitry Andric llvm::SmallString<128> Sysroot = GetEffectiveSysroot(DriverArgs); 25450b57cec5SDimitry Andric 25460b57cec5SDimitry Andric switch (GetCXXStdlibType(DriverArgs)) { 25470b57cec5SDimitry Andric case ToolChain::CST_Libcxx: { 25485f757f3fSDimitry Andric // On Darwin, libc++ can be installed in one of the following places: 25490fca6ea1SDimitry Andric // 1. Alongside the compiler in <clang-executable-folder>/../include/c++/v1 25500fca6ea1SDimitry Andric // 2. In a SDK (or a custom sysroot) in <sysroot>/usr/include/c++/v1 2551e8d8bef9SDimitry Andric // 25525f757f3fSDimitry Andric // The precedence of paths is as listed above, i.e. we take the first path 25535f757f3fSDimitry Andric // that exists. Note that we never include libc++ twice -- we take the first 25545f757f3fSDimitry Andric // path that exists and don't send the other paths to CC1 (otherwise 2555e8d8bef9SDimitry Andric // include_next could break). 2556e8d8bef9SDimitry Andric 2557e8d8bef9SDimitry Andric // Check for (1) 2558e8d8bef9SDimitry Andric // Get from '<install>/bin' to '<install>/include/c++/v1'. 2559e8d8bef9SDimitry Andric // Note that InstallBin can be relative, so we use '..' instead of 2560e8d8bef9SDimitry Andric // parent_path. 25610fca6ea1SDimitry Andric llvm::SmallString<128> InstallBin(getDriver().Dir); // <install>/bin 2562e8d8bef9SDimitry Andric llvm::sys::path::append(InstallBin, "..", "include", "c++", "v1"); 2563e8d8bef9SDimitry Andric if (getVFS().exists(InstallBin)) { 2564e8d8bef9SDimitry Andric addSystemInclude(DriverArgs, CC1Args, InstallBin); 2565e8d8bef9SDimitry Andric return; 2566e8d8bef9SDimitry Andric } else if (DriverArgs.hasArg(options::OPT_v)) { 2567e8d8bef9SDimitry Andric llvm::errs() << "ignoring nonexistent directory \"" << InstallBin 2568e8d8bef9SDimitry Andric << "\"\n"; 25690b57cec5SDimitry Andric } 2570e8d8bef9SDimitry Andric 25710fca6ea1SDimitry Andric // Otherwise, check for (2) 2572e8d8bef9SDimitry Andric llvm::SmallString<128> SysrootUsr = Sysroot; 2573e8d8bef9SDimitry Andric llvm::sys::path::append(SysrootUsr, "usr", "include", "c++", "v1"); 2574e8d8bef9SDimitry Andric if (getVFS().exists(SysrootUsr)) { 2575e8d8bef9SDimitry Andric addSystemInclude(DriverArgs, CC1Args, SysrootUsr); 2576e8d8bef9SDimitry Andric return; 2577e8d8bef9SDimitry Andric } else if (DriverArgs.hasArg(options::OPT_v)) { 2578e8d8bef9SDimitry Andric llvm::errs() << "ignoring nonexistent directory \"" << SysrootUsr 2579e8d8bef9SDimitry Andric << "\"\n"; 25800b57cec5SDimitry Andric } 2581e8d8bef9SDimitry Andric 2582e8d8bef9SDimitry Andric // Otherwise, don't add any path. 25830b57cec5SDimitry Andric break; 25840b57cec5SDimitry Andric } 25850b57cec5SDimitry Andric 25860b57cec5SDimitry Andric case ToolChain::CST_Libstdcxx: 25870b57cec5SDimitry Andric llvm::SmallString<128> UsrIncludeCxx = Sysroot; 25880b57cec5SDimitry Andric llvm::sys::path::append(UsrIncludeCxx, "usr", "include", "c++"); 25890b57cec5SDimitry Andric 25900b57cec5SDimitry Andric llvm::Triple::ArchType arch = getTriple().getArch(); 25910b57cec5SDimitry Andric bool IsBaseFound = true; 25920b57cec5SDimitry Andric switch (arch) { 25930b57cec5SDimitry Andric default: break; 25940b57cec5SDimitry Andric 25950b57cec5SDimitry Andric case llvm::Triple::x86: 25960b57cec5SDimitry Andric case llvm::Triple::x86_64: 25970b57cec5SDimitry Andric IsBaseFound = AddGnuCPlusPlusIncludePaths(DriverArgs, CC1Args, UsrIncludeCxx, 25980b57cec5SDimitry Andric "4.2.1", 25990b57cec5SDimitry Andric "i686-apple-darwin10", 26000b57cec5SDimitry Andric arch == llvm::Triple::x86_64 ? "x86_64" : ""); 26010b57cec5SDimitry Andric IsBaseFound |= AddGnuCPlusPlusIncludePaths(DriverArgs, CC1Args, UsrIncludeCxx, 26020b57cec5SDimitry Andric "4.0.0", "i686-apple-darwin8", 26030b57cec5SDimitry Andric ""); 26040b57cec5SDimitry Andric break; 26050b57cec5SDimitry Andric 26060b57cec5SDimitry Andric case llvm::Triple::arm: 26070b57cec5SDimitry Andric case llvm::Triple::thumb: 26080b57cec5SDimitry Andric IsBaseFound = AddGnuCPlusPlusIncludePaths(DriverArgs, CC1Args, UsrIncludeCxx, 26090b57cec5SDimitry Andric "4.2.1", 26100b57cec5SDimitry Andric "arm-apple-darwin10", 26110b57cec5SDimitry Andric "v7"); 26120b57cec5SDimitry Andric IsBaseFound |= AddGnuCPlusPlusIncludePaths(DriverArgs, CC1Args, UsrIncludeCxx, 26130b57cec5SDimitry Andric "4.2.1", 26140b57cec5SDimitry Andric "arm-apple-darwin10", 26150b57cec5SDimitry Andric "v6"); 26160b57cec5SDimitry Andric break; 26170b57cec5SDimitry Andric 26180b57cec5SDimitry Andric case llvm::Triple::aarch64: 26190b57cec5SDimitry Andric IsBaseFound = AddGnuCPlusPlusIncludePaths(DriverArgs, CC1Args, UsrIncludeCxx, 26200b57cec5SDimitry Andric "4.2.1", 26210b57cec5SDimitry Andric "arm64-apple-darwin10", 26220b57cec5SDimitry Andric ""); 26230b57cec5SDimitry Andric break; 26240b57cec5SDimitry Andric } 26250b57cec5SDimitry Andric 26260b57cec5SDimitry Andric if (!IsBaseFound) { 26270b57cec5SDimitry Andric getDriver().Diag(diag::warn_drv_libstdcxx_not_found); 26280b57cec5SDimitry Andric } 26290b57cec5SDimitry Andric 26300b57cec5SDimitry Andric break; 26310b57cec5SDimitry Andric } 26320b57cec5SDimitry Andric } 2633fcaf7f86SDimitry Andric 26340b57cec5SDimitry Andric void DarwinClang::AddCXXStdlibLibArgs(const ArgList &Args, 26350b57cec5SDimitry Andric ArgStringList &CmdArgs) const { 26360b57cec5SDimitry Andric CXXStdlibType Type = GetCXXStdlibType(Args); 26370b57cec5SDimitry Andric 26380b57cec5SDimitry Andric switch (Type) { 26390b57cec5SDimitry Andric case ToolChain::CST_Libcxx: 26400b57cec5SDimitry Andric CmdArgs.push_back("-lc++"); 2641fcaf7f86SDimitry Andric if (Args.hasArg(options::OPT_fexperimental_library)) 2642fcaf7f86SDimitry Andric CmdArgs.push_back("-lc++experimental"); 26430b57cec5SDimitry Andric break; 26440b57cec5SDimitry Andric 26450b57cec5SDimitry Andric case ToolChain::CST_Libstdcxx: 26460b57cec5SDimitry Andric // Unfortunately, -lstdc++ doesn't always exist in the standard search path; 26470b57cec5SDimitry Andric // it was previously found in the gcc lib dir. However, for all the Darwin 26480b57cec5SDimitry Andric // platforms we care about it was -lstdc++.6, so we search for that 26490b57cec5SDimitry Andric // explicitly if we can't see an obvious -lstdc++ candidate. 26500b57cec5SDimitry Andric 26510b57cec5SDimitry Andric // Check in the sysroot first. 26520b57cec5SDimitry Andric if (const Arg *A = Args.getLastArg(options::OPT_isysroot)) { 26530b57cec5SDimitry Andric SmallString<128> P(A->getValue()); 26540b57cec5SDimitry Andric llvm::sys::path::append(P, "usr", "lib", "libstdc++.dylib"); 26550b57cec5SDimitry Andric 26560b57cec5SDimitry Andric if (!getVFS().exists(P)) { 26570b57cec5SDimitry Andric llvm::sys::path::remove_filename(P); 26580b57cec5SDimitry Andric llvm::sys::path::append(P, "libstdc++.6.dylib"); 26590b57cec5SDimitry Andric if (getVFS().exists(P)) { 26600b57cec5SDimitry Andric CmdArgs.push_back(Args.MakeArgString(P)); 26610b57cec5SDimitry Andric return; 26620b57cec5SDimitry Andric } 26630b57cec5SDimitry Andric } 26640b57cec5SDimitry Andric } 26650b57cec5SDimitry Andric 26660b57cec5SDimitry Andric // Otherwise, look in the root. 26670b57cec5SDimitry Andric // FIXME: This should be removed someday when we don't have to care about 26680b57cec5SDimitry Andric // 10.6 and earlier, where /usr/lib/libstdc++.dylib does not exist. 26690b57cec5SDimitry Andric if (!getVFS().exists("/usr/lib/libstdc++.dylib") && 26700b57cec5SDimitry Andric getVFS().exists("/usr/lib/libstdc++.6.dylib")) { 26710b57cec5SDimitry Andric CmdArgs.push_back("/usr/lib/libstdc++.6.dylib"); 26720b57cec5SDimitry Andric return; 26730b57cec5SDimitry Andric } 26740b57cec5SDimitry Andric 26750b57cec5SDimitry Andric // Otherwise, let the linker search. 26760b57cec5SDimitry Andric CmdArgs.push_back("-lstdc++"); 26770b57cec5SDimitry Andric break; 26780b57cec5SDimitry Andric } 26790b57cec5SDimitry Andric } 26800b57cec5SDimitry Andric 26810b57cec5SDimitry Andric void DarwinClang::AddCCKextLibArgs(const ArgList &Args, 26820b57cec5SDimitry Andric ArgStringList &CmdArgs) const { 26830b57cec5SDimitry Andric // For Darwin platforms, use the compiler-rt-based support library 26840b57cec5SDimitry Andric // instead of the gcc-provided one (which is also incidentally 26850b57cec5SDimitry Andric // only present in the gcc lib dir, which makes it hard to find). 26860b57cec5SDimitry Andric 26870b57cec5SDimitry Andric SmallString<128> P(getDriver().ResourceDir); 26880b57cec5SDimitry Andric llvm::sys::path::append(P, "lib", "darwin"); 26890b57cec5SDimitry Andric 26900b57cec5SDimitry Andric // Use the newer cc_kext for iOS ARM after 6.0. 26910b57cec5SDimitry Andric if (isTargetWatchOS()) { 26920b57cec5SDimitry Andric llvm::sys::path::append(P, "libclang_rt.cc_kext_watchos.a"); 26930b57cec5SDimitry Andric } else if (isTargetTvOS()) { 26940b57cec5SDimitry Andric llvm::sys::path::append(P, "libclang_rt.cc_kext_tvos.a"); 26950b57cec5SDimitry Andric } else if (isTargetIPhoneOS()) { 26960b57cec5SDimitry Andric llvm::sys::path::append(P, "libclang_rt.cc_kext_ios.a"); 269781ad6265SDimitry Andric } else if (isTargetDriverKit()) { 269881ad6265SDimitry Andric // DriverKit doesn't want extra runtime support. 26997a6dacacSDimitry Andric } else if (isTargetXROSDevice()) { 27007a6dacacSDimitry Andric llvm::sys::path::append( 27017a6dacacSDimitry Andric P, llvm::Twine("libclang_rt.cc_kext_") + 27027a6dacacSDimitry Andric llvm::Triple::getOSTypeName(llvm::Triple::XROS) + ".a"); 27030b57cec5SDimitry Andric } else { 27040b57cec5SDimitry Andric llvm::sys::path::append(P, "libclang_rt.cc_kext.a"); 27050b57cec5SDimitry Andric } 27060b57cec5SDimitry Andric 27070b57cec5SDimitry Andric // For now, allow missing resource libraries to support developers who may 27080b57cec5SDimitry Andric // not have compiler-rt checked out or integrated into their build. 27090b57cec5SDimitry Andric if (getVFS().exists(P)) 27100b57cec5SDimitry Andric CmdArgs.push_back(Args.MakeArgString(P)); 27110b57cec5SDimitry Andric } 27120b57cec5SDimitry Andric 27130b57cec5SDimitry Andric DerivedArgList *MachO::TranslateArgs(const DerivedArgList &Args, 27140b57cec5SDimitry Andric StringRef BoundArch, 27150b57cec5SDimitry Andric Action::OffloadKind) const { 27160b57cec5SDimitry Andric DerivedArgList *DAL = new DerivedArgList(Args.getBaseArgs()); 27170b57cec5SDimitry Andric const OptTable &Opts = getDriver().getOpts(); 27180b57cec5SDimitry Andric 27190b57cec5SDimitry Andric // FIXME: We really want to get out of the tool chain level argument 27200b57cec5SDimitry Andric // translation business, as it makes the driver functionality much 27210b57cec5SDimitry Andric // more opaque. For now, we follow gcc closely solely for the 27220b57cec5SDimitry Andric // purpose of easily achieving feature parity & testability. Once we 27230b57cec5SDimitry Andric // have something that works, we should reevaluate each translation 27240b57cec5SDimitry Andric // and try to push it down into tool specific logic. 27250b57cec5SDimitry Andric 27260b57cec5SDimitry Andric for (Arg *A : Args) { 27270b57cec5SDimitry Andric if (A->getOption().matches(options::OPT_Xarch__)) { 27280b57cec5SDimitry Andric // Skip this argument unless the architecture matches either the toolchain 27290b57cec5SDimitry Andric // triple arch, or the arch being bound. 273081ad6265SDimitry Andric StringRef XarchArch = A->getValue(0); 273181ad6265SDimitry Andric if (!(XarchArch == getArchName() || 273281ad6265SDimitry Andric (!BoundArch.empty() && XarchArch == BoundArch))) 27330b57cec5SDimitry Andric continue; 27340b57cec5SDimitry Andric 27350b57cec5SDimitry Andric Arg *OriginalArg = A; 27365ffd83dbSDimitry Andric TranslateXarchArgs(Args, A, DAL); 27370b57cec5SDimitry Andric 27380b57cec5SDimitry Andric // Linker input arguments require custom handling. The problem is that we 27390b57cec5SDimitry Andric // have already constructed the phase actions, so we can not treat them as 27400b57cec5SDimitry Andric // "input arguments". 27410b57cec5SDimitry Andric if (A->getOption().hasFlag(options::LinkerInput)) { 27420b57cec5SDimitry Andric // Convert the argument into individual Zlinker_input_args. 27430b57cec5SDimitry Andric for (const char *Value : A->getValues()) { 27440b57cec5SDimitry Andric DAL->AddSeparateArg( 27450b57cec5SDimitry Andric OriginalArg, Opts.getOption(options::OPT_Zlinker_input), Value); 27460b57cec5SDimitry Andric } 27470b57cec5SDimitry Andric continue; 27480b57cec5SDimitry Andric } 27490b57cec5SDimitry Andric } 27500b57cec5SDimitry Andric 27510b57cec5SDimitry Andric // Sob. These is strictly gcc compatible for the time being. Apple 27520b57cec5SDimitry Andric // gcc translates options twice, which means that self-expanding 27530b57cec5SDimitry Andric // options add duplicates. 27540b57cec5SDimitry Andric switch ((options::ID)A->getOption().getID()) { 27550b57cec5SDimitry Andric default: 27560b57cec5SDimitry Andric DAL->append(A); 27570b57cec5SDimitry Andric break; 27580b57cec5SDimitry Andric 27590b57cec5SDimitry Andric case options::OPT_mkernel: 27600b57cec5SDimitry Andric case options::OPT_fapple_kext: 27610b57cec5SDimitry Andric DAL->append(A); 27620b57cec5SDimitry Andric DAL->AddFlagArg(A, Opts.getOption(options::OPT_static)); 27630b57cec5SDimitry Andric break; 27640b57cec5SDimitry Andric 27650b57cec5SDimitry Andric case options::OPT_dependency_file: 27660b57cec5SDimitry Andric DAL->AddSeparateArg(A, Opts.getOption(options::OPT_MF), A->getValue()); 27670b57cec5SDimitry Andric break; 27680b57cec5SDimitry Andric 27690b57cec5SDimitry Andric case options::OPT_gfull: 27700b57cec5SDimitry Andric DAL->AddFlagArg(A, Opts.getOption(options::OPT_g_Flag)); 27710b57cec5SDimitry Andric DAL->AddFlagArg( 27720b57cec5SDimitry Andric A, Opts.getOption(options::OPT_fno_eliminate_unused_debug_symbols)); 27730b57cec5SDimitry Andric break; 27740b57cec5SDimitry Andric 27750b57cec5SDimitry Andric case options::OPT_gused: 27760b57cec5SDimitry Andric DAL->AddFlagArg(A, Opts.getOption(options::OPT_g_Flag)); 27770b57cec5SDimitry Andric DAL->AddFlagArg( 27780b57cec5SDimitry Andric A, Opts.getOption(options::OPT_feliminate_unused_debug_symbols)); 27790b57cec5SDimitry Andric break; 27800b57cec5SDimitry Andric 27810b57cec5SDimitry Andric case options::OPT_shared: 27820b57cec5SDimitry Andric DAL->AddFlagArg(A, Opts.getOption(options::OPT_dynamiclib)); 27830b57cec5SDimitry Andric break; 27840b57cec5SDimitry Andric 27850b57cec5SDimitry Andric case options::OPT_fconstant_cfstrings: 27860b57cec5SDimitry Andric DAL->AddFlagArg(A, Opts.getOption(options::OPT_mconstant_cfstrings)); 27870b57cec5SDimitry Andric break; 27880b57cec5SDimitry Andric 27890b57cec5SDimitry Andric case options::OPT_fno_constant_cfstrings: 27900b57cec5SDimitry Andric DAL->AddFlagArg(A, Opts.getOption(options::OPT_mno_constant_cfstrings)); 27910b57cec5SDimitry Andric break; 27920b57cec5SDimitry Andric 27930b57cec5SDimitry Andric case options::OPT_Wnonportable_cfstrings: 27940b57cec5SDimitry Andric DAL->AddFlagArg(A, 27950b57cec5SDimitry Andric Opts.getOption(options::OPT_mwarn_nonportable_cfstrings)); 27960b57cec5SDimitry Andric break; 27970b57cec5SDimitry Andric 27980b57cec5SDimitry Andric case options::OPT_Wno_nonportable_cfstrings: 27990b57cec5SDimitry Andric DAL->AddFlagArg( 28000b57cec5SDimitry Andric A, Opts.getOption(options::OPT_mno_warn_nonportable_cfstrings)); 28010b57cec5SDimitry Andric break; 28020b57cec5SDimitry Andric } 28030b57cec5SDimitry Andric } 28040b57cec5SDimitry Andric 28050b57cec5SDimitry Andric // Add the arch options based on the particular spelling of -arch, to match 2806bdd1243dSDimitry Andric // how the driver works. 28070b57cec5SDimitry Andric if (!BoundArch.empty()) { 28080b57cec5SDimitry Andric StringRef Name = BoundArch; 28090b57cec5SDimitry Andric const Option MCpu = Opts.getOption(options::OPT_mcpu_EQ); 28100b57cec5SDimitry Andric const Option MArch = Opts.getOption(clang::driver::options::OPT_march_EQ); 28110b57cec5SDimitry Andric 28120b57cec5SDimitry Andric // This code must be kept in sync with LLVM's getArchTypeForDarwinArch, 28130b57cec5SDimitry Andric // which defines the list of which architectures we accept. 28140b57cec5SDimitry Andric if (Name == "ppc") 28150b57cec5SDimitry Andric ; 28160b57cec5SDimitry Andric else if (Name == "ppc601") 28170b57cec5SDimitry Andric DAL->AddJoinedArg(nullptr, MCpu, "601"); 28180b57cec5SDimitry Andric else if (Name == "ppc603") 28190b57cec5SDimitry Andric DAL->AddJoinedArg(nullptr, MCpu, "603"); 28200b57cec5SDimitry Andric else if (Name == "ppc604") 28210b57cec5SDimitry Andric DAL->AddJoinedArg(nullptr, MCpu, "604"); 28220b57cec5SDimitry Andric else if (Name == "ppc604e") 28230b57cec5SDimitry Andric DAL->AddJoinedArg(nullptr, MCpu, "604e"); 28240b57cec5SDimitry Andric else if (Name == "ppc750") 28250b57cec5SDimitry Andric DAL->AddJoinedArg(nullptr, MCpu, "750"); 28260b57cec5SDimitry Andric else if (Name == "ppc7400") 28270b57cec5SDimitry Andric DAL->AddJoinedArg(nullptr, MCpu, "7400"); 28280b57cec5SDimitry Andric else if (Name == "ppc7450") 28290b57cec5SDimitry Andric DAL->AddJoinedArg(nullptr, MCpu, "7450"); 28300b57cec5SDimitry Andric else if (Name == "ppc970") 28310b57cec5SDimitry Andric DAL->AddJoinedArg(nullptr, MCpu, "970"); 28320b57cec5SDimitry Andric 28330b57cec5SDimitry Andric else if (Name == "ppc64" || Name == "ppc64le") 28340b57cec5SDimitry Andric DAL->AddFlagArg(nullptr, Opts.getOption(options::OPT_m64)); 28350b57cec5SDimitry Andric 28360b57cec5SDimitry Andric else if (Name == "i386") 28370b57cec5SDimitry Andric ; 28380b57cec5SDimitry Andric else if (Name == "i486") 28390b57cec5SDimitry Andric DAL->AddJoinedArg(nullptr, MArch, "i486"); 28400b57cec5SDimitry Andric else if (Name == "i586") 28410b57cec5SDimitry Andric DAL->AddJoinedArg(nullptr, MArch, "i586"); 28420b57cec5SDimitry Andric else if (Name == "i686") 28430b57cec5SDimitry Andric DAL->AddJoinedArg(nullptr, MArch, "i686"); 28440b57cec5SDimitry Andric else if (Name == "pentium") 28450b57cec5SDimitry Andric DAL->AddJoinedArg(nullptr, MArch, "pentium"); 28460b57cec5SDimitry Andric else if (Name == "pentium2") 28470b57cec5SDimitry Andric DAL->AddJoinedArg(nullptr, MArch, "pentium2"); 28480b57cec5SDimitry Andric else if (Name == "pentpro") 28490b57cec5SDimitry Andric DAL->AddJoinedArg(nullptr, MArch, "pentiumpro"); 28500b57cec5SDimitry Andric else if (Name == "pentIIm3") 28510b57cec5SDimitry Andric DAL->AddJoinedArg(nullptr, MArch, "pentium2"); 28520b57cec5SDimitry Andric 28530b57cec5SDimitry Andric else if (Name == "x86_64" || Name == "x86_64h") 28540b57cec5SDimitry Andric DAL->AddFlagArg(nullptr, Opts.getOption(options::OPT_m64)); 28550b57cec5SDimitry Andric 28560b57cec5SDimitry Andric else if (Name == "arm") 28570b57cec5SDimitry Andric DAL->AddJoinedArg(nullptr, MArch, "armv4t"); 28580b57cec5SDimitry Andric else if (Name == "armv4t") 28590b57cec5SDimitry Andric DAL->AddJoinedArg(nullptr, MArch, "armv4t"); 28600b57cec5SDimitry Andric else if (Name == "armv5") 28610b57cec5SDimitry Andric DAL->AddJoinedArg(nullptr, MArch, "armv5tej"); 28620b57cec5SDimitry Andric else if (Name == "xscale") 28630b57cec5SDimitry Andric DAL->AddJoinedArg(nullptr, MArch, "xscale"); 28640b57cec5SDimitry Andric else if (Name == "armv6") 28650b57cec5SDimitry Andric DAL->AddJoinedArg(nullptr, MArch, "armv6k"); 28660b57cec5SDimitry Andric else if (Name == "armv6m") 28670b57cec5SDimitry Andric DAL->AddJoinedArg(nullptr, MArch, "armv6m"); 28680b57cec5SDimitry Andric else if (Name == "armv7") 28690b57cec5SDimitry Andric DAL->AddJoinedArg(nullptr, MArch, "armv7a"); 28700b57cec5SDimitry Andric else if (Name == "armv7em") 28710b57cec5SDimitry Andric DAL->AddJoinedArg(nullptr, MArch, "armv7em"); 28720b57cec5SDimitry Andric else if (Name == "armv7k") 28730b57cec5SDimitry Andric DAL->AddJoinedArg(nullptr, MArch, "armv7k"); 28740b57cec5SDimitry Andric else if (Name == "armv7m") 28750b57cec5SDimitry Andric DAL->AddJoinedArg(nullptr, MArch, "armv7m"); 28760b57cec5SDimitry Andric else if (Name == "armv7s") 28770b57cec5SDimitry Andric DAL->AddJoinedArg(nullptr, MArch, "armv7s"); 28780b57cec5SDimitry Andric } 28790b57cec5SDimitry Andric 28800b57cec5SDimitry Andric return DAL; 28810b57cec5SDimitry Andric } 28820b57cec5SDimitry Andric 28830b57cec5SDimitry Andric void MachO::AddLinkRuntimeLibArgs(const ArgList &Args, 28840b57cec5SDimitry Andric ArgStringList &CmdArgs, 28850b57cec5SDimitry Andric bool ForceLinkBuiltinRT) const { 28860b57cec5SDimitry Andric // Embedded targets are simple at the moment, not supporting sanitizers and 28870b57cec5SDimitry Andric // with different libraries for each member of the product { static, PIC } x 28880b57cec5SDimitry Andric // { hard-float, soft-float } 28890b57cec5SDimitry Andric llvm::SmallString<32> CompilerRT = StringRef(""); 28900b57cec5SDimitry Andric CompilerRT += 28910b57cec5SDimitry Andric (tools::arm::getARMFloatABI(*this, Args) == tools::arm::FloatABI::Hard) 28920b57cec5SDimitry Andric ? "hard" 28930b57cec5SDimitry Andric : "soft"; 28940b57cec5SDimitry Andric CompilerRT += Args.hasArg(options::OPT_fPIC) ? "_pic" : "_static"; 28950b57cec5SDimitry Andric 28960b57cec5SDimitry Andric AddLinkRuntimeLib(Args, CmdArgs, CompilerRT, RLO_IsEmbedded); 28970b57cec5SDimitry Andric } 28980b57cec5SDimitry Andric 28990b57cec5SDimitry Andric bool Darwin::isAlignedAllocationUnavailable() const { 29000b57cec5SDimitry Andric llvm::Triple::OSType OS; 29010b57cec5SDimitry Andric 2902fe6060f1SDimitry Andric if (isTargetMacCatalyst()) 2903fe6060f1SDimitry Andric return TargetVersion < alignedAllocMinVersion(llvm::Triple::MacOSX); 29040b57cec5SDimitry Andric switch (TargetPlatform) { 29050b57cec5SDimitry Andric case MacOS: // Earlier than 10.13. 29060b57cec5SDimitry Andric OS = llvm::Triple::MacOSX; 29070b57cec5SDimitry Andric break; 29080b57cec5SDimitry Andric case IPhoneOS: 29090b57cec5SDimitry Andric OS = llvm::Triple::IOS; 29100b57cec5SDimitry Andric break; 29110b57cec5SDimitry Andric case TvOS: // Earlier than 11.0. 29120b57cec5SDimitry Andric OS = llvm::Triple::TvOS; 29130b57cec5SDimitry Andric break; 29140b57cec5SDimitry Andric case WatchOS: // Earlier than 4.0. 29150b57cec5SDimitry Andric OS = llvm::Triple::WatchOS; 29160b57cec5SDimitry Andric break; 29177a6dacacSDimitry Andric case XROS: // Always available. 29187a6dacacSDimitry Andric return false; 291981ad6265SDimitry Andric case DriverKit: // Always available. 292081ad6265SDimitry Andric return false; 29210b57cec5SDimitry Andric } 29220b57cec5SDimitry Andric 29230b57cec5SDimitry Andric return TargetVersion < alignedAllocMinVersion(OS); 29240b57cec5SDimitry Andric } 29250b57cec5SDimitry Andric 292662987288SDimitry Andric static bool sdkSupportsBuiltinModules( 292762987288SDimitry Andric const Darwin::DarwinPlatformKind &TargetPlatform, 292862987288SDimitry Andric const Darwin::DarwinEnvironmentKind &TargetEnvironment, 292962987288SDimitry Andric const std::optional<DarwinSDKInfo> &SDKInfo) { 293062987288SDimitry Andric if (TargetEnvironment == Darwin::NativeEnvironment || 293162987288SDimitry Andric TargetEnvironment == Darwin::Simulator || 293262987288SDimitry Andric TargetEnvironment == Darwin::MacCatalyst) { 293362987288SDimitry Andric // Standard xnu/Mach/Darwin based environments 293462987288SDimitry Andric // depend on the SDK version. 293562987288SDimitry Andric } else { 293662987288SDimitry Andric // All other environments support builtin modules from the start. 293762987288SDimitry Andric return true; 293862987288SDimitry Andric } 293962987288SDimitry Andric 29405f757f3fSDimitry Andric if (!SDKInfo) 294162987288SDimitry Andric // If there is no SDK info, assume this is building against a 294262987288SDimitry Andric // pre-SDK version of macOS (i.e. before Mac OS X 10.4). Those 294362987288SDimitry Andric // don't support modules anyway, but the headers definitely 294462987288SDimitry Andric // don't support builtin modules either. It might also be some 294562987288SDimitry Andric // kind of degenerate build environment, err on the side of 294662987288SDimitry Andric // the old behavior which is to not use builtin modules. 29475f757f3fSDimitry Andric return false; 29485f757f3fSDimitry Andric 29495f757f3fSDimitry Andric VersionTuple SDKVersion = SDKInfo->getVersion(); 29505f757f3fSDimitry Andric switch (TargetPlatform) { 295162987288SDimitry Andric // Existing SDKs added support for builtin modules in the fall 295262987288SDimitry Andric // 2024 major releases. 29535f757f3fSDimitry Andric case Darwin::MacOS: 295462987288SDimitry Andric return SDKVersion >= VersionTuple(15U); 29555f757f3fSDimitry Andric case Darwin::IPhoneOS: 2956*6c4b055cSDimitry Andric switch (TargetEnvironment) { 2957*6c4b055cSDimitry Andric case Darwin::MacCatalyst: 2958*6c4b055cSDimitry Andric // Mac Catalyst uses `-target arm64-apple-ios18.0-macabi` so the platform 2959*6c4b055cSDimitry Andric // is iOS, but it builds with the macOS SDK, so it's the macOS SDK version 2960*6c4b055cSDimitry Andric // that's relevant. 2961*6c4b055cSDimitry Andric return SDKVersion >= VersionTuple(15U); 2962*6c4b055cSDimitry Andric default: 296362987288SDimitry Andric return SDKVersion >= VersionTuple(18U); 2964*6c4b055cSDimitry Andric } 29655f757f3fSDimitry Andric case Darwin::TvOS: 296662987288SDimitry Andric return SDKVersion >= VersionTuple(18U); 29675f757f3fSDimitry Andric case Darwin::WatchOS: 296862987288SDimitry Andric return SDKVersion >= VersionTuple(11U); 29697a6dacacSDimitry Andric case Darwin::XROS: 297062987288SDimitry Andric return SDKVersion >= VersionTuple(2U); 297162987288SDimitry Andric 297262987288SDimitry Andric // New SDKs support builtin modules from the start. 29735f757f3fSDimitry Andric default: 29745f757f3fSDimitry Andric return true; 29755f757f3fSDimitry Andric } 29765f757f3fSDimitry Andric } 29775f757f3fSDimitry Andric 29780fca6ea1SDimitry Andric static inline llvm::VersionTuple 29790fca6ea1SDimitry Andric sizedDeallocMinVersion(llvm::Triple::OSType OS) { 29800fca6ea1SDimitry Andric switch (OS) { 29810fca6ea1SDimitry Andric default: 29820fca6ea1SDimitry Andric break; 29830fca6ea1SDimitry Andric case llvm::Triple::Darwin: 29840fca6ea1SDimitry Andric case llvm::Triple::MacOSX: // Earliest supporting version is 10.12. 29850fca6ea1SDimitry Andric return llvm::VersionTuple(10U, 12U); 29860fca6ea1SDimitry Andric case llvm::Triple::IOS: 29870fca6ea1SDimitry Andric case llvm::Triple::TvOS: // Earliest supporting version is 10.0.0. 29880fca6ea1SDimitry Andric return llvm::VersionTuple(10U); 29890fca6ea1SDimitry Andric case llvm::Triple::WatchOS: // Earliest supporting version is 3.0.0. 29900fca6ea1SDimitry Andric return llvm::VersionTuple(3U); 29910fca6ea1SDimitry Andric } 29920fca6ea1SDimitry Andric 29930fca6ea1SDimitry Andric llvm_unreachable("Unexpected OS"); 29940fca6ea1SDimitry Andric } 29950fca6ea1SDimitry Andric 29960fca6ea1SDimitry Andric bool Darwin::isSizedDeallocationUnavailable() const { 29970fca6ea1SDimitry Andric llvm::Triple::OSType OS; 29980fca6ea1SDimitry Andric 29990fca6ea1SDimitry Andric if (isTargetMacCatalyst()) 30000fca6ea1SDimitry Andric return TargetVersion < sizedDeallocMinVersion(llvm::Triple::MacOSX); 30010fca6ea1SDimitry Andric switch (TargetPlatform) { 30020fca6ea1SDimitry Andric case MacOS: // Earlier than 10.12. 30030fca6ea1SDimitry Andric OS = llvm::Triple::MacOSX; 30040fca6ea1SDimitry Andric break; 30050fca6ea1SDimitry Andric case IPhoneOS: 30060fca6ea1SDimitry Andric OS = llvm::Triple::IOS; 30070fca6ea1SDimitry Andric break; 30080fca6ea1SDimitry Andric case TvOS: // Earlier than 10.0. 30090fca6ea1SDimitry Andric OS = llvm::Triple::TvOS; 30100fca6ea1SDimitry Andric break; 30110fca6ea1SDimitry Andric case WatchOS: // Earlier than 3.0. 30120fca6ea1SDimitry Andric OS = llvm::Triple::WatchOS; 30130fca6ea1SDimitry Andric break; 30140fca6ea1SDimitry Andric case DriverKit: 30150fca6ea1SDimitry Andric case XROS: 30160fca6ea1SDimitry Andric // Always available. 30170fca6ea1SDimitry Andric return false; 30180fca6ea1SDimitry Andric } 30190fca6ea1SDimitry Andric 30200fca6ea1SDimitry Andric return TargetVersion < sizedDeallocMinVersion(OS); 30210fca6ea1SDimitry Andric } 30220fca6ea1SDimitry Andric 30230fca6ea1SDimitry Andric void Darwin::addClangTargetOptions( 30240fca6ea1SDimitry Andric const llvm::opt::ArgList &DriverArgs, llvm::opt::ArgStringList &CC1Args, 30250b57cec5SDimitry Andric Action::OffloadKind DeviceOffloadKind) const { 30260b57cec5SDimitry Andric // Pass "-faligned-alloc-unavailable" only when the user hasn't manually 30270b57cec5SDimitry Andric // enabled or disabled aligned allocations. 30280b57cec5SDimitry Andric if (!DriverArgs.hasArgNoClaim(options::OPT_faligned_allocation, 30290b57cec5SDimitry Andric options::OPT_fno_aligned_allocation) && 30300b57cec5SDimitry Andric isAlignedAllocationUnavailable()) 30310b57cec5SDimitry Andric CC1Args.push_back("-faligned-alloc-unavailable"); 30320b57cec5SDimitry Andric 30330fca6ea1SDimitry Andric // Pass "-fno-sized-deallocation" only when the user hasn't manually enabled 30340fca6ea1SDimitry Andric // or disabled sized deallocations. 30350fca6ea1SDimitry Andric if (!DriverArgs.hasArgNoClaim(options::OPT_fsized_deallocation, 30360fca6ea1SDimitry Andric options::OPT_fno_sized_deallocation) && 30370fca6ea1SDimitry Andric isSizedDeallocationUnavailable()) 30380fca6ea1SDimitry Andric CC1Args.push_back("-fno-sized-deallocation"); 30390fca6ea1SDimitry Andric 3040bdd1243dSDimitry Andric addClangCC1ASTargetOptions(DriverArgs, CC1Args); 3041bdd1243dSDimitry Andric 3042bdd1243dSDimitry Andric // Enable compatibility mode for NSItemProviderCompletionHandler in 3043bdd1243dSDimitry Andric // Foundation/NSItemProvider.h. 3044bdd1243dSDimitry Andric CC1Args.push_back("-fcompatibility-qualified-id-block-type-checking"); 3045bdd1243dSDimitry Andric 3046bdd1243dSDimitry Andric // Give static local variables in inline functions hidden visibility when 3047bdd1243dSDimitry Andric // -fvisibility-inlines-hidden is enabled. 3048bdd1243dSDimitry Andric if (!DriverArgs.getLastArgNoClaim( 3049bdd1243dSDimitry Andric options::OPT_fvisibility_inlines_hidden_static_local_var, 3050bdd1243dSDimitry Andric options::OPT_fno_visibility_inlines_hidden_static_local_var)) 3051bdd1243dSDimitry Andric CC1Args.push_back("-fvisibility-inlines-hidden-static-local-var"); 30525f757f3fSDimitry Andric 30535f757f3fSDimitry Andric // Earlier versions of the darwin SDK have the C standard library headers 30545f757f3fSDimitry Andric // all together in the Darwin module. That leads to module cycles with 30555f757f3fSDimitry Andric // the _Builtin_ modules. e.g. <inttypes.h> on darwin includes <stdint.h>. 30565f757f3fSDimitry Andric // The builtin <stdint.h> include-nexts <stdint.h>. When both of those 30575f757f3fSDimitry Andric // darwin headers are in the Darwin module, there's a module cycle Darwin -> 30585f757f3fSDimitry Andric // _Builtin_stdint -> Darwin (i.e. inttypes.h (darwin) -> stdint.h (builtin) -> 30595f757f3fSDimitry Andric // stdint.h (darwin)). This is fixed in later versions of the darwin SDK, 30605f757f3fSDimitry Andric // but until then, the builtin headers need to join the system modules. 30615f757f3fSDimitry Andric // i.e. when the builtin stdint.h is in the Darwin module too, the cycle 30625f757f3fSDimitry Andric // goes away. Note that -fbuiltin-headers-in-system-modules does nothing 30635f757f3fSDimitry Andric // to fix the same problem with C++ headers, and is generally fragile. 306462987288SDimitry Andric if (!sdkSupportsBuiltinModules(TargetPlatform, TargetEnvironment, SDKInfo)) 30655f757f3fSDimitry Andric CC1Args.push_back("-fbuiltin-headers-in-system-modules"); 30667a6dacacSDimitry Andric 30677a6dacacSDimitry Andric if (!DriverArgs.hasArgNoClaim(options::OPT_fdefine_target_os_macros, 30687a6dacacSDimitry Andric options::OPT_fno_define_target_os_macros)) 30697a6dacacSDimitry Andric CC1Args.push_back("-fdefine-target-os-macros"); 3070bdd1243dSDimitry Andric } 3071bdd1243dSDimitry Andric 3072bdd1243dSDimitry Andric void Darwin::addClangCC1ASTargetOptions( 3073bdd1243dSDimitry Andric const llvm::opt::ArgList &Args, llvm::opt::ArgStringList &CC1ASArgs) const { 307481ad6265SDimitry Andric if (TargetVariantTriple) { 3075bdd1243dSDimitry Andric CC1ASArgs.push_back("-darwin-target-variant-triple"); 3076bdd1243dSDimitry Andric CC1ASArgs.push_back(Args.MakeArgString(TargetVariantTriple->getTriple())); 307781ad6265SDimitry Andric } 307881ad6265SDimitry Andric 30790b57cec5SDimitry Andric if (SDKInfo) { 30800b57cec5SDimitry Andric /// Pass the SDK version to the compiler when the SDK information is 30810b57cec5SDimitry Andric /// available. 3082fe6060f1SDimitry Andric auto EmitTargetSDKVersionArg = [&](const VersionTuple &V) { 30830b57cec5SDimitry Andric std::string Arg; 30840b57cec5SDimitry Andric llvm::raw_string_ostream OS(Arg); 3085fe6060f1SDimitry Andric OS << "-target-sdk-version=" << V; 30860fca6ea1SDimitry Andric CC1ASArgs.push_back(Args.MakeArgString(Arg)); 3087fe6060f1SDimitry Andric }; 3088fe6060f1SDimitry Andric 3089fe6060f1SDimitry Andric if (isTargetMacCatalyst()) { 3090fe6060f1SDimitry Andric if (const auto *MacOStoMacCatalystMapping = SDKInfo->getVersionMapping( 3091fe6060f1SDimitry Andric DarwinSDKInfo::OSEnvPair::macOStoMacCatalystPair())) { 3092bdd1243dSDimitry Andric std::optional<VersionTuple> SDKVersion = MacOStoMacCatalystMapping->map( 3093bdd1243dSDimitry Andric SDKInfo->getVersion(), minimumMacCatalystDeploymentTarget(), 3094bdd1243dSDimitry Andric std::nullopt); 3095fe6060f1SDimitry Andric EmitTargetSDKVersionArg( 3096fe6060f1SDimitry Andric SDKVersion ? *SDKVersion : minimumMacCatalystDeploymentTarget()); 3097fe6060f1SDimitry Andric } 3098fe6060f1SDimitry Andric } else { 3099fe6060f1SDimitry Andric EmitTargetSDKVersionArg(SDKInfo->getVersion()); 3100fe6060f1SDimitry Andric } 310181ad6265SDimitry Andric 310281ad6265SDimitry Andric /// Pass the target variant SDK version to the compiler when the SDK 310381ad6265SDimitry Andric /// information is available and is required for target variant. 310481ad6265SDimitry Andric if (TargetVariantTriple) { 310581ad6265SDimitry Andric if (isTargetMacCatalyst()) { 310681ad6265SDimitry Andric std::string Arg; 310781ad6265SDimitry Andric llvm::raw_string_ostream OS(Arg); 310881ad6265SDimitry Andric OS << "-darwin-target-variant-sdk-version=" << SDKInfo->getVersion(); 31090fca6ea1SDimitry Andric CC1ASArgs.push_back(Args.MakeArgString(Arg)); 311081ad6265SDimitry Andric } else if (const auto *MacOStoMacCatalystMapping = 311181ad6265SDimitry Andric SDKInfo->getVersionMapping( 311281ad6265SDimitry Andric DarwinSDKInfo::OSEnvPair::macOStoMacCatalystPair())) { 3113bdd1243dSDimitry Andric if (std::optional<VersionTuple> SDKVersion = 3114bdd1243dSDimitry Andric MacOStoMacCatalystMapping->map( 311581ad6265SDimitry Andric SDKInfo->getVersion(), minimumMacCatalystDeploymentTarget(), 3116bdd1243dSDimitry Andric std::nullopt)) { 311781ad6265SDimitry Andric std::string Arg; 311881ad6265SDimitry Andric llvm::raw_string_ostream OS(Arg); 311981ad6265SDimitry Andric OS << "-darwin-target-variant-sdk-version=" << *SDKVersion; 31200fca6ea1SDimitry Andric CC1ASArgs.push_back(Args.MakeArgString(Arg)); 312181ad6265SDimitry Andric } 312281ad6265SDimitry Andric } 312381ad6265SDimitry Andric } 31240b57cec5SDimitry Andric } 31250b57cec5SDimitry Andric } 31260b57cec5SDimitry Andric 31270b57cec5SDimitry Andric DerivedArgList * 31280b57cec5SDimitry Andric Darwin::TranslateArgs(const DerivedArgList &Args, StringRef BoundArch, 31290b57cec5SDimitry Andric Action::OffloadKind DeviceOffloadKind) const { 31300b57cec5SDimitry Andric // First get the generic Apple args, before moving onto Darwin-specific ones. 31310b57cec5SDimitry Andric DerivedArgList *DAL = 31320b57cec5SDimitry Andric MachO::TranslateArgs(Args, BoundArch, DeviceOffloadKind); 31330b57cec5SDimitry Andric 31340b57cec5SDimitry Andric // If no architecture is bound, none of the translations here are relevant. 31350b57cec5SDimitry Andric if (BoundArch.empty()) 31360b57cec5SDimitry Andric return DAL; 31370b57cec5SDimitry Andric 31380b57cec5SDimitry Andric // Add an explicit version min argument for the deployment target. We do this 31390b57cec5SDimitry Andric // after argument translation because -Xarch_ arguments may add a version min 31400b57cec5SDimitry Andric // argument. 31410b57cec5SDimitry Andric AddDeploymentTarget(*DAL); 31420b57cec5SDimitry Andric 31430b57cec5SDimitry Andric // For iOS 6, undo the translation to add -static for -mkernel/-fapple-kext. 31440b57cec5SDimitry Andric // FIXME: It would be far better to avoid inserting those -static arguments, 31450b57cec5SDimitry Andric // but we can't check the deployment target in the translation code until 31460b57cec5SDimitry Andric // it is set here. 31477a6dacacSDimitry Andric if (isTargetWatchOSBased() || isTargetDriverKit() || isTargetXROS() || 31480b57cec5SDimitry Andric (isTargetIOSBased() && !isIPhoneOSVersionLT(6, 0))) { 31490b57cec5SDimitry Andric for (ArgList::iterator it = DAL->begin(), ie = DAL->end(); it != ie; ) { 31500b57cec5SDimitry Andric Arg *A = *it; 31510b57cec5SDimitry Andric ++it; 31520b57cec5SDimitry Andric if (A->getOption().getID() != options::OPT_mkernel && 31530b57cec5SDimitry Andric A->getOption().getID() != options::OPT_fapple_kext) 31540b57cec5SDimitry Andric continue; 31550b57cec5SDimitry Andric assert(it != ie && "unexpected argument translation"); 31560b57cec5SDimitry Andric A = *it; 31570b57cec5SDimitry Andric assert(A->getOption().getID() == options::OPT_static && 31580b57cec5SDimitry Andric "missing expected -static argument"); 31590b57cec5SDimitry Andric *it = nullptr; 31600b57cec5SDimitry Andric ++it; 31610b57cec5SDimitry Andric } 31620b57cec5SDimitry Andric } 31630b57cec5SDimitry Andric 31640b57cec5SDimitry Andric auto Arch = tools::darwin::getArchTypeForMachOArchName(BoundArch); 31650b57cec5SDimitry Andric if ((Arch == llvm::Triple::arm || Arch == llvm::Triple::thumb)) { 31660b57cec5SDimitry Andric if (Args.hasFlag(options::OPT_fomit_frame_pointer, 31670b57cec5SDimitry Andric options::OPT_fno_omit_frame_pointer, false)) 31680b57cec5SDimitry Andric getDriver().Diag(clang::diag::warn_drv_unsupported_opt_for_target) 31690b57cec5SDimitry Andric << "-fomit-frame-pointer" << BoundArch; 31700b57cec5SDimitry Andric } 31710b57cec5SDimitry Andric 31720b57cec5SDimitry Andric return DAL; 31730b57cec5SDimitry Andric } 31740b57cec5SDimitry Andric 3175bdd1243dSDimitry Andric ToolChain::UnwindTableLevel MachO::getDefaultUnwindTableLevel(const ArgList &Args) const { 31760b57cec5SDimitry Andric // Unwind tables are not emitted if -fno-exceptions is supplied (except when 31770b57cec5SDimitry Andric // targeting x86_64). 3178bdd1243dSDimitry Andric if (getArch() == llvm::Triple::x86_64 || 31790b57cec5SDimitry Andric (GetExceptionModel(Args) != llvm::ExceptionHandling::SjLj && 31800b57cec5SDimitry Andric Args.hasFlag(options::OPT_fexceptions, options::OPT_fno_exceptions, 3181bdd1243dSDimitry Andric true))) 318206c3fb27SDimitry Andric return (getArch() == llvm::Triple::aarch64 || 318306c3fb27SDimitry Andric getArch() == llvm::Triple::aarch64_32) 318406c3fb27SDimitry Andric ? UnwindTableLevel::Synchronous 3185bdd1243dSDimitry Andric : UnwindTableLevel::Asynchronous; 3186bdd1243dSDimitry Andric 3187bdd1243dSDimitry Andric return UnwindTableLevel::None; 31880b57cec5SDimitry Andric } 31890b57cec5SDimitry Andric 31900b57cec5SDimitry Andric bool MachO::UseDwarfDebugFlags() const { 31910b57cec5SDimitry Andric if (const char *S = ::getenv("RC_DEBUG_OPTIONS")) 31920b57cec5SDimitry Andric return S[0] != '\0'; 31930b57cec5SDimitry Andric return false; 31940b57cec5SDimitry Andric } 31950b57cec5SDimitry Andric 319681ad6265SDimitry Andric std::string MachO::GetGlobalDebugPathRemapping() const { 319781ad6265SDimitry Andric if (const char *S = ::getenv("RC_DEBUG_PREFIX_MAP")) 319881ad6265SDimitry Andric return S; 319981ad6265SDimitry Andric return {}; 320081ad6265SDimitry Andric } 320181ad6265SDimitry Andric 32020b57cec5SDimitry Andric llvm::ExceptionHandling Darwin::GetExceptionModel(const ArgList &Args) const { 32030b57cec5SDimitry Andric // Darwin uses SjLj exceptions on ARM. 32040b57cec5SDimitry Andric if (getTriple().getArch() != llvm::Triple::arm && 32050b57cec5SDimitry Andric getTriple().getArch() != llvm::Triple::thumb) 32060b57cec5SDimitry Andric return llvm::ExceptionHandling::None; 32070b57cec5SDimitry Andric 32080b57cec5SDimitry Andric // Only watchOS uses the new DWARF/Compact unwinding method. 32090b57cec5SDimitry Andric llvm::Triple Triple(ComputeLLVMTriple(Args)); 32100b57cec5SDimitry Andric if (Triple.isWatchABI()) 32110b57cec5SDimitry Andric return llvm::ExceptionHandling::DwarfCFI; 32120b57cec5SDimitry Andric 32130b57cec5SDimitry Andric return llvm::ExceptionHandling::SjLj; 32140b57cec5SDimitry Andric } 32150b57cec5SDimitry Andric 32160b57cec5SDimitry Andric bool Darwin::SupportsEmbeddedBitcode() const { 32170b57cec5SDimitry Andric assert(TargetInitialized && "Target not initialized!"); 32180b57cec5SDimitry Andric if (isTargetIPhoneOS() && isIPhoneOSVersionLT(6, 0)) 32190b57cec5SDimitry Andric return false; 32200b57cec5SDimitry Andric return true; 32210b57cec5SDimitry Andric } 32220b57cec5SDimitry Andric 32230b57cec5SDimitry Andric bool MachO::isPICDefault() const { return true; } 32240b57cec5SDimitry Andric 3225349cc55cSDimitry Andric bool MachO::isPIEDefault(const llvm::opt::ArgList &Args) const { return false; } 32260b57cec5SDimitry Andric 32270b57cec5SDimitry Andric bool MachO::isPICDefaultForced() const { 32280b57cec5SDimitry Andric return (getArch() == llvm::Triple::x86_64 || 32290b57cec5SDimitry Andric getArch() == llvm::Triple::aarch64); 32300b57cec5SDimitry Andric } 32310b57cec5SDimitry Andric 32320b57cec5SDimitry Andric bool MachO::SupportsProfiling() const { 32330b57cec5SDimitry Andric // Profiling instrumentation is only supported on x86. 3234480093f4SDimitry Andric return getTriple().isX86(); 32350b57cec5SDimitry Andric } 32360b57cec5SDimitry Andric 32370b57cec5SDimitry Andric void Darwin::addMinVersionArgs(const ArgList &Args, 32380b57cec5SDimitry Andric ArgStringList &CmdArgs) const { 3239fe6060f1SDimitry Andric VersionTuple TargetVersion = getTripleTargetVersion(); 32400b57cec5SDimitry Andric 32417a6dacacSDimitry Andric assert(!isTargetXROS() && "xrOS always uses -platform-version"); 32427a6dacacSDimitry Andric 32430b57cec5SDimitry Andric if (isTargetWatchOS()) 32440b57cec5SDimitry Andric CmdArgs.push_back("-watchos_version_min"); 32450b57cec5SDimitry Andric else if (isTargetWatchOSSimulator()) 32460b57cec5SDimitry Andric CmdArgs.push_back("-watchos_simulator_version_min"); 32470b57cec5SDimitry Andric else if (isTargetTvOS()) 32480b57cec5SDimitry Andric CmdArgs.push_back("-tvos_version_min"); 32490b57cec5SDimitry Andric else if (isTargetTvOSSimulator()) 32500b57cec5SDimitry Andric CmdArgs.push_back("-tvos_simulator_version_min"); 325181ad6265SDimitry Andric else if (isTargetDriverKit()) 325281ad6265SDimitry Andric CmdArgs.push_back("-driverkit_version_min"); 32530b57cec5SDimitry Andric else if (isTargetIOSSimulator()) 32540b57cec5SDimitry Andric CmdArgs.push_back("-ios_simulator_version_min"); 32550b57cec5SDimitry Andric else if (isTargetIOSBased()) 32560b57cec5SDimitry Andric CmdArgs.push_back("-iphoneos_version_min"); 3257fe6060f1SDimitry Andric else if (isTargetMacCatalyst()) 3258fe6060f1SDimitry Andric CmdArgs.push_back("-maccatalyst_version_min"); 32590b57cec5SDimitry Andric else { 32600b57cec5SDimitry Andric assert(isTargetMacOS() && "unexpected target"); 32610b57cec5SDimitry Andric CmdArgs.push_back("-macosx_version_min"); 32620b57cec5SDimitry Andric } 32630b57cec5SDimitry Andric 32645ffd83dbSDimitry Andric VersionTuple MinTgtVers = getEffectiveTriple().getMinimumSupportedOSVersion(); 32655ffd83dbSDimitry Andric if (!MinTgtVers.empty() && MinTgtVers > TargetVersion) 32665ffd83dbSDimitry Andric TargetVersion = MinTgtVers; 32670b57cec5SDimitry Andric CmdArgs.push_back(Args.MakeArgString(TargetVersion.getAsString())); 326881ad6265SDimitry Andric if (TargetVariantTriple) { 326981ad6265SDimitry Andric assert(isTargetMacOSBased() && "unexpected target"); 327081ad6265SDimitry Andric VersionTuple VariantTargetVersion; 327181ad6265SDimitry Andric if (TargetVariantTriple->isMacOSX()) { 327281ad6265SDimitry Andric CmdArgs.push_back("-macosx_version_min"); 327381ad6265SDimitry Andric TargetVariantTriple->getMacOSXVersion(VariantTargetVersion); 327481ad6265SDimitry Andric } else { 327581ad6265SDimitry Andric assert(TargetVariantTriple->isiOS() && 327681ad6265SDimitry Andric TargetVariantTriple->isMacCatalystEnvironment() && 327781ad6265SDimitry Andric "unexpected target variant triple"); 327881ad6265SDimitry Andric CmdArgs.push_back("-maccatalyst_version_min"); 327981ad6265SDimitry Andric VariantTargetVersion = TargetVariantTriple->getiOSVersion(); 328081ad6265SDimitry Andric } 328181ad6265SDimitry Andric VersionTuple MinTgtVers = 328281ad6265SDimitry Andric TargetVariantTriple->getMinimumSupportedOSVersion(); 328381ad6265SDimitry Andric if (MinTgtVers.getMajor() && MinTgtVers > VariantTargetVersion) 328481ad6265SDimitry Andric VariantTargetVersion = MinTgtVers; 328581ad6265SDimitry Andric CmdArgs.push_back(Args.MakeArgString(VariantTargetVersion.getAsString())); 328681ad6265SDimitry Andric } 32870b57cec5SDimitry Andric } 32880b57cec5SDimitry Andric 3289480093f4SDimitry Andric static const char *getPlatformName(Darwin::DarwinPlatformKind Platform, 3290480093f4SDimitry Andric Darwin::DarwinEnvironmentKind Environment) { 3291480093f4SDimitry Andric switch (Platform) { 3292480093f4SDimitry Andric case Darwin::MacOS: 3293480093f4SDimitry Andric return "macos"; 3294480093f4SDimitry Andric case Darwin::IPhoneOS: 3295fe6060f1SDimitry Andric if (Environment == Darwin::MacCatalyst) 3296fe6060f1SDimitry Andric return "mac catalyst"; 3297480093f4SDimitry Andric return "ios"; 3298480093f4SDimitry Andric case Darwin::TvOS: 3299480093f4SDimitry Andric return "tvos"; 3300480093f4SDimitry Andric case Darwin::WatchOS: 3301480093f4SDimitry Andric return "watchos"; 33027a6dacacSDimitry Andric case Darwin::XROS: 33037a6dacacSDimitry Andric return "xros"; 330481ad6265SDimitry Andric case Darwin::DriverKit: 330581ad6265SDimitry Andric return "driverkit"; 3306480093f4SDimitry Andric } 3307480093f4SDimitry Andric llvm_unreachable("invalid platform"); 3308480093f4SDimitry Andric } 3309480093f4SDimitry Andric 3310480093f4SDimitry Andric void Darwin::addPlatformVersionArgs(const llvm::opt::ArgList &Args, 3311480093f4SDimitry Andric llvm::opt::ArgStringList &CmdArgs) const { 331281ad6265SDimitry Andric auto EmitPlatformVersionArg = 331381ad6265SDimitry Andric [&](const VersionTuple &TV, Darwin::DarwinPlatformKind TargetPlatform, 331481ad6265SDimitry Andric Darwin::DarwinEnvironmentKind TargetEnvironment, 331581ad6265SDimitry Andric const llvm::Triple &TT) { 3316480093f4SDimitry Andric // -platform_version <platform> <target_version> <sdk_version> 3317480093f4SDimitry Andric // Both the target and SDK version support only up to 3 components. 3318480093f4SDimitry Andric CmdArgs.push_back("-platform_version"); 331981ad6265SDimitry Andric std::string PlatformName = 332081ad6265SDimitry Andric getPlatformName(TargetPlatform, TargetEnvironment); 3321480093f4SDimitry Andric if (TargetEnvironment == Darwin::Simulator) 3322480093f4SDimitry Andric PlatformName += "-simulator"; 3323480093f4SDimitry Andric CmdArgs.push_back(Args.MakeArgString(PlatformName)); 332481ad6265SDimitry Andric VersionTuple TargetVersion = TV.withoutBuild(); 332581ad6265SDimitry Andric if ((TargetPlatform == Darwin::IPhoneOS || 332681ad6265SDimitry Andric TargetPlatform == Darwin::TvOS) && 332781ad6265SDimitry Andric getTriple().getArchName() == "arm64e" && 332881ad6265SDimitry Andric TargetVersion.getMajor() < 14) { 332981ad6265SDimitry Andric // arm64e slice is supported on iOS/tvOS 14+ only. 333081ad6265SDimitry Andric TargetVersion = VersionTuple(14, 0); 333181ad6265SDimitry Andric } 333281ad6265SDimitry Andric VersionTuple MinTgtVers = TT.getMinimumSupportedOSVersion(); 33335ffd83dbSDimitry Andric if (!MinTgtVers.empty() && MinTgtVers > TargetVersion) 33345ffd83dbSDimitry Andric TargetVersion = MinTgtVers; 3335480093f4SDimitry Andric CmdArgs.push_back(Args.MakeArgString(TargetVersion.getAsString())); 3336fe6060f1SDimitry Andric 333781ad6265SDimitry Andric if (TargetPlatform == IPhoneOS && TargetEnvironment == MacCatalyst) { 3338fe6060f1SDimitry Andric // Mac Catalyst programs must use the appropriate iOS SDK version 3339fe6060f1SDimitry Andric // that corresponds to the macOS SDK version used for the compilation. 3340bdd1243dSDimitry Andric std::optional<VersionTuple> iOSSDKVersion; 3341fe6060f1SDimitry Andric if (SDKInfo) { 334281ad6265SDimitry Andric if (const auto *MacOStoMacCatalystMapping = 334381ad6265SDimitry Andric SDKInfo->getVersionMapping( 3344fe6060f1SDimitry Andric DarwinSDKInfo::OSEnvPair::macOStoMacCatalystPair())) { 3345fe6060f1SDimitry Andric iOSSDKVersion = MacOStoMacCatalystMapping->map( 3346fe6060f1SDimitry Andric SDKInfo->getVersion().withoutBuild(), 3347bdd1243dSDimitry Andric minimumMacCatalystDeploymentTarget(), std::nullopt); 3348fe6060f1SDimitry Andric } 3349fe6060f1SDimitry Andric } 3350fe6060f1SDimitry Andric CmdArgs.push_back(Args.MakeArgString( 335181ad6265SDimitry Andric (iOSSDKVersion ? *iOSSDKVersion 335281ad6265SDimitry Andric : minimumMacCatalystDeploymentTarget()) 3353fe6060f1SDimitry Andric .getAsString())); 3354fe6060f1SDimitry Andric return; 3355fe6060f1SDimitry Andric } 3356fe6060f1SDimitry Andric 3357480093f4SDimitry Andric if (SDKInfo) { 3358480093f4SDimitry Andric VersionTuple SDKVersion = SDKInfo->getVersion().withoutBuild(); 3359bdd1243dSDimitry Andric if (!SDKVersion.getMinor()) 3360bdd1243dSDimitry Andric SDKVersion = VersionTuple(SDKVersion.getMajor(), 0); 3361480093f4SDimitry Andric CmdArgs.push_back(Args.MakeArgString(SDKVersion.getAsString())); 3362480093f4SDimitry Andric } else { 3363fe6060f1SDimitry Andric // Use an SDK version that's matching the deployment target if the SDK 336481ad6265SDimitry Andric // version is missing. This is preferred over an empty SDK version 336581ad6265SDimitry Andric // (0.0.0) as the system's runtime might expect the linked binary to 336681ad6265SDimitry Andric // contain a valid SDK version in order for the binary to work 336781ad6265SDimitry Andric // correctly. It's reasonable to use the deployment target version as 336881ad6265SDimitry Andric // a proxy for the SDK version because older SDKs don't guarantee 336981ad6265SDimitry Andric // support for deployment targets newer than the SDK versions, so that 337081ad6265SDimitry Andric // rules out using some predetermined older SDK version, which leaves 337181ad6265SDimitry Andric // the deployment target version as the only reasonable choice. 3372fe6060f1SDimitry Andric CmdArgs.push_back(Args.MakeArgString(TargetVersion.getAsString())); 3373480093f4SDimitry Andric } 337481ad6265SDimitry Andric }; 337581ad6265SDimitry Andric EmitPlatformVersionArg(getTripleTargetVersion(), TargetPlatform, 337681ad6265SDimitry Andric TargetEnvironment, getEffectiveTriple()); 337781ad6265SDimitry Andric if (!TargetVariantTriple) 337881ad6265SDimitry Andric return; 337981ad6265SDimitry Andric Darwin::DarwinPlatformKind Platform; 338081ad6265SDimitry Andric Darwin::DarwinEnvironmentKind Environment; 338181ad6265SDimitry Andric VersionTuple TargetVariantVersion; 338281ad6265SDimitry Andric if (TargetVariantTriple->isMacOSX()) { 338381ad6265SDimitry Andric TargetVariantTriple->getMacOSXVersion(TargetVariantVersion); 338481ad6265SDimitry Andric Platform = Darwin::MacOS; 338581ad6265SDimitry Andric Environment = Darwin::NativeEnvironment; 338681ad6265SDimitry Andric } else { 338781ad6265SDimitry Andric assert(TargetVariantTriple->isiOS() && 338881ad6265SDimitry Andric TargetVariantTriple->isMacCatalystEnvironment() && 338981ad6265SDimitry Andric "unexpected target variant triple"); 339081ad6265SDimitry Andric TargetVariantVersion = TargetVariantTriple->getiOSVersion(); 339181ad6265SDimitry Andric Platform = Darwin::IPhoneOS; 339281ad6265SDimitry Andric Environment = Darwin::MacCatalyst; 339381ad6265SDimitry Andric } 339481ad6265SDimitry Andric EmitPlatformVersionArg(TargetVariantVersion, Platform, Environment, 339581ad6265SDimitry Andric *TargetVariantTriple); 3396480093f4SDimitry Andric } 3397480093f4SDimitry Andric 33985ffd83dbSDimitry Andric // Add additional link args for the -dynamiclib option. 33995ffd83dbSDimitry Andric static void addDynamicLibLinkArgs(const Darwin &D, const ArgList &Args, 34005ffd83dbSDimitry Andric ArgStringList &CmdArgs) { 34010b57cec5SDimitry Andric // Derived from darwin_dylib1 spec. 34025ffd83dbSDimitry Andric if (D.isTargetIPhoneOS()) { 34035ffd83dbSDimitry Andric if (D.isIPhoneOSVersionLT(3, 1)) 34040b57cec5SDimitry Andric CmdArgs.push_back("-ldylib1.o"); 34055ffd83dbSDimitry Andric return; 34065ffd83dbSDimitry Andric } 34075ffd83dbSDimitry Andric 34085ffd83dbSDimitry Andric if (!D.isTargetMacOS()) 34095ffd83dbSDimitry Andric return; 34105ffd83dbSDimitry Andric if (D.isMacosxVersionLT(10, 5)) 34110b57cec5SDimitry Andric CmdArgs.push_back("-ldylib1.o"); 34125ffd83dbSDimitry Andric else if (D.isMacosxVersionLT(10, 6)) 34130b57cec5SDimitry Andric CmdArgs.push_back("-ldylib1.10.5.o"); 34140b57cec5SDimitry Andric } 34155ffd83dbSDimitry Andric 34165ffd83dbSDimitry Andric // Add additional link args for the -bundle option. 34175ffd83dbSDimitry Andric static void addBundleLinkArgs(const Darwin &D, const ArgList &Args, 34185ffd83dbSDimitry Andric ArgStringList &CmdArgs) { 34195ffd83dbSDimitry Andric if (Args.hasArg(options::OPT_static)) 34205ffd83dbSDimitry Andric return; 34210b57cec5SDimitry Andric // Derived from darwin_bundle1 spec. 34225ffd83dbSDimitry Andric if ((D.isTargetIPhoneOS() && D.isIPhoneOSVersionLT(3, 1)) || 34235ffd83dbSDimitry Andric (D.isTargetMacOS() && D.isMacosxVersionLT(10, 6))) 34240b57cec5SDimitry Andric CmdArgs.push_back("-lbundle1.o"); 34250b57cec5SDimitry Andric } 34265ffd83dbSDimitry Andric 34275ffd83dbSDimitry Andric // Add additional link args for the -pg option. 34285ffd83dbSDimitry Andric static void addPgProfilingLinkArgs(const Darwin &D, const ArgList &Args, 34295ffd83dbSDimitry Andric ArgStringList &CmdArgs) { 34305ffd83dbSDimitry Andric if (D.isTargetMacOS() && D.isMacosxVersionLT(10, 9)) { 34315ffd83dbSDimitry Andric if (Args.hasArg(options::OPT_static) || Args.hasArg(options::OPT_object) || 34320b57cec5SDimitry Andric Args.hasArg(options::OPT_preload)) { 34330b57cec5SDimitry Andric CmdArgs.push_back("-lgcrt0.o"); 34340b57cec5SDimitry Andric } else { 34350b57cec5SDimitry Andric CmdArgs.push_back("-lgcrt1.o"); 34360b57cec5SDimitry Andric 34370b57cec5SDimitry Andric // darwin_crt2 spec is empty. 34380b57cec5SDimitry Andric } 34390b57cec5SDimitry Andric // By default on OS X 10.8 and later, we don't link with a crt1.o 34400b57cec5SDimitry Andric // file and the linker knows to use _main as the entry point. But, 34410b57cec5SDimitry Andric // when compiling with -pg, we need to link with the gcrt1.o file, 34420b57cec5SDimitry Andric // so pass the -no_new_main option to tell the linker to use the 34430b57cec5SDimitry Andric // "start" symbol as the entry point. 34445ffd83dbSDimitry Andric if (!D.isMacosxVersionLT(10, 8)) 34450b57cec5SDimitry Andric CmdArgs.push_back("-no_new_main"); 34460b57cec5SDimitry Andric } else { 34475ffd83dbSDimitry Andric D.getDriver().Diag(diag::err_drv_clang_unsupported_opt_pg_darwin) 3448fe6060f1SDimitry Andric << D.isTargetMacOSBased(); 34490b57cec5SDimitry Andric } 34505ffd83dbSDimitry Andric } 34510b57cec5SDimitry Andric 34525ffd83dbSDimitry Andric static void addDefaultCRTLinkArgs(const Darwin &D, const ArgList &Args, 34535ffd83dbSDimitry Andric ArgStringList &CmdArgs) { 34545ffd83dbSDimitry Andric // Derived from darwin_crt1 spec. 34555ffd83dbSDimitry Andric if (D.isTargetIPhoneOS()) { 34565ffd83dbSDimitry Andric if (D.getArch() == llvm::Triple::aarch64) 34575ffd83dbSDimitry Andric ; // iOS does not need any crt1 files for arm64 34585ffd83dbSDimitry Andric else if (D.isIPhoneOSVersionLT(3, 1)) 34595ffd83dbSDimitry Andric CmdArgs.push_back("-lcrt1.o"); 34605ffd83dbSDimitry Andric else if (D.isIPhoneOSVersionLT(6, 0)) 34615ffd83dbSDimitry Andric CmdArgs.push_back("-lcrt1.3.1.o"); 34625ffd83dbSDimitry Andric return; 34635ffd83dbSDimitry Andric } 34645ffd83dbSDimitry Andric 34655ffd83dbSDimitry Andric if (!D.isTargetMacOS()) 34665ffd83dbSDimitry Andric return; 34675ffd83dbSDimitry Andric if (D.isMacosxVersionLT(10, 5)) 34685ffd83dbSDimitry Andric CmdArgs.push_back("-lcrt1.o"); 34695ffd83dbSDimitry Andric else if (D.isMacosxVersionLT(10, 6)) 34705ffd83dbSDimitry Andric CmdArgs.push_back("-lcrt1.10.5.o"); 34715ffd83dbSDimitry Andric else if (D.isMacosxVersionLT(10, 8)) 34725ffd83dbSDimitry Andric CmdArgs.push_back("-lcrt1.10.6.o"); 34730b57cec5SDimitry Andric // darwin_crt2 spec is empty. 34740b57cec5SDimitry Andric } 34750b57cec5SDimitry Andric 34765ffd83dbSDimitry Andric void Darwin::addStartObjectFileArgs(const ArgList &Args, 34775ffd83dbSDimitry Andric ArgStringList &CmdArgs) const { 34785ffd83dbSDimitry Andric // Derived from startfile spec. 34795ffd83dbSDimitry Andric if (Args.hasArg(options::OPT_dynamiclib)) 34805ffd83dbSDimitry Andric addDynamicLibLinkArgs(*this, Args, CmdArgs); 34815ffd83dbSDimitry Andric else if (Args.hasArg(options::OPT_bundle)) 34825ffd83dbSDimitry Andric addBundleLinkArgs(*this, Args, CmdArgs); 34835ffd83dbSDimitry Andric else if (Args.hasArg(options::OPT_pg) && SupportsProfiling()) 34845ffd83dbSDimitry Andric addPgProfilingLinkArgs(*this, Args, CmdArgs); 34855ffd83dbSDimitry Andric else if (Args.hasArg(options::OPT_static) || 34865ffd83dbSDimitry Andric Args.hasArg(options::OPT_object) || 34875ffd83dbSDimitry Andric Args.hasArg(options::OPT_preload)) 34885ffd83dbSDimitry Andric CmdArgs.push_back("-lcrt0.o"); 34895ffd83dbSDimitry Andric else 34905ffd83dbSDimitry Andric addDefaultCRTLinkArgs(*this, Args, CmdArgs); 34915ffd83dbSDimitry Andric 34925ffd83dbSDimitry Andric if (isTargetMacOS() && Args.hasArg(options::OPT_shared_libgcc) && 34935ffd83dbSDimitry Andric isMacosxVersionLT(10, 5)) { 34940b57cec5SDimitry Andric const char *Str = Args.MakeArgString(GetFilePath("crt3.o")); 34950b57cec5SDimitry Andric CmdArgs.push_back(Str); 34960b57cec5SDimitry Andric } 34970b57cec5SDimitry Andric } 34980b57cec5SDimitry Andric 34990b57cec5SDimitry Andric void Darwin::CheckObjCARC() const { 35007a6dacacSDimitry Andric if (isTargetIOSBased() || isTargetWatchOSBased() || isTargetXROS() || 3501fe6060f1SDimitry Andric (isTargetMacOSBased() && !isMacosxVersionLT(10, 6))) 35020b57cec5SDimitry Andric return; 35030b57cec5SDimitry Andric getDriver().Diag(diag::err_arc_unsupported_on_toolchain); 35040b57cec5SDimitry Andric } 35050b57cec5SDimitry Andric 35060b57cec5SDimitry Andric SanitizerMask Darwin::getSupportedSanitizers() const { 35070b57cec5SDimitry Andric const bool IsX86_64 = getTriple().getArch() == llvm::Triple::x86_64; 3508e8d8bef9SDimitry Andric const bool IsAArch64 = getTriple().getArch() == llvm::Triple::aarch64; 35090b57cec5SDimitry Andric SanitizerMask Res = ToolChain::getSupportedSanitizers(); 35100b57cec5SDimitry Andric Res |= SanitizerKind::Address; 35110b57cec5SDimitry Andric Res |= SanitizerKind::PointerCompare; 35120b57cec5SDimitry Andric Res |= SanitizerKind::PointerSubtract; 35130b57cec5SDimitry Andric Res |= SanitizerKind::Leak; 35140b57cec5SDimitry Andric Res |= SanitizerKind::Fuzzer; 35150b57cec5SDimitry Andric Res |= SanitizerKind::FuzzerNoLink; 35165ffd83dbSDimitry Andric Res |= SanitizerKind::ObjCCast; 35170b57cec5SDimitry Andric 35180b57cec5SDimitry Andric // Prior to 10.9, macOS shipped a version of the C++ standard library without 35190b57cec5SDimitry Andric // C++11 support. The same is true of iOS prior to version 5. These OS'es are 35200b57cec5SDimitry Andric // incompatible with -fsanitize=vptr. 3521fe6060f1SDimitry Andric if (!(isTargetMacOSBased() && isMacosxVersionLT(10, 9)) && 3522fe6060f1SDimitry Andric !(isTargetIPhoneOS() && isIPhoneOSVersionLT(5, 0))) 35230b57cec5SDimitry Andric Res |= SanitizerKind::Vptr; 35240b57cec5SDimitry Andric 3525bdd1243dSDimitry Andric if ((IsX86_64 || IsAArch64) && 3526bdd1243dSDimitry Andric (isTargetMacOSBased() || isTargetIOSSimulator() || 3527bdd1243dSDimitry Andric isTargetTvOSSimulator() || isTargetWatchOSSimulator())) { 35280b57cec5SDimitry Andric Res |= SanitizerKind::Thread; 35290b57cec5SDimitry Andric } 35300fca6ea1SDimitry Andric 35310fca6ea1SDimitry Andric if (IsX86_64) 35320fca6ea1SDimitry Andric Res |= SanitizerKind::NumericalStability; 35330fca6ea1SDimitry Andric 35340b57cec5SDimitry Andric return Res; 35350b57cec5SDimitry Andric } 35360b57cec5SDimitry Andric 35370b57cec5SDimitry Andric void Darwin::printVerboseInfo(raw_ostream &OS) const { 35387a6dacacSDimitry Andric CudaInstallation->print(OS); 35397a6dacacSDimitry Andric RocmInstallation->print(OS); 35400b57cec5SDimitry Andric } 3541