17330f729Sjoerg //===--- Darwin.cpp - Darwin Tool and ToolChain Implementations -*- C++ -*-===//
27330f729Sjoerg //
37330f729Sjoerg // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
47330f729Sjoerg // See https://llvm.org/LICENSE.txt for license information.
57330f729Sjoerg // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
67330f729Sjoerg //
77330f729Sjoerg //===----------------------------------------------------------------------===//
87330f729Sjoerg
97330f729Sjoerg #include "Darwin.h"
10*e038c9c4Sjoerg #include "Arch/AArch64.h"
117330f729Sjoerg #include "Arch/ARM.h"
127330f729Sjoerg #include "CommonArgs.h"
137330f729Sjoerg #include "clang/Basic/AlignedAllocation.h"
147330f729Sjoerg #include "clang/Basic/ObjCRuntime.h"
157330f729Sjoerg #include "clang/Config/config.h"
167330f729Sjoerg #include "clang/Driver/Compilation.h"
177330f729Sjoerg #include "clang/Driver/Driver.h"
187330f729Sjoerg #include "clang/Driver/DriverDiagnostic.h"
197330f729Sjoerg #include "clang/Driver/Options.h"
207330f729Sjoerg #include "clang/Driver/SanitizerArgs.h"
217330f729Sjoerg #include "llvm/ADT/StringSwitch.h"
227330f729Sjoerg #include "llvm/Option/ArgList.h"
23*e038c9c4Sjoerg #include "llvm/ProfileData/InstrProf.h"
247330f729Sjoerg #include "llvm/Support/Path.h"
257330f729Sjoerg #include "llvm/Support/ScopedPrinter.h"
267330f729Sjoerg #include "llvm/Support/TargetParser.h"
27*e038c9c4Sjoerg #include "llvm/Support/Threading.h"
287330f729Sjoerg #include "llvm/Support/VirtualFileSystem.h"
297330f729Sjoerg #include <cstdlib> // ::getenv
307330f729Sjoerg
317330f729Sjoerg using namespace clang::driver;
327330f729Sjoerg using namespace clang::driver::tools;
337330f729Sjoerg using namespace clang::driver::toolchains;
347330f729Sjoerg using namespace clang;
357330f729Sjoerg using namespace llvm::opt;
367330f729Sjoerg
getArchTypeForMachOArchName(StringRef Str)377330f729Sjoerg llvm::Triple::ArchType darwin::getArchTypeForMachOArchName(StringRef Str) {
387330f729Sjoerg // See arch(3) and llvm-gcc's driver-driver.c. We don't implement support for
397330f729Sjoerg // archs which Darwin doesn't use.
407330f729Sjoerg
417330f729Sjoerg // The matching this routine does is fairly pointless, since it is neither the
427330f729Sjoerg // complete architecture list, nor a reasonable subset. The problem is that
437330f729Sjoerg // historically the driver driver accepts this and also ties its -march=
447330f729Sjoerg // handling to the architecture name, so we need to be careful before removing
457330f729Sjoerg // support for it.
467330f729Sjoerg
477330f729Sjoerg // This code must be kept in sync with Clang's Darwin specific argument
487330f729Sjoerg // translation.
497330f729Sjoerg
507330f729Sjoerg return llvm::StringSwitch<llvm::Triple::ArchType>(Str)
517330f729Sjoerg .Cases("ppc", "ppc601", "ppc603", "ppc604", "ppc604e", llvm::Triple::ppc)
527330f729Sjoerg .Cases("ppc750", "ppc7400", "ppc7450", "ppc970", llvm::Triple::ppc)
537330f729Sjoerg .Case("ppc64", llvm::Triple::ppc64)
547330f729Sjoerg .Cases("i386", "i486", "i486SX", "i586", "i686", llvm::Triple::x86)
557330f729Sjoerg .Cases("pentium", "pentpro", "pentIIm3", "pentIIm5", "pentium4",
567330f729Sjoerg llvm::Triple::x86)
577330f729Sjoerg .Cases("x86_64", "x86_64h", llvm::Triple::x86_64)
587330f729Sjoerg // This is derived from the driver driver.
597330f729Sjoerg .Cases("arm", "armv4t", "armv5", "armv6", "armv6m", llvm::Triple::arm)
607330f729Sjoerg .Cases("armv7", "armv7em", "armv7k", "armv7m", llvm::Triple::arm)
617330f729Sjoerg .Cases("armv7s", "xscale", llvm::Triple::arm)
62*e038c9c4Sjoerg .Cases("arm64", "arm64e", llvm::Triple::aarch64)
63*e038c9c4Sjoerg .Case("arm64_32", llvm::Triple::aarch64_32)
647330f729Sjoerg .Case("r600", llvm::Triple::r600)
657330f729Sjoerg .Case("amdgcn", llvm::Triple::amdgcn)
667330f729Sjoerg .Case("nvptx", llvm::Triple::nvptx)
677330f729Sjoerg .Case("nvptx64", llvm::Triple::nvptx64)
687330f729Sjoerg .Case("amdil", llvm::Triple::amdil)
697330f729Sjoerg .Case("spir", llvm::Triple::spir)
707330f729Sjoerg .Default(llvm::Triple::UnknownArch);
717330f729Sjoerg }
727330f729Sjoerg
setTripleTypeForMachOArchName(llvm::Triple & T,StringRef Str)737330f729Sjoerg void darwin::setTripleTypeForMachOArchName(llvm::Triple &T, StringRef Str) {
747330f729Sjoerg const llvm::Triple::ArchType Arch = getArchTypeForMachOArchName(Str);
757330f729Sjoerg llvm::ARM::ArchKind ArchKind = llvm::ARM::parseArch(Str);
767330f729Sjoerg T.setArch(Arch);
77*e038c9c4Sjoerg if (Arch != llvm::Triple::UnknownArch)
787330f729Sjoerg T.setArchName(Str);
79*e038c9c4Sjoerg
80*e038c9c4Sjoerg if (ArchKind == llvm::ARM::ArchKind::ARMV6M ||
817330f729Sjoerg ArchKind == llvm::ARM::ArchKind::ARMV7M ||
827330f729Sjoerg ArchKind == llvm::ARM::ArchKind::ARMV7EM) {
837330f729Sjoerg T.setOS(llvm::Triple::UnknownOS);
847330f729Sjoerg T.setObjectFormat(llvm::Triple::MachO);
857330f729Sjoerg }
867330f729Sjoerg }
877330f729Sjoerg
ConstructJob(Compilation & C,const JobAction & JA,const InputInfo & Output,const InputInfoList & Inputs,const ArgList & Args,const char * LinkingOutput) const887330f729Sjoerg void darwin::Assembler::ConstructJob(Compilation &C, const JobAction &JA,
897330f729Sjoerg const InputInfo &Output,
907330f729Sjoerg const InputInfoList &Inputs,
917330f729Sjoerg const ArgList &Args,
927330f729Sjoerg const char *LinkingOutput) const {
937330f729Sjoerg ArgStringList CmdArgs;
947330f729Sjoerg
957330f729Sjoerg assert(Inputs.size() == 1 && "Unexpected number of inputs.");
967330f729Sjoerg const InputInfo &Input = Inputs[0];
977330f729Sjoerg
987330f729Sjoerg // Determine the original source input.
997330f729Sjoerg const Action *SourceAction = &JA;
1007330f729Sjoerg while (SourceAction->getKind() != Action::InputClass) {
1017330f729Sjoerg assert(!SourceAction->getInputs().empty() && "unexpected root action!");
1027330f729Sjoerg SourceAction = SourceAction->getInputs()[0];
1037330f729Sjoerg }
1047330f729Sjoerg
1057330f729Sjoerg // If -fno-integrated-as is used add -Q to the darwin assembler driver to make
1067330f729Sjoerg // sure it runs its system assembler not clang's integrated assembler.
1077330f729Sjoerg // Applicable to darwin11+ and Xcode 4+. darwin<10 lacked integrated-as.
1087330f729Sjoerg // FIXME: at run-time detect assembler capabilities or rely on version
1097330f729Sjoerg // information forwarded by -target-assembler-version.
1107330f729Sjoerg if (Args.hasArg(options::OPT_fno_integrated_as)) {
1117330f729Sjoerg const llvm::Triple &T(getToolChain().getTriple());
1127330f729Sjoerg if (!(T.isMacOSX() && T.isMacOSXVersionLT(10, 7)))
1137330f729Sjoerg CmdArgs.push_back("-Q");
1147330f729Sjoerg }
1157330f729Sjoerg
1167330f729Sjoerg // Forward -g, assuming we are dealing with an actual assembly file.
1177330f729Sjoerg if (SourceAction->getType() == types::TY_Asm ||
1187330f729Sjoerg SourceAction->getType() == types::TY_PP_Asm) {
1197330f729Sjoerg if (Args.hasArg(options::OPT_gstabs))
1207330f729Sjoerg CmdArgs.push_back("--gstabs");
1217330f729Sjoerg else if (Args.hasArg(options::OPT_g_Group))
1227330f729Sjoerg CmdArgs.push_back("-g");
1237330f729Sjoerg }
1247330f729Sjoerg
1257330f729Sjoerg // Derived from asm spec.
1267330f729Sjoerg AddMachOArch(Args, CmdArgs);
1277330f729Sjoerg
1287330f729Sjoerg // Use -force_cpusubtype_ALL on x86 by default.
129*e038c9c4Sjoerg if (getToolChain().getTriple().isX86() ||
1307330f729Sjoerg Args.hasArg(options::OPT_force__cpusubtype__ALL))
1317330f729Sjoerg CmdArgs.push_back("-force_cpusubtype_ALL");
1327330f729Sjoerg
1337330f729Sjoerg if (getToolChain().getArch() != llvm::Triple::x86_64 &&
1347330f729Sjoerg (((Args.hasArg(options::OPT_mkernel) ||
1357330f729Sjoerg Args.hasArg(options::OPT_fapple_kext)) &&
1367330f729Sjoerg getMachOToolChain().isKernelStatic()) ||
1377330f729Sjoerg Args.hasArg(options::OPT_static)))
1387330f729Sjoerg CmdArgs.push_back("-static");
1397330f729Sjoerg
1407330f729Sjoerg Args.AddAllArgValues(CmdArgs, options::OPT_Wa_COMMA, options::OPT_Xassembler);
1417330f729Sjoerg
1427330f729Sjoerg assert(Output.isFilename() && "Unexpected lipo output.");
1437330f729Sjoerg CmdArgs.push_back("-o");
1447330f729Sjoerg CmdArgs.push_back(Output.getFilename());
1457330f729Sjoerg
1467330f729Sjoerg assert(Input.isFilename() && "Invalid input.");
1477330f729Sjoerg CmdArgs.push_back(Input.getFilename());
1487330f729Sjoerg
1497330f729Sjoerg // asm_final spec is empty.
1507330f729Sjoerg
1517330f729Sjoerg const char *Exec = Args.MakeArgString(getToolChain().GetProgramPath("as"));
152*e038c9c4Sjoerg C.addCommand(std::make_unique<Command>(JA, *this, ResponseFileSupport::None(),
153*e038c9c4Sjoerg Exec, CmdArgs, Inputs, Output));
1547330f729Sjoerg }
1557330f729Sjoerg
anchor()1567330f729Sjoerg void darwin::MachOTool::anchor() {}
1577330f729Sjoerg
AddMachOArch(const ArgList & Args,ArgStringList & CmdArgs) const1587330f729Sjoerg void darwin::MachOTool::AddMachOArch(const ArgList &Args,
1597330f729Sjoerg ArgStringList &CmdArgs) const {
1607330f729Sjoerg StringRef ArchName = getMachOToolChain().getMachOArchName(Args);
1617330f729Sjoerg
1627330f729Sjoerg // Derived from darwin_arch spec.
1637330f729Sjoerg CmdArgs.push_back("-arch");
1647330f729Sjoerg CmdArgs.push_back(Args.MakeArgString(ArchName));
1657330f729Sjoerg
1667330f729Sjoerg // FIXME: Is this needed anymore?
1677330f729Sjoerg if (ArchName == "arm")
1687330f729Sjoerg CmdArgs.push_back("-force_cpusubtype_ALL");
1697330f729Sjoerg }
1707330f729Sjoerg
NeedsTempPath(const InputInfoList & Inputs) const1717330f729Sjoerg bool darwin::Linker::NeedsTempPath(const InputInfoList &Inputs) const {
1727330f729Sjoerg // We only need to generate a temp path for LTO if we aren't compiling object
1737330f729Sjoerg // files. When compiling source files, we run 'dsymutil' after linking. We
1747330f729Sjoerg // don't run 'dsymutil' when compiling object files.
1757330f729Sjoerg for (const auto &Input : Inputs)
1767330f729Sjoerg if (Input.getType() != types::TY_Object)
1777330f729Sjoerg return true;
1787330f729Sjoerg
1797330f729Sjoerg return false;
1807330f729Sjoerg }
1817330f729Sjoerg
1827330f729Sjoerg /// Pass -no_deduplicate to ld64 under certain conditions:
1837330f729Sjoerg ///
1847330f729Sjoerg /// - Either -O0 or -O1 is explicitly specified
1857330f729Sjoerg /// - No -O option is specified *and* this is a compile+link (implicit -O0)
1867330f729Sjoerg ///
1877330f729Sjoerg /// Also do *not* add -no_deduplicate when no -O option is specified and this
1887330f729Sjoerg /// is just a link (we can't imply -O0)
shouldLinkerNotDedup(bool IsLinkerOnlyAction,const ArgList & Args)1897330f729Sjoerg static bool shouldLinkerNotDedup(bool IsLinkerOnlyAction, const ArgList &Args) {
1907330f729Sjoerg if (Arg *A = Args.getLastArg(options::OPT_O_Group)) {
1917330f729Sjoerg if (A->getOption().matches(options::OPT_O0))
1927330f729Sjoerg return true;
1937330f729Sjoerg if (A->getOption().matches(options::OPT_O))
1947330f729Sjoerg return llvm::StringSwitch<bool>(A->getValue())
1957330f729Sjoerg .Case("1", true)
1967330f729Sjoerg .Default(false);
1977330f729Sjoerg return false; // OPT_Ofast & OPT_O4
1987330f729Sjoerg }
1997330f729Sjoerg
2007330f729Sjoerg if (!IsLinkerOnlyAction) // Implicit -O0 for compile+linker only.
2017330f729Sjoerg return true;
2027330f729Sjoerg return false;
2037330f729Sjoerg }
2047330f729Sjoerg
AddLinkArgs(Compilation & C,const ArgList & Args,ArgStringList & CmdArgs,const InputInfoList & Inputs,unsigned Version[5],bool LinkerIsLLD,bool LinkerIsLLDDarwinNew) const2057330f729Sjoerg void darwin::Linker::AddLinkArgs(Compilation &C, const ArgList &Args,
2067330f729Sjoerg ArgStringList &CmdArgs,
207*e038c9c4Sjoerg const InputInfoList &Inputs,
208*e038c9c4Sjoerg unsigned Version[5], bool LinkerIsLLD,
209*e038c9c4Sjoerg bool LinkerIsLLDDarwinNew) const {
2107330f729Sjoerg const Driver &D = getToolChain().getDriver();
2117330f729Sjoerg const toolchains::MachO &MachOTC = getMachOToolChain();
2127330f729Sjoerg
2137330f729Sjoerg // Newer linkers support -demangle. Pass it if supported and not disabled by
2147330f729Sjoerg // the user.
215*e038c9c4Sjoerg if ((Version[0] >= 100 || LinkerIsLLD) &&
216*e038c9c4Sjoerg !Args.hasArg(options::OPT_Z_Xlinker__no_demangle))
2177330f729Sjoerg CmdArgs.push_back("-demangle");
2187330f729Sjoerg
219*e038c9c4Sjoerg // FIXME: Pass most of the flags below that check Version if LinkerIsLLD too.
220*e038c9c4Sjoerg
2217330f729Sjoerg if (Args.hasArg(options::OPT_rdynamic) && Version[0] >= 137)
2227330f729Sjoerg CmdArgs.push_back("-export_dynamic");
2237330f729Sjoerg
2247330f729Sjoerg // If we are using App Extension restrictions, pass a flag to the linker
2257330f729Sjoerg // telling it that the compiled code has been audited.
2267330f729Sjoerg if (Args.hasFlag(options::OPT_fapplication_extension,
2277330f729Sjoerg options::OPT_fno_application_extension, false))
2287330f729Sjoerg CmdArgs.push_back("-application_extension");
2297330f729Sjoerg
2307330f729Sjoerg if (D.isUsingLTO() && Version[0] >= 116 && NeedsTempPath(Inputs)) {
2317330f729Sjoerg std::string TmpPathName;
2327330f729Sjoerg if (D.getLTOMode() == LTOK_Full) {
2337330f729Sjoerg // If we are using full LTO, then automatically create a temporary file
2347330f729Sjoerg // path for the linker to use, so that it's lifetime will extend past a
2357330f729Sjoerg // possible dsymutil step.
2367330f729Sjoerg TmpPathName =
2377330f729Sjoerg D.GetTemporaryPath("cc", types::getTypeTempSuffix(types::TY_Object));
2387330f729Sjoerg } else if (D.getLTOMode() == LTOK_Thin)
2397330f729Sjoerg // If we are using thin LTO, then create a directory instead.
2407330f729Sjoerg TmpPathName = D.GetTemporaryDirectory("thinlto");
2417330f729Sjoerg
2427330f729Sjoerg if (!TmpPathName.empty()) {
2437330f729Sjoerg auto *TmpPath = C.getArgs().MakeArgString(TmpPathName);
2447330f729Sjoerg C.addTempFile(TmpPath);
2457330f729Sjoerg CmdArgs.push_back("-object_path_lto");
2467330f729Sjoerg CmdArgs.push_back(TmpPath);
2477330f729Sjoerg }
2487330f729Sjoerg }
2497330f729Sjoerg
2507330f729Sjoerg // Use -lto_library option to specify the libLTO.dylib path. Try to find
2517330f729Sjoerg // it in clang installed libraries. ld64 will only look at this argument
2527330f729Sjoerg // when it actually uses LTO, so libLTO.dylib only needs to exist at link
2537330f729Sjoerg // time if ld64 decides that it needs to use LTO.
2547330f729Sjoerg // Since this is passed unconditionally, ld64 will never look for libLTO.dylib
2557330f729Sjoerg // next to it. That's ok since ld64 using a libLTO.dylib not matching the
2567330f729Sjoerg // clang version won't work anyways.
257*e038c9c4Sjoerg // lld is built at the same revision as clang and statically links in
258*e038c9c4Sjoerg // LLVM libraries, so it doesn't need libLTO.dylib.
259*e038c9c4Sjoerg if (Version[0] >= 133 && !LinkerIsLLD) {
2607330f729Sjoerg // Search for libLTO in <InstalledDir>/../lib/libLTO.dylib
2617330f729Sjoerg StringRef P = llvm::sys::path::parent_path(D.Dir);
2627330f729Sjoerg SmallString<128> LibLTOPath(P);
2637330f729Sjoerg llvm::sys::path::append(LibLTOPath, "lib");
2647330f729Sjoerg llvm::sys::path::append(LibLTOPath, "libLTO.dylib");
2657330f729Sjoerg CmdArgs.push_back("-lto_library");
2667330f729Sjoerg CmdArgs.push_back(C.getArgs().MakeArgString(LibLTOPath));
2677330f729Sjoerg }
2687330f729Sjoerg
2697330f729Sjoerg // ld64 version 262 and above run the deduplicate pass by default.
2707330f729Sjoerg if (Version[0] >= 262 && shouldLinkerNotDedup(C.getJobs().empty(), Args))
2717330f729Sjoerg CmdArgs.push_back("-no_deduplicate");
2727330f729Sjoerg
2737330f729Sjoerg // Derived from the "link" spec.
2747330f729Sjoerg Args.AddAllArgs(CmdArgs, options::OPT_static);
2757330f729Sjoerg if (!Args.hasArg(options::OPT_static))
2767330f729Sjoerg CmdArgs.push_back("-dynamic");
2777330f729Sjoerg if (Args.hasArg(options::OPT_fgnu_runtime)) {
2787330f729Sjoerg // FIXME: gcc replaces -lobjc in forward args with -lobjc-gnu
2797330f729Sjoerg // here. How do we wish to handle such things?
2807330f729Sjoerg }
2817330f729Sjoerg
2827330f729Sjoerg if (!Args.hasArg(options::OPT_dynamiclib)) {
2837330f729Sjoerg AddMachOArch(Args, CmdArgs);
2847330f729Sjoerg // FIXME: Why do this only on this path?
2857330f729Sjoerg Args.AddLastArg(CmdArgs, options::OPT_force__cpusubtype__ALL);
2867330f729Sjoerg
2877330f729Sjoerg Args.AddLastArg(CmdArgs, options::OPT_bundle);
2887330f729Sjoerg Args.AddAllArgs(CmdArgs, options::OPT_bundle__loader);
2897330f729Sjoerg Args.AddAllArgs(CmdArgs, options::OPT_client__name);
2907330f729Sjoerg
2917330f729Sjoerg Arg *A;
2927330f729Sjoerg if ((A = Args.getLastArg(options::OPT_compatibility__version)) ||
2937330f729Sjoerg (A = Args.getLastArg(options::OPT_current__version)) ||
2947330f729Sjoerg (A = Args.getLastArg(options::OPT_install__name)))
2957330f729Sjoerg D.Diag(diag::err_drv_argument_only_allowed_with) << A->getAsString(Args)
2967330f729Sjoerg << "-dynamiclib";
2977330f729Sjoerg
2987330f729Sjoerg Args.AddLastArg(CmdArgs, options::OPT_force__flat__namespace);
2997330f729Sjoerg Args.AddLastArg(CmdArgs, options::OPT_keep__private__externs);
3007330f729Sjoerg Args.AddLastArg(CmdArgs, options::OPT_private__bundle);
3017330f729Sjoerg } else {
3027330f729Sjoerg CmdArgs.push_back("-dylib");
3037330f729Sjoerg
3047330f729Sjoerg Arg *A;
3057330f729Sjoerg if ((A = Args.getLastArg(options::OPT_bundle)) ||
3067330f729Sjoerg (A = Args.getLastArg(options::OPT_bundle__loader)) ||
3077330f729Sjoerg (A = Args.getLastArg(options::OPT_client__name)) ||
3087330f729Sjoerg (A = Args.getLastArg(options::OPT_force__flat__namespace)) ||
3097330f729Sjoerg (A = Args.getLastArg(options::OPT_keep__private__externs)) ||
3107330f729Sjoerg (A = Args.getLastArg(options::OPT_private__bundle)))
3117330f729Sjoerg D.Diag(diag::err_drv_argument_not_allowed_with) << A->getAsString(Args)
3127330f729Sjoerg << "-dynamiclib";
3137330f729Sjoerg
3147330f729Sjoerg Args.AddAllArgsTranslated(CmdArgs, options::OPT_compatibility__version,
3157330f729Sjoerg "-dylib_compatibility_version");
3167330f729Sjoerg Args.AddAllArgsTranslated(CmdArgs, options::OPT_current__version,
3177330f729Sjoerg "-dylib_current_version");
3187330f729Sjoerg
3197330f729Sjoerg AddMachOArch(Args, CmdArgs);
3207330f729Sjoerg
3217330f729Sjoerg Args.AddAllArgsTranslated(CmdArgs, options::OPT_install__name,
3227330f729Sjoerg "-dylib_install_name");
3237330f729Sjoerg }
3247330f729Sjoerg
3257330f729Sjoerg Args.AddLastArg(CmdArgs, options::OPT_all__load);
3267330f729Sjoerg Args.AddAllArgs(CmdArgs, options::OPT_allowable__client);
3277330f729Sjoerg Args.AddLastArg(CmdArgs, options::OPT_bind__at__load);
3287330f729Sjoerg if (MachOTC.isTargetIOSBased())
3297330f729Sjoerg Args.AddLastArg(CmdArgs, options::OPT_arch__errors__fatal);
3307330f729Sjoerg Args.AddLastArg(CmdArgs, options::OPT_dead__strip);
3317330f729Sjoerg Args.AddLastArg(CmdArgs, options::OPT_no__dead__strip__inits__and__terms);
3327330f729Sjoerg Args.AddAllArgs(CmdArgs, options::OPT_dylib__file);
3337330f729Sjoerg Args.AddLastArg(CmdArgs, options::OPT_dynamic);
3347330f729Sjoerg Args.AddAllArgs(CmdArgs, options::OPT_exported__symbols__list);
3357330f729Sjoerg Args.AddLastArg(CmdArgs, options::OPT_flat__namespace);
3367330f729Sjoerg Args.AddAllArgs(CmdArgs, options::OPT_force__load);
3377330f729Sjoerg Args.AddAllArgs(CmdArgs, options::OPT_headerpad__max__install__names);
3387330f729Sjoerg Args.AddAllArgs(CmdArgs, options::OPT_image__base);
3397330f729Sjoerg Args.AddAllArgs(CmdArgs, options::OPT_init);
3407330f729Sjoerg
3417330f729Sjoerg // Add the deployment target.
342*e038c9c4Sjoerg if (Version[0] >= 520 || LinkerIsLLDDarwinNew)
343*e038c9c4Sjoerg MachOTC.addPlatformVersionArgs(Args, CmdArgs);
344*e038c9c4Sjoerg else
3457330f729Sjoerg MachOTC.addMinVersionArgs(Args, CmdArgs);
3467330f729Sjoerg
3477330f729Sjoerg Args.AddLastArg(CmdArgs, options::OPT_nomultidefs);
3487330f729Sjoerg Args.AddLastArg(CmdArgs, options::OPT_multi__module);
3497330f729Sjoerg Args.AddLastArg(CmdArgs, options::OPT_single__module);
3507330f729Sjoerg Args.AddAllArgs(CmdArgs, options::OPT_multiply__defined);
3517330f729Sjoerg Args.AddAllArgs(CmdArgs, options::OPT_multiply__defined__unused);
3527330f729Sjoerg
3537330f729Sjoerg if (const Arg *A =
3547330f729Sjoerg Args.getLastArg(options::OPT_fpie, options::OPT_fPIE,
3557330f729Sjoerg options::OPT_fno_pie, options::OPT_fno_PIE)) {
3567330f729Sjoerg if (A->getOption().matches(options::OPT_fpie) ||
3577330f729Sjoerg A->getOption().matches(options::OPT_fPIE))
3587330f729Sjoerg CmdArgs.push_back("-pie");
3597330f729Sjoerg else
3607330f729Sjoerg CmdArgs.push_back("-no_pie");
3617330f729Sjoerg }
3627330f729Sjoerg
3637330f729Sjoerg // for embed-bitcode, use -bitcode_bundle in linker command
3647330f729Sjoerg if (C.getDriver().embedBitcodeEnabled()) {
3657330f729Sjoerg // Check if the toolchain supports bitcode build flow.
3667330f729Sjoerg if (MachOTC.SupportsEmbeddedBitcode()) {
3677330f729Sjoerg CmdArgs.push_back("-bitcode_bundle");
3687330f729Sjoerg if (C.getDriver().embedBitcodeMarkerOnly() && Version[0] >= 278) {
3697330f729Sjoerg CmdArgs.push_back("-bitcode_process_mode");
3707330f729Sjoerg CmdArgs.push_back("marker");
3717330f729Sjoerg }
3727330f729Sjoerg } else
3737330f729Sjoerg D.Diag(diag::err_drv_bitcode_unsupported_on_toolchain);
3747330f729Sjoerg }
3757330f729Sjoerg
376*e038c9c4Sjoerg // If GlobalISel is enabled, pass it through to LLVM.
377*e038c9c4Sjoerg if (Arg *A = Args.getLastArg(options::OPT_fglobal_isel,
378*e038c9c4Sjoerg options::OPT_fno_global_isel)) {
379*e038c9c4Sjoerg if (A->getOption().matches(options::OPT_fglobal_isel)) {
380*e038c9c4Sjoerg CmdArgs.push_back("-mllvm");
381*e038c9c4Sjoerg CmdArgs.push_back("-global-isel");
382*e038c9c4Sjoerg // Disable abort and fall back to SDAG silently.
383*e038c9c4Sjoerg CmdArgs.push_back("-mllvm");
384*e038c9c4Sjoerg CmdArgs.push_back("-global-isel-abort=0");
385*e038c9c4Sjoerg }
386*e038c9c4Sjoerg }
387*e038c9c4Sjoerg
3887330f729Sjoerg Args.AddLastArg(CmdArgs, options::OPT_prebind);
3897330f729Sjoerg Args.AddLastArg(CmdArgs, options::OPT_noprebind);
3907330f729Sjoerg Args.AddLastArg(CmdArgs, options::OPT_nofixprebinding);
3917330f729Sjoerg Args.AddLastArg(CmdArgs, options::OPT_prebind__all__twolevel__modules);
3927330f729Sjoerg Args.AddLastArg(CmdArgs, options::OPT_read__only__relocs);
3937330f729Sjoerg Args.AddAllArgs(CmdArgs, options::OPT_sectcreate);
3947330f729Sjoerg Args.AddAllArgs(CmdArgs, options::OPT_sectorder);
3957330f729Sjoerg Args.AddAllArgs(CmdArgs, options::OPT_seg1addr);
3967330f729Sjoerg Args.AddAllArgs(CmdArgs, options::OPT_segprot);
3977330f729Sjoerg Args.AddAllArgs(CmdArgs, options::OPT_segaddr);
3987330f729Sjoerg Args.AddAllArgs(CmdArgs, options::OPT_segs__read__only__addr);
3997330f729Sjoerg Args.AddAllArgs(CmdArgs, options::OPT_segs__read__write__addr);
4007330f729Sjoerg Args.AddAllArgs(CmdArgs, options::OPT_seg__addr__table);
4017330f729Sjoerg Args.AddAllArgs(CmdArgs, options::OPT_seg__addr__table__filename);
4027330f729Sjoerg Args.AddAllArgs(CmdArgs, options::OPT_sub__library);
4037330f729Sjoerg Args.AddAllArgs(CmdArgs, options::OPT_sub__umbrella);
4047330f729Sjoerg
4057330f729Sjoerg // Give --sysroot= preference, over the Apple specific behavior to also use
4067330f729Sjoerg // --isysroot as the syslibroot.
4077330f729Sjoerg StringRef sysroot = C.getSysRoot();
4087330f729Sjoerg if (sysroot != "") {
4097330f729Sjoerg CmdArgs.push_back("-syslibroot");
4107330f729Sjoerg CmdArgs.push_back(C.getArgs().MakeArgString(sysroot));
4117330f729Sjoerg } else if (const Arg *A = Args.getLastArg(options::OPT_isysroot)) {
4127330f729Sjoerg CmdArgs.push_back("-syslibroot");
4137330f729Sjoerg CmdArgs.push_back(A->getValue());
4147330f729Sjoerg }
4157330f729Sjoerg
4167330f729Sjoerg Args.AddLastArg(CmdArgs, options::OPT_twolevel__namespace);
4177330f729Sjoerg Args.AddLastArg(CmdArgs, options::OPT_twolevel__namespace__hints);
4187330f729Sjoerg Args.AddAllArgs(CmdArgs, options::OPT_umbrella);
4197330f729Sjoerg Args.AddAllArgs(CmdArgs, options::OPT_undefined);
4207330f729Sjoerg Args.AddAllArgs(CmdArgs, options::OPT_unexported__symbols__list);
4217330f729Sjoerg Args.AddAllArgs(CmdArgs, options::OPT_weak__reference__mismatches);
4227330f729Sjoerg Args.AddLastArg(CmdArgs, options::OPT_X_Flag);
4237330f729Sjoerg Args.AddAllArgs(CmdArgs, options::OPT_y);
4247330f729Sjoerg Args.AddLastArg(CmdArgs, options::OPT_w);
4257330f729Sjoerg Args.AddAllArgs(CmdArgs, options::OPT_pagezero__size);
4267330f729Sjoerg Args.AddAllArgs(CmdArgs, options::OPT_segs__read__);
4277330f729Sjoerg Args.AddLastArg(CmdArgs, options::OPT_seglinkedit);
4287330f729Sjoerg Args.AddLastArg(CmdArgs, options::OPT_noseglinkedit);
4297330f729Sjoerg Args.AddAllArgs(CmdArgs, options::OPT_sectalign);
4307330f729Sjoerg Args.AddAllArgs(CmdArgs, options::OPT_sectobjectsymbols);
4317330f729Sjoerg Args.AddAllArgs(CmdArgs, options::OPT_segcreate);
432*e038c9c4Sjoerg Args.AddLastArg(CmdArgs, options::OPT_why_load);
4337330f729Sjoerg Args.AddLastArg(CmdArgs, options::OPT_whatsloaded);
4347330f729Sjoerg Args.AddAllArgs(CmdArgs, options::OPT_dylinker__install__name);
4357330f729Sjoerg Args.AddLastArg(CmdArgs, options::OPT_dylinker);
4367330f729Sjoerg Args.AddLastArg(CmdArgs, options::OPT_Mach);
4377330f729Sjoerg }
4387330f729Sjoerg
4397330f729Sjoerg /// Determine whether we are linking the ObjC runtime.
isObjCRuntimeLinked(const ArgList & Args)4407330f729Sjoerg static bool isObjCRuntimeLinked(const ArgList &Args) {
4417330f729Sjoerg if (isObjCAutoRefCount(Args)) {
4427330f729Sjoerg Args.ClaimAllArgs(options::OPT_fobjc_link_runtime);
4437330f729Sjoerg return true;
4447330f729Sjoerg }
4457330f729Sjoerg return Args.hasArg(options::OPT_fobjc_link_runtime);
4467330f729Sjoerg }
4477330f729Sjoerg
checkRemarksOptions(const Driver & D,const ArgList & Args,const llvm::Triple & Triple)448*e038c9c4Sjoerg static bool checkRemarksOptions(const Driver &D, const ArgList &Args,
449*e038c9c4Sjoerg const llvm::Triple &Triple) {
450*e038c9c4Sjoerg // When enabling remarks, we need to error if:
451*e038c9c4Sjoerg // * The remark file is specified but we're targeting multiple architectures,
452*e038c9c4Sjoerg // which means more than one remark file is being generated.
453*e038c9c4Sjoerg bool hasMultipleInvocations =
454*e038c9c4Sjoerg Args.getAllArgValues(options::OPT_arch).size() > 1;
455*e038c9c4Sjoerg bool hasExplicitOutputFile =
456*e038c9c4Sjoerg Args.getLastArg(options::OPT_foptimization_record_file_EQ);
457*e038c9c4Sjoerg if (hasMultipleInvocations && hasExplicitOutputFile) {
458*e038c9c4Sjoerg D.Diag(diag::err_drv_invalid_output_with_multiple_archs)
459*e038c9c4Sjoerg << "-foptimization-record-file";
460*e038c9c4Sjoerg return false;
461*e038c9c4Sjoerg }
462*e038c9c4Sjoerg return true;
463*e038c9c4Sjoerg }
464*e038c9c4Sjoerg
renderRemarksOptions(const ArgList & Args,ArgStringList & CmdArgs,const llvm::Triple & Triple,const InputInfo & Output,const JobAction & JA)465*e038c9c4Sjoerg static void renderRemarksOptions(const ArgList &Args, ArgStringList &CmdArgs,
466*e038c9c4Sjoerg const llvm::Triple &Triple,
467*e038c9c4Sjoerg const InputInfo &Output, const JobAction &JA) {
468*e038c9c4Sjoerg StringRef Format = "yaml";
469*e038c9c4Sjoerg if (const Arg *A = Args.getLastArg(options::OPT_fsave_optimization_record_EQ))
470*e038c9c4Sjoerg Format = A->getValue();
471*e038c9c4Sjoerg
472*e038c9c4Sjoerg CmdArgs.push_back("-mllvm");
473*e038c9c4Sjoerg CmdArgs.push_back("-lto-pass-remarks-output");
474*e038c9c4Sjoerg CmdArgs.push_back("-mllvm");
475*e038c9c4Sjoerg
476*e038c9c4Sjoerg const Arg *A = Args.getLastArg(options::OPT_foptimization_record_file_EQ);
477*e038c9c4Sjoerg if (A) {
478*e038c9c4Sjoerg CmdArgs.push_back(A->getValue());
479*e038c9c4Sjoerg } else {
480*e038c9c4Sjoerg assert(Output.isFilename() && "Unexpected ld output.");
481*e038c9c4Sjoerg SmallString<128> F;
482*e038c9c4Sjoerg F = Output.getFilename();
483*e038c9c4Sjoerg F += ".opt.";
484*e038c9c4Sjoerg F += Format;
485*e038c9c4Sjoerg
486*e038c9c4Sjoerg CmdArgs.push_back(Args.MakeArgString(F));
487*e038c9c4Sjoerg }
488*e038c9c4Sjoerg
489*e038c9c4Sjoerg if (const Arg *A =
490*e038c9c4Sjoerg Args.getLastArg(options::OPT_foptimization_record_passes_EQ)) {
491*e038c9c4Sjoerg CmdArgs.push_back("-mllvm");
492*e038c9c4Sjoerg std::string Passes =
493*e038c9c4Sjoerg std::string("-lto-pass-remarks-filter=") + A->getValue();
494*e038c9c4Sjoerg CmdArgs.push_back(Args.MakeArgString(Passes));
495*e038c9c4Sjoerg }
496*e038c9c4Sjoerg
497*e038c9c4Sjoerg if (!Format.empty()) {
498*e038c9c4Sjoerg CmdArgs.push_back("-mllvm");
499*e038c9c4Sjoerg Twine FormatArg = Twine("-lto-pass-remarks-format=") + Format;
500*e038c9c4Sjoerg CmdArgs.push_back(Args.MakeArgString(FormatArg));
501*e038c9c4Sjoerg }
502*e038c9c4Sjoerg
503*e038c9c4Sjoerg if (getLastProfileUseArg(Args)) {
504*e038c9c4Sjoerg CmdArgs.push_back("-mllvm");
505*e038c9c4Sjoerg CmdArgs.push_back("-lto-pass-remarks-with-hotness");
506*e038c9c4Sjoerg
507*e038c9c4Sjoerg if (const Arg *A =
508*e038c9c4Sjoerg Args.getLastArg(options::OPT_fdiagnostics_hotness_threshold_EQ)) {
509*e038c9c4Sjoerg CmdArgs.push_back("-mllvm");
510*e038c9c4Sjoerg std::string Opt =
511*e038c9c4Sjoerg std::string("-lto-pass-remarks-hotness-threshold=") + A->getValue();
512*e038c9c4Sjoerg CmdArgs.push_back(Args.MakeArgString(Opt));
513*e038c9c4Sjoerg }
514*e038c9c4Sjoerg }
515*e038c9c4Sjoerg }
516*e038c9c4Sjoerg
ConstructJob(Compilation & C,const JobAction & JA,const InputInfo & Output,const InputInfoList & Inputs,const ArgList & Args,const char * LinkingOutput) const5177330f729Sjoerg void darwin::Linker::ConstructJob(Compilation &C, const JobAction &JA,
5187330f729Sjoerg const InputInfo &Output,
5197330f729Sjoerg const InputInfoList &Inputs,
5207330f729Sjoerg const ArgList &Args,
5217330f729Sjoerg const char *LinkingOutput) const {
5227330f729Sjoerg assert(Output.getType() == types::TY_Image && "Invalid linker output type.");
5237330f729Sjoerg
5247330f729Sjoerg // If the number of arguments surpasses the system limits, we will encode the
5257330f729Sjoerg // input files in a separate file, shortening the command line. To this end,
5267330f729Sjoerg // build a list of input file names that can be passed via a file with the
5277330f729Sjoerg // -filelist linker option.
5287330f729Sjoerg llvm::opt::ArgStringList InputFileList;
5297330f729Sjoerg
5307330f729Sjoerg // The logic here is derived from gcc's behavior; most of which
5317330f729Sjoerg // comes from specs (starting with link_command). Consult gcc for
5327330f729Sjoerg // more information.
5337330f729Sjoerg ArgStringList CmdArgs;
5347330f729Sjoerg
5357330f729Sjoerg /// Hack(tm) to ignore linking errors when we are doing ARC migration.
5367330f729Sjoerg if (Args.hasArg(options::OPT_ccc_arcmt_check,
5377330f729Sjoerg options::OPT_ccc_arcmt_migrate)) {
5387330f729Sjoerg for (const auto &Arg : Args)
5397330f729Sjoerg Arg->claim();
5407330f729Sjoerg const char *Exec =
5417330f729Sjoerg Args.MakeArgString(getToolChain().GetProgramPath("touch"));
5427330f729Sjoerg CmdArgs.push_back(Output.getFilename());
543*e038c9c4Sjoerg C.addCommand(std::make_unique<Command>(
544*e038c9c4Sjoerg JA, *this, ResponseFileSupport::None(), Exec, CmdArgs, None, Output));
5457330f729Sjoerg return;
5467330f729Sjoerg }
5477330f729Sjoerg
548*e038c9c4Sjoerg unsigned Version[5] = {0, 0, 0, 0, 0};
549*e038c9c4Sjoerg if (Arg *A = Args.getLastArg(options::OPT_mlinker_version_EQ)) {
550*e038c9c4Sjoerg if (!Driver::GetReleaseVersion(A->getValue(), Version))
551*e038c9c4Sjoerg getToolChain().getDriver().Diag(diag::err_drv_invalid_version_number)
552*e038c9c4Sjoerg << A->getAsString(Args);
553*e038c9c4Sjoerg }
554*e038c9c4Sjoerg
555*e038c9c4Sjoerg bool LinkerIsLLD, LinkerIsLLDDarwinNew;
556*e038c9c4Sjoerg const char *Exec = Args.MakeArgString(
557*e038c9c4Sjoerg getToolChain().GetLinkerPath(&LinkerIsLLD, &LinkerIsLLDDarwinNew));
558*e038c9c4Sjoerg
5597330f729Sjoerg // I'm not sure why this particular decomposition exists in gcc, but
5607330f729Sjoerg // we follow suite for ease of comparison.
561*e038c9c4Sjoerg AddLinkArgs(C, Args, CmdArgs, Inputs, Version, LinkerIsLLD,
562*e038c9c4Sjoerg LinkerIsLLDDarwinNew);
5637330f729Sjoerg
564*e038c9c4Sjoerg if (willEmitRemarks(Args) &&
565*e038c9c4Sjoerg checkRemarksOptions(getToolChain().getDriver(), Args,
566*e038c9c4Sjoerg getToolChain().getTriple()))
567*e038c9c4Sjoerg renderRemarksOptions(Args, CmdArgs, getToolChain().getTriple(), Output, JA);
5687330f729Sjoerg
5697330f729Sjoerg // Propagate the -moutline flag to the linker in LTO.
5707330f729Sjoerg if (Arg *A =
5717330f729Sjoerg Args.getLastArg(options::OPT_moutline, options::OPT_mno_outline)) {
5727330f729Sjoerg if (A->getOption().matches(options::OPT_moutline)) {
5737330f729Sjoerg if (getMachOToolChain().getMachOArchName(Args) == "arm64") {
5747330f729Sjoerg CmdArgs.push_back("-mllvm");
5757330f729Sjoerg CmdArgs.push_back("-enable-machine-outliner");
5767330f729Sjoerg
5777330f729Sjoerg // Outline from linkonceodr functions by default in LTO.
5787330f729Sjoerg CmdArgs.push_back("-mllvm");
5797330f729Sjoerg CmdArgs.push_back("-enable-linkonceodr-outlining");
5807330f729Sjoerg }
5817330f729Sjoerg } else {
5827330f729Sjoerg // Disable all outlining behaviour if we have mno-outline. We need to do
5837330f729Sjoerg // this explicitly, because targets which support default outlining will
5847330f729Sjoerg // try to do work if we don't.
5857330f729Sjoerg CmdArgs.push_back("-mllvm");
5867330f729Sjoerg CmdArgs.push_back("-enable-machine-outliner=never");
5877330f729Sjoerg }
5887330f729Sjoerg }
5897330f729Sjoerg
5907330f729Sjoerg // Setup statistics file output.
5917330f729Sjoerg SmallString<128> StatsFile =
5927330f729Sjoerg getStatsFileName(Args, Output, Inputs[0], getToolChain().getDriver());
5937330f729Sjoerg if (!StatsFile.empty()) {
5947330f729Sjoerg CmdArgs.push_back("-mllvm");
5957330f729Sjoerg CmdArgs.push_back(Args.MakeArgString("-lto-stats-file=" + StatsFile.str()));
5967330f729Sjoerg }
5977330f729Sjoerg
5987330f729Sjoerg // It seems that the 'e' option is completely ignored for dynamic executables
5997330f729Sjoerg // (the default), and with static executables, the last one wins, as expected.
6007330f729Sjoerg Args.AddAllArgs(CmdArgs, {options::OPT_d_Flag, options::OPT_s, options::OPT_t,
6017330f729Sjoerg options::OPT_Z_Flag, options::OPT_u_Group,
6027330f729Sjoerg options::OPT_e, options::OPT_r});
6037330f729Sjoerg
6047330f729Sjoerg // Forward -ObjC when either -ObjC or -ObjC++ is used, to force loading
6057330f729Sjoerg // members of static archive libraries which implement Objective-C classes or
6067330f729Sjoerg // categories.
6077330f729Sjoerg if (Args.hasArg(options::OPT_ObjC) || Args.hasArg(options::OPT_ObjCXX))
6087330f729Sjoerg CmdArgs.push_back("-ObjC");
6097330f729Sjoerg
6107330f729Sjoerg CmdArgs.push_back("-o");
6117330f729Sjoerg CmdArgs.push_back(Output.getFilename());
6127330f729Sjoerg
6137330f729Sjoerg if (!Args.hasArg(options::OPT_nostdlib, options::OPT_nostartfiles))
6147330f729Sjoerg getMachOToolChain().addStartObjectFileArgs(Args, CmdArgs);
6157330f729Sjoerg
6167330f729Sjoerg Args.AddAllArgs(CmdArgs, options::OPT_L);
6177330f729Sjoerg
6187330f729Sjoerg AddLinkerInputs(getToolChain(), Inputs, Args, CmdArgs, JA);
6197330f729Sjoerg // Build the input file for -filelist (list of linker input files) in case we
6207330f729Sjoerg // need it later
6217330f729Sjoerg for (const auto &II : Inputs) {
6227330f729Sjoerg if (!II.isFilename()) {
6237330f729Sjoerg // This is a linker input argument.
6247330f729Sjoerg // We cannot mix input arguments and file names in a -filelist input, thus
6257330f729Sjoerg // we prematurely stop our list (remaining files shall be passed as
6267330f729Sjoerg // arguments).
6277330f729Sjoerg if (InputFileList.size() > 0)
6287330f729Sjoerg break;
6297330f729Sjoerg
6307330f729Sjoerg continue;
6317330f729Sjoerg }
6327330f729Sjoerg
6337330f729Sjoerg InputFileList.push_back(II.getFilename());
6347330f729Sjoerg }
6357330f729Sjoerg
6367330f729Sjoerg if (!Args.hasArg(options::OPT_nostdlib, options::OPT_nodefaultlibs))
6377330f729Sjoerg addOpenMPRuntime(CmdArgs, getToolChain(), Args);
6387330f729Sjoerg
6397330f729Sjoerg if (isObjCRuntimeLinked(Args) &&
6407330f729Sjoerg !Args.hasArg(options::OPT_nostdlib, options::OPT_nodefaultlibs)) {
6417330f729Sjoerg // We use arclite library for both ARC and subscripting support.
6427330f729Sjoerg getMachOToolChain().AddLinkARCArgs(Args, CmdArgs);
6437330f729Sjoerg
6447330f729Sjoerg CmdArgs.push_back("-framework");
6457330f729Sjoerg CmdArgs.push_back("Foundation");
6467330f729Sjoerg // Link libobj.
6477330f729Sjoerg CmdArgs.push_back("-lobjc");
6487330f729Sjoerg }
6497330f729Sjoerg
6507330f729Sjoerg if (LinkingOutput) {
6517330f729Sjoerg CmdArgs.push_back("-arch_multiple");
6527330f729Sjoerg CmdArgs.push_back("-final_output");
6537330f729Sjoerg CmdArgs.push_back(LinkingOutput);
6547330f729Sjoerg }
6557330f729Sjoerg
6567330f729Sjoerg if (Args.hasArg(options::OPT_fnested_functions))
6577330f729Sjoerg CmdArgs.push_back("-allow_stack_execute");
6587330f729Sjoerg
6597330f729Sjoerg getMachOToolChain().addProfileRTLibs(Args, CmdArgs);
6607330f729Sjoerg
661*e038c9c4Sjoerg StringRef Parallelism = getLTOParallelism(Args, getToolChain().getDriver());
662*e038c9c4Sjoerg if (!Parallelism.empty()) {
6637330f729Sjoerg CmdArgs.push_back("-mllvm");
664*e038c9c4Sjoerg unsigned NumThreads =
665*e038c9c4Sjoerg llvm::get_threadpool_strategy(Parallelism)->compute_thread_count();
666*e038c9c4Sjoerg CmdArgs.push_back(Args.MakeArgString("-threads=" + Twine(NumThreads)));
6677330f729Sjoerg }
6687330f729Sjoerg
6697330f729Sjoerg if (getToolChain().ShouldLinkCXXStdlib(Args))
6707330f729Sjoerg getToolChain().AddCXXStdlibLibArgs(Args, CmdArgs);
6717330f729Sjoerg
6727330f729Sjoerg bool NoStdOrDefaultLibs =
6737330f729Sjoerg Args.hasArg(options::OPT_nostdlib, options::OPT_nodefaultlibs);
6747330f729Sjoerg bool ForceLinkBuiltins = Args.hasArg(options::OPT_fapple_link_rtlib);
6757330f729Sjoerg if (!NoStdOrDefaultLibs || ForceLinkBuiltins) {
6767330f729Sjoerg // link_ssp spec is empty.
6777330f729Sjoerg
6787330f729Sjoerg // If we have both -nostdlib/nodefaultlibs and -fapple-link-rtlib then
6797330f729Sjoerg // we just want to link the builtins, not the other libs like libSystem.
6807330f729Sjoerg if (NoStdOrDefaultLibs && ForceLinkBuiltins) {
6817330f729Sjoerg getMachOToolChain().AddLinkRuntimeLib(Args, CmdArgs, "builtins");
6827330f729Sjoerg } else {
6837330f729Sjoerg // Let the tool chain choose which runtime library to link.
6847330f729Sjoerg getMachOToolChain().AddLinkRuntimeLibArgs(Args, CmdArgs,
6857330f729Sjoerg ForceLinkBuiltins);
6867330f729Sjoerg
6877330f729Sjoerg // No need to do anything for pthreads. Claim argument to avoid warning.
6887330f729Sjoerg Args.ClaimAllArgs(options::OPT_pthread);
6897330f729Sjoerg Args.ClaimAllArgs(options::OPT_pthreads);
6907330f729Sjoerg }
6917330f729Sjoerg }
6927330f729Sjoerg
6937330f729Sjoerg if (!Args.hasArg(options::OPT_nostdlib, options::OPT_nostartfiles)) {
6947330f729Sjoerg // endfile_spec is empty.
6957330f729Sjoerg }
6967330f729Sjoerg
6977330f729Sjoerg Args.AddAllArgs(CmdArgs, options::OPT_T_Group);
6987330f729Sjoerg Args.AddAllArgs(CmdArgs, options::OPT_F);
6997330f729Sjoerg
7007330f729Sjoerg // -iframework should be forwarded as -F.
7017330f729Sjoerg for (const Arg *A : Args.filtered(options::OPT_iframework))
7027330f729Sjoerg CmdArgs.push_back(Args.MakeArgString(std::string("-F") + A->getValue()));
7037330f729Sjoerg
7047330f729Sjoerg if (!Args.hasArg(options::OPT_nostdlib, options::OPT_nodefaultlibs)) {
7057330f729Sjoerg if (Arg *A = Args.getLastArg(options::OPT_fveclib)) {
7067330f729Sjoerg if (A->getValue() == StringRef("Accelerate")) {
7077330f729Sjoerg CmdArgs.push_back("-framework");
7087330f729Sjoerg CmdArgs.push_back("Accelerate");
7097330f729Sjoerg }
7107330f729Sjoerg }
7117330f729Sjoerg }
7127330f729Sjoerg
713*e038c9c4Sjoerg ResponseFileSupport ResponseSupport;
714*e038c9c4Sjoerg if (LinkerIsLLDDarwinNew) {
715*e038c9c4Sjoerg // Xcode12's ld64 added support for @response files, but it's crashy:
716*e038c9c4Sjoerg // https://openradar.appspot.com/radar?id=4933317065441280
717*e038c9c4Sjoerg // FIXME: Pass this for ld64 once it no longer crashes.
718*e038c9c4Sjoerg ResponseSupport = ResponseFileSupport::AtFileUTF8();
719*e038c9c4Sjoerg } else {
720*e038c9c4Sjoerg // For older versions of the linker, use the legacy filelist method instead.
721*e038c9c4Sjoerg ResponseSupport = {ResponseFileSupport::RF_FileList, llvm::sys::WEM_UTF8,
722*e038c9c4Sjoerg "-filelist"};
723*e038c9c4Sjoerg }
724*e038c9c4Sjoerg
725*e038c9c4Sjoerg std::unique_ptr<Command> Cmd = std::make_unique<Command>(
726*e038c9c4Sjoerg JA, *this, ResponseSupport, Exec, CmdArgs, Inputs, Output);
7277330f729Sjoerg Cmd->setInputFileList(std::move(InputFileList));
7287330f729Sjoerg C.addCommand(std::move(Cmd));
7297330f729Sjoerg }
7307330f729Sjoerg
ConstructJob(Compilation & C,const JobAction & JA,const InputInfo & Output,const InputInfoList & Inputs,const ArgList & Args,const char * LinkingOutput) const7317330f729Sjoerg void darwin::Lipo::ConstructJob(Compilation &C, const JobAction &JA,
7327330f729Sjoerg const InputInfo &Output,
7337330f729Sjoerg const InputInfoList &Inputs,
7347330f729Sjoerg const ArgList &Args,
7357330f729Sjoerg const char *LinkingOutput) const {
7367330f729Sjoerg ArgStringList CmdArgs;
7377330f729Sjoerg
7387330f729Sjoerg CmdArgs.push_back("-create");
7397330f729Sjoerg assert(Output.isFilename() && "Unexpected lipo output.");
7407330f729Sjoerg
7417330f729Sjoerg CmdArgs.push_back("-output");
7427330f729Sjoerg CmdArgs.push_back(Output.getFilename());
7437330f729Sjoerg
7447330f729Sjoerg for (const auto &II : Inputs) {
7457330f729Sjoerg assert(II.isFilename() && "Unexpected lipo input.");
7467330f729Sjoerg CmdArgs.push_back(II.getFilename());
7477330f729Sjoerg }
7487330f729Sjoerg
7497330f729Sjoerg const char *Exec = Args.MakeArgString(getToolChain().GetProgramPath("lipo"));
750*e038c9c4Sjoerg C.addCommand(std::make_unique<Command>(JA, *this, ResponseFileSupport::None(),
751*e038c9c4Sjoerg Exec, CmdArgs, Inputs, Output));
7527330f729Sjoerg }
7537330f729Sjoerg
ConstructJob(Compilation & C,const JobAction & JA,const InputInfo & Output,const InputInfoList & Inputs,const ArgList & Args,const char * LinkingOutput) const7547330f729Sjoerg void darwin::Dsymutil::ConstructJob(Compilation &C, const JobAction &JA,
7557330f729Sjoerg const InputInfo &Output,
7567330f729Sjoerg const InputInfoList &Inputs,
7577330f729Sjoerg const ArgList &Args,
7587330f729Sjoerg const char *LinkingOutput) const {
7597330f729Sjoerg ArgStringList CmdArgs;
7607330f729Sjoerg
7617330f729Sjoerg CmdArgs.push_back("-o");
7627330f729Sjoerg CmdArgs.push_back(Output.getFilename());
7637330f729Sjoerg
7647330f729Sjoerg assert(Inputs.size() == 1 && "Unable to handle multiple inputs.");
7657330f729Sjoerg const InputInfo &Input = Inputs[0];
7667330f729Sjoerg assert(Input.isFilename() && "Unexpected dsymutil input.");
7677330f729Sjoerg CmdArgs.push_back(Input.getFilename());
7687330f729Sjoerg
7697330f729Sjoerg const char *Exec =
7707330f729Sjoerg Args.MakeArgString(getToolChain().GetProgramPath("dsymutil"));
771*e038c9c4Sjoerg C.addCommand(std::make_unique<Command>(JA, *this, ResponseFileSupport::None(),
772*e038c9c4Sjoerg Exec, CmdArgs, Inputs, Output));
7737330f729Sjoerg }
7747330f729Sjoerg
ConstructJob(Compilation & C,const JobAction & JA,const InputInfo & Output,const InputInfoList & Inputs,const ArgList & Args,const char * LinkingOutput) const7757330f729Sjoerg void darwin::VerifyDebug::ConstructJob(Compilation &C, const JobAction &JA,
7767330f729Sjoerg const InputInfo &Output,
7777330f729Sjoerg const InputInfoList &Inputs,
7787330f729Sjoerg const ArgList &Args,
7797330f729Sjoerg const char *LinkingOutput) const {
7807330f729Sjoerg ArgStringList CmdArgs;
7817330f729Sjoerg CmdArgs.push_back("--verify");
7827330f729Sjoerg CmdArgs.push_back("--debug-info");
7837330f729Sjoerg CmdArgs.push_back("--eh-frame");
7847330f729Sjoerg CmdArgs.push_back("--quiet");
7857330f729Sjoerg
7867330f729Sjoerg assert(Inputs.size() == 1 && "Unable to handle multiple inputs.");
7877330f729Sjoerg const InputInfo &Input = Inputs[0];
7887330f729Sjoerg assert(Input.isFilename() && "Unexpected verify input");
7897330f729Sjoerg
7907330f729Sjoerg // Grabbing the output of the earlier dsymutil run.
7917330f729Sjoerg CmdArgs.push_back(Input.getFilename());
7927330f729Sjoerg
7937330f729Sjoerg const char *Exec =
7947330f729Sjoerg Args.MakeArgString(getToolChain().GetProgramPath("dwarfdump"));
795*e038c9c4Sjoerg C.addCommand(std::make_unique<Command>(JA, *this, ResponseFileSupport::None(),
796*e038c9c4Sjoerg Exec, CmdArgs, Inputs, Output));
7977330f729Sjoerg }
7987330f729Sjoerg
MachO(const Driver & D,const llvm::Triple & Triple,const ArgList & Args)7997330f729Sjoerg MachO::MachO(const Driver &D, const llvm::Triple &Triple, const ArgList &Args)
8007330f729Sjoerg : ToolChain(D, Triple, Args) {
8017330f729Sjoerg // We expect 'as', 'ld', etc. to be adjacent to our install dir.
8027330f729Sjoerg getProgramPaths().push_back(getDriver().getInstalledDir());
8037330f729Sjoerg if (getDriver().getInstalledDir() != getDriver().Dir)
8047330f729Sjoerg getProgramPaths().push_back(getDriver().Dir);
8057330f729Sjoerg }
8067330f729Sjoerg
8077330f729Sjoerg /// Darwin - Darwin tool chain for i386 and x86_64.
Darwin(const Driver & D,const llvm::Triple & Triple,const ArgList & Args)8087330f729Sjoerg Darwin::Darwin(const Driver &D, const llvm::Triple &Triple, const ArgList &Args)
8097330f729Sjoerg : MachO(D, Triple, Args), TargetInitialized(false),
810*e038c9c4Sjoerg CudaInstallation(D, Triple, Args), RocmInstallation(D, Triple, Args) {}
8117330f729Sjoerg
LookupTypeForExtension(StringRef Ext) const8127330f729Sjoerg types::ID MachO::LookupTypeForExtension(StringRef Ext) const {
813*e038c9c4Sjoerg types::ID Ty = ToolChain::LookupTypeForExtension(Ext);
8147330f729Sjoerg
8157330f729Sjoerg // Darwin always preprocesses assembly files (unless -x is used explicitly).
8167330f729Sjoerg if (Ty == types::TY_PP_Asm)
8177330f729Sjoerg return types::TY_Asm;
8187330f729Sjoerg
8197330f729Sjoerg return Ty;
8207330f729Sjoerg }
8217330f729Sjoerg
HasNativeLLVMSupport() const8227330f729Sjoerg bool MachO::HasNativeLLVMSupport() const { return true; }
8237330f729Sjoerg
GetDefaultCXXStdlibType() const8247330f729Sjoerg ToolChain::CXXStdlibType Darwin::GetDefaultCXXStdlibType() const {
8257330f729Sjoerg // Default to use libc++ on OS X 10.9+ and iOS 7+.
8267330f729Sjoerg if ((isTargetMacOS() && !isMacosxVersionLT(10, 9)) ||
8277330f729Sjoerg (isTargetIOSBased() && !isIPhoneOSVersionLT(7, 0)) ||
8287330f729Sjoerg isTargetWatchOSBased())
8297330f729Sjoerg return ToolChain::CST_Libcxx;
8307330f729Sjoerg
8317330f729Sjoerg return ToolChain::CST_Libstdcxx;
8327330f729Sjoerg }
8337330f729Sjoerg
8347330f729Sjoerg /// Darwin provides an ARC runtime starting in MacOS X 10.7 and iOS 5.0.
getDefaultObjCRuntime(bool isNonFragile) const8357330f729Sjoerg ObjCRuntime Darwin::getDefaultObjCRuntime(bool isNonFragile) const {
8367330f729Sjoerg if (isTargetWatchOSBased())
8377330f729Sjoerg return ObjCRuntime(ObjCRuntime::WatchOS, TargetVersion);
8387330f729Sjoerg if (isTargetIOSBased())
8397330f729Sjoerg return ObjCRuntime(ObjCRuntime::iOS, TargetVersion);
8407330f729Sjoerg if (isNonFragile)
8417330f729Sjoerg return ObjCRuntime(ObjCRuntime::MacOSX, TargetVersion);
8427330f729Sjoerg return ObjCRuntime(ObjCRuntime::FragileMacOSX, TargetVersion);
8437330f729Sjoerg }
8447330f729Sjoerg
8457330f729Sjoerg /// Darwin provides a blocks runtime starting in MacOS X 10.6 and iOS 3.2.
hasBlocksRuntime() const8467330f729Sjoerg bool Darwin::hasBlocksRuntime() const {
8477330f729Sjoerg if (isTargetWatchOSBased())
8487330f729Sjoerg return true;
8497330f729Sjoerg else if (isTargetIOSBased())
8507330f729Sjoerg return !isIPhoneOSVersionLT(3, 2);
8517330f729Sjoerg else {
8527330f729Sjoerg assert(isTargetMacOS() && "unexpected darwin target");
8537330f729Sjoerg return !isMacosxVersionLT(10, 6);
8547330f729Sjoerg }
8557330f729Sjoerg }
8567330f729Sjoerg
AddCudaIncludeArgs(const ArgList & DriverArgs,ArgStringList & CC1Args) const8577330f729Sjoerg void Darwin::AddCudaIncludeArgs(const ArgList &DriverArgs,
8587330f729Sjoerg ArgStringList &CC1Args) const {
8597330f729Sjoerg CudaInstallation.AddCudaIncludeArgs(DriverArgs, CC1Args);
8607330f729Sjoerg }
8617330f729Sjoerg
AddHIPIncludeArgs(const ArgList & DriverArgs,ArgStringList & CC1Args) const862*e038c9c4Sjoerg void Darwin::AddHIPIncludeArgs(const ArgList &DriverArgs,
863*e038c9c4Sjoerg ArgStringList &CC1Args) const {
864*e038c9c4Sjoerg RocmInstallation.AddHIPIncludeArgs(DriverArgs, CC1Args);
865*e038c9c4Sjoerg }
866*e038c9c4Sjoerg
8677330f729Sjoerg // This is just a MachO name translation routine and there's no
8687330f729Sjoerg // way to join this into ARMTargetParser without breaking all
8697330f729Sjoerg // other assumptions. Maybe MachO should consider standardising
8707330f729Sjoerg // their nomenclature.
ArmMachOArchName(StringRef Arch)8717330f729Sjoerg static const char *ArmMachOArchName(StringRef Arch) {
8727330f729Sjoerg return llvm::StringSwitch<const char *>(Arch)
8737330f729Sjoerg .Case("armv6k", "armv6")
8747330f729Sjoerg .Case("armv6m", "armv6m")
8757330f729Sjoerg .Case("armv5tej", "armv5")
8767330f729Sjoerg .Case("xscale", "xscale")
8777330f729Sjoerg .Case("armv4t", "armv4t")
8787330f729Sjoerg .Case("armv7", "armv7")
8797330f729Sjoerg .Cases("armv7a", "armv7-a", "armv7")
8807330f729Sjoerg .Cases("armv7r", "armv7-r", "armv7")
8817330f729Sjoerg .Cases("armv7em", "armv7e-m", "armv7em")
8827330f729Sjoerg .Cases("armv7k", "armv7-k", "armv7k")
8837330f729Sjoerg .Cases("armv7m", "armv7-m", "armv7m")
8847330f729Sjoerg .Cases("armv7s", "armv7-s", "armv7s")
8857330f729Sjoerg .Default(nullptr);
8867330f729Sjoerg }
8877330f729Sjoerg
ArmMachOArchNameCPU(StringRef CPU)8887330f729Sjoerg static const char *ArmMachOArchNameCPU(StringRef CPU) {
8897330f729Sjoerg llvm::ARM::ArchKind ArchKind = llvm::ARM::parseCPUArch(CPU);
8907330f729Sjoerg if (ArchKind == llvm::ARM::ArchKind::INVALID)
8917330f729Sjoerg return nullptr;
8927330f729Sjoerg StringRef Arch = llvm::ARM::getArchName(ArchKind);
8937330f729Sjoerg
8947330f729Sjoerg // FIXME: Make sure this MachO triple mangling is really necessary.
8957330f729Sjoerg // ARMv5* normalises to ARMv5.
8967330f729Sjoerg if (Arch.startswith("armv5"))
8977330f729Sjoerg Arch = Arch.substr(0, 5);
8987330f729Sjoerg // ARMv6*, except ARMv6M, normalises to ARMv6.
8997330f729Sjoerg else if (Arch.startswith("armv6") && !Arch.endswith("6m"))
9007330f729Sjoerg Arch = Arch.substr(0, 5);
9017330f729Sjoerg // ARMv7A normalises to ARMv7.
9027330f729Sjoerg else if (Arch.endswith("v7a"))
9037330f729Sjoerg Arch = Arch.substr(0, 5);
9047330f729Sjoerg return Arch.data();
9057330f729Sjoerg }
9067330f729Sjoerg
getMachOArchName(const ArgList & Args) const9077330f729Sjoerg StringRef MachO::getMachOArchName(const ArgList &Args) const {
9087330f729Sjoerg switch (getTriple().getArch()) {
9097330f729Sjoerg default:
9107330f729Sjoerg return getDefaultUniversalArchName();
9117330f729Sjoerg
912*e038c9c4Sjoerg case llvm::Triple::aarch64_32:
913*e038c9c4Sjoerg return "arm64_32";
914*e038c9c4Sjoerg
915*e038c9c4Sjoerg case llvm::Triple::aarch64: {
916*e038c9c4Sjoerg if (getTriple().isArm64e())
917*e038c9c4Sjoerg return "arm64e";
9187330f729Sjoerg return "arm64";
919*e038c9c4Sjoerg }
9207330f729Sjoerg
9217330f729Sjoerg case llvm::Triple::thumb:
9227330f729Sjoerg case llvm::Triple::arm:
9237330f729Sjoerg if (const Arg *A = Args.getLastArg(clang::driver::options::OPT_march_EQ))
9247330f729Sjoerg if (const char *Arch = ArmMachOArchName(A->getValue()))
9257330f729Sjoerg return Arch;
9267330f729Sjoerg
9277330f729Sjoerg if (const Arg *A = Args.getLastArg(options::OPT_mcpu_EQ))
9287330f729Sjoerg if (const char *Arch = ArmMachOArchNameCPU(A->getValue()))
9297330f729Sjoerg return Arch;
9307330f729Sjoerg
9317330f729Sjoerg return "arm";
9327330f729Sjoerg }
9337330f729Sjoerg }
9347330f729Sjoerg
~Darwin()9357330f729Sjoerg Darwin::~Darwin() {}
9367330f729Sjoerg
~MachO()9377330f729Sjoerg MachO::~MachO() {}
9387330f729Sjoerg
ComputeEffectiveClangTriple(const ArgList & Args,types::ID InputType) const9397330f729Sjoerg std::string Darwin::ComputeEffectiveClangTriple(const ArgList &Args,
9407330f729Sjoerg types::ID InputType) const {
9417330f729Sjoerg llvm::Triple Triple(ComputeLLVMTriple(Args, InputType));
9427330f729Sjoerg
9437330f729Sjoerg // If the target isn't initialized (e.g., an unknown Darwin platform, return
9447330f729Sjoerg // the default triple).
9457330f729Sjoerg if (!isTargetInitialized())
9467330f729Sjoerg return Triple.getTriple();
9477330f729Sjoerg
9487330f729Sjoerg SmallString<16> Str;
9497330f729Sjoerg if (isTargetWatchOSBased())
9507330f729Sjoerg Str += "watchos";
9517330f729Sjoerg else if (isTargetTvOSBased())
9527330f729Sjoerg Str += "tvos";
9537330f729Sjoerg else if (isTargetIOSBased())
9547330f729Sjoerg Str += "ios";
9557330f729Sjoerg else
9567330f729Sjoerg Str += "macosx";
9577330f729Sjoerg Str += getTargetVersion().getAsString();
9587330f729Sjoerg Triple.setOSName(Str);
9597330f729Sjoerg
9607330f729Sjoerg return Triple.getTriple();
9617330f729Sjoerg }
9627330f729Sjoerg
getTool(Action::ActionClass AC) const9637330f729Sjoerg Tool *MachO::getTool(Action::ActionClass AC) const {
9647330f729Sjoerg switch (AC) {
9657330f729Sjoerg case Action::LipoJobClass:
9667330f729Sjoerg if (!Lipo)
9677330f729Sjoerg Lipo.reset(new tools::darwin::Lipo(*this));
9687330f729Sjoerg return Lipo.get();
9697330f729Sjoerg case Action::DsymutilJobClass:
9707330f729Sjoerg if (!Dsymutil)
9717330f729Sjoerg Dsymutil.reset(new tools::darwin::Dsymutil(*this));
9727330f729Sjoerg return Dsymutil.get();
9737330f729Sjoerg case Action::VerifyDebugInfoJobClass:
9747330f729Sjoerg if (!VerifyDebug)
9757330f729Sjoerg VerifyDebug.reset(new tools::darwin::VerifyDebug(*this));
9767330f729Sjoerg return VerifyDebug.get();
9777330f729Sjoerg default:
9787330f729Sjoerg return ToolChain::getTool(AC);
9797330f729Sjoerg }
9807330f729Sjoerg }
9817330f729Sjoerg
buildLinker() const9827330f729Sjoerg Tool *MachO::buildLinker() const { return new tools::darwin::Linker(*this); }
9837330f729Sjoerg
buildAssembler() const9847330f729Sjoerg Tool *MachO::buildAssembler() const {
9857330f729Sjoerg return new tools::darwin::Assembler(*this);
9867330f729Sjoerg }
9877330f729Sjoerg
DarwinClang(const Driver & D,const llvm::Triple & Triple,const ArgList & Args)9887330f729Sjoerg DarwinClang::DarwinClang(const Driver &D, const llvm::Triple &Triple,
9897330f729Sjoerg const ArgList &Args)
9907330f729Sjoerg : Darwin(D, Triple, Args) {}
9917330f729Sjoerg
addClangWarningOptions(ArgStringList & CC1Args) const9927330f729Sjoerg void DarwinClang::addClangWarningOptions(ArgStringList &CC1Args) const {
993*e038c9c4Sjoerg // Always error about undefined 'TARGET_OS_*' macros.
994*e038c9c4Sjoerg CC1Args.push_back("-Wundef-prefix=TARGET_OS_");
995*e038c9c4Sjoerg CC1Args.push_back("-Werror=undef-prefix");
996*e038c9c4Sjoerg
9977330f729Sjoerg // For modern targets, promote certain warnings to errors.
9987330f729Sjoerg if (isTargetWatchOSBased() || getTriple().isArch64Bit()) {
9997330f729Sjoerg // Always enable -Wdeprecated-objc-isa-usage and promote it
10007330f729Sjoerg // to an error.
10017330f729Sjoerg CC1Args.push_back("-Wdeprecated-objc-isa-usage");
10027330f729Sjoerg CC1Args.push_back("-Werror=deprecated-objc-isa-usage");
10037330f729Sjoerg
10047330f729Sjoerg // For iOS and watchOS, also error about implicit function declarations,
10057330f729Sjoerg // as that can impact calling conventions.
10067330f729Sjoerg if (!isTargetMacOS())
10077330f729Sjoerg CC1Args.push_back("-Werror=implicit-function-declaration");
10087330f729Sjoerg }
10097330f729Sjoerg }
10107330f729Sjoerg
10117330f729Sjoerg /// Take a path that speculatively points into Xcode and return the
10127330f729Sjoerg /// `XCODE/Contents/Developer` path if it is an Xcode path, or an empty path
10137330f729Sjoerg /// otherwise.
getXcodeDeveloperPath(StringRef PathIntoXcode)10147330f729Sjoerg static StringRef getXcodeDeveloperPath(StringRef PathIntoXcode) {
10157330f729Sjoerg static constexpr llvm::StringLiteral XcodeAppSuffix(
10167330f729Sjoerg ".app/Contents/Developer");
10177330f729Sjoerg size_t Index = PathIntoXcode.find(XcodeAppSuffix);
10187330f729Sjoerg if (Index == StringRef::npos)
10197330f729Sjoerg return "";
10207330f729Sjoerg return PathIntoXcode.take_front(Index + XcodeAppSuffix.size());
10217330f729Sjoerg }
10227330f729Sjoerg
AddLinkARCArgs(const ArgList & Args,ArgStringList & CmdArgs) const10237330f729Sjoerg void DarwinClang::AddLinkARCArgs(const ArgList &Args,
10247330f729Sjoerg ArgStringList &CmdArgs) const {
10257330f729Sjoerg // Avoid linking compatibility stubs on i386 mac.
10267330f729Sjoerg if (isTargetMacOS() && getArch() == llvm::Triple::x86)
10277330f729Sjoerg return;
1028*e038c9c4Sjoerg if (isTargetAppleSiliconMac())
1029*e038c9c4Sjoerg return;
1030*e038c9c4Sjoerg // ARC runtime is supported everywhere on arm64e.
1031*e038c9c4Sjoerg if (getTriple().isArm64e())
1032*e038c9c4Sjoerg return;
10337330f729Sjoerg
10347330f729Sjoerg ObjCRuntime runtime = getDefaultObjCRuntime(/*nonfragile*/ true);
10357330f729Sjoerg
10367330f729Sjoerg if ((runtime.hasNativeARC() || !isObjCAutoRefCount(Args)) &&
10377330f729Sjoerg runtime.hasSubscripting())
10387330f729Sjoerg return;
10397330f729Sjoerg
10407330f729Sjoerg SmallString<128> P(getDriver().ClangExecutable);
10417330f729Sjoerg llvm::sys::path::remove_filename(P); // 'clang'
10427330f729Sjoerg llvm::sys::path::remove_filename(P); // 'bin'
10437330f729Sjoerg
10447330f729Sjoerg // 'libarclite' usually lives in the same toolchain as 'clang'. However, the
10457330f729Sjoerg // Swift open source toolchains for macOS distribute Clang without libarclite.
10467330f729Sjoerg // In that case, to allow the linker to find 'libarclite', we point to the
10477330f729Sjoerg // 'libarclite' in the XcodeDefault toolchain instead.
10487330f729Sjoerg if (getXcodeDeveloperPath(P).empty()) {
10497330f729Sjoerg if (const Arg *A = Args.getLastArg(options::OPT_isysroot)) {
10507330f729Sjoerg // Try to infer the path to 'libarclite' in the toolchain from the
10517330f729Sjoerg // specified SDK path.
10527330f729Sjoerg StringRef XcodePathForSDK = getXcodeDeveloperPath(A->getValue());
10537330f729Sjoerg if (!XcodePathForSDK.empty()) {
10547330f729Sjoerg P = XcodePathForSDK;
10557330f729Sjoerg llvm::sys::path::append(P, "Toolchains/XcodeDefault.xctoolchain/usr");
10567330f729Sjoerg }
10577330f729Sjoerg }
10587330f729Sjoerg }
10597330f729Sjoerg
10607330f729Sjoerg CmdArgs.push_back("-force_load");
10617330f729Sjoerg llvm::sys::path::append(P, "lib", "arc", "libarclite_");
10627330f729Sjoerg // Mash in the platform.
10637330f729Sjoerg if (isTargetWatchOSSimulator())
10647330f729Sjoerg P += "watchsimulator";
10657330f729Sjoerg else if (isTargetWatchOS())
10667330f729Sjoerg P += "watchos";
10677330f729Sjoerg else if (isTargetTvOSSimulator())
10687330f729Sjoerg P += "appletvsimulator";
10697330f729Sjoerg else if (isTargetTvOS())
10707330f729Sjoerg P += "appletvos";
10717330f729Sjoerg else if (isTargetIOSSimulator())
10727330f729Sjoerg P += "iphonesimulator";
10737330f729Sjoerg else if (isTargetIPhoneOS())
10747330f729Sjoerg P += "iphoneos";
10757330f729Sjoerg else
10767330f729Sjoerg P += "macosx";
10777330f729Sjoerg P += ".a";
10787330f729Sjoerg
10797330f729Sjoerg CmdArgs.push_back(Args.MakeArgString(P));
10807330f729Sjoerg }
10817330f729Sjoerg
GetDefaultDwarfVersion() const10827330f729Sjoerg unsigned DarwinClang::GetDefaultDwarfVersion() const {
10837330f729Sjoerg // Default to use DWARF 2 on OS X 10.10 / iOS 8 and lower.
10847330f729Sjoerg if ((isTargetMacOS() && isMacosxVersionLT(10, 11)) ||
10857330f729Sjoerg (isTargetIOSBased() && isIPhoneOSVersionLT(9)))
10867330f729Sjoerg return 2;
10877330f729Sjoerg return 4;
10887330f729Sjoerg }
10897330f729Sjoerg
AddLinkRuntimeLib(const ArgList & Args,ArgStringList & CmdArgs,StringRef Component,RuntimeLinkOptions Opts,bool IsShared) const10907330f729Sjoerg void MachO::AddLinkRuntimeLib(const ArgList &Args, ArgStringList &CmdArgs,
10917330f729Sjoerg StringRef Component, RuntimeLinkOptions Opts,
10927330f729Sjoerg bool IsShared) const {
10937330f729Sjoerg SmallString<64> DarwinLibName = StringRef("libclang_rt.");
10947330f729Sjoerg // an Darwin the builtins compomnent is not in the library name
10957330f729Sjoerg if (Component != "builtins") {
10967330f729Sjoerg DarwinLibName += Component;
10977330f729Sjoerg if (!(Opts & RLO_IsEmbedded))
10987330f729Sjoerg DarwinLibName += "_";
1099*e038c9c4Sjoerg }
11007330f729Sjoerg
1101*e038c9c4Sjoerg DarwinLibName += getOSLibraryNameSuffix();
11027330f729Sjoerg DarwinLibName += IsShared ? "_dynamic.dylib" : ".a";
11037330f729Sjoerg SmallString<128> Dir(getDriver().ResourceDir);
11047330f729Sjoerg llvm::sys::path::append(
11057330f729Sjoerg Dir, "lib", (Opts & RLO_IsEmbedded) ? "macho_embedded" : "darwin");
11067330f729Sjoerg
11077330f729Sjoerg SmallString<128> P(Dir);
11087330f729Sjoerg llvm::sys::path::append(P, DarwinLibName);
11097330f729Sjoerg
11107330f729Sjoerg // For now, allow missing resource libraries to support developers who may
11117330f729Sjoerg // not have compiler-rt checked out or integrated into their build (unless
11127330f729Sjoerg // we explicitly force linking with this library).
11137330f729Sjoerg if ((Opts & RLO_AlwaysLink) || getVFS().exists(P)) {
11147330f729Sjoerg const char *LibArg = Args.MakeArgString(P);
11157330f729Sjoerg if (Opts & RLO_FirstLink)
11167330f729Sjoerg CmdArgs.insert(CmdArgs.begin(), LibArg);
11177330f729Sjoerg else
11187330f729Sjoerg CmdArgs.push_back(LibArg);
11197330f729Sjoerg }
11207330f729Sjoerg
11217330f729Sjoerg // Adding the rpaths might negatively interact when other rpaths are involved,
11227330f729Sjoerg // so we should make sure we add the rpaths last, after all user-specified
11237330f729Sjoerg // rpaths. This is currently true from this place, but we need to be
11247330f729Sjoerg // careful if this function is ever called before user's rpaths are emitted.
11257330f729Sjoerg if (Opts & RLO_AddRPath) {
11267330f729Sjoerg assert(DarwinLibName.endswith(".dylib") && "must be a dynamic library");
11277330f729Sjoerg
11287330f729Sjoerg // Add @executable_path to rpath to support having the dylib copied with
11297330f729Sjoerg // the executable.
11307330f729Sjoerg CmdArgs.push_back("-rpath");
11317330f729Sjoerg CmdArgs.push_back("@executable_path");
11327330f729Sjoerg
11337330f729Sjoerg // Add the path to the resource dir to rpath to support using the dylib
11347330f729Sjoerg // from the default location without copying.
11357330f729Sjoerg CmdArgs.push_back("-rpath");
11367330f729Sjoerg CmdArgs.push_back(Args.MakeArgString(Dir));
11377330f729Sjoerg }
11387330f729Sjoerg }
11397330f729Sjoerg
getPlatformFamily() const11407330f729Sjoerg StringRef Darwin::getPlatformFamily() const {
11417330f729Sjoerg switch (TargetPlatform) {
11427330f729Sjoerg case DarwinPlatformKind::MacOS:
11437330f729Sjoerg return "MacOSX";
11447330f729Sjoerg case DarwinPlatformKind::IPhoneOS:
11457330f729Sjoerg return "iPhone";
11467330f729Sjoerg case DarwinPlatformKind::TvOS:
11477330f729Sjoerg return "AppleTV";
11487330f729Sjoerg case DarwinPlatformKind::WatchOS:
11497330f729Sjoerg return "Watch";
11507330f729Sjoerg }
11517330f729Sjoerg llvm_unreachable("Unsupported platform");
11527330f729Sjoerg }
11537330f729Sjoerg
getSDKName(StringRef isysroot)11547330f729Sjoerg StringRef Darwin::getSDKName(StringRef isysroot) {
11557330f729Sjoerg // Assume SDK has path: SOME_PATH/SDKs/PlatformXX.YY.sdk
1156*e038c9c4Sjoerg auto BeginSDK = llvm::sys::path::rbegin(isysroot);
1157*e038c9c4Sjoerg auto EndSDK = llvm::sys::path::rend(isysroot);
11587330f729Sjoerg for (auto IT = BeginSDK; IT != EndSDK; ++IT) {
11597330f729Sjoerg StringRef SDK = *IT;
11607330f729Sjoerg if (SDK.endswith(".sdk"))
11617330f729Sjoerg return SDK.slice(0, SDK.size() - 4);
11627330f729Sjoerg }
11637330f729Sjoerg return "";
11647330f729Sjoerg }
11657330f729Sjoerg
getOSLibraryNameSuffix(bool IgnoreSim) const11667330f729Sjoerg StringRef Darwin::getOSLibraryNameSuffix(bool IgnoreSim) const {
11677330f729Sjoerg switch (TargetPlatform) {
11687330f729Sjoerg case DarwinPlatformKind::MacOS:
11697330f729Sjoerg return "osx";
11707330f729Sjoerg case DarwinPlatformKind::IPhoneOS:
11717330f729Sjoerg return TargetEnvironment == NativeEnvironment || IgnoreSim ? "ios"
11727330f729Sjoerg : "iossim";
11737330f729Sjoerg case DarwinPlatformKind::TvOS:
11747330f729Sjoerg return TargetEnvironment == NativeEnvironment || IgnoreSim ? "tvos"
11757330f729Sjoerg : "tvossim";
11767330f729Sjoerg case DarwinPlatformKind::WatchOS:
11777330f729Sjoerg return TargetEnvironment == NativeEnvironment || IgnoreSim ? "watchos"
11787330f729Sjoerg : "watchossim";
11797330f729Sjoerg }
11807330f729Sjoerg llvm_unreachable("Unsupported platform");
11817330f729Sjoerg }
11827330f729Sjoerg
11837330f729Sjoerg /// Check if the link command contains a symbol export directive.
hasExportSymbolDirective(const ArgList & Args)11847330f729Sjoerg static bool hasExportSymbolDirective(const ArgList &Args) {
11857330f729Sjoerg for (Arg *A : Args) {
11867330f729Sjoerg if (A->getOption().matches(options::OPT_exported__symbols__list))
11877330f729Sjoerg return true;
11887330f729Sjoerg if (!A->getOption().matches(options::OPT_Wl_COMMA) &&
11897330f729Sjoerg !A->getOption().matches(options::OPT_Xlinker))
11907330f729Sjoerg continue;
11917330f729Sjoerg if (A->containsValue("-exported_symbols_list") ||
11927330f729Sjoerg A->containsValue("-exported_symbol"))
11937330f729Sjoerg return true;
11947330f729Sjoerg }
11957330f729Sjoerg return false;
11967330f729Sjoerg }
11977330f729Sjoerg
11987330f729Sjoerg /// Add an export directive for \p Symbol to the link command.
addExportedSymbol(ArgStringList & CmdArgs,const char * Symbol)11997330f729Sjoerg static void addExportedSymbol(ArgStringList &CmdArgs, const char *Symbol) {
12007330f729Sjoerg CmdArgs.push_back("-exported_symbol");
12017330f729Sjoerg CmdArgs.push_back(Symbol);
12027330f729Sjoerg }
12037330f729Sjoerg
1204*e038c9c4Sjoerg /// Add a sectalign directive for \p Segment and \p Section to the maximum
1205*e038c9c4Sjoerg /// expected page size for Darwin.
1206*e038c9c4Sjoerg ///
1207*e038c9c4Sjoerg /// On iPhone 6+ the max supported page size is 16K. On macOS, the max is 4K.
1208*e038c9c4Sjoerg /// Use a common alignment constant (16K) for now, and reduce the alignment on
1209*e038c9c4Sjoerg /// macOS if it proves important.
addSectalignToPage(const ArgList & Args,ArgStringList & CmdArgs,StringRef Segment,StringRef Section)1210*e038c9c4Sjoerg static void addSectalignToPage(const ArgList &Args, ArgStringList &CmdArgs,
1211*e038c9c4Sjoerg StringRef Segment, StringRef Section) {
1212*e038c9c4Sjoerg for (const char *A : {"-sectalign", Args.MakeArgString(Segment),
1213*e038c9c4Sjoerg Args.MakeArgString(Section), "0x4000"})
1214*e038c9c4Sjoerg CmdArgs.push_back(A);
1215*e038c9c4Sjoerg }
1216*e038c9c4Sjoerg
addProfileRTLibs(const ArgList & Args,ArgStringList & CmdArgs) const12177330f729Sjoerg void Darwin::addProfileRTLibs(const ArgList &Args,
12187330f729Sjoerg ArgStringList &CmdArgs) const {
1219*e038c9c4Sjoerg if (!needsProfileRT(Args) && !needsGCovInstrumentation(Args))
1220*e038c9c4Sjoerg return;
12217330f729Sjoerg
12227330f729Sjoerg AddLinkRuntimeLib(Args, CmdArgs, "profile",
12237330f729Sjoerg RuntimeLinkOptions(RLO_AlwaysLink | RLO_FirstLink));
12247330f729Sjoerg
1225*e038c9c4Sjoerg bool ForGCOV = needsGCovInstrumentation(Args);
1226*e038c9c4Sjoerg
12277330f729Sjoerg // If we have a symbol export directive and we're linking in the profile
12287330f729Sjoerg // runtime, automatically export symbols necessary to implement some of the
12297330f729Sjoerg // runtime's functionality.
12307330f729Sjoerg if (hasExportSymbolDirective(Args)) {
1231*e038c9c4Sjoerg if (ForGCOV) {
1232*e038c9c4Sjoerg addExportedSymbol(CmdArgs, "___gcov_dump");
1233*e038c9c4Sjoerg addExportedSymbol(CmdArgs, "___gcov_reset");
12347330f729Sjoerg addExportedSymbol(CmdArgs, "_writeout_fn_list");
1235*e038c9c4Sjoerg addExportedSymbol(CmdArgs, "_reset_fn_list");
12367330f729Sjoerg } else {
12377330f729Sjoerg addExportedSymbol(CmdArgs, "___llvm_profile_filename");
12387330f729Sjoerg addExportedSymbol(CmdArgs, "___llvm_profile_raw_version");
12397330f729Sjoerg }
12407330f729Sjoerg addExportedSymbol(CmdArgs, "_lprofDirMode");
12417330f729Sjoerg }
1242*e038c9c4Sjoerg
1243*e038c9c4Sjoerg // Align __llvm_prf_{cnts,data} sections to the maximum expected page
1244*e038c9c4Sjoerg // alignment. This allows profile counters to be mmap()'d to disk. Note that
1245*e038c9c4Sjoerg // it's not enough to just page-align __llvm_prf_cnts: the following section
1246*e038c9c4Sjoerg // must also be page-aligned so that its data is not clobbered by mmap().
1247*e038c9c4Sjoerg //
1248*e038c9c4Sjoerg // The section alignment is only needed when continuous profile sync is
1249*e038c9c4Sjoerg // enabled, but this is expected to be the default in Xcode. Specifying the
1250*e038c9c4Sjoerg // extra alignment also allows the same binary to be used with/without sync
1251*e038c9c4Sjoerg // enabled.
1252*e038c9c4Sjoerg if (!ForGCOV) {
1253*e038c9c4Sjoerg for (auto IPSK : {llvm::IPSK_cnts, llvm::IPSK_data}) {
1254*e038c9c4Sjoerg addSectalignToPage(
1255*e038c9c4Sjoerg Args, CmdArgs, "__DATA",
1256*e038c9c4Sjoerg llvm::getInstrProfSectionName(IPSK, llvm::Triple::MachO,
1257*e038c9c4Sjoerg /*AddSegmentInfo=*/false));
1258*e038c9c4Sjoerg }
1259*e038c9c4Sjoerg }
12607330f729Sjoerg }
12617330f729Sjoerg
AddLinkSanitizerLibArgs(const ArgList & Args,ArgStringList & CmdArgs,StringRef Sanitizer,bool Shared) const12627330f729Sjoerg void DarwinClang::AddLinkSanitizerLibArgs(const ArgList &Args,
12637330f729Sjoerg ArgStringList &CmdArgs,
12647330f729Sjoerg StringRef Sanitizer,
12657330f729Sjoerg bool Shared) const {
12667330f729Sjoerg auto RLO = RuntimeLinkOptions(RLO_AlwaysLink | (Shared ? RLO_AddRPath : 0U));
12677330f729Sjoerg AddLinkRuntimeLib(Args, CmdArgs, Sanitizer, RLO, Shared);
12687330f729Sjoerg }
12697330f729Sjoerg
GetRuntimeLibType(const ArgList & Args) const12707330f729Sjoerg ToolChain::RuntimeLibType DarwinClang::GetRuntimeLibType(
12717330f729Sjoerg const ArgList &Args) const {
12727330f729Sjoerg if (Arg* A = Args.getLastArg(options::OPT_rtlib_EQ)) {
12737330f729Sjoerg StringRef Value = A->getValue();
12747330f729Sjoerg if (Value != "compiler-rt")
12757330f729Sjoerg getDriver().Diag(clang::diag::err_drv_unsupported_rtlib_for_platform)
12767330f729Sjoerg << Value << "darwin";
12777330f729Sjoerg }
12787330f729Sjoerg
12797330f729Sjoerg return ToolChain::RLT_CompilerRT;
12807330f729Sjoerg }
12817330f729Sjoerg
AddLinkRuntimeLibArgs(const ArgList & Args,ArgStringList & CmdArgs,bool ForceLinkBuiltinRT) const12827330f729Sjoerg void DarwinClang::AddLinkRuntimeLibArgs(const ArgList &Args,
12837330f729Sjoerg ArgStringList &CmdArgs,
12847330f729Sjoerg bool ForceLinkBuiltinRT) const {
12857330f729Sjoerg // Call once to ensure diagnostic is printed if wrong value was specified
12867330f729Sjoerg GetRuntimeLibType(Args);
12877330f729Sjoerg
12887330f729Sjoerg // Darwin doesn't support real static executables, don't link any runtime
12897330f729Sjoerg // libraries with -static.
12907330f729Sjoerg if (Args.hasArg(options::OPT_static) ||
12917330f729Sjoerg Args.hasArg(options::OPT_fapple_kext) ||
12927330f729Sjoerg Args.hasArg(options::OPT_mkernel)) {
12937330f729Sjoerg if (ForceLinkBuiltinRT)
12947330f729Sjoerg AddLinkRuntimeLib(Args, CmdArgs, "builtins");
12957330f729Sjoerg return;
12967330f729Sjoerg }
12977330f729Sjoerg
12987330f729Sjoerg // Reject -static-libgcc for now, we can deal with this when and if someone
12997330f729Sjoerg // cares. This is useful in situations where someone wants to statically link
13007330f729Sjoerg // something like libstdc++, and needs its runtime support routines.
13017330f729Sjoerg if (const Arg *A = Args.getLastArg(options::OPT_static_libgcc)) {
13027330f729Sjoerg getDriver().Diag(diag::err_drv_unsupported_opt) << A->getAsString(Args);
13037330f729Sjoerg return;
13047330f729Sjoerg }
13057330f729Sjoerg
13067330f729Sjoerg const SanitizerArgs &Sanitize = getSanitizerArgs();
13077330f729Sjoerg if (Sanitize.needsAsanRt())
13087330f729Sjoerg AddLinkSanitizerLibArgs(Args, CmdArgs, "asan");
13097330f729Sjoerg if (Sanitize.needsLsanRt())
13107330f729Sjoerg AddLinkSanitizerLibArgs(Args, CmdArgs, "lsan");
13117330f729Sjoerg if (Sanitize.needsUbsanRt())
13127330f729Sjoerg AddLinkSanitizerLibArgs(Args, CmdArgs,
13137330f729Sjoerg Sanitize.requiresMinimalRuntime() ? "ubsan_minimal"
13147330f729Sjoerg : "ubsan",
13157330f729Sjoerg Sanitize.needsSharedRt());
13167330f729Sjoerg if (Sanitize.needsTsanRt())
13177330f729Sjoerg AddLinkSanitizerLibArgs(Args, CmdArgs, "tsan");
13187330f729Sjoerg if (Sanitize.needsFuzzer() && !Args.hasArg(options::OPT_dynamiclib)) {
13197330f729Sjoerg AddLinkSanitizerLibArgs(Args, CmdArgs, "fuzzer", /*shared=*/false);
13207330f729Sjoerg
13217330f729Sjoerg // Libfuzzer is written in C++ and requires libcxx.
13227330f729Sjoerg AddCXXStdlibLibArgs(Args, CmdArgs);
13237330f729Sjoerg }
13247330f729Sjoerg if (Sanitize.needsStatsRt()) {
13257330f729Sjoerg AddLinkRuntimeLib(Args, CmdArgs, "stats_client", RLO_AlwaysLink);
13267330f729Sjoerg AddLinkSanitizerLibArgs(Args, CmdArgs, "stats");
13277330f729Sjoerg }
13287330f729Sjoerg
13297330f729Sjoerg const XRayArgs &XRay = getXRayArgs();
13307330f729Sjoerg if (XRay.needsXRayRt()) {
13317330f729Sjoerg AddLinkRuntimeLib(Args, CmdArgs, "xray");
13327330f729Sjoerg AddLinkRuntimeLib(Args, CmdArgs, "xray-basic");
13337330f729Sjoerg AddLinkRuntimeLib(Args, CmdArgs, "xray-fdr");
13347330f729Sjoerg }
13357330f729Sjoerg
13367330f729Sjoerg // Otherwise link libSystem, then the dynamic runtime library, and finally any
13377330f729Sjoerg // target specific static runtime library.
13387330f729Sjoerg CmdArgs.push_back("-lSystem");
13397330f729Sjoerg
13407330f729Sjoerg // Select the dynamic runtime library and the target specific static library.
13417330f729Sjoerg if (isTargetIOSBased()) {
13427330f729Sjoerg // If we are compiling as iOS / simulator, don't attempt to link libgcc_s.1,
13437330f729Sjoerg // it never went into the SDK.
13447330f729Sjoerg // Linking against libgcc_s.1 isn't needed for iOS 5.0+
13457330f729Sjoerg if (isIPhoneOSVersionLT(5, 0) && !isTargetIOSSimulator() &&
13467330f729Sjoerg getTriple().getArch() != llvm::Triple::aarch64)
13477330f729Sjoerg CmdArgs.push_back("-lgcc_s.1");
13487330f729Sjoerg }
13497330f729Sjoerg AddLinkRuntimeLib(Args, CmdArgs, "builtins");
13507330f729Sjoerg }
13517330f729Sjoerg
13527330f729Sjoerg /// Returns the most appropriate macOS target version for the current process.
13537330f729Sjoerg ///
13547330f729Sjoerg /// If the macOS SDK version is the same or earlier than the system version,
13557330f729Sjoerg /// then the SDK version is returned. Otherwise the system version is returned.
getSystemOrSDKMacOSVersion(StringRef MacOSSDKVersion)13567330f729Sjoerg static std::string getSystemOrSDKMacOSVersion(StringRef MacOSSDKVersion) {
13577330f729Sjoerg unsigned Major, Minor, Micro;
13587330f729Sjoerg llvm::Triple SystemTriple(llvm::sys::getProcessTriple());
13597330f729Sjoerg if (!SystemTriple.isMacOSX())
1360*e038c9c4Sjoerg return std::string(MacOSSDKVersion);
13617330f729Sjoerg SystemTriple.getMacOSXVersion(Major, Minor, Micro);
13627330f729Sjoerg VersionTuple SystemVersion(Major, Minor, Micro);
13637330f729Sjoerg bool HadExtra;
13647330f729Sjoerg if (!Driver::GetReleaseVersion(MacOSSDKVersion, Major, Minor, Micro,
13657330f729Sjoerg HadExtra))
1366*e038c9c4Sjoerg return std::string(MacOSSDKVersion);
13677330f729Sjoerg VersionTuple SDKVersion(Major, Minor, Micro);
13687330f729Sjoerg if (SDKVersion > SystemVersion)
13697330f729Sjoerg return SystemVersion.getAsString();
1370*e038c9c4Sjoerg return std::string(MacOSSDKVersion);
13717330f729Sjoerg }
13727330f729Sjoerg
13737330f729Sjoerg namespace {
13747330f729Sjoerg
13757330f729Sjoerg /// The Darwin OS that was selected or inferred from arguments / environment.
13767330f729Sjoerg struct DarwinPlatform {
13777330f729Sjoerg enum SourceKind {
13787330f729Sjoerg /// The OS was specified using the -target argument.
13797330f729Sjoerg TargetArg,
13807330f729Sjoerg /// The OS was specified using the -m<os>-version-min argument.
13817330f729Sjoerg OSVersionArg,
13827330f729Sjoerg /// The OS was specified using the OS_DEPLOYMENT_TARGET environment.
13837330f729Sjoerg DeploymentTargetEnv,
13847330f729Sjoerg /// The OS was inferred from the SDK.
13857330f729Sjoerg InferredFromSDK,
13867330f729Sjoerg /// The OS was inferred from the -arch.
13877330f729Sjoerg InferredFromArch
13887330f729Sjoerg };
13897330f729Sjoerg
13907330f729Sjoerg using DarwinPlatformKind = Darwin::DarwinPlatformKind;
13917330f729Sjoerg using DarwinEnvironmentKind = Darwin::DarwinEnvironmentKind;
13927330f729Sjoerg
getPlatform__anonbbcfd8880111::DarwinPlatform13937330f729Sjoerg DarwinPlatformKind getPlatform() const { return Platform; }
13947330f729Sjoerg
getEnvironment__anonbbcfd8880111::DarwinPlatform13957330f729Sjoerg DarwinEnvironmentKind getEnvironment() const { return Environment; }
13967330f729Sjoerg
setEnvironment__anonbbcfd8880111::DarwinPlatform13977330f729Sjoerg void setEnvironment(DarwinEnvironmentKind Kind) {
13987330f729Sjoerg Environment = Kind;
13997330f729Sjoerg InferSimulatorFromArch = false;
14007330f729Sjoerg }
14017330f729Sjoerg
getOSVersion__anonbbcfd8880111::DarwinPlatform14027330f729Sjoerg StringRef getOSVersion() const {
14037330f729Sjoerg if (Kind == OSVersionArg)
14047330f729Sjoerg return Argument->getValue();
14057330f729Sjoerg return OSVersion;
14067330f729Sjoerg }
14077330f729Sjoerg
setOSVersion__anonbbcfd8880111::DarwinPlatform14087330f729Sjoerg void setOSVersion(StringRef S) {
14097330f729Sjoerg assert(Kind == TargetArg && "Unexpected kind!");
1410*e038c9c4Sjoerg OSVersion = std::string(S);
14117330f729Sjoerg }
14127330f729Sjoerg
hasOSVersion__anonbbcfd8880111::DarwinPlatform14137330f729Sjoerg bool hasOSVersion() const { return HasOSVersion; }
14147330f729Sjoerg
14157330f729Sjoerg /// Returns true if the target OS was explicitly specified.
isExplicitlySpecified__anonbbcfd8880111::DarwinPlatform14167330f729Sjoerg bool isExplicitlySpecified() const { return Kind <= DeploymentTargetEnv; }
14177330f729Sjoerg
14187330f729Sjoerg /// Returns true if the simulator environment can be inferred from the arch.
canInferSimulatorFromArch__anonbbcfd8880111::DarwinPlatform14197330f729Sjoerg bool canInferSimulatorFromArch() const { return InferSimulatorFromArch; }
14207330f729Sjoerg
14217330f729Sjoerg /// Adds the -m<os>-version-min argument to the compiler invocation.
addOSVersionMinArgument__anonbbcfd8880111::DarwinPlatform14227330f729Sjoerg void addOSVersionMinArgument(DerivedArgList &Args, const OptTable &Opts) {
14237330f729Sjoerg if (Argument)
14247330f729Sjoerg return;
14257330f729Sjoerg assert(Kind != TargetArg && Kind != OSVersionArg && "Invalid kind");
14267330f729Sjoerg options::ID Opt;
14277330f729Sjoerg switch (Platform) {
14287330f729Sjoerg case DarwinPlatformKind::MacOS:
14297330f729Sjoerg Opt = options::OPT_mmacosx_version_min_EQ;
14307330f729Sjoerg break;
14317330f729Sjoerg case DarwinPlatformKind::IPhoneOS:
14327330f729Sjoerg Opt = options::OPT_miphoneos_version_min_EQ;
14337330f729Sjoerg break;
14347330f729Sjoerg case DarwinPlatformKind::TvOS:
14357330f729Sjoerg Opt = options::OPT_mtvos_version_min_EQ;
14367330f729Sjoerg break;
14377330f729Sjoerg case DarwinPlatformKind::WatchOS:
14387330f729Sjoerg Opt = options::OPT_mwatchos_version_min_EQ;
14397330f729Sjoerg break;
14407330f729Sjoerg }
14417330f729Sjoerg Argument = Args.MakeJoinedArg(nullptr, Opts.getOption(Opt), OSVersion);
14427330f729Sjoerg Args.append(Argument);
14437330f729Sjoerg }
14447330f729Sjoerg
14457330f729Sjoerg /// Returns the OS version with the argument / environment variable that
14467330f729Sjoerg /// specified it.
getAsString__anonbbcfd8880111::DarwinPlatform14477330f729Sjoerg std::string getAsString(DerivedArgList &Args, const OptTable &Opts) {
14487330f729Sjoerg switch (Kind) {
14497330f729Sjoerg case TargetArg:
14507330f729Sjoerg case OSVersionArg:
14517330f729Sjoerg case InferredFromSDK:
14527330f729Sjoerg case InferredFromArch:
14537330f729Sjoerg assert(Argument && "OS version argument not yet inferred");
14547330f729Sjoerg return Argument->getAsString(Args);
14557330f729Sjoerg case DeploymentTargetEnv:
14567330f729Sjoerg return (llvm::Twine(EnvVarName) + "=" + OSVersion).str();
14577330f729Sjoerg }
14587330f729Sjoerg llvm_unreachable("Unsupported Darwin Source Kind");
14597330f729Sjoerg }
14607330f729Sjoerg
createFromTarget__anonbbcfd8880111::DarwinPlatform14617330f729Sjoerg static DarwinPlatform createFromTarget(const llvm::Triple &TT,
14627330f729Sjoerg StringRef OSVersion, Arg *A) {
14637330f729Sjoerg DarwinPlatform Result(TargetArg, getPlatformFromOS(TT.getOS()), OSVersion,
14647330f729Sjoerg A);
14657330f729Sjoerg switch (TT.getEnvironment()) {
14667330f729Sjoerg case llvm::Triple::Simulator:
14677330f729Sjoerg Result.Environment = DarwinEnvironmentKind::Simulator;
14687330f729Sjoerg break;
14697330f729Sjoerg default:
14707330f729Sjoerg break;
14717330f729Sjoerg }
14727330f729Sjoerg unsigned Major, Minor, Micro;
14737330f729Sjoerg TT.getOSVersion(Major, Minor, Micro);
14747330f729Sjoerg if (Major == 0)
14757330f729Sjoerg Result.HasOSVersion = false;
14767330f729Sjoerg return Result;
14777330f729Sjoerg }
createOSVersionArg__anonbbcfd8880111::DarwinPlatform14787330f729Sjoerg static DarwinPlatform createOSVersionArg(DarwinPlatformKind Platform,
14797330f729Sjoerg Arg *A) {
14807330f729Sjoerg return DarwinPlatform(OSVersionArg, Platform, A);
14817330f729Sjoerg }
createDeploymentTargetEnv__anonbbcfd8880111::DarwinPlatform14827330f729Sjoerg static DarwinPlatform createDeploymentTargetEnv(DarwinPlatformKind Platform,
14837330f729Sjoerg StringRef EnvVarName,
14847330f729Sjoerg StringRef Value) {
14857330f729Sjoerg DarwinPlatform Result(DeploymentTargetEnv, Platform, Value);
14867330f729Sjoerg Result.EnvVarName = EnvVarName;
14877330f729Sjoerg return Result;
14887330f729Sjoerg }
createFromSDK__anonbbcfd8880111::DarwinPlatform14897330f729Sjoerg static DarwinPlatform createFromSDK(DarwinPlatformKind Platform,
14907330f729Sjoerg StringRef Value,
14917330f729Sjoerg bool IsSimulator = false) {
14927330f729Sjoerg DarwinPlatform Result(InferredFromSDK, Platform, Value);
14937330f729Sjoerg if (IsSimulator)
14947330f729Sjoerg Result.Environment = DarwinEnvironmentKind::Simulator;
14957330f729Sjoerg Result.InferSimulatorFromArch = false;
14967330f729Sjoerg return Result;
14977330f729Sjoerg }
createFromArch__anonbbcfd8880111::DarwinPlatform14987330f729Sjoerg static DarwinPlatform createFromArch(llvm::Triple::OSType OS,
14997330f729Sjoerg StringRef Value) {
15007330f729Sjoerg return DarwinPlatform(InferredFromArch, getPlatformFromOS(OS), Value);
15017330f729Sjoerg }
15027330f729Sjoerg
15037330f729Sjoerg /// Constructs an inferred SDKInfo value based on the version inferred from
15047330f729Sjoerg /// the SDK path itself. Only works for values that were created by inferring
15057330f729Sjoerg /// the platform from the SDKPath.
inferSDKInfo__anonbbcfd8880111::DarwinPlatform15067330f729Sjoerg DarwinSDKInfo inferSDKInfo() {
15077330f729Sjoerg assert(Kind == InferredFromSDK && "can infer SDK info only");
15087330f729Sjoerg llvm::VersionTuple Version;
15097330f729Sjoerg bool IsValid = !Version.tryParse(OSVersion);
15107330f729Sjoerg (void)IsValid;
15117330f729Sjoerg assert(IsValid && "invalid SDK version");
15127330f729Sjoerg return DarwinSDKInfo(Version);
15137330f729Sjoerg }
15147330f729Sjoerg
15157330f729Sjoerg private:
DarwinPlatform__anonbbcfd8880111::DarwinPlatform15167330f729Sjoerg DarwinPlatform(SourceKind Kind, DarwinPlatformKind Platform, Arg *Argument)
15177330f729Sjoerg : Kind(Kind), Platform(Platform), Argument(Argument) {}
DarwinPlatform__anonbbcfd8880111::DarwinPlatform15187330f729Sjoerg DarwinPlatform(SourceKind Kind, DarwinPlatformKind Platform, StringRef Value,
15197330f729Sjoerg Arg *Argument = nullptr)
15207330f729Sjoerg : Kind(Kind), Platform(Platform), OSVersion(Value), Argument(Argument) {}
15217330f729Sjoerg
getPlatformFromOS__anonbbcfd8880111::DarwinPlatform15227330f729Sjoerg static DarwinPlatformKind getPlatformFromOS(llvm::Triple::OSType OS) {
15237330f729Sjoerg switch (OS) {
15247330f729Sjoerg case llvm::Triple::Darwin:
15257330f729Sjoerg case llvm::Triple::MacOSX:
15267330f729Sjoerg return DarwinPlatformKind::MacOS;
15277330f729Sjoerg case llvm::Triple::IOS:
15287330f729Sjoerg return DarwinPlatformKind::IPhoneOS;
15297330f729Sjoerg case llvm::Triple::TvOS:
15307330f729Sjoerg return DarwinPlatformKind::TvOS;
15317330f729Sjoerg case llvm::Triple::WatchOS:
15327330f729Sjoerg return DarwinPlatformKind::WatchOS;
15337330f729Sjoerg default:
15347330f729Sjoerg llvm_unreachable("Unable to infer Darwin variant");
15357330f729Sjoerg }
15367330f729Sjoerg }
15377330f729Sjoerg
15387330f729Sjoerg SourceKind Kind;
15397330f729Sjoerg DarwinPlatformKind Platform;
15407330f729Sjoerg DarwinEnvironmentKind Environment = DarwinEnvironmentKind::NativeEnvironment;
15417330f729Sjoerg std::string OSVersion;
15427330f729Sjoerg bool HasOSVersion = true, InferSimulatorFromArch = true;
15437330f729Sjoerg Arg *Argument;
15447330f729Sjoerg StringRef EnvVarName;
15457330f729Sjoerg };
15467330f729Sjoerg
15477330f729Sjoerg /// Returns the deployment target that's specified using the -m<os>-version-min
15487330f729Sjoerg /// argument.
15497330f729Sjoerg Optional<DarwinPlatform>
getDeploymentTargetFromOSVersionArg(DerivedArgList & Args,const Driver & TheDriver)15507330f729Sjoerg getDeploymentTargetFromOSVersionArg(DerivedArgList &Args,
15517330f729Sjoerg const Driver &TheDriver) {
15527330f729Sjoerg Arg *OSXVersion = Args.getLastArg(options::OPT_mmacosx_version_min_EQ);
15537330f729Sjoerg Arg *iOSVersion = Args.getLastArg(options::OPT_miphoneos_version_min_EQ,
15547330f729Sjoerg options::OPT_mios_simulator_version_min_EQ);
15557330f729Sjoerg Arg *TvOSVersion =
15567330f729Sjoerg Args.getLastArg(options::OPT_mtvos_version_min_EQ,
15577330f729Sjoerg options::OPT_mtvos_simulator_version_min_EQ);
15587330f729Sjoerg Arg *WatchOSVersion =
15597330f729Sjoerg Args.getLastArg(options::OPT_mwatchos_version_min_EQ,
15607330f729Sjoerg options::OPT_mwatchos_simulator_version_min_EQ);
15617330f729Sjoerg if (OSXVersion) {
15627330f729Sjoerg if (iOSVersion || TvOSVersion || WatchOSVersion) {
15637330f729Sjoerg TheDriver.Diag(diag::err_drv_argument_not_allowed_with)
15647330f729Sjoerg << OSXVersion->getAsString(Args)
15657330f729Sjoerg << (iOSVersion ? iOSVersion
15667330f729Sjoerg : TvOSVersion ? TvOSVersion : WatchOSVersion)
15677330f729Sjoerg ->getAsString(Args);
15687330f729Sjoerg }
15697330f729Sjoerg return DarwinPlatform::createOSVersionArg(Darwin::MacOS, OSXVersion);
15707330f729Sjoerg } else if (iOSVersion) {
15717330f729Sjoerg if (TvOSVersion || WatchOSVersion) {
15727330f729Sjoerg TheDriver.Diag(diag::err_drv_argument_not_allowed_with)
15737330f729Sjoerg << iOSVersion->getAsString(Args)
15747330f729Sjoerg << (TvOSVersion ? TvOSVersion : WatchOSVersion)->getAsString(Args);
15757330f729Sjoerg }
15767330f729Sjoerg return DarwinPlatform::createOSVersionArg(Darwin::IPhoneOS, iOSVersion);
15777330f729Sjoerg } else if (TvOSVersion) {
15787330f729Sjoerg if (WatchOSVersion) {
15797330f729Sjoerg TheDriver.Diag(diag::err_drv_argument_not_allowed_with)
15807330f729Sjoerg << TvOSVersion->getAsString(Args)
15817330f729Sjoerg << WatchOSVersion->getAsString(Args);
15827330f729Sjoerg }
15837330f729Sjoerg return DarwinPlatform::createOSVersionArg(Darwin::TvOS, TvOSVersion);
15847330f729Sjoerg } else if (WatchOSVersion)
15857330f729Sjoerg return DarwinPlatform::createOSVersionArg(Darwin::WatchOS, WatchOSVersion);
15867330f729Sjoerg return None;
15877330f729Sjoerg }
15887330f729Sjoerg
15897330f729Sjoerg /// Returns the deployment target that's specified using the
15907330f729Sjoerg /// OS_DEPLOYMENT_TARGET environment variable.
15917330f729Sjoerg Optional<DarwinPlatform>
getDeploymentTargetFromEnvironmentVariables(const Driver & TheDriver,const llvm::Triple & Triple)15927330f729Sjoerg getDeploymentTargetFromEnvironmentVariables(const Driver &TheDriver,
15937330f729Sjoerg const llvm::Triple &Triple) {
15947330f729Sjoerg std::string Targets[Darwin::LastDarwinPlatform + 1];
15957330f729Sjoerg const char *EnvVars[] = {
15967330f729Sjoerg "MACOSX_DEPLOYMENT_TARGET",
15977330f729Sjoerg "IPHONEOS_DEPLOYMENT_TARGET",
15987330f729Sjoerg "TVOS_DEPLOYMENT_TARGET",
15997330f729Sjoerg "WATCHOS_DEPLOYMENT_TARGET",
16007330f729Sjoerg };
16017330f729Sjoerg static_assert(llvm::array_lengthof(EnvVars) == Darwin::LastDarwinPlatform + 1,
16027330f729Sjoerg "Missing platform");
16037330f729Sjoerg for (const auto &I : llvm::enumerate(llvm::makeArrayRef(EnvVars))) {
16047330f729Sjoerg if (char *Env = ::getenv(I.value()))
16057330f729Sjoerg Targets[I.index()] = Env;
16067330f729Sjoerg }
16077330f729Sjoerg
16087330f729Sjoerg // Allow conflicts among OSX and iOS for historical reasons, but choose the
16097330f729Sjoerg // default platform.
16107330f729Sjoerg if (!Targets[Darwin::MacOS].empty() &&
16117330f729Sjoerg (!Targets[Darwin::IPhoneOS].empty() ||
16127330f729Sjoerg !Targets[Darwin::WatchOS].empty() || !Targets[Darwin::TvOS].empty())) {
16137330f729Sjoerg if (Triple.getArch() == llvm::Triple::arm ||
16147330f729Sjoerg Triple.getArch() == llvm::Triple::aarch64 ||
16157330f729Sjoerg Triple.getArch() == llvm::Triple::thumb)
16167330f729Sjoerg Targets[Darwin::MacOS] = "";
16177330f729Sjoerg else
16187330f729Sjoerg Targets[Darwin::IPhoneOS] = Targets[Darwin::WatchOS] =
16197330f729Sjoerg Targets[Darwin::TvOS] = "";
16207330f729Sjoerg } else {
16217330f729Sjoerg // Don't allow conflicts in any other platform.
1622*e038c9c4Sjoerg unsigned FirstTarget = llvm::array_lengthof(Targets);
1623*e038c9c4Sjoerg for (unsigned I = 0; I != llvm::array_lengthof(Targets); ++I) {
16247330f729Sjoerg if (Targets[I].empty())
16257330f729Sjoerg continue;
16267330f729Sjoerg if (FirstTarget == llvm::array_lengthof(Targets))
16277330f729Sjoerg FirstTarget = I;
16287330f729Sjoerg else
16297330f729Sjoerg TheDriver.Diag(diag::err_drv_conflicting_deployment_targets)
16307330f729Sjoerg << Targets[FirstTarget] << Targets[I];
16317330f729Sjoerg }
16327330f729Sjoerg }
16337330f729Sjoerg
16347330f729Sjoerg for (const auto &Target : llvm::enumerate(llvm::makeArrayRef(Targets))) {
16357330f729Sjoerg if (!Target.value().empty())
16367330f729Sjoerg return DarwinPlatform::createDeploymentTargetEnv(
16377330f729Sjoerg (Darwin::DarwinPlatformKind)Target.index(), EnvVars[Target.index()],
16387330f729Sjoerg Target.value());
16397330f729Sjoerg }
16407330f729Sjoerg return None;
16417330f729Sjoerg }
16427330f729Sjoerg
1643*e038c9c4Sjoerg /// Returns the SDK name without the optional prefix that ends with a '.' or an
1644*e038c9c4Sjoerg /// empty string otherwise.
dropSDKNamePrefix(StringRef SDKName)1645*e038c9c4Sjoerg static StringRef dropSDKNamePrefix(StringRef SDKName) {
1646*e038c9c4Sjoerg size_t PrefixPos = SDKName.find('.');
1647*e038c9c4Sjoerg if (PrefixPos == StringRef::npos)
1648*e038c9c4Sjoerg return "";
1649*e038c9c4Sjoerg return SDKName.substr(PrefixPos + 1);
1650*e038c9c4Sjoerg }
1651*e038c9c4Sjoerg
16527330f729Sjoerg /// Tries to infer the deployment target from the SDK specified by -isysroot
16537330f729Sjoerg /// (or SDKROOT). Uses the version specified in the SDKSettings.json file if
16547330f729Sjoerg /// it's available.
16557330f729Sjoerg Optional<DarwinPlatform>
inferDeploymentTargetFromSDK(DerivedArgList & Args,const Optional<DarwinSDKInfo> & SDKInfo)16567330f729Sjoerg inferDeploymentTargetFromSDK(DerivedArgList &Args,
16577330f729Sjoerg const Optional<DarwinSDKInfo> &SDKInfo) {
16587330f729Sjoerg const Arg *A = Args.getLastArg(options::OPT_isysroot);
16597330f729Sjoerg if (!A)
16607330f729Sjoerg return None;
16617330f729Sjoerg StringRef isysroot = A->getValue();
16627330f729Sjoerg StringRef SDK = Darwin::getSDKName(isysroot);
16637330f729Sjoerg if (!SDK.size())
16647330f729Sjoerg return None;
16657330f729Sjoerg
16667330f729Sjoerg std::string Version;
16677330f729Sjoerg if (SDKInfo) {
16687330f729Sjoerg // Get the version from the SDKSettings.json if it's available.
16697330f729Sjoerg Version = SDKInfo->getVersion().getAsString();
16707330f729Sjoerg } else {
16717330f729Sjoerg // Slice the version number out.
16727330f729Sjoerg // Version number is between the first and the last number.
16737330f729Sjoerg size_t StartVer = SDK.find_first_of("0123456789");
16747330f729Sjoerg size_t EndVer = SDK.find_last_of("0123456789");
16757330f729Sjoerg if (StartVer != StringRef::npos && EndVer > StartVer)
1676*e038c9c4Sjoerg Version = std::string(SDK.slice(StartVer, EndVer + 1));
16777330f729Sjoerg }
16787330f729Sjoerg if (Version.empty())
16797330f729Sjoerg return None;
16807330f729Sjoerg
1681*e038c9c4Sjoerg auto CreatePlatformFromSDKName =
1682*e038c9c4Sjoerg [&](StringRef SDK) -> Optional<DarwinPlatform> {
16837330f729Sjoerg if (SDK.startswith("iPhoneOS") || SDK.startswith("iPhoneSimulator"))
16847330f729Sjoerg return DarwinPlatform::createFromSDK(
16857330f729Sjoerg Darwin::IPhoneOS, Version,
16867330f729Sjoerg /*IsSimulator=*/SDK.startswith("iPhoneSimulator"));
16877330f729Sjoerg else if (SDK.startswith("MacOSX"))
16887330f729Sjoerg return DarwinPlatform::createFromSDK(Darwin::MacOS,
16897330f729Sjoerg getSystemOrSDKMacOSVersion(Version));
16907330f729Sjoerg else if (SDK.startswith("WatchOS") || SDK.startswith("WatchSimulator"))
16917330f729Sjoerg return DarwinPlatform::createFromSDK(
16927330f729Sjoerg Darwin::WatchOS, Version,
16937330f729Sjoerg /*IsSimulator=*/SDK.startswith("WatchSimulator"));
16947330f729Sjoerg else if (SDK.startswith("AppleTVOS") || SDK.startswith("AppleTVSimulator"))
16957330f729Sjoerg return DarwinPlatform::createFromSDK(
16967330f729Sjoerg Darwin::TvOS, Version,
16977330f729Sjoerg /*IsSimulator=*/SDK.startswith("AppleTVSimulator"));
16987330f729Sjoerg return None;
1699*e038c9c4Sjoerg };
1700*e038c9c4Sjoerg if (auto Result = CreatePlatformFromSDKName(SDK))
1701*e038c9c4Sjoerg return Result;
1702*e038c9c4Sjoerg // The SDK can be an SDK variant with a name like `<prefix>.<platform>`.
1703*e038c9c4Sjoerg return CreatePlatformFromSDKName(dropSDKNamePrefix(SDK));
17047330f729Sjoerg }
17057330f729Sjoerg
getOSVersion(llvm::Triple::OSType OS,const llvm::Triple & Triple,const Driver & TheDriver)17067330f729Sjoerg std::string getOSVersion(llvm::Triple::OSType OS, const llvm::Triple &Triple,
17077330f729Sjoerg const Driver &TheDriver) {
17087330f729Sjoerg unsigned Major, Minor, Micro;
17097330f729Sjoerg llvm::Triple SystemTriple(llvm::sys::getProcessTriple());
17107330f729Sjoerg switch (OS) {
17117330f729Sjoerg case llvm::Triple::Darwin:
17127330f729Sjoerg case llvm::Triple::MacOSX:
17137330f729Sjoerg // If there is no version specified on triple, and both host and target are
17147330f729Sjoerg // macos, use the host triple to infer OS version.
17157330f729Sjoerg if (Triple.isMacOSX() && SystemTriple.isMacOSX() &&
17167330f729Sjoerg !Triple.getOSMajorVersion())
17177330f729Sjoerg SystemTriple.getMacOSXVersion(Major, Minor, Micro);
17187330f729Sjoerg else if (!Triple.getMacOSXVersion(Major, Minor, Micro))
17197330f729Sjoerg TheDriver.Diag(diag::err_drv_invalid_darwin_version)
17207330f729Sjoerg << Triple.getOSName();
17217330f729Sjoerg break;
17227330f729Sjoerg case llvm::Triple::IOS:
17237330f729Sjoerg Triple.getiOSVersion(Major, Minor, Micro);
17247330f729Sjoerg break;
17257330f729Sjoerg case llvm::Triple::TvOS:
17267330f729Sjoerg Triple.getOSVersion(Major, Minor, Micro);
17277330f729Sjoerg break;
17287330f729Sjoerg case llvm::Triple::WatchOS:
17297330f729Sjoerg Triple.getWatchOSVersion(Major, Minor, Micro);
17307330f729Sjoerg break;
17317330f729Sjoerg default:
17327330f729Sjoerg llvm_unreachable("Unexpected OS type");
17337330f729Sjoerg break;
17347330f729Sjoerg }
17357330f729Sjoerg
17367330f729Sjoerg std::string OSVersion;
17377330f729Sjoerg llvm::raw_string_ostream(OSVersion) << Major << '.' << Minor << '.' << Micro;
17387330f729Sjoerg return OSVersion;
17397330f729Sjoerg }
17407330f729Sjoerg
17417330f729Sjoerg /// Tries to infer the target OS from the -arch.
17427330f729Sjoerg Optional<DarwinPlatform>
inferDeploymentTargetFromArch(DerivedArgList & Args,const Darwin & Toolchain,const llvm::Triple & Triple,const Driver & TheDriver)17437330f729Sjoerg inferDeploymentTargetFromArch(DerivedArgList &Args, const Darwin &Toolchain,
17447330f729Sjoerg const llvm::Triple &Triple,
17457330f729Sjoerg const Driver &TheDriver) {
17467330f729Sjoerg llvm::Triple::OSType OSTy = llvm::Triple::UnknownOS;
17477330f729Sjoerg
17487330f729Sjoerg StringRef MachOArchName = Toolchain.getMachOArchName(Args);
1749*e038c9c4Sjoerg if (MachOArchName == "arm64" || MachOArchName == "arm64e") {
1750*e038c9c4Sjoerg #if __arm64__
1751*e038c9c4Sjoerg // A clang running on an Apple Silicon mac defaults
1752*e038c9c4Sjoerg // to building for mac when building for arm64 rather than
1753*e038c9c4Sjoerg // defaulting to iOS.
1754*e038c9c4Sjoerg OSTy = llvm::Triple::MacOSX;
1755*e038c9c4Sjoerg #else
17567330f729Sjoerg OSTy = llvm::Triple::IOS;
1757*e038c9c4Sjoerg #endif
1758*e038c9c4Sjoerg } else if (MachOArchName == "armv7" || MachOArchName == "armv7s")
1759*e038c9c4Sjoerg OSTy = llvm::Triple::IOS;
1760*e038c9c4Sjoerg else if (MachOArchName == "armv7k" || MachOArchName == "arm64_32")
17617330f729Sjoerg OSTy = llvm::Triple::WatchOS;
17627330f729Sjoerg else if (MachOArchName != "armv6m" && MachOArchName != "armv7m" &&
17637330f729Sjoerg MachOArchName != "armv7em")
17647330f729Sjoerg OSTy = llvm::Triple::MacOSX;
17657330f729Sjoerg
17667330f729Sjoerg if (OSTy == llvm::Triple::UnknownOS)
17677330f729Sjoerg return None;
17687330f729Sjoerg return DarwinPlatform::createFromArch(OSTy,
17697330f729Sjoerg getOSVersion(OSTy, Triple, TheDriver));
17707330f729Sjoerg }
17717330f729Sjoerg
17727330f729Sjoerg /// Returns the deployment target that's specified using the -target option.
getDeploymentTargetFromTargetArg(DerivedArgList & Args,const llvm::Triple & Triple,const Driver & TheDriver)17737330f729Sjoerg Optional<DarwinPlatform> getDeploymentTargetFromTargetArg(
17747330f729Sjoerg DerivedArgList &Args, const llvm::Triple &Triple, const Driver &TheDriver) {
17757330f729Sjoerg if (!Args.hasArg(options::OPT_target))
17767330f729Sjoerg return None;
17777330f729Sjoerg if (Triple.getOS() == llvm::Triple::Darwin ||
17787330f729Sjoerg Triple.getOS() == llvm::Triple::UnknownOS)
17797330f729Sjoerg return None;
17807330f729Sjoerg std::string OSVersion = getOSVersion(Triple.getOS(), Triple, TheDriver);
17817330f729Sjoerg return DarwinPlatform::createFromTarget(Triple, OSVersion,
17827330f729Sjoerg Args.getLastArg(options::OPT_target));
17837330f729Sjoerg }
17847330f729Sjoerg
parseSDKSettings(llvm::vfs::FileSystem & VFS,const ArgList & Args,const Driver & TheDriver)17857330f729Sjoerg Optional<DarwinSDKInfo> parseSDKSettings(llvm::vfs::FileSystem &VFS,
17867330f729Sjoerg const ArgList &Args,
17877330f729Sjoerg const Driver &TheDriver) {
17887330f729Sjoerg const Arg *A = Args.getLastArg(options::OPT_isysroot);
17897330f729Sjoerg if (!A)
17907330f729Sjoerg return None;
17917330f729Sjoerg StringRef isysroot = A->getValue();
17927330f729Sjoerg auto SDKInfoOrErr = driver::parseDarwinSDKInfo(VFS, isysroot);
17937330f729Sjoerg if (!SDKInfoOrErr) {
17947330f729Sjoerg llvm::consumeError(SDKInfoOrErr.takeError());
17957330f729Sjoerg TheDriver.Diag(diag::warn_drv_darwin_sdk_invalid_settings);
17967330f729Sjoerg return None;
17977330f729Sjoerg }
17987330f729Sjoerg return *SDKInfoOrErr;
17997330f729Sjoerg }
18007330f729Sjoerg
18017330f729Sjoerg } // namespace
18027330f729Sjoerg
AddDeploymentTarget(DerivedArgList & Args) const18037330f729Sjoerg void Darwin::AddDeploymentTarget(DerivedArgList &Args) const {
18047330f729Sjoerg const OptTable &Opts = getDriver().getOpts();
18057330f729Sjoerg
18067330f729Sjoerg // Support allowing the SDKROOT environment variable used by xcrun and other
18077330f729Sjoerg // Xcode tools to define the default sysroot, by making it the default for
18087330f729Sjoerg // isysroot.
18097330f729Sjoerg if (const Arg *A = Args.getLastArg(options::OPT_isysroot)) {
18107330f729Sjoerg // Warn if the path does not exist.
18117330f729Sjoerg if (!getVFS().exists(A->getValue()))
18127330f729Sjoerg getDriver().Diag(clang::diag::warn_missing_sysroot) << A->getValue();
18137330f729Sjoerg } else {
18147330f729Sjoerg if (char *env = ::getenv("SDKROOT")) {
18157330f729Sjoerg // We only use this value as the default if it is an absolute path,
18167330f729Sjoerg // exists, and it is not the root path.
18177330f729Sjoerg if (llvm::sys::path::is_absolute(env) && getVFS().exists(env) &&
18187330f729Sjoerg StringRef(env) != "/") {
18197330f729Sjoerg Args.append(Args.MakeSeparateArg(
18207330f729Sjoerg nullptr, Opts.getOption(options::OPT_isysroot), env));
18217330f729Sjoerg }
18227330f729Sjoerg }
18237330f729Sjoerg }
18247330f729Sjoerg
18257330f729Sjoerg // Read the SDKSettings.json file for more information, like the SDK version
18267330f729Sjoerg // that we can pass down to the compiler.
18277330f729Sjoerg SDKInfo = parseSDKSettings(getVFS(), Args, getDriver());
18287330f729Sjoerg
18297330f729Sjoerg // The OS and the version can be specified using the -target argument.
18307330f729Sjoerg Optional<DarwinPlatform> OSTarget =
18317330f729Sjoerg getDeploymentTargetFromTargetArg(Args, getTriple(), getDriver());
18327330f729Sjoerg if (OSTarget) {
18337330f729Sjoerg Optional<DarwinPlatform> OSVersionArgTarget =
18347330f729Sjoerg getDeploymentTargetFromOSVersionArg(Args, getDriver());
18357330f729Sjoerg if (OSVersionArgTarget) {
18367330f729Sjoerg unsigned TargetMajor, TargetMinor, TargetMicro;
18377330f729Sjoerg bool TargetExtra;
18387330f729Sjoerg unsigned ArgMajor, ArgMinor, ArgMicro;
18397330f729Sjoerg bool ArgExtra;
18407330f729Sjoerg if (OSTarget->getPlatform() != OSVersionArgTarget->getPlatform() ||
18417330f729Sjoerg (Driver::GetReleaseVersion(OSTarget->getOSVersion(), TargetMajor,
18427330f729Sjoerg TargetMinor, TargetMicro, TargetExtra) &&
18437330f729Sjoerg Driver::GetReleaseVersion(OSVersionArgTarget->getOSVersion(),
18447330f729Sjoerg ArgMajor, ArgMinor, ArgMicro, ArgExtra) &&
18457330f729Sjoerg (VersionTuple(TargetMajor, TargetMinor, TargetMicro) !=
18467330f729Sjoerg VersionTuple(ArgMajor, ArgMinor, ArgMicro) ||
18477330f729Sjoerg TargetExtra != ArgExtra))) {
18487330f729Sjoerg // Select the OS version from the -m<os>-version-min argument when
18497330f729Sjoerg // the -target does not include an OS version.
18507330f729Sjoerg if (OSTarget->getPlatform() == OSVersionArgTarget->getPlatform() &&
18517330f729Sjoerg !OSTarget->hasOSVersion()) {
18527330f729Sjoerg OSTarget->setOSVersion(OSVersionArgTarget->getOSVersion());
18537330f729Sjoerg } else {
18547330f729Sjoerg // Warn about -m<os>-version-min that doesn't match the OS version
18557330f729Sjoerg // that's specified in the target.
18567330f729Sjoerg std::string OSVersionArg =
18577330f729Sjoerg OSVersionArgTarget->getAsString(Args, Opts);
18587330f729Sjoerg std::string TargetArg = OSTarget->getAsString(Args, Opts);
18597330f729Sjoerg getDriver().Diag(clang::diag::warn_drv_overriding_flag_option)
18607330f729Sjoerg << OSVersionArg << TargetArg;
18617330f729Sjoerg }
18627330f729Sjoerg }
18637330f729Sjoerg }
18647330f729Sjoerg } else {
18657330f729Sjoerg // The OS target can be specified using the -m<os>version-min argument.
18667330f729Sjoerg OSTarget = getDeploymentTargetFromOSVersionArg(Args, getDriver());
18677330f729Sjoerg // If no deployment target was specified on the command line, check for
18687330f729Sjoerg // environment defines.
18697330f729Sjoerg if (!OSTarget) {
18707330f729Sjoerg OSTarget =
18717330f729Sjoerg getDeploymentTargetFromEnvironmentVariables(getDriver(), getTriple());
18727330f729Sjoerg if (OSTarget) {
18737330f729Sjoerg // Don't infer simulator from the arch when the SDK is also specified.
18747330f729Sjoerg Optional<DarwinPlatform> SDKTarget =
18757330f729Sjoerg inferDeploymentTargetFromSDK(Args, SDKInfo);
18767330f729Sjoerg if (SDKTarget)
18777330f729Sjoerg OSTarget->setEnvironment(SDKTarget->getEnvironment());
18787330f729Sjoerg }
18797330f729Sjoerg }
18807330f729Sjoerg // If there is no command-line argument to specify the Target version and
18817330f729Sjoerg // no environment variable defined, see if we can set the default based
18827330f729Sjoerg // on -isysroot using SDKSettings.json if it exists.
18837330f729Sjoerg if (!OSTarget) {
18847330f729Sjoerg OSTarget = inferDeploymentTargetFromSDK(Args, SDKInfo);
18857330f729Sjoerg /// If the target was successfully constructed from the SDK path, try to
18867330f729Sjoerg /// infer the SDK info if the SDK doesn't have it.
18877330f729Sjoerg if (OSTarget && !SDKInfo)
18887330f729Sjoerg SDKInfo = OSTarget->inferSDKInfo();
18897330f729Sjoerg }
18907330f729Sjoerg // If no OS targets have been specified, try to guess platform from -target
18917330f729Sjoerg // or arch name and compute the version from the triple.
18927330f729Sjoerg if (!OSTarget)
18937330f729Sjoerg OSTarget =
18947330f729Sjoerg inferDeploymentTargetFromArch(Args, *this, getTriple(), getDriver());
18957330f729Sjoerg }
18967330f729Sjoerg
18977330f729Sjoerg assert(OSTarget && "Unable to infer Darwin variant");
18987330f729Sjoerg OSTarget->addOSVersionMinArgument(Args, Opts);
18997330f729Sjoerg DarwinPlatformKind Platform = OSTarget->getPlatform();
19007330f729Sjoerg
19017330f729Sjoerg unsigned Major, Minor, Micro;
19027330f729Sjoerg bool HadExtra;
19037330f729Sjoerg // Set the tool chain target information.
19047330f729Sjoerg if (Platform == MacOS) {
19057330f729Sjoerg if (!Driver::GetReleaseVersion(OSTarget->getOSVersion(), Major, Minor,
19067330f729Sjoerg Micro, HadExtra) ||
1907*e038c9c4Sjoerg HadExtra || Major < 10 || Major >= 100 || Minor >= 100 || Micro >= 100)
19087330f729Sjoerg getDriver().Diag(diag::err_drv_invalid_version_number)
19097330f729Sjoerg << OSTarget->getAsString(Args, Opts);
19107330f729Sjoerg } else if (Platform == IPhoneOS) {
19117330f729Sjoerg if (!Driver::GetReleaseVersion(OSTarget->getOSVersion(), Major, Minor,
19127330f729Sjoerg Micro, HadExtra) ||
19137330f729Sjoerg HadExtra || Major >= 100 || Minor >= 100 || Micro >= 100)
19147330f729Sjoerg getDriver().Diag(diag::err_drv_invalid_version_number)
19157330f729Sjoerg << OSTarget->getAsString(Args, Opts);
19167330f729Sjoerg ;
19177330f729Sjoerg // For 32-bit targets, the deployment target for iOS has to be earlier than
19187330f729Sjoerg // iOS 11.
19197330f729Sjoerg if (getTriple().isArch32Bit() && Major >= 11) {
19207330f729Sjoerg // If the deployment target is explicitly specified, print a diagnostic.
19217330f729Sjoerg if (OSTarget->isExplicitlySpecified()) {
19227330f729Sjoerg getDriver().Diag(diag::warn_invalid_ios_deployment_target)
19237330f729Sjoerg << OSTarget->getAsString(Args, Opts);
19247330f729Sjoerg // Otherwise, set it to 10.99.99.
19257330f729Sjoerg } else {
19267330f729Sjoerg Major = 10;
19277330f729Sjoerg Minor = 99;
19287330f729Sjoerg Micro = 99;
19297330f729Sjoerg }
19307330f729Sjoerg }
19317330f729Sjoerg } else if (Platform == TvOS) {
19327330f729Sjoerg if (!Driver::GetReleaseVersion(OSTarget->getOSVersion(), Major, Minor,
19337330f729Sjoerg Micro, HadExtra) ||
19347330f729Sjoerg HadExtra || Major >= 100 || Minor >= 100 || Micro >= 100)
19357330f729Sjoerg getDriver().Diag(diag::err_drv_invalid_version_number)
19367330f729Sjoerg << OSTarget->getAsString(Args, Opts);
19377330f729Sjoerg } else if (Platform == WatchOS) {
19387330f729Sjoerg if (!Driver::GetReleaseVersion(OSTarget->getOSVersion(), Major, Minor,
19397330f729Sjoerg Micro, HadExtra) ||
19407330f729Sjoerg HadExtra || Major >= 10 || Minor >= 100 || Micro >= 100)
19417330f729Sjoerg getDriver().Diag(diag::err_drv_invalid_version_number)
19427330f729Sjoerg << OSTarget->getAsString(Args, Opts);
19437330f729Sjoerg } else
19447330f729Sjoerg llvm_unreachable("unknown kind of Darwin platform");
19457330f729Sjoerg
19467330f729Sjoerg DarwinEnvironmentKind Environment = OSTarget->getEnvironment();
19477330f729Sjoerg // Recognize iOS targets with an x86 architecture as the iOS simulator.
19487330f729Sjoerg if (Environment == NativeEnvironment && Platform != MacOS &&
1949*e038c9c4Sjoerg OSTarget->canInferSimulatorFromArch() && getTriple().isX86())
19507330f729Sjoerg Environment = Simulator;
19517330f729Sjoerg
19527330f729Sjoerg setTarget(Platform, Environment, Major, Minor, Micro);
19537330f729Sjoerg
19547330f729Sjoerg if (const Arg *A = Args.getLastArg(options::OPT_isysroot)) {
19557330f729Sjoerg StringRef SDK = getSDKName(A->getValue());
19567330f729Sjoerg if (SDK.size() > 0) {
19577330f729Sjoerg size_t StartVer = SDK.find_first_of("0123456789");
19587330f729Sjoerg StringRef SDKName = SDK.slice(0, StartVer);
1959*e038c9c4Sjoerg if (!SDKName.startswith(getPlatformFamily()) &&
1960*e038c9c4Sjoerg !dropSDKNamePrefix(SDKName).startswith(getPlatformFamily()))
19617330f729Sjoerg getDriver().Diag(diag::warn_incompatible_sysroot)
19627330f729Sjoerg << SDKName << getPlatformFamily();
19637330f729Sjoerg }
19647330f729Sjoerg }
19657330f729Sjoerg }
19667330f729Sjoerg
19677330f729Sjoerg // Returns the effective header sysroot path to use. This comes either from
19687330f729Sjoerg // -isysroot or --sysroot.
GetHeaderSysroot(const llvm::opt::ArgList & DriverArgs) const19697330f729Sjoerg llvm::StringRef DarwinClang::GetHeaderSysroot(const llvm::opt::ArgList &DriverArgs) const {
19707330f729Sjoerg if(DriverArgs.hasArg(options::OPT_isysroot))
19717330f729Sjoerg return DriverArgs.getLastArgValue(options::OPT_isysroot);
19727330f729Sjoerg if (!getDriver().SysRoot.empty())
19737330f729Sjoerg return getDriver().SysRoot;
19747330f729Sjoerg return "/";
19757330f729Sjoerg }
19767330f729Sjoerg
AddClangSystemIncludeArgs(const llvm::opt::ArgList & DriverArgs,llvm::opt::ArgStringList & CC1Args) const19777330f729Sjoerg void DarwinClang::AddClangSystemIncludeArgs(const llvm::opt::ArgList &DriverArgs,
19787330f729Sjoerg llvm::opt::ArgStringList &CC1Args) const {
19797330f729Sjoerg const Driver &D = getDriver();
19807330f729Sjoerg
19817330f729Sjoerg llvm::StringRef Sysroot = GetHeaderSysroot(DriverArgs);
19827330f729Sjoerg
19837330f729Sjoerg bool NoStdInc = DriverArgs.hasArg(options::OPT_nostdinc);
19847330f729Sjoerg bool NoStdlibInc = DriverArgs.hasArg(options::OPT_nostdlibinc);
1985*e038c9c4Sjoerg bool NoBuiltinInc = DriverArgs.hasFlag(
1986*e038c9c4Sjoerg options::OPT_nobuiltininc, options::OPT_ibuiltininc, /*Default=*/false);
1987*e038c9c4Sjoerg bool ForceBuiltinInc = DriverArgs.hasFlag(
1988*e038c9c4Sjoerg options::OPT_ibuiltininc, options::OPT_nobuiltininc, /*Default=*/false);
19897330f729Sjoerg
19907330f729Sjoerg // Add <sysroot>/usr/local/include
19917330f729Sjoerg if (!NoStdInc && !NoStdlibInc) {
19927330f729Sjoerg SmallString<128> P(Sysroot);
19937330f729Sjoerg llvm::sys::path::append(P, "usr", "local", "include");
19947330f729Sjoerg addSystemInclude(DriverArgs, CC1Args, P);
19957330f729Sjoerg }
19967330f729Sjoerg
19977330f729Sjoerg // Add the Clang builtin headers (<resource>/include)
1998*e038c9c4Sjoerg if (!(NoStdInc && !ForceBuiltinInc) && !NoBuiltinInc) {
19997330f729Sjoerg SmallString<128> P(D.ResourceDir);
20007330f729Sjoerg llvm::sys::path::append(P, "include");
20017330f729Sjoerg addSystemInclude(DriverArgs, CC1Args, P);
20027330f729Sjoerg }
20037330f729Sjoerg
20047330f729Sjoerg if (NoStdInc || NoStdlibInc)
20057330f729Sjoerg return;
20067330f729Sjoerg
20077330f729Sjoerg // Check for configure-time C include directories.
20087330f729Sjoerg llvm::StringRef CIncludeDirs(C_INCLUDE_DIRS);
20097330f729Sjoerg if (!CIncludeDirs.empty()) {
20107330f729Sjoerg llvm::SmallVector<llvm::StringRef, 5> dirs;
20117330f729Sjoerg CIncludeDirs.split(dirs, ":");
20127330f729Sjoerg for (llvm::StringRef dir : dirs) {
20137330f729Sjoerg llvm::StringRef Prefix =
2014*e038c9c4Sjoerg llvm::sys::path::is_absolute(dir) ? "" : llvm::StringRef(Sysroot);
20157330f729Sjoerg addExternCSystemInclude(DriverArgs, CC1Args, Prefix + dir);
20167330f729Sjoerg }
20177330f729Sjoerg } else {
20187330f729Sjoerg // Otherwise, add <sysroot>/usr/include.
20197330f729Sjoerg SmallString<128> P(Sysroot);
20207330f729Sjoerg llvm::sys::path::append(P, "usr", "include");
20217330f729Sjoerg addExternCSystemInclude(DriverArgs, CC1Args, P.str());
20227330f729Sjoerg }
20237330f729Sjoerg }
20247330f729Sjoerg
AddGnuCPlusPlusIncludePaths(const llvm::opt::ArgList & DriverArgs,llvm::opt::ArgStringList & CC1Args,llvm::SmallString<128> Base,llvm::StringRef Version,llvm::StringRef ArchDir,llvm::StringRef BitDir) const20257330f729Sjoerg bool DarwinClang::AddGnuCPlusPlusIncludePaths(const llvm::opt::ArgList &DriverArgs,
20267330f729Sjoerg llvm::opt::ArgStringList &CC1Args,
20277330f729Sjoerg llvm::SmallString<128> Base,
20287330f729Sjoerg llvm::StringRef Version,
20297330f729Sjoerg llvm::StringRef ArchDir,
20307330f729Sjoerg llvm::StringRef BitDir) const {
20317330f729Sjoerg llvm::sys::path::append(Base, Version);
20327330f729Sjoerg
20337330f729Sjoerg // Add the base dir
20347330f729Sjoerg addSystemInclude(DriverArgs, CC1Args, Base);
20357330f729Sjoerg
20367330f729Sjoerg // Add the multilib dirs
20377330f729Sjoerg {
20387330f729Sjoerg llvm::SmallString<128> P = Base;
20397330f729Sjoerg if (!ArchDir.empty())
20407330f729Sjoerg llvm::sys::path::append(P, ArchDir);
20417330f729Sjoerg if (!BitDir.empty())
20427330f729Sjoerg llvm::sys::path::append(P, BitDir);
20437330f729Sjoerg addSystemInclude(DriverArgs, CC1Args, P);
20447330f729Sjoerg }
20457330f729Sjoerg
20467330f729Sjoerg // Add the backward dir
20477330f729Sjoerg {
20487330f729Sjoerg llvm::SmallString<128> P = Base;
20497330f729Sjoerg llvm::sys::path::append(P, "backward");
20507330f729Sjoerg addSystemInclude(DriverArgs, CC1Args, P);
20517330f729Sjoerg }
20527330f729Sjoerg
20537330f729Sjoerg return getVFS().exists(Base);
20547330f729Sjoerg }
20557330f729Sjoerg
AddClangCXXStdlibIncludeArgs(const llvm::opt::ArgList & DriverArgs,llvm::opt::ArgStringList & CC1Args) const20567330f729Sjoerg void DarwinClang::AddClangCXXStdlibIncludeArgs(
20577330f729Sjoerg const llvm::opt::ArgList &DriverArgs,
20587330f729Sjoerg llvm::opt::ArgStringList &CC1Args) const {
20597330f729Sjoerg // The implementation from a base class will pass through the -stdlib to
20607330f729Sjoerg // CC1Args.
20617330f729Sjoerg // FIXME: this should not be necessary, remove usages in the frontend
20627330f729Sjoerg // (e.g. HeaderSearchOptions::UseLibcxx) and don't pipe -stdlib.
20637330f729Sjoerg // Also check whether this is used for setting library search paths.
20647330f729Sjoerg ToolChain::AddClangCXXStdlibIncludeArgs(DriverArgs, CC1Args);
20657330f729Sjoerg
20667330f729Sjoerg if (DriverArgs.hasArg(options::OPT_nostdlibinc) ||
20677330f729Sjoerg DriverArgs.hasArg(options::OPT_nostdincxx))
20687330f729Sjoerg return;
20697330f729Sjoerg
20707330f729Sjoerg llvm::StringRef Sysroot = GetHeaderSysroot(DriverArgs);
20717330f729Sjoerg
20727330f729Sjoerg switch (GetCXXStdlibType(DriverArgs)) {
20737330f729Sjoerg case ToolChain::CST_Libcxx: {
2074*e038c9c4Sjoerg // On Darwin, libc++ can be installed in one of the following two places:
2075*e038c9c4Sjoerg // 1. Alongside the compiler in <install>/include/c++/v1
2076*e038c9c4Sjoerg // 2. In a SDK (or a custom sysroot) in <sysroot>/usr/include/c++/v1
2077*e038c9c4Sjoerg //
2078*e038c9c4Sjoerg // The precendence of paths is as listed above, i.e. we take the first path
2079*e038c9c4Sjoerg // that exists. Also note that we never include libc++ twice -- we take the
2080*e038c9c4Sjoerg // first path that exists and don't send the other paths to CC1 (otherwise
2081*e038c9c4Sjoerg // include_next could break).
2082*e038c9c4Sjoerg
2083*e038c9c4Sjoerg // Check for (1)
2084*e038c9c4Sjoerg // Get from '<install>/bin' to '<install>/include/c++/v1'.
2085*e038c9c4Sjoerg // Note that InstallBin can be relative, so we use '..' instead of
2086*e038c9c4Sjoerg // parent_path.
2087*e038c9c4Sjoerg llvm::SmallString<128> InstallBin =
2088*e038c9c4Sjoerg llvm::StringRef(getDriver().getInstalledDir()); // <install>/bin
2089*e038c9c4Sjoerg llvm::sys::path::append(InstallBin, "..", "include", "c++", "v1");
2090*e038c9c4Sjoerg if (getVFS().exists(InstallBin)) {
2091*e038c9c4Sjoerg addSystemInclude(DriverArgs, CC1Args, InstallBin);
2092*e038c9c4Sjoerg return;
2093*e038c9c4Sjoerg } else if (DriverArgs.hasArg(options::OPT_v)) {
2094*e038c9c4Sjoerg llvm::errs() << "ignoring nonexistent directory \"" << InstallBin
2095*e038c9c4Sjoerg << "\"\n";
20967330f729Sjoerg }
2097*e038c9c4Sjoerg
2098*e038c9c4Sjoerg // Otherwise, check for (2)
2099*e038c9c4Sjoerg llvm::SmallString<128> SysrootUsr = Sysroot;
2100*e038c9c4Sjoerg llvm::sys::path::append(SysrootUsr, "usr", "include", "c++", "v1");
2101*e038c9c4Sjoerg if (getVFS().exists(SysrootUsr)) {
2102*e038c9c4Sjoerg addSystemInclude(DriverArgs, CC1Args, SysrootUsr);
2103*e038c9c4Sjoerg return;
2104*e038c9c4Sjoerg } else if (DriverArgs.hasArg(options::OPT_v)) {
2105*e038c9c4Sjoerg llvm::errs() << "ignoring nonexistent directory \"" << SysrootUsr
2106*e038c9c4Sjoerg << "\"\n";
21077330f729Sjoerg }
2108*e038c9c4Sjoerg
2109*e038c9c4Sjoerg // Otherwise, don't add any path.
21107330f729Sjoerg break;
21117330f729Sjoerg }
21127330f729Sjoerg
21137330f729Sjoerg case ToolChain::CST_Libstdcxx:
21147330f729Sjoerg llvm::SmallString<128> UsrIncludeCxx = Sysroot;
21157330f729Sjoerg llvm::sys::path::append(UsrIncludeCxx, "usr", "include", "c++");
21167330f729Sjoerg
21177330f729Sjoerg llvm::Triple::ArchType arch = getTriple().getArch();
21187330f729Sjoerg bool IsBaseFound = true;
21197330f729Sjoerg switch (arch) {
21207330f729Sjoerg default: break;
21217330f729Sjoerg
21227330f729Sjoerg case llvm::Triple::ppc:
21237330f729Sjoerg case llvm::Triple::ppc64:
21247330f729Sjoerg IsBaseFound = AddGnuCPlusPlusIncludePaths(DriverArgs, CC1Args, UsrIncludeCxx,
21257330f729Sjoerg "4.2.1",
21267330f729Sjoerg "powerpc-apple-darwin10",
21277330f729Sjoerg arch == llvm::Triple::ppc64 ? "ppc64" : "");
21287330f729Sjoerg IsBaseFound |= AddGnuCPlusPlusIncludePaths(DriverArgs, CC1Args, UsrIncludeCxx,
21297330f729Sjoerg "4.0.0", "powerpc-apple-darwin10",
21307330f729Sjoerg arch == llvm::Triple::ppc64 ? "ppc64" : "");
21317330f729Sjoerg break;
21327330f729Sjoerg
21337330f729Sjoerg case llvm::Triple::x86:
21347330f729Sjoerg case llvm::Triple::x86_64:
21357330f729Sjoerg IsBaseFound = AddGnuCPlusPlusIncludePaths(DriverArgs, CC1Args, UsrIncludeCxx,
21367330f729Sjoerg "4.2.1",
21377330f729Sjoerg "i686-apple-darwin10",
21387330f729Sjoerg arch == llvm::Triple::x86_64 ? "x86_64" : "");
21397330f729Sjoerg IsBaseFound |= AddGnuCPlusPlusIncludePaths(DriverArgs, CC1Args, UsrIncludeCxx,
21407330f729Sjoerg "4.0.0", "i686-apple-darwin8",
21417330f729Sjoerg "");
21427330f729Sjoerg break;
21437330f729Sjoerg
21447330f729Sjoerg case llvm::Triple::arm:
21457330f729Sjoerg case llvm::Triple::thumb:
21467330f729Sjoerg IsBaseFound = AddGnuCPlusPlusIncludePaths(DriverArgs, CC1Args, UsrIncludeCxx,
21477330f729Sjoerg "4.2.1",
21487330f729Sjoerg "arm-apple-darwin10",
21497330f729Sjoerg "v7");
21507330f729Sjoerg IsBaseFound |= AddGnuCPlusPlusIncludePaths(DriverArgs, CC1Args, UsrIncludeCxx,
21517330f729Sjoerg "4.2.1",
21527330f729Sjoerg "arm-apple-darwin10",
21537330f729Sjoerg "v6");
21547330f729Sjoerg break;
21557330f729Sjoerg
21567330f729Sjoerg case llvm::Triple::aarch64:
21577330f729Sjoerg IsBaseFound = AddGnuCPlusPlusIncludePaths(DriverArgs, CC1Args, UsrIncludeCxx,
21587330f729Sjoerg "4.2.1",
21597330f729Sjoerg "arm64-apple-darwin10",
21607330f729Sjoerg "");
21617330f729Sjoerg break;
21627330f729Sjoerg }
21637330f729Sjoerg
21647330f729Sjoerg if (!IsBaseFound) {
21657330f729Sjoerg getDriver().Diag(diag::warn_drv_libstdcxx_not_found);
21667330f729Sjoerg }
21677330f729Sjoerg
21687330f729Sjoerg break;
21697330f729Sjoerg }
21707330f729Sjoerg }
AddCXXStdlibLibArgs(const ArgList & Args,ArgStringList & CmdArgs) const21717330f729Sjoerg void DarwinClang::AddCXXStdlibLibArgs(const ArgList &Args,
21727330f729Sjoerg ArgStringList &CmdArgs) const {
21737330f729Sjoerg CXXStdlibType Type = GetCXXStdlibType(Args);
21747330f729Sjoerg
21757330f729Sjoerg switch (Type) {
21767330f729Sjoerg case ToolChain::CST_Libcxx:
21777330f729Sjoerg CmdArgs.push_back("-lc++");
21787330f729Sjoerg break;
21797330f729Sjoerg
21807330f729Sjoerg case ToolChain::CST_Libstdcxx:
21817330f729Sjoerg // Unfortunately, -lstdc++ doesn't always exist in the standard search path;
21827330f729Sjoerg // it was previously found in the gcc lib dir. However, for all the Darwin
21837330f729Sjoerg // platforms we care about it was -lstdc++.6, so we search for that
21847330f729Sjoerg // explicitly if we can't see an obvious -lstdc++ candidate.
21857330f729Sjoerg
21867330f729Sjoerg // Check in the sysroot first.
21877330f729Sjoerg if (const Arg *A = Args.getLastArg(options::OPT_isysroot)) {
21887330f729Sjoerg SmallString<128> P(A->getValue());
21897330f729Sjoerg llvm::sys::path::append(P, "usr", "lib", "libstdc++.dylib");
21907330f729Sjoerg
21917330f729Sjoerg if (!getVFS().exists(P)) {
21927330f729Sjoerg llvm::sys::path::remove_filename(P);
21937330f729Sjoerg llvm::sys::path::append(P, "libstdc++.6.dylib");
21947330f729Sjoerg if (getVFS().exists(P)) {
21957330f729Sjoerg CmdArgs.push_back(Args.MakeArgString(P));
21967330f729Sjoerg return;
21977330f729Sjoerg }
21987330f729Sjoerg }
21997330f729Sjoerg }
22007330f729Sjoerg
22017330f729Sjoerg // Otherwise, look in the root.
22027330f729Sjoerg // FIXME: This should be removed someday when we don't have to care about
22037330f729Sjoerg // 10.6 and earlier, where /usr/lib/libstdc++.dylib does not exist.
22047330f729Sjoerg if (!getVFS().exists("/usr/lib/libstdc++.dylib") &&
22057330f729Sjoerg getVFS().exists("/usr/lib/libstdc++.6.dylib")) {
22067330f729Sjoerg CmdArgs.push_back("/usr/lib/libstdc++.6.dylib");
22077330f729Sjoerg return;
22087330f729Sjoerg }
22097330f729Sjoerg
22107330f729Sjoerg // Otherwise, let the linker search.
22117330f729Sjoerg CmdArgs.push_back("-lstdc++");
22127330f729Sjoerg break;
22137330f729Sjoerg }
22147330f729Sjoerg }
22157330f729Sjoerg
AddCCKextLibArgs(const ArgList & Args,ArgStringList & CmdArgs) const22167330f729Sjoerg void DarwinClang::AddCCKextLibArgs(const ArgList &Args,
22177330f729Sjoerg ArgStringList &CmdArgs) const {
22187330f729Sjoerg // For Darwin platforms, use the compiler-rt-based support library
22197330f729Sjoerg // instead of the gcc-provided one (which is also incidentally
22207330f729Sjoerg // only present in the gcc lib dir, which makes it hard to find).
22217330f729Sjoerg
22227330f729Sjoerg SmallString<128> P(getDriver().ResourceDir);
22237330f729Sjoerg llvm::sys::path::append(P, "lib", "darwin");
22247330f729Sjoerg
22257330f729Sjoerg // Use the newer cc_kext for iOS ARM after 6.0.
22267330f729Sjoerg if (isTargetWatchOS()) {
22277330f729Sjoerg llvm::sys::path::append(P, "libclang_rt.cc_kext_watchos.a");
22287330f729Sjoerg } else if (isTargetTvOS()) {
22297330f729Sjoerg llvm::sys::path::append(P, "libclang_rt.cc_kext_tvos.a");
22307330f729Sjoerg } else if (isTargetIPhoneOS()) {
22317330f729Sjoerg llvm::sys::path::append(P, "libclang_rt.cc_kext_ios.a");
22327330f729Sjoerg } else {
22337330f729Sjoerg llvm::sys::path::append(P, "libclang_rt.cc_kext.a");
22347330f729Sjoerg }
22357330f729Sjoerg
22367330f729Sjoerg // For now, allow missing resource libraries to support developers who may
22377330f729Sjoerg // not have compiler-rt checked out or integrated into their build.
22387330f729Sjoerg if (getVFS().exists(P))
22397330f729Sjoerg CmdArgs.push_back(Args.MakeArgString(P));
22407330f729Sjoerg }
22417330f729Sjoerg
TranslateArgs(const DerivedArgList & Args,StringRef BoundArch,Action::OffloadKind) const22427330f729Sjoerg DerivedArgList *MachO::TranslateArgs(const DerivedArgList &Args,
22437330f729Sjoerg StringRef BoundArch,
22447330f729Sjoerg Action::OffloadKind) const {
22457330f729Sjoerg DerivedArgList *DAL = new DerivedArgList(Args.getBaseArgs());
22467330f729Sjoerg const OptTable &Opts = getDriver().getOpts();
22477330f729Sjoerg
22487330f729Sjoerg // FIXME: We really want to get out of the tool chain level argument
22497330f729Sjoerg // translation business, as it makes the driver functionality much
22507330f729Sjoerg // more opaque. For now, we follow gcc closely solely for the
22517330f729Sjoerg // purpose of easily achieving feature parity & testability. Once we
22527330f729Sjoerg // have something that works, we should reevaluate each translation
22537330f729Sjoerg // and try to push it down into tool specific logic.
22547330f729Sjoerg
22557330f729Sjoerg for (Arg *A : Args) {
22567330f729Sjoerg if (A->getOption().matches(options::OPT_Xarch__)) {
22577330f729Sjoerg // Skip this argument unless the architecture matches either the toolchain
22587330f729Sjoerg // triple arch, or the arch being bound.
22597330f729Sjoerg llvm::Triple::ArchType XarchArch =
22607330f729Sjoerg tools::darwin::getArchTypeForMachOArchName(A->getValue(0));
22617330f729Sjoerg if (!(XarchArch == getArch() ||
22627330f729Sjoerg (!BoundArch.empty() &&
22637330f729Sjoerg XarchArch ==
22647330f729Sjoerg tools::darwin::getArchTypeForMachOArchName(BoundArch))))
22657330f729Sjoerg continue;
22667330f729Sjoerg
22677330f729Sjoerg Arg *OriginalArg = A;
2268*e038c9c4Sjoerg TranslateXarchArgs(Args, A, DAL);
22697330f729Sjoerg
22707330f729Sjoerg // Linker input arguments require custom handling. The problem is that we
22717330f729Sjoerg // have already constructed the phase actions, so we can not treat them as
22727330f729Sjoerg // "input arguments".
22737330f729Sjoerg if (A->getOption().hasFlag(options::LinkerInput)) {
22747330f729Sjoerg // Convert the argument into individual Zlinker_input_args.
22757330f729Sjoerg for (const char *Value : A->getValues()) {
22767330f729Sjoerg DAL->AddSeparateArg(
22777330f729Sjoerg OriginalArg, Opts.getOption(options::OPT_Zlinker_input), Value);
22787330f729Sjoerg }
22797330f729Sjoerg continue;
22807330f729Sjoerg }
22817330f729Sjoerg }
22827330f729Sjoerg
22837330f729Sjoerg // Sob. These is strictly gcc compatible for the time being. Apple
22847330f729Sjoerg // gcc translates options twice, which means that self-expanding
22857330f729Sjoerg // options add duplicates.
22867330f729Sjoerg switch ((options::ID)A->getOption().getID()) {
22877330f729Sjoerg default:
22887330f729Sjoerg DAL->append(A);
22897330f729Sjoerg break;
22907330f729Sjoerg
22917330f729Sjoerg case options::OPT_mkernel:
22927330f729Sjoerg case options::OPT_fapple_kext:
22937330f729Sjoerg DAL->append(A);
22947330f729Sjoerg DAL->AddFlagArg(A, Opts.getOption(options::OPT_static));
22957330f729Sjoerg break;
22967330f729Sjoerg
22977330f729Sjoerg case options::OPT_dependency_file:
22987330f729Sjoerg DAL->AddSeparateArg(A, Opts.getOption(options::OPT_MF), A->getValue());
22997330f729Sjoerg break;
23007330f729Sjoerg
23017330f729Sjoerg case options::OPT_gfull:
23027330f729Sjoerg DAL->AddFlagArg(A, Opts.getOption(options::OPT_g_Flag));
23037330f729Sjoerg DAL->AddFlagArg(
23047330f729Sjoerg A, Opts.getOption(options::OPT_fno_eliminate_unused_debug_symbols));
23057330f729Sjoerg break;
23067330f729Sjoerg
23077330f729Sjoerg case options::OPT_gused:
23087330f729Sjoerg DAL->AddFlagArg(A, Opts.getOption(options::OPT_g_Flag));
23097330f729Sjoerg DAL->AddFlagArg(
23107330f729Sjoerg A, Opts.getOption(options::OPT_feliminate_unused_debug_symbols));
23117330f729Sjoerg break;
23127330f729Sjoerg
23137330f729Sjoerg case options::OPT_shared:
23147330f729Sjoerg DAL->AddFlagArg(A, Opts.getOption(options::OPT_dynamiclib));
23157330f729Sjoerg break;
23167330f729Sjoerg
23177330f729Sjoerg case options::OPT_fconstant_cfstrings:
23187330f729Sjoerg DAL->AddFlagArg(A, Opts.getOption(options::OPT_mconstant_cfstrings));
23197330f729Sjoerg break;
23207330f729Sjoerg
23217330f729Sjoerg case options::OPT_fno_constant_cfstrings:
23227330f729Sjoerg DAL->AddFlagArg(A, Opts.getOption(options::OPT_mno_constant_cfstrings));
23237330f729Sjoerg break;
23247330f729Sjoerg
23257330f729Sjoerg case options::OPT_Wnonportable_cfstrings:
23267330f729Sjoerg DAL->AddFlagArg(A,
23277330f729Sjoerg Opts.getOption(options::OPT_mwarn_nonportable_cfstrings));
23287330f729Sjoerg break;
23297330f729Sjoerg
23307330f729Sjoerg case options::OPT_Wno_nonportable_cfstrings:
23317330f729Sjoerg DAL->AddFlagArg(
23327330f729Sjoerg A, Opts.getOption(options::OPT_mno_warn_nonportable_cfstrings));
23337330f729Sjoerg break;
23347330f729Sjoerg
23357330f729Sjoerg case options::OPT_fpascal_strings:
23367330f729Sjoerg DAL->AddFlagArg(A, Opts.getOption(options::OPT_mpascal_strings));
23377330f729Sjoerg break;
23387330f729Sjoerg
23397330f729Sjoerg case options::OPT_fno_pascal_strings:
23407330f729Sjoerg DAL->AddFlagArg(A, Opts.getOption(options::OPT_mno_pascal_strings));
23417330f729Sjoerg break;
23427330f729Sjoerg }
23437330f729Sjoerg }
23447330f729Sjoerg
23457330f729Sjoerg // Add the arch options based on the particular spelling of -arch, to match
23467330f729Sjoerg // how the driver driver works.
23477330f729Sjoerg if (!BoundArch.empty()) {
23487330f729Sjoerg StringRef Name = BoundArch;
23497330f729Sjoerg const Option MCpu = Opts.getOption(options::OPT_mcpu_EQ);
23507330f729Sjoerg const Option MArch = Opts.getOption(clang::driver::options::OPT_march_EQ);
23517330f729Sjoerg
23527330f729Sjoerg // This code must be kept in sync with LLVM's getArchTypeForDarwinArch,
23537330f729Sjoerg // which defines the list of which architectures we accept.
23547330f729Sjoerg if (Name == "ppc")
23557330f729Sjoerg ;
23567330f729Sjoerg else if (Name == "ppc601")
23577330f729Sjoerg DAL->AddJoinedArg(nullptr, MCpu, "601");
23587330f729Sjoerg else if (Name == "ppc603")
23597330f729Sjoerg DAL->AddJoinedArg(nullptr, MCpu, "603");
23607330f729Sjoerg else if (Name == "ppc604")
23617330f729Sjoerg DAL->AddJoinedArg(nullptr, MCpu, "604");
23627330f729Sjoerg else if (Name == "ppc604e")
23637330f729Sjoerg DAL->AddJoinedArg(nullptr, MCpu, "604e");
23647330f729Sjoerg else if (Name == "ppc750")
23657330f729Sjoerg DAL->AddJoinedArg(nullptr, MCpu, "750");
23667330f729Sjoerg else if (Name == "ppc7400")
23677330f729Sjoerg DAL->AddJoinedArg(nullptr, MCpu, "7400");
23687330f729Sjoerg else if (Name == "ppc7450")
23697330f729Sjoerg DAL->AddJoinedArg(nullptr, MCpu, "7450");
23707330f729Sjoerg else if (Name == "ppc970")
23717330f729Sjoerg DAL->AddJoinedArg(nullptr, MCpu, "970");
23727330f729Sjoerg
23737330f729Sjoerg else if (Name == "ppc64" || Name == "ppc64le")
23747330f729Sjoerg DAL->AddFlagArg(nullptr, Opts.getOption(options::OPT_m64));
23757330f729Sjoerg
23767330f729Sjoerg else if (Name == "i386")
23777330f729Sjoerg ;
23787330f729Sjoerg else if (Name == "i486")
23797330f729Sjoerg DAL->AddJoinedArg(nullptr, MArch, "i486");
23807330f729Sjoerg else if (Name == "i586")
23817330f729Sjoerg DAL->AddJoinedArg(nullptr, MArch, "i586");
23827330f729Sjoerg else if (Name == "i686")
23837330f729Sjoerg DAL->AddJoinedArg(nullptr, MArch, "i686");
23847330f729Sjoerg else if (Name == "pentium")
23857330f729Sjoerg DAL->AddJoinedArg(nullptr, MArch, "pentium");
23867330f729Sjoerg else if (Name == "pentium2")
23877330f729Sjoerg DAL->AddJoinedArg(nullptr, MArch, "pentium2");
23887330f729Sjoerg else if (Name == "pentpro")
23897330f729Sjoerg DAL->AddJoinedArg(nullptr, MArch, "pentiumpro");
23907330f729Sjoerg else if (Name == "pentIIm3")
23917330f729Sjoerg DAL->AddJoinedArg(nullptr, MArch, "pentium2");
23927330f729Sjoerg
23937330f729Sjoerg else if (Name == "x86_64" || Name == "x86_64h")
23947330f729Sjoerg DAL->AddFlagArg(nullptr, Opts.getOption(options::OPT_m64));
23957330f729Sjoerg
23967330f729Sjoerg else if (Name == "arm")
23977330f729Sjoerg DAL->AddJoinedArg(nullptr, MArch, "armv4t");
23987330f729Sjoerg else if (Name == "armv4t")
23997330f729Sjoerg DAL->AddJoinedArg(nullptr, MArch, "armv4t");
24007330f729Sjoerg else if (Name == "armv5")
24017330f729Sjoerg DAL->AddJoinedArg(nullptr, MArch, "armv5tej");
24027330f729Sjoerg else if (Name == "xscale")
24037330f729Sjoerg DAL->AddJoinedArg(nullptr, MArch, "xscale");
24047330f729Sjoerg else if (Name == "armv6")
24057330f729Sjoerg DAL->AddJoinedArg(nullptr, MArch, "armv6k");
24067330f729Sjoerg else if (Name == "armv6m")
24077330f729Sjoerg DAL->AddJoinedArg(nullptr, MArch, "armv6m");
24087330f729Sjoerg else if (Name == "armv7")
24097330f729Sjoerg DAL->AddJoinedArg(nullptr, MArch, "armv7a");
24107330f729Sjoerg else if (Name == "armv7em")
24117330f729Sjoerg DAL->AddJoinedArg(nullptr, MArch, "armv7em");
24127330f729Sjoerg else if (Name == "armv7k")
24137330f729Sjoerg DAL->AddJoinedArg(nullptr, MArch, "armv7k");
24147330f729Sjoerg else if (Name == "armv7m")
24157330f729Sjoerg DAL->AddJoinedArg(nullptr, MArch, "armv7m");
24167330f729Sjoerg else if (Name == "armv7s")
24177330f729Sjoerg DAL->AddJoinedArg(nullptr, MArch, "armv7s");
24187330f729Sjoerg }
24197330f729Sjoerg
24207330f729Sjoerg return DAL;
24217330f729Sjoerg }
24227330f729Sjoerg
AddLinkRuntimeLibArgs(const ArgList & Args,ArgStringList & CmdArgs,bool ForceLinkBuiltinRT) const24237330f729Sjoerg void MachO::AddLinkRuntimeLibArgs(const ArgList &Args,
24247330f729Sjoerg ArgStringList &CmdArgs,
24257330f729Sjoerg bool ForceLinkBuiltinRT) const {
24267330f729Sjoerg // Embedded targets are simple at the moment, not supporting sanitizers and
24277330f729Sjoerg // with different libraries for each member of the product { static, PIC } x
24287330f729Sjoerg // { hard-float, soft-float }
24297330f729Sjoerg llvm::SmallString<32> CompilerRT = StringRef("");
24307330f729Sjoerg CompilerRT +=
24317330f729Sjoerg (tools::arm::getARMFloatABI(*this, Args) == tools::arm::FloatABI::Hard)
24327330f729Sjoerg ? "hard"
24337330f729Sjoerg : "soft";
24347330f729Sjoerg CompilerRT += Args.hasArg(options::OPT_fPIC) ? "_pic" : "_static";
24357330f729Sjoerg
24367330f729Sjoerg AddLinkRuntimeLib(Args, CmdArgs, CompilerRT, RLO_IsEmbedded);
24377330f729Sjoerg }
24387330f729Sjoerg
isAlignedAllocationUnavailable() const24397330f729Sjoerg bool Darwin::isAlignedAllocationUnavailable() const {
24407330f729Sjoerg llvm::Triple::OSType OS;
24417330f729Sjoerg
24427330f729Sjoerg switch (TargetPlatform) {
24437330f729Sjoerg case MacOS: // Earlier than 10.13.
24447330f729Sjoerg OS = llvm::Triple::MacOSX;
24457330f729Sjoerg break;
24467330f729Sjoerg case IPhoneOS:
24477330f729Sjoerg OS = llvm::Triple::IOS;
24487330f729Sjoerg break;
24497330f729Sjoerg case TvOS: // Earlier than 11.0.
24507330f729Sjoerg OS = llvm::Triple::TvOS;
24517330f729Sjoerg break;
24527330f729Sjoerg case WatchOS: // Earlier than 4.0.
24537330f729Sjoerg OS = llvm::Triple::WatchOS;
24547330f729Sjoerg break;
24557330f729Sjoerg }
24567330f729Sjoerg
24577330f729Sjoerg return TargetVersion < alignedAllocMinVersion(OS);
24587330f729Sjoerg }
24597330f729Sjoerg
addClangTargetOptions(const llvm::opt::ArgList & DriverArgs,llvm::opt::ArgStringList & CC1Args,Action::OffloadKind DeviceOffloadKind) const24607330f729Sjoerg void Darwin::addClangTargetOptions(const llvm::opt::ArgList &DriverArgs,
24617330f729Sjoerg llvm::opt::ArgStringList &CC1Args,
24627330f729Sjoerg Action::OffloadKind DeviceOffloadKind) const {
24637330f729Sjoerg // Pass "-faligned-alloc-unavailable" only when the user hasn't manually
24647330f729Sjoerg // enabled or disabled aligned allocations.
24657330f729Sjoerg if (!DriverArgs.hasArgNoClaim(options::OPT_faligned_allocation,
24667330f729Sjoerg options::OPT_fno_aligned_allocation) &&
24677330f729Sjoerg isAlignedAllocationUnavailable())
24687330f729Sjoerg CC1Args.push_back("-faligned-alloc-unavailable");
24697330f729Sjoerg
24707330f729Sjoerg if (SDKInfo) {
24717330f729Sjoerg /// Pass the SDK version to the compiler when the SDK information is
24727330f729Sjoerg /// available.
24737330f729Sjoerg std::string Arg;
24747330f729Sjoerg llvm::raw_string_ostream OS(Arg);
24757330f729Sjoerg OS << "-target-sdk-version=" << SDKInfo->getVersion();
24767330f729Sjoerg CC1Args.push_back(DriverArgs.MakeArgString(OS.str()));
24777330f729Sjoerg }
2478*e038c9c4Sjoerg
2479*e038c9c4Sjoerg // Enable compatibility mode for NSItemProviderCompletionHandler in
2480*e038c9c4Sjoerg // Foundation/NSItemProvider.h.
2481*e038c9c4Sjoerg CC1Args.push_back("-fcompatibility-qualified-id-block-type-checking");
2482*e038c9c4Sjoerg
2483*e038c9c4Sjoerg // Give static local variables in inline functions hidden visibility when
2484*e038c9c4Sjoerg // -fvisibility-inlines-hidden is enabled.
2485*e038c9c4Sjoerg if (!DriverArgs.getLastArgNoClaim(
2486*e038c9c4Sjoerg options::OPT_fvisibility_inlines_hidden_static_local_var,
2487*e038c9c4Sjoerg options::OPT_fno_visibility_inlines_hidden_static_local_var))
2488*e038c9c4Sjoerg CC1Args.push_back("-fvisibility-inlines-hidden-static-local-var");
24897330f729Sjoerg }
24907330f729Sjoerg
24917330f729Sjoerg DerivedArgList *
TranslateArgs(const DerivedArgList & Args,StringRef BoundArch,Action::OffloadKind DeviceOffloadKind) const24927330f729Sjoerg Darwin::TranslateArgs(const DerivedArgList &Args, StringRef BoundArch,
24937330f729Sjoerg Action::OffloadKind DeviceOffloadKind) const {
24947330f729Sjoerg // First get the generic Apple args, before moving onto Darwin-specific ones.
24957330f729Sjoerg DerivedArgList *DAL =
24967330f729Sjoerg MachO::TranslateArgs(Args, BoundArch, DeviceOffloadKind);
24977330f729Sjoerg const OptTable &Opts = getDriver().getOpts();
24987330f729Sjoerg
24997330f729Sjoerg // If no architecture is bound, none of the translations here are relevant.
25007330f729Sjoerg if (BoundArch.empty())
25017330f729Sjoerg return DAL;
25027330f729Sjoerg
25037330f729Sjoerg // Add an explicit version min argument for the deployment target. We do this
25047330f729Sjoerg // after argument translation because -Xarch_ arguments may add a version min
25057330f729Sjoerg // argument.
25067330f729Sjoerg AddDeploymentTarget(*DAL);
25077330f729Sjoerg
25087330f729Sjoerg // For iOS 6, undo the translation to add -static for -mkernel/-fapple-kext.
25097330f729Sjoerg // FIXME: It would be far better to avoid inserting those -static arguments,
25107330f729Sjoerg // but we can't check the deployment target in the translation code until
25117330f729Sjoerg // it is set here.
25127330f729Sjoerg if (isTargetWatchOSBased() ||
25137330f729Sjoerg (isTargetIOSBased() && !isIPhoneOSVersionLT(6, 0))) {
25147330f729Sjoerg for (ArgList::iterator it = DAL->begin(), ie = DAL->end(); it != ie; ) {
25157330f729Sjoerg Arg *A = *it;
25167330f729Sjoerg ++it;
25177330f729Sjoerg if (A->getOption().getID() != options::OPT_mkernel &&
25187330f729Sjoerg A->getOption().getID() != options::OPT_fapple_kext)
25197330f729Sjoerg continue;
25207330f729Sjoerg assert(it != ie && "unexpected argument translation");
25217330f729Sjoerg A = *it;
25227330f729Sjoerg assert(A->getOption().getID() == options::OPT_static &&
25237330f729Sjoerg "missing expected -static argument");
25247330f729Sjoerg *it = nullptr;
25257330f729Sjoerg ++it;
25267330f729Sjoerg }
25277330f729Sjoerg }
25287330f729Sjoerg
25297330f729Sjoerg if (!Args.getLastArg(options::OPT_stdlib_EQ) &&
25307330f729Sjoerg GetCXXStdlibType(Args) == ToolChain::CST_Libcxx)
25317330f729Sjoerg DAL->AddJoinedArg(nullptr, Opts.getOption(options::OPT_stdlib_EQ),
25327330f729Sjoerg "libc++");
25337330f729Sjoerg
25347330f729Sjoerg // Validate the C++ standard library choice.
25357330f729Sjoerg CXXStdlibType Type = GetCXXStdlibType(*DAL);
25367330f729Sjoerg if (Type == ToolChain::CST_Libcxx) {
25377330f729Sjoerg // Check whether the target provides libc++.
25387330f729Sjoerg StringRef where;
25397330f729Sjoerg
25407330f729Sjoerg // Complain about targeting iOS < 5.0 in any way.
25417330f729Sjoerg if (isTargetIOSBased() && isIPhoneOSVersionLT(5, 0))
25427330f729Sjoerg where = "iOS 5.0";
25437330f729Sjoerg
25447330f729Sjoerg if (where != StringRef()) {
25457330f729Sjoerg getDriver().Diag(clang::diag::err_drv_invalid_libcxx_deployment) << where;
25467330f729Sjoerg }
25477330f729Sjoerg }
25487330f729Sjoerg
25497330f729Sjoerg auto Arch = tools::darwin::getArchTypeForMachOArchName(BoundArch);
25507330f729Sjoerg if ((Arch == llvm::Triple::arm || Arch == llvm::Triple::thumb)) {
25517330f729Sjoerg if (Args.hasFlag(options::OPT_fomit_frame_pointer,
25527330f729Sjoerg options::OPT_fno_omit_frame_pointer, false))
25537330f729Sjoerg getDriver().Diag(clang::diag::warn_drv_unsupported_opt_for_target)
25547330f729Sjoerg << "-fomit-frame-pointer" << BoundArch;
25557330f729Sjoerg }
25567330f729Sjoerg
25577330f729Sjoerg return DAL;
25587330f729Sjoerg }
25597330f729Sjoerg
IsUnwindTablesDefault(const ArgList & Args) const25607330f729Sjoerg bool MachO::IsUnwindTablesDefault(const ArgList &Args) const {
25617330f729Sjoerg // Unwind tables are not emitted if -fno-exceptions is supplied (except when
25627330f729Sjoerg // targeting x86_64).
25637330f729Sjoerg return getArch() == llvm::Triple::x86_64 ||
25647330f729Sjoerg (GetExceptionModel(Args) != llvm::ExceptionHandling::SjLj &&
25657330f729Sjoerg Args.hasFlag(options::OPT_fexceptions, options::OPT_fno_exceptions,
25667330f729Sjoerg true));
25677330f729Sjoerg }
25687330f729Sjoerg
UseDwarfDebugFlags() const25697330f729Sjoerg bool MachO::UseDwarfDebugFlags() const {
25707330f729Sjoerg if (const char *S = ::getenv("RC_DEBUG_OPTIONS"))
25717330f729Sjoerg return S[0] != '\0';
25727330f729Sjoerg return false;
25737330f729Sjoerg }
25747330f729Sjoerg
GetExceptionModel(const ArgList & Args) const25757330f729Sjoerg llvm::ExceptionHandling Darwin::GetExceptionModel(const ArgList &Args) const {
25767330f729Sjoerg // Darwin uses SjLj exceptions on ARM.
25777330f729Sjoerg if (getTriple().getArch() != llvm::Triple::arm &&
25787330f729Sjoerg getTriple().getArch() != llvm::Triple::thumb)
25797330f729Sjoerg return llvm::ExceptionHandling::None;
25807330f729Sjoerg
25817330f729Sjoerg // Only watchOS uses the new DWARF/Compact unwinding method.
25827330f729Sjoerg llvm::Triple Triple(ComputeLLVMTriple(Args));
25837330f729Sjoerg if (Triple.isWatchABI())
25847330f729Sjoerg return llvm::ExceptionHandling::DwarfCFI;
25857330f729Sjoerg
25867330f729Sjoerg return llvm::ExceptionHandling::SjLj;
25877330f729Sjoerg }
25887330f729Sjoerg
SupportsEmbeddedBitcode() const25897330f729Sjoerg bool Darwin::SupportsEmbeddedBitcode() const {
25907330f729Sjoerg assert(TargetInitialized && "Target not initialized!");
25917330f729Sjoerg if (isTargetIPhoneOS() && isIPhoneOSVersionLT(6, 0))
25927330f729Sjoerg return false;
25937330f729Sjoerg return true;
25947330f729Sjoerg }
25957330f729Sjoerg
isPICDefault() const25967330f729Sjoerg bool MachO::isPICDefault() const { return true; }
25977330f729Sjoerg
isPIEDefault() const25987330f729Sjoerg bool MachO::isPIEDefault() const { return false; }
25997330f729Sjoerg
isPICDefaultForced() const26007330f729Sjoerg bool MachO::isPICDefaultForced() const {
26017330f729Sjoerg return (getArch() == llvm::Triple::x86_64 ||
26027330f729Sjoerg getArch() == llvm::Triple::aarch64);
26037330f729Sjoerg }
26047330f729Sjoerg
SupportsProfiling() const26057330f729Sjoerg bool MachO::SupportsProfiling() const {
26067330f729Sjoerg // Profiling instrumentation is only supported on x86.
2607*e038c9c4Sjoerg return getTriple().isX86();
26087330f729Sjoerg }
26097330f729Sjoerg
addMinVersionArgs(const ArgList & Args,ArgStringList & CmdArgs) const26107330f729Sjoerg void Darwin::addMinVersionArgs(const ArgList &Args,
26117330f729Sjoerg ArgStringList &CmdArgs) const {
26127330f729Sjoerg VersionTuple TargetVersion = getTargetVersion();
26137330f729Sjoerg
26147330f729Sjoerg if (isTargetWatchOS())
26157330f729Sjoerg CmdArgs.push_back("-watchos_version_min");
26167330f729Sjoerg else if (isTargetWatchOSSimulator())
26177330f729Sjoerg CmdArgs.push_back("-watchos_simulator_version_min");
26187330f729Sjoerg else if (isTargetTvOS())
26197330f729Sjoerg CmdArgs.push_back("-tvos_version_min");
26207330f729Sjoerg else if (isTargetTvOSSimulator())
26217330f729Sjoerg CmdArgs.push_back("-tvos_simulator_version_min");
26227330f729Sjoerg else if (isTargetIOSSimulator())
26237330f729Sjoerg CmdArgs.push_back("-ios_simulator_version_min");
26247330f729Sjoerg else if (isTargetIOSBased())
26257330f729Sjoerg CmdArgs.push_back("-iphoneos_version_min");
26267330f729Sjoerg else {
26277330f729Sjoerg assert(isTargetMacOS() && "unexpected target");
26287330f729Sjoerg CmdArgs.push_back("-macosx_version_min");
26297330f729Sjoerg }
26307330f729Sjoerg
2631*e038c9c4Sjoerg VersionTuple MinTgtVers = getEffectiveTriple().getMinimumSupportedOSVersion();
2632*e038c9c4Sjoerg if (!MinTgtVers.empty() && MinTgtVers > TargetVersion)
2633*e038c9c4Sjoerg TargetVersion = MinTgtVers;
26347330f729Sjoerg CmdArgs.push_back(Args.MakeArgString(TargetVersion.getAsString()));
26357330f729Sjoerg }
26367330f729Sjoerg
getPlatformName(Darwin::DarwinPlatformKind Platform,Darwin::DarwinEnvironmentKind Environment)2637*e038c9c4Sjoerg static const char *getPlatformName(Darwin::DarwinPlatformKind Platform,
2638*e038c9c4Sjoerg Darwin::DarwinEnvironmentKind Environment) {
2639*e038c9c4Sjoerg switch (Platform) {
2640*e038c9c4Sjoerg case Darwin::MacOS:
2641*e038c9c4Sjoerg return "macos";
2642*e038c9c4Sjoerg case Darwin::IPhoneOS:
2643*e038c9c4Sjoerg if (Environment == Darwin::NativeEnvironment ||
2644*e038c9c4Sjoerg Environment == Darwin::Simulator)
2645*e038c9c4Sjoerg return "ios";
2646*e038c9c4Sjoerg // FIXME: Add macCatalyst support here ("\"mac catalyst\"").
2647*e038c9c4Sjoerg llvm_unreachable("macCatalyst isn't yet supported");
2648*e038c9c4Sjoerg case Darwin::TvOS:
2649*e038c9c4Sjoerg return "tvos";
2650*e038c9c4Sjoerg case Darwin::WatchOS:
2651*e038c9c4Sjoerg return "watchos";
2652*e038c9c4Sjoerg }
2653*e038c9c4Sjoerg llvm_unreachable("invalid platform");
2654*e038c9c4Sjoerg }
2655*e038c9c4Sjoerg
addPlatformVersionArgs(const llvm::opt::ArgList & Args,llvm::opt::ArgStringList & CmdArgs) const2656*e038c9c4Sjoerg void Darwin::addPlatformVersionArgs(const llvm::opt::ArgList &Args,
2657*e038c9c4Sjoerg llvm::opt::ArgStringList &CmdArgs) const {
2658*e038c9c4Sjoerg // -platform_version <platform> <target_version> <sdk_version>
2659*e038c9c4Sjoerg // Both the target and SDK version support only up to 3 components.
2660*e038c9c4Sjoerg CmdArgs.push_back("-platform_version");
2661*e038c9c4Sjoerg std::string PlatformName = getPlatformName(TargetPlatform, TargetEnvironment);
2662*e038c9c4Sjoerg if (TargetEnvironment == Darwin::Simulator)
2663*e038c9c4Sjoerg PlatformName += "-simulator";
2664*e038c9c4Sjoerg CmdArgs.push_back(Args.MakeArgString(PlatformName));
2665*e038c9c4Sjoerg VersionTuple TargetVersion = getTargetVersion().withoutBuild();
2666*e038c9c4Sjoerg VersionTuple MinTgtVers = getEffectiveTriple().getMinimumSupportedOSVersion();
2667*e038c9c4Sjoerg if (!MinTgtVers.empty() && MinTgtVers > TargetVersion)
2668*e038c9c4Sjoerg TargetVersion = MinTgtVers;
2669*e038c9c4Sjoerg CmdArgs.push_back(Args.MakeArgString(TargetVersion.getAsString()));
2670*e038c9c4Sjoerg if (SDKInfo) {
2671*e038c9c4Sjoerg VersionTuple SDKVersion = SDKInfo->getVersion().withoutBuild();
2672*e038c9c4Sjoerg CmdArgs.push_back(Args.MakeArgString(SDKVersion.getAsString()));
26737330f729Sjoerg } else {
2674*e038c9c4Sjoerg // Use an SDK version that's matching the deployment target if the SDK
2675*e038c9c4Sjoerg // version is missing. This is preferred over an empty SDK version (0.0.0)
2676*e038c9c4Sjoerg // as the system's runtime might expect the linked binary to contain a
2677*e038c9c4Sjoerg // valid SDK version in order for the binary to work correctly. It's
2678*e038c9c4Sjoerg // reasonable to use the deployment target version as a proxy for the
2679*e038c9c4Sjoerg // SDK version because older SDKs don't guarantee support for deployment
2680*e038c9c4Sjoerg // targets newer than the SDK versions, so that rules out using some
2681*e038c9c4Sjoerg // predetermined older SDK version, which leaves the deployment target
2682*e038c9c4Sjoerg // version as the only reasonable choice.
2683*e038c9c4Sjoerg CmdArgs.push_back(Args.MakeArgString(TargetVersion.getAsString()));
2684*e038c9c4Sjoerg }
2685*e038c9c4Sjoerg }
2686*e038c9c4Sjoerg
2687*e038c9c4Sjoerg // Add additional link args for the -dynamiclib option.
addDynamicLibLinkArgs(const Darwin & D,const ArgList & Args,ArgStringList & CmdArgs)2688*e038c9c4Sjoerg static void addDynamicLibLinkArgs(const Darwin &D, const ArgList &Args,
2689*e038c9c4Sjoerg ArgStringList &CmdArgs) {
2690*e038c9c4Sjoerg // Derived from darwin_dylib1 spec.
2691*e038c9c4Sjoerg if (D.isTargetIPhoneOS()) {
2692*e038c9c4Sjoerg if (D.isIPhoneOSVersionLT(3, 1))
26937330f729Sjoerg CmdArgs.push_back("-ldylib1.o");
2694*e038c9c4Sjoerg return;
2695*e038c9c4Sjoerg }
2696*e038c9c4Sjoerg
2697*e038c9c4Sjoerg if (!D.isTargetMacOS())
2698*e038c9c4Sjoerg return;
2699*e038c9c4Sjoerg if (D.isMacosxVersionLT(10, 5))
2700*e038c9c4Sjoerg CmdArgs.push_back("-ldylib1.o");
2701*e038c9c4Sjoerg else if (D.isMacosxVersionLT(10, 6))
27027330f729Sjoerg CmdArgs.push_back("-ldylib1.10.5.o");
27037330f729Sjoerg }
2704*e038c9c4Sjoerg
2705*e038c9c4Sjoerg // Add additional link args for the -bundle option.
addBundleLinkArgs(const Darwin & D,const ArgList & Args,ArgStringList & CmdArgs)2706*e038c9c4Sjoerg static void addBundleLinkArgs(const Darwin &D, const ArgList &Args,
2707*e038c9c4Sjoerg ArgStringList &CmdArgs) {
2708*e038c9c4Sjoerg if (Args.hasArg(options::OPT_static))
2709*e038c9c4Sjoerg return;
27107330f729Sjoerg // Derived from darwin_bundle1 spec.
2711*e038c9c4Sjoerg if ((D.isTargetIPhoneOS() && D.isIPhoneOSVersionLT(3, 1)) ||
2712*e038c9c4Sjoerg (D.isTargetMacOS() && D.isMacosxVersionLT(10, 6)))
27137330f729Sjoerg CmdArgs.push_back("-lbundle1.o");
27147330f729Sjoerg }
2715*e038c9c4Sjoerg
2716*e038c9c4Sjoerg // Add additional link args for the -pg option.
addPgProfilingLinkArgs(const Darwin & D,const ArgList & Args,ArgStringList & CmdArgs)2717*e038c9c4Sjoerg static void addPgProfilingLinkArgs(const Darwin &D, const ArgList &Args,
2718*e038c9c4Sjoerg ArgStringList &CmdArgs) {
2719*e038c9c4Sjoerg if (D.isTargetMacOS() && D.isMacosxVersionLT(10, 9)) {
2720*e038c9c4Sjoerg if (Args.hasArg(options::OPT_static) || Args.hasArg(options::OPT_object) ||
27217330f729Sjoerg Args.hasArg(options::OPT_preload)) {
27227330f729Sjoerg CmdArgs.push_back("-lgcrt0.o");
27237330f729Sjoerg } else {
27247330f729Sjoerg CmdArgs.push_back("-lgcrt1.o");
27257330f729Sjoerg
27267330f729Sjoerg // darwin_crt2 spec is empty.
27277330f729Sjoerg }
27287330f729Sjoerg // By default on OS X 10.8 and later, we don't link with a crt1.o
27297330f729Sjoerg // file and the linker knows to use _main as the entry point. But,
27307330f729Sjoerg // when compiling with -pg, we need to link with the gcrt1.o file,
27317330f729Sjoerg // so pass the -no_new_main option to tell the linker to use the
27327330f729Sjoerg // "start" symbol as the entry point.
2733*e038c9c4Sjoerg if (!D.isMacosxVersionLT(10, 8))
27347330f729Sjoerg CmdArgs.push_back("-no_new_main");
27357330f729Sjoerg } else {
2736*e038c9c4Sjoerg D.getDriver().Diag(diag::err_drv_clang_unsupported_opt_pg_darwin)
2737*e038c9c4Sjoerg << D.isTargetMacOS();
27387330f729Sjoerg }
2739*e038c9c4Sjoerg }
27407330f729Sjoerg
addDefaultCRTLinkArgs(const Darwin & D,const ArgList & Args,ArgStringList & CmdArgs)2741*e038c9c4Sjoerg static void addDefaultCRTLinkArgs(const Darwin &D, const ArgList &Args,
2742*e038c9c4Sjoerg ArgStringList &CmdArgs) {
2743*e038c9c4Sjoerg // Derived from darwin_crt1 spec.
2744*e038c9c4Sjoerg if (D.isTargetIPhoneOS()) {
2745*e038c9c4Sjoerg if (D.getArch() == llvm::Triple::aarch64)
2746*e038c9c4Sjoerg ; // iOS does not need any crt1 files for arm64
2747*e038c9c4Sjoerg else if (D.isIPhoneOSVersionLT(3, 1))
2748*e038c9c4Sjoerg CmdArgs.push_back("-lcrt1.o");
2749*e038c9c4Sjoerg else if (D.isIPhoneOSVersionLT(6, 0))
2750*e038c9c4Sjoerg CmdArgs.push_back("-lcrt1.3.1.o");
2751*e038c9c4Sjoerg return;
2752*e038c9c4Sjoerg }
2753*e038c9c4Sjoerg
2754*e038c9c4Sjoerg if (!D.isTargetMacOS())
2755*e038c9c4Sjoerg return;
2756*e038c9c4Sjoerg if (D.isMacosxVersionLT(10, 5))
2757*e038c9c4Sjoerg CmdArgs.push_back("-lcrt1.o");
2758*e038c9c4Sjoerg else if (D.isMacosxVersionLT(10, 6))
2759*e038c9c4Sjoerg CmdArgs.push_back("-lcrt1.10.5.o");
2760*e038c9c4Sjoerg else if (D.isMacosxVersionLT(10, 8))
2761*e038c9c4Sjoerg CmdArgs.push_back("-lcrt1.10.6.o");
27627330f729Sjoerg // darwin_crt2 spec is empty.
27637330f729Sjoerg }
27647330f729Sjoerg
addStartObjectFileArgs(const ArgList & Args,ArgStringList & CmdArgs) const2765*e038c9c4Sjoerg void Darwin::addStartObjectFileArgs(const ArgList &Args,
2766*e038c9c4Sjoerg ArgStringList &CmdArgs) const {
2767*e038c9c4Sjoerg // Derived from startfile spec.
2768*e038c9c4Sjoerg if (Args.hasArg(options::OPT_dynamiclib))
2769*e038c9c4Sjoerg addDynamicLibLinkArgs(*this, Args, CmdArgs);
2770*e038c9c4Sjoerg else if (Args.hasArg(options::OPT_bundle))
2771*e038c9c4Sjoerg addBundleLinkArgs(*this, Args, CmdArgs);
2772*e038c9c4Sjoerg else if (Args.hasArg(options::OPT_pg) && SupportsProfiling())
2773*e038c9c4Sjoerg addPgProfilingLinkArgs(*this, Args, CmdArgs);
2774*e038c9c4Sjoerg else if (Args.hasArg(options::OPT_static) ||
2775*e038c9c4Sjoerg Args.hasArg(options::OPT_object) ||
2776*e038c9c4Sjoerg Args.hasArg(options::OPT_preload))
2777*e038c9c4Sjoerg CmdArgs.push_back("-lcrt0.o");
2778*e038c9c4Sjoerg else
2779*e038c9c4Sjoerg addDefaultCRTLinkArgs(*this, Args, CmdArgs);
2780*e038c9c4Sjoerg
2781*e038c9c4Sjoerg if (isTargetMacOS() && Args.hasArg(options::OPT_shared_libgcc) &&
2782*e038c9c4Sjoerg isMacosxVersionLT(10, 5)) {
27837330f729Sjoerg const char *Str = Args.MakeArgString(GetFilePath("crt3.o"));
27847330f729Sjoerg CmdArgs.push_back(Str);
27857330f729Sjoerg }
27867330f729Sjoerg }
27877330f729Sjoerg
CheckObjCARC() const27887330f729Sjoerg void Darwin::CheckObjCARC() const {
27897330f729Sjoerg if (isTargetIOSBased() || isTargetWatchOSBased() ||
27907330f729Sjoerg (isTargetMacOS() && !isMacosxVersionLT(10, 6)))
27917330f729Sjoerg return;
27927330f729Sjoerg getDriver().Diag(diag::err_arc_unsupported_on_toolchain);
27937330f729Sjoerg }
27947330f729Sjoerg
getSupportedSanitizers() const27957330f729Sjoerg SanitizerMask Darwin::getSupportedSanitizers() const {
27967330f729Sjoerg const bool IsX86_64 = getTriple().getArch() == llvm::Triple::x86_64;
2797*e038c9c4Sjoerg const bool IsAArch64 = getTriple().getArch() == llvm::Triple::aarch64;
27987330f729Sjoerg SanitizerMask Res = ToolChain::getSupportedSanitizers();
27997330f729Sjoerg Res |= SanitizerKind::Address;
28007330f729Sjoerg Res |= SanitizerKind::PointerCompare;
28017330f729Sjoerg Res |= SanitizerKind::PointerSubtract;
28027330f729Sjoerg Res |= SanitizerKind::Leak;
28037330f729Sjoerg Res |= SanitizerKind::Fuzzer;
28047330f729Sjoerg Res |= SanitizerKind::FuzzerNoLink;
28057330f729Sjoerg Res |= SanitizerKind::Function;
2806*e038c9c4Sjoerg Res |= SanitizerKind::ObjCCast;
28077330f729Sjoerg
28087330f729Sjoerg // Prior to 10.9, macOS shipped a version of the C++ standard library without
28097330f729Sjoerg // C++11 support. The same is true of iOS prior to version 5. These OS'es are
28107330f729Sjoerg // incompatible with -fsanitize=vptr.
28117330f729Sjoerg if (!(isTargetMacOS() && isMacosxVersionLT(10, 9))
28127330f729Sjoerg && !(isTargetIPhoneOS() && isIPhoneOSVersionLT(5, 0)))
28137330f729Sjoerg Res |= SanitizerKind::Vptr;
28147330f729Sjoerg
2815*e038c9c4Sjoerg if ((IsX86_64 || IsAArch64) && isTargetMacOS()) {
28167330f729Sjoerg Res |= SanitizerKind::Thread;
28177330f729Sjoerg } else if (isTargetIOSSimulator() || isTargetTvOSSimulator()) {
28187330f729Sjoerg if (IsX86_64)
28197330f729Sjoerg Res |= SanitizerKind::Thread;
28207330f729Sjoerg }
28217330f729Sjoerg return Res;
28227330f729Sjoerg }
28237330f729Sjoerg
printVerboseInfo(raw_ostream & OS) const28247330f729Sjoerg void Darwin::printVerboseInfo(raw_ostream &OS) const {
28257330f729Sjoerg CudaInstallation.print(OS);
2826*e038c9c4Sjoerg RocmInstallation.print(OS);
28277330f729Sjoerg }
2828