3793 lines · cpp
1//===--- Darwin.cpp - Darwin Tool and ToolChain Implementations -*- C++ -*-===//2//3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.4// See https://llvm.org/LICENSE.txt for license information.5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception6//7//===----------------------------------------------------------------------===//8 9#include "Darwin.h"10#include "Arch/ARM.h"11#include "clang/Basic/AlignedAllocation.h"12#include "clang/Basic/ObjCRuntime.h"13#include "clang/Config/config.h"14#include "clang/Driver/CommonArgs.h"15#include "clang/Driver/Compilation.h"16#include "clang/Driver/Driver.h"17#include "clang/Driver/SanitizerArgs.h"18#include "clang/Options/Options.h"19#include "llvm/ADT/StringSwitch.h"20#include "llvm/Option/ArgList.h"21#include "llvm/ProfileData/InstrProf.h"22#include "llvm/ProfileData/MemProf.h"23#include "llvm/Support/Path.h"24#include "llvm/Support/Threading.h"25#include "llvm/Support/VirtualFileSystem.h"26#include "llvm/TargetParser/TargetParser.h"27#include "llvm/TargetParser/Triple.h"28#include <cstdlib> // ::getenv29 30using namespace clang::driver;31using namespace clang::driver::tools;32using namespace clang::driver::toolchains;33using namespace clang;34using namespace llvm::opt;35 36static VersionTuple minimumMacCatalystDeploymentTarget() {37 return VersionTuple(13, 1);38}39 40llvm::Triple::ArchType darwin::getArchTypeForMachOArchName(StringRef Str) {41 // See arch(3) and llvm-gcc's driver-driver.c. We don't implement support for42 // archs which Darwin doesn't use.43 44 // The matching this routine does is fairly pointless, since it is neither the45 // complete architecture list, nor a reasonable subset. The problem is that46 // historically the driver accepts this and also ties its -march=47 // handling to the architecture name, so we need to be careful before removing48 // support for it.49 50 // This code must be kept in sync with Clang's Darwin specific argument51 // translation.52 53 return llvm::StringSwitch<llvm::Triple::ArchType>(Str)54 .Cases({"i386", "i486", "i486SX", "i586", "i686"}, llvm::Triple::x86)55 .Cases({"pentium", "pentpro", "pentIIm3", "pentIIm5", "pentium4"},56 llvm::Triple::x86)57 .Cases({"x86_64", "x86_64h"}, llvm::Triple::x86_64)58 // This is derived from the driver.59 .Cases({"arm", "armv4t", "armv5", "armv6", "armv6m"}, llvm::Triple::arm)60 .Cases({"armv7", "armv7em", "armv7k", "armv7m"}, llvm::Triple::arm)61 .Cases({"armv7s", "xscale"}, llvm::Triple::arm)62 .Cases({"arm64", "arm64e"}, llvm::Triple::aarch64)63 .Case("arm64_32", llvm::Triple::aarch64_32)64 .Case("r600", llvm::Triple::r600)65 .Case("amdgcn", llvm::Triple::amdgcn)66 .Case("nvptx", llvm::Triple::nvptx)67 .Case("nvptx64", llvm::Triple::nvptx64)68 .Case("amdil", llvm::Triple::amdil)69 .Case("spir", llvm::Triple::spir)70 .Default(llvm::Triple::UnknownArch);71}72 73void darwin::setTripleTypeForMachOArchName(llvm::Triple &T, StringRef Str,74 const ArgList &Args) {75 const llvm::Triple::ArchType Arch = getArchTypeForMachOArchName(Str);76 llvm::ARM::ArchKind ArchKind = llvm::ARM::parseArch(Str);77 T.setArch(Arch);78 if (Arch != llvm::Triple::UnknownArch)79 T.setArchName(Str);80 81 if (ArchKind == llvm::ARM::ArchKind::ARMV6M ||82 ArchKind == llvm::ARM::ArchKind::ARMV7M ||83 ArchKind == llvm::ARM::ArchKind::ARMV7EM) {84 // Don't reject these -version-min= if we have the appropriate triple.85 if (T.getOS() == llvm::Triple::IOS)86 for (Arg *A : Args.filtered(options::OPT_mios_version_min_EQ))87 A->ignoreTargetSpecific();88 if (T.getOS() == llvm::Triple::WatchOS)89 for (Arg *A : Args.filtered(options::OPT_mwatchos_version_min_EQ))90 A->ignoreTargetSpecific();91 if (T.getOS() == llvm::Triple::TvOS)92 for (Arg *A : Args.filtered(options::OPT_mtvos_version_min_EQ))93 A->ignoreTargetSpecific();94 95 T.setOS(llvm::Triple::UnknownOS);96 T.setObjectFormat(llvm::Triple::MachO);97 }98}99 100void darwin::Assembler::ConstructJob(Compilation &C, const JobAction &JA,101 const InputInfo &Output,102 const InputInfoList &Inputs,103 const ArgList &Args,104 const char *LinkingOutput) const {105 const llvm::Triple &T(getToolChain().getTriple());106 107 ArgStringList CmdArgs;108 109 assert(Inputs.size() == 1 && "Unexpected number of inputs.");110 const InputInfo &Input = Inputs[0];111 112 // Determine the original source input.113 const Action *SourceAction = &JA;114 while (SourceAction->getKind() != Action::InputClass) {115 assert(!SourceAction->getInputs().empty() && "unexpected root action!");116 SourceAction = SourceAction->getInputs()[0];117 }118 119 // If -fno-integrated-as is used add -Q to the darwin assembler driver to make120 // sure it runs its system assembler not clang's integrated assembler.121 // Applicable to darwin11+ and Xcode 4+. darwin<10 lacked integrated-as.122 // FIXME: at run-time detect assembler capabilities or rely on version123 // information forwarded by -target-assembler-version.124 if (Args.hasArg(options::OPT_fno_integrated_as)) {125 if (!(T.isMacOSX() && T.isMacOSXVersionLT(10, 7)))126 CmdArgs.push_back("-Q");127 }128 129 // Forward -g, assuming we are dealing with an actual assembly file.130 if (SourceAction->getType() == types::TY_Asm ||131 SourceAction->getType() == types::TY_PP_Asm) {132 if (Args.hasArg(options::OPT_gstabs))133 CmdArgs.push_back("--gstabs");134 else if (Args.hasArg(options::OPT_g_Group))135 CmdArgs.push_back("-g");136 }137 138 // Derived from asm spec.139 AddMachOArch(Args, CmdArgs);140 141 // Use -force_cpusubtype_ALL on x86 by default.142 if (T.isX86() || Args.hasArg(options::OPT_force__cpusubtype__ALL))143 CmdArgs.push_back("-force_cpusubtype_ALL");144 145 if (getToolChain().getArch() != llvm::Triple::x86_64 &&146 (((Args.hasArg(options::OPT_mkernel) ||147 Args.hasArg(options::OPT_fapple_kext)) &&148 getMachOToolChain().isKernelStatic()) ||149 Args.hasArg(options::OPT_static)))150 CmdArgs.push_back("-static");151 152 Args.AddAllArgValues(CmdArgs, options::OPT_Wa_COMMA, options::OPT_Xassembler);153 154 assert(Output.isFilename() && "Unexpected lipo output.");155 CmdArgs.push_back("-o");156 CmdArgs.push_back(Output.getFilename());157 158 assert(Input.isFilename() && "Invalid input.");159 CmdArgs.push_back(Input.getFilename());160 161 // asm_final spec is empty.162 163 const char *Exec = Args.MakeArgString(getToolChain().GetProgramPath("as"));164 C.addCommand(std::make_unique<Command>(JA, *this, ResponseFileSupport::None(),165 Exec, CmdArgs, Inputs, Output));166}167 168void darwin::MachOTool::anchor() {}169 170void darwin::MachOTool::AddMachOArch(const ArgList &Args,171 ArgStringList &CmdArgs) const {172 StringRef ArchName = getMachOToolChain().getMachOArchName(Args);173 174 // Derived from darwin_arch spec.175 CmdArgs.push_back("-arch");176 CmdArgs.push_back(Args.MakeArgString(ArchName));177 178 // FIXME: Is this needed anymore?179 if (ArchName == "arm")180 CmdArgs.push_back("-force_cpusubtype_ALL");181}182 183bool darwin::Linker::NeedsTempPath(const InputInfoList &Inputs) const {184 // We only need to generate a temp path for LTO if we aren't compiling object185 // files. When compiling source files, we run 'dsymutil' after linking. We186 // don't run 'dsymutil' when compiling object files.187 for (const auto &Input : Inputs)188 if (Input.getType() != types::TY_Object)189 return true;190 191 return false;192}193 194/// Pass -no_deduplicate to ld64 under certain conditions:195///196/// - Either -O0 or -O1 is explicitly specified197/// - No -O option is specified *and* this is a compile+link (implicit -O0)198///199/// Also do *not* add -no_deduplicate when no -O option is specified and this200/// is just a link (we can't imply -O0)201static bool shouldLinkerNotDedup(bool IsLinkerOnlyAction, const ArgList &Args) {202 if (Arg *A = Args.getLastArg(options::OPT_O_Group)) {203 if (A->getOption().matches(options::OPT_O0))204 return true;205 if (A->getOption().matches(options::OPT_O))206 return llvm::StringSwitch<bool>(A->getValue())207 .Case("1", true)208 .Default(false);209 return false; // OPT_Ofast & OPT_O4210 }211 212 if (!IsLinkerOnlyAction) // Implicit -O0 for compile+linker only.213 return true;214 return false;215}216 217void darwin::Linker::AddLinkArgs(Compilation &C, const ArgList &Args,218 ArgStringList &CmdArgs,219 const InputInfoList &Inputs,220 VersionTuple Version, bool LinkerIsLLD,221 bool UsePlatformVersion) const {222 const Driver &D = getToolChain().getDriver();223 const toolchains::MachO &MachOTC = getMachOToolChain();224 225 // Newer linkers support -demangle. Pass it if supported and not disabled by226 // the user.227 if ((Version >= VersionTuple(100) || LinkerIsLLD) &&228 !Args.hasArg(options::OPT_Z_Xlinker__no_demangle))229 CmdArgs.push_back("-demangle");230 231 if (Args.hasArg(options::OPT_rdynamic) &&232 (Version >= VersionTuple(137) || LinkerIsLLD))233 CmdArgs.push_back("-export_dynamic");234 235 // If we are using App Extension restrictions, pass a flag to the linker236 // telling it that the compiled code has been audited.237 if (Args.hasFlag(options::OPT_fapplication_extension,238 options::OPT_fno_application_extension, false))239 CmdArgs.push_back("-application_extension");240 241 if (D.isUsingLTO() && (Version >= VersionTuple(116) || LinkerIsLLD) &&242 NeedsTempPath(Inputs)) {243 std::string TmpPathName;244 if (D.getLTOMode() == LTOK_Full) {245 // If we are using full LTO, then automatically create a temporary file246 // path for the linker to use, so that it's lifetime will extend past a247 // possible dsymutil step.248 TmpPathName =249 D.GetTemporaryPath("cc", types::getTypeTempSuffix(types::TY_Object));250 } else if (D.getLTOMode() == LTOK_Thin)251 // If we are using thin LTO, then create a directory instead.252 TmpPathName = D.GetTemporaryDirectory("thinlto");253 254 if (!TmpPathName.empty()) {255 auto *TmpPath = C.getArgs().MakeArgString(TmpPathName);256 C.addTempFile(TmpPath);257 CmdArgs.push_back("-object_path_lto");258 CmdArgs.push_back(TmpPath);259 }260 }261 262 // Use -lto_library option to specify the libLTO.dylib path. Try to find263 // it in clang installed libraries. ld64 will only look at this argument264 // when it actually uses LTO, so libLTO.dylib only needs to exist at link265 // time if ld64 decides that it needs to use LTO.266 // Since this is passed unconditionally, ld64 will never look for libLTO.dylib267 // next to it. That's ok since ld64 using a libLTO.dylib not matching the268 // clang version won't work anyways.269 // lld is built at the same revision as clang and statically links in270 // LLVM libraries, so it doesn't need libLTO.dylib.271 if (Version >= VersionTuple(133) && !LinkerIsLLD) {272 // Search for libLTO in <InstalledDir>/../lib/libLTO.dylib273 StringRef P = llvm::sys::path::parent_path(D.Dir);274 SmallString<128> LibLTOPath(P);275 llvm::sys::path::append(LibLTOPath, "lib");276 llvm::sys::path::append(LibLTOPath, "libLTO.dylib");277 CmdArgs.push_back("-lto_library");278 CmdArgs.push_back(C.getArgs().MakeArgString(LibLTOPath));279 }280 281 // ld64 version 262 and above runs the deduplicate pass by default.282 // FIXME: lld doesn't dedup by default. Should we pass `--icf=safe`283 // if `!shouldLinkerNotDedup()` if LinkerIsLLD here?284 if (Version >= VersionTuple(262) &&285 shouldLinkerNotDedup(C.getJobs().empty(), Args))286 CmdArgs.push_back("-no_deduplicate");287 288 // Derived from the "link" spec.289 Args.AddAllArgs(CmdArgs, options::OPT_static);290 if (!Args.hasArg(options::OPT_static))291 CmdArgs.push_back("-dynamic");292 if (Args.hasArg(options::OPT_fgnu_runtime)) {293 // FIXME: gcc replaces -lobjc in forward args with -lobjc-gnu294 // here. How do we wish to handle such things?295 }296 297 if (!Args.hasArg(options::OPT_dynamiclib)) {298 AddMachOArch(Args, CmdArgs);299 // FIXME: Why do this only on this path?300 Args.AddLastArg(CmdArgs, options::OPT_force__cpusubtype__ALL);301 302 Args.AddLastArg(CmdArgs, options::OPT_bundle);303 Args.AddAllArgs(CmdArgs, options::OPT_bundle__loader);304 Args.AddAllArgs(CmdArgs, options::OPT_client__name);305 306 Arg *A;307 if ((A = Args.getLastArg(options::OPT_compatibility__version)) ||308 (A = Args.getLastArg(options::OPT_current__version)) ||309 (A = Args.getLastArg(options::OPT_install__name)))310 D.Diag(diag::err_drv_argument_only_allowed_with) << A->getAsString(Args)311 << "-dynamiclib";312 313 Args.AddLastArg(CmdArgs, options::OPT_force__flat__namespace);314 Args.AddLastArg(CmdArgs, options::OPT_keep__private__externs);315 Args.AddLastArg(CmdArgs, options::OPT_private__bundle);316 } else {317 CmdArgs.push_back("-dylib");318 319 Arg *A;320 if ((A = Args.getLastArg(options::OPT_bundle)) ||321 (A = Args.getLastArg(options::OPT_bundle__loader)) ||322 (A = Args.getLastArg(options::OPT_client__name)) ||323 (A = Args.getLastArg(options::OPT_force__flat__namespace)) ||324 (A = Args.getLastArg(options::OPT_keep__private__externs)) ||325 (A = Args.getLastArg(options::OPT_private__bundle)))326 D.Diag(diag::err_drv_argument_not_allowed_with) << A->getAsString(Args)327 << "-dynamiclib";328 329 Args.AddAllArgsTranslated(CmdArgs, options::OPT_compatibility__version,330 "-dylib_compatibility_version");331 Args.AddAllArgsTranslated(CmdArgs, options::OPT_current__version,332 "-dylib_current_version");333 334 AddMachOArch(Args, CmdArgs);335 336 Args.AddAllArgsTranslated(CmdArgs, options::OPT_install__name,337 "-dylib_install_name");338 }339 340 Args.AddLastArg(CmdArgs, options::OPT_all__load);341 Args.AddAllArgs(CmdArgs, options::OPT_allowable__client);342 Args.AddLastArg(CmdArgs, options::OPT_bind__at__load);343 if (MachOTC.isTargetIOSBased())344 Args.AddLastArg(CmdArgs, options::OPT_arch__errors__fatal);345 Args.AddLastArg(CmdArgs, options::OPT_dead__strip);346 Args.AddLastArg(CmdArgs, options::OPT_no__dead__strip__inits__and__terms);347 Args.AddAllArgs(CmdArgs, options::OPT_dylib__file);348 Args.AddLastArg(CmdArgs, options::OPT_dynamic);349 Args.AddAllArgs(CmdArgs, options::OPT_exported__symbols__list);350 Args.AddLastArg(CmdArgs, options::OPT_flat__namespace);351 Args.AddAllArgs(CmdArgs, options::OPT_force__load);352 Args.AddAllArgs(CmdArgs, options::OPT_headerpad__max__install__names);353 Args.AddAllArgs(CmdArgs, options::OPT_image__base);354 Args.AddAllArgs(CmdArgs, options::OPT_init);355 356 // Add the deployment target.357 if (Version >= VersionTuple(520) || LinkerIsLLD || UsePlatformVersion)358 MachOTC.addPlatformVersionArgs(Args, CmdArgs);359 else360 MachOTC.addMinVersionArgs(Args, CmdArgs);361 362 Args.AddLastArg(CmdArgs, options::OPT_nomultidefs);363 Args.AddLastArg(CmdArgs, options::OPT_multi__module);364 Args.AddLastArg(CmdArgs, options::OPT_single__module);365 Args.AddAllArgs(CmdArgs, options::OPT_multiply__defined);366 Args.AddAllArgs(CmdArgs, options::OPT_multiply__defined__unused);367 368 if (const Arg *A =369 Args.getLastArg(options::OPT_fpie, options::OPT_fPIE,370 options::OPT_fno_pie, options::OPT_fno_PIE)) {371 if (A->getOption().matches(options::OPT_fpie) ||372 A->getOption().matches(options::OPT_fPIE))373 CmdArgs.push_back("-pie");374 else375 CmdArgs.push_back("-no_pie");376 }377 378 // for embed-bitcode, use -bitcode_bundle in linker command379 if (C.getDriver().embedBitcodeEnabled()) {380 // Check if the toolchain supports bitcode build flow.381 if (MachOTC.SupportsEmbeddedBitcode()) {382 CmdArgs.push_back("-bitcode_bundle");383 // FIXME: Pass this if LinkerIsLLD too, once it implements this flag.384 if (C.getDriver().embedBitcodeMarkerOnly() &&385 Version >= VersionTuple(278)) {386 CmdArgs.push_back("-bitcode_process_mode");387 CmdArgs.push_back("marker");388 }389 } else390 D.Diag(diag::err_drv_bitcode_unsupported_on_toolchain);391 }392 393 // If GlobalISel is enabled, pass it through to LLVM.394 if (Arg *A = Args.getLastArg(options::OPT_fglobal_isel,395 options::OPT_fno_global_isel)) {396 if (A->getOption().matches(options::OPT_fglobal_isel)) {397 CmdArgs.push_back("-mllvm");398 CmdArgs.push_back("-global-isel");399 // Disable abort and fall back to SDAG silently.400 CmdArgs.push_back("-mllvm");401 CmdArgs.push_back("-global-isel-abort=0");402 }403 }404 405 if (Args.hasArg(options::OPT_mkernel) ||406 Args.hasArg(options::OPT_fapple_kext) ||407 Args.hasArg(options::OPT_ffreestanding)) {408 CmdArgs.push_back("-mllvm");409 CmdArgs.push_back("-disable-atexit-based-global-dtor-lowering");410 }411 412 Args.AddLastArg(CmdArgs, options::OPT_prebind);413 Args.AddLastArg(CmdArgs, options::OPT_noprebind);414 Args.AddLastArg(CmdArgs, options::OPT_nofixprebinding);415 Args.AddLastArg(CmdArgs, options::OPT_prebind__all__twolevel__modules);416 Args.AddLastArg(CmdArgs, options::OPT_read__only__relocs);417 Args.AddAllArgs(CmdArgs, options::OPT_sectcreate);418 Args.AddAllArgs(CmdArgs, options::OPT_sectorder);419 Args.AddAllArgs(CmdArgs, options::OPT_seg1addr);420 Args.AddAllArgs(CmdArgs, options::OPT_segprot);421 Args.AddAllArgs(CmdArgs, options::OPT_segaddr);422 Args.AddAllArgs(CmdArgs, options::OPT_segs__read__only__addr);423 Args.AddAllArgs(CmdArgs, options::OPT_segs__read__write__addr);424 Args.AddAllArgs(CmdArgs, options::OPT_seg__addr__table);425 Args.AddAllArgs(CmdArgs, options::OPT_seg__addr__table__filename);426 Args.AddAllArgs(CmdArgs, options::OPT_sub__library);427 Args.AddAllArgs(CmdArgs, options::OPT_sub__umbrella);428 429 // Give --sysroot= preference, over the Apple specific behavior to also use430 // --isysroot as the syslibroot.431 // We check `OPT__sysroot_EQ` directly instead of `getSysRoot` to make sure we432 // prioritise command line arguments over configuration of `DEFAULT_SYSROOT`.433 if (const Arg *A = Args.getLastArg(options::OPT__sysroot_EQ)) {434 CmdArgs.push_back("-syslibroot");435 CmdArgs.push_back(A->getValue());436 } else if (const Arg *A = Args.getLastArg(options::OPT_isysroot)) {437 CmdArgs.push_back("-syslibroot");438 CmdArgs.push_back(A->getValue());439 } else if (StringRef sysroot = C.getSysRoot(); sysroot != "") {440 CmdArgs.push_back("-syslibroot");441 CmdArgs.push_back(C.getArgs().MakeArgString(sysroot));442 }443 444 Args.AddLastArg(CmdArgs, options::OPT_twolevel__namespace);445 Args.AddLastArg(CmdArgs, options::OPT_twolevel__namespace__hints);446 Args.AddAllArgs(CmdArgs, options::OPT_umbrella);447 Args.AddAllArgs(CmdArgs, options::OPT_undefined);448 Args.AddAllArgs(CmdArgs, options::OPT_unexported__symbols__list);449 Args.AddAllArgs(CmdArgs, options::OPT_weak__reference__mismatches);450 Args.AddLastArg(CmdArgs, options::OPT_X_Flag);451 Args.AddAllArgs(CmdArgs, options::OPT_y);452 Args.AddLastArg(CmdArgs, options::OPT_w);453 Args.AddAllArgs(CmdArgs, options::OPT_pagezero__size);454 Args.AddAllArgs(CmdArgs, options::OPT_segs__read__);455 Args.AddLastArg(CmdArgs, options::OPT_seglinkedit);456 Args.AddLastArg(CmdArgs, options::OPT_noseglinkedit);457 Args.AddAllArgs(CmdArgs, options::OPT_sectalign);458 Args.AddAllArgs(CmdArgs, options::OPT_sectobjectsymbols);459 Args.AddAllArgs(CmdArgs, options::OPT_segcreate);460 Args.AddLastArg(CmdArgs, options::OPT_why_load);461 Args.AddLastArg(CmdArgs, options::OPT_whatsloaded);462 Args.AddAllArgs(CmdArgs, options::OPT_dylinker__install__name);463 Args.AddLastArg(CmdArgs, options::OPT_dylinker);464 Args.AddLastArg(CmdArgs, options::OPT_Mach);465 466 if (LinkerIsLLD) {467 if (auto *CSPGOGenerateArg = getLastCSProfileGenerateArg(Args)) {468 SmallString<128> Path(CSPGOGenerateArg->getNumValues() == 0469 ? ""470 : CSPGOGenerateArg->getValue());471 llvm::sys::path::append(Path, "default_%m.profraw");472 CmdArgs.push_back("--cs-profile-generate");473 CmdArgs.push_back(Args.MakeArgString(Twine("--cs-profile-path=") + Path));474 } else if (auto *ProfileUseArg = getLastProfileUseArg(Args)) {475 SmallString<128> Path(476 ProfileUseArg->getNumValues() == 0 ? "" : ProfileUseArg->getValue());477 if (Path.empty() || llvm::sys::fs::is_directory(Path))478 llvm::sys::path::append(Path, "default.profdata");479 CmdArgs.push_back(Args.MakeArgString(Twine("--cs-profile-path=") + Path));480 }481 482 auto *CodeGenDataGenArg =483 Args.getLastArg(options::OPT_fcodegen_data_generate_EQ);484 if (CodeGenDataGenArg)485 CmdArgs.push_back(486 Args.MakeArgString(Twine("--codegen-data-generate-path=") +487 CodeGenDataGenArg->getValue()));488 }489}490 491/// Determine whether we are linking the ObjC runtime.492static bool isObjCRuntimeLinked(const ArgList &Args) {493 if (isObjCAutoRefCount(Args)) {494 Args.ClaimAllArgs(options::OPT_fobjc_link_runtime);495 return true;496 }497 return Args.hasArg(options::OPT_fobjc_link_runtime);498}499 500static bool checkRemarksOptions(const Driver &D, const ArgList &Args,501 const llvm::Triple &Triple) {502 // When enabling remarks, we need to error if:503 // * The remark file is specified but we're targeting multiple architectures,504 // which means more than one remark file is being generated.505 bool hasMultipleInvocations =506 Args.getAllArgValues(options::OPT_arch).size() > 1;507 bool hasExplicitOutputFile =508 Args.getLastArg(options::OPT_foptimization_record_file_EQ);509 if (hasMultipleInvocations && hasExplicitOutputFile) {510 D.Diag(diag::err_drv_invalid_output_with_multiple_archs)511 << "-foptimization-record-file";512 return false;513 }514 return true;515}516 517static void renderRemarksOptions(const ArgList &Args, ArgStringList &CmdArgs,518 const llvm::Triple &Triple,519 const InputInfo &Output, const JobAction &JA) {520 StringRef Format = "yaml";521 if (const Arg *A = Args.getLastArg(options::OPT_fsave_optimization_record_EQ))522 Format = A->getValue();523 524 CmdArgs.push_back("-mllvm");525 CmdArgs.push_back("-lto-pass-remarks-output");526 CmdArgs.push_back("-mllvm");527 528 const Arg *A = Args.getLastArg(options::OPT_foptimization_record_file_EQ);529 if (A) {530 CmdArgs.push_back(A->getValue());531 } else {532 assert(Output.isFilename() && "Unexpected ld output.");533 SmallString<128> F;534 F = Output.getFilename();535 F += ".opt.";536 F += Format;537 538 CmdArgs.push_back(Args.MakeArgString(F));539 }540 541 if (const Arg *A =542 Args.getLastArg(options::OPT_foptimization_record_passes_EQ)) {543 CmdArgs.push_back("-mllvm");544 std::string Passes =545 std::string("-lto-pass-remarks-filter=") + A->getValue();546 CmdArgs.push_back(Args.MakeArgString(Passes));547 }548 549 if (!Format.empty()) {550 CmdArgs.push_back("-mllvm");551 Twine FormatArg = Twine("-lto-pass-remarks-format=") + Format;552 CmdArgs.push_back(Args.MakeArgString(FormatArg));553 }554 555 if (getLastProfileUseArg(Args)) {556 CmdArgs.push_back("-mllvm");557 CmdArgs.push_back("-lto-pass-remarks-with-hotness");558 559 if (const Arg *A =560 Args.getLastArg(options::OPT_fdiagnostics_hotness_threshold_EQ)) {561 CmdArgs.push_back("-mllvm");562 std::string Opt =563 std::string("-lto-pass-remarks-hotness-threshold=") + A->getValue();564 CmdArgs.push_back(Args.MakeArgString(Opt));565 }566 }567}568 569static void AppendPlatformPrefix(SmallString<128> &Path, const llvm::Triple &T);570 571void darwin::Linker::ConstructJob(Compilation &C, const JobAction &JA,572 const InputInfo &Output,573 const InputInfoList &Inputs,574 const ArgList &Args,575 const char *LinkingOutput) const {576 assert(Output.getType() == types::TY_Image && "Invalid linker output type.");577 578 // If the number of arguments surpasses the system limits, we will encode the579 // input files in a separate file, shortening the command line. To this end,580 // build a list of input file names that can be passed via a file with the581 // -filelist linker option.582 llvm::opt::ArgStringList InputFileList;583 584 // The logic here is derived from gcc's behavior; most of which585 // comes from specs (starting with link_command). Consult gcc for586 // more information.587 ArgStringList CmdArgs;588 589 VersionTuple Version = getMachOToolChain().getLinkerVersion(Args);590 591 bool LinkerIsLLD;592 const char *Exec =593 Args.MakeArgString(getToolChain().GetLinkerPath(&LinkerIsLLD));594 595 // xrOS always uses -platform-version.596 bool UsePlatformVersion = getToolChain().getTriple().isXROS();597 598 // I'm not sure why this particular decomposition exists in gcc, but599 // we follow suite for ease of comparison.600 AddLinkArgs(C, Args, CmdArgs, Inputs, Version, LinkerIsLLD,601 UsePlatformVersion);602 603 if (willEmitRemarks(Args) &&604 checkRemarksOptions(getToolChain().getDriver(), Args,605 getToolChain().getTriple()))606 renderRemarksOptions(Args, CmdArgs, getToolChain().getTriple(), Output, JA);607 608 // Propagate the -moutline flag to the linker in LTO.609 if (Arg *A =610 Args.getLastArg(options::OPT_moutline, options::OPT_mno_outline)) {611 if (A->getOption().matches(options::OPT_moutline)) {612 if (getMachOToolChain().getMachOArchName(Args) == "arm64") {613 CmdArgs.push_back("-mllvm");614 CmdArgs.push_back("-enable-machine-outliner");615 }616 } else {617 // Disable all outlining behaviour if we have mno-outline. We need to do618 // this explicitly, because targets which support default outlining will619 // try to do work if we don't.620 CmdArgs.push_back("-mllvm");621 CmdArgs.push_back("-enable-machine-outliner=never");622 }623 }624 625 // Outline from linkonceodr functions by default in LTO, whenever the outliner626 // is enabled. Note that the target may enable the machine outliner627 // independently of -moutline.628 CmdArgs.push_back("-mllvm");629 CmdArgs.push_back("-enable-linkonceodr-outlining");630 631 // Propagate codegen data flags to the linker for the LLVM backend.632 auto *CodeGenDataGenArg =633 Args.getLastArg(options::OPT_fcodegen_data_generate_EQ);634 auto *CodeGenDataUseArg = Args.getLastArg(options::OPT_fcodegen_data_use_EQ);635 636 // We only allow one of them to be specified.637 const Driver &D = getToolChain().getDriver();638 if (CodeGenDataGenArg && CodeGenDataUseArg)639 D.Diag(diag::err_drv_argument_not_allowed_with)640 << CodeGenDataGenArg->getAsString(Args)641 << CodeGenDataUseArg->getAsString(Args);642 643 // For codegen data gen, the output file is passed to the linker644 // while a boolean flag is passed to the LLVM backend.645 if (CodeGenDataGenArg) {646 CmdArgs.push_back("-mllvm");647 CmdArgs.push_back("-codegen-data-generate");648 }649 650 // For codegen data use, the input file is passed to the LLVM backend.651 if (CodeGenDataUseArg) {652 CmdArgs.push_back("-mllvm");653 CmdArgs.push_back(Args.MakeArgString(Twine("-codegen-data-use-path=") +654 CodeGenDataUseArg->getValue()));655 }656 657 // Setup statistics file output.658 SmallString<128> StatsFile =659 getStatsFileName(Args, Output, Inputs[0], getToolChain().getDriver());660 if (!StatsFile.empty()) {661 CmdArgs.push_back("-mllvm");662 CmdArgs.push_back(Args.MakeArgString("-lto-stats-file=" + StatsFile.str()));663 }664 665 // It seems that the 'e' option is completely ignored for dynamic executables666 // (the default), and with static executables, the last one wins, as expected.667 Args.addAllArgs(CmdArgs, {options::OPT_d_Flag, options::OPT_s, options::OPT_t,668 options::OPT_Z_Flag, options::OPT_u_Group});669 670 // Forward -ObjC when either -ObjC or -ObjC++ is used, to force loading671 // members of static archive libraries which implement Objective-C classes or672 // categories.673 if (Args.hasArg(options::OPT_ObjC) || Args.hasArg(options::OPT_ObjCXX))674 CmdArgs.push_back("-ObjC");675 676 CmdArgs.push_back("-o");677 CmdArgs.push_back(Output.getFilename());678 679 if (!Args.hasArg(options::OPT_nostdlib, options::OPT_nostartfiles))680 getMachOToolChain().addStartObjectFileArgs(Args, CmdArgs);681 682 Args.AddAllArgs(CmdArgs, options::OPT_L);683 684 AddLinkerInputs(getToolChain(), Inputs, Args, CmdArgs, JA);685 // Build the input file for -filelist (list of linker input files) in case we686 // need it later687 for (const auto &II : Inputs) {688 if (!II.isFilename()) {689 // This is a linker input argument.690 // We cannot mix input arguments and file names in a -filelist input, thus691 // we prematurely stop our list (remaining files shall be passed as692 // arguments).693 if (InputFileList.size() > 0)694 break;695 696 continue;697 }698 699 InputFileList.push_back(II.getFilename());700 }701 702 // Additional linker set-up and flags for Fortran. This is required in order703 // to generate executables.704 if (getToolChain().getDriver().IsFlangMode() &&705 !Args.hasArg(options::OPT_nostdlib, options::OPT_nodefaultlibs)) {706 getToolChain().addFortranRuntimeLibraryPath(Args, CmdArgs);707 getToolChain().addFortranRuntimeLibs(Args, CmdArgs);708 }709 710 if (!Args.hasArg(options::OPT_nostdlib, options::OPT_nodefaultlibs))711 addOpenMPRuntime(C, CmdArgs, getToolChain(), Args);712 713 if (isObjCRuntimeLinked(Args) &&714 !Args.hasArg(options::OPT_nostdlib, options::OPT_nodefaultlibs)) {715 // We use arclite library for both ARC and subscripting support.716 getMachOToolChain().AddLinkARCArgs(Args, CmdArgs);717 718 CmdArgs.push_back("-framework");719 CmdArgs.push_back("Foundation");720 // Link libobj.721 CmdArgs.push_back("-lobjc");722 }723 724 if (LinkingOutput) {725 CmdArgs.push_back("-arch_multiple");726 CmdArgs.push_back("-final_output");727 CmdArgs.push_back(LinkingOutput);728 }729 730 if (Args.hasArg(options::OPT_fnested_functions))731 CmdArgs.push_back("-allow_stack_execute");732 733 getMachOToolChain().addProfileRTLibs(Args, CmdArgs);734 735 StringRef Parallelism = getLTOParallelism(Args, getToolChain().getDriver());736 if (!Parallelism.empty()) {737 CmdArgs.push_back("-mllvm");738 unsigned NumThreads =739 llvm::get_threadpool_strategy(Parallelism)->compute_thread_count();740 CmdArgs.push_back(Args.MakeArgString("-threads=" + Twine(NumThreads)));741 }742 743 if (getToolChain().ShouldLinkCXXStdlib(Args))744 getToolChain().AddCXXStdlibLibArgs(Args, CmdArgs);745 746 bool NoStdOrDefaultLibs =747 Args.hasArg(options::OPT_nostdlib, options::OPT_nodefaultlibs);748 bool ForceLinkBuiltins = Args.hasArg(options::OPT_fapple_link_rtlib);749 if (!NoStdOrDefaultLibs || ForceLinkBuiltins) {750 // link_ssp spec is empty.751 752 // If we have both -nostdlib/nodefaultlibs and -fapple-link-rtlib then753 // we just want to link the builtins, not the other libs like libSystem.754 if (NoStdOrDefaultLibs && ForceLinkBuiltins) {755 getMachOToolChain().AddLinkRuntimeLib(Args, CmdArgs, "builtins");756 } else {757 // Let the tool chain choose which runtime library to link.758 getMachOToolChain().AddLinkRuntimeLibArgs(Args, CmdArgs,759 ForceLinkBuiltins);760 761 // No need to do anything for pthreads. Claim argument to avoid warning.762 Args.ClaimAllArgs(options::OPT_pthread);763 Args.ClaimAllArgs(options::OPT_pthreads);764 }765 }766 767 if (!Args.hasArg(options::OPT_nostdlib, options::OPT_nostartfiles)) {768 // endfile_spec is empty.769 }770 771 Args.AddAllArgs(CmdArgs, options::OPT_T_Group);772 Args.AddAllArgs(CmdArgs, options::OPT_F);773 774 // -iframework should be forwarded as -F.775 for (const Arg *A : Args.filtered(options::OPT_iframework))776 CmdArgs.push_back(Args.MakeArgString(std::string("-F") + A->getValue()));777 778 if (!Args.hasArg(options::OPT_nostdlib, options::OPT_nodefaultlibs)) {779 if (Arg *A = Args.getLastArg(options::OPT_fveclib)) {780 if (A->getValue() == StringRef("Accelerate")) {781 CmdArgs.push_back("-framework");782 CmdArgs.push_back("Accelerate");783 }784 }785 }786 787 // Add non-standard, platform-specific search paths, e.g., for DriverKit:788 // -L<sysroot>/System/DriverKit/usr/lib789 // -F<sysroot>/System/DriverKit/System/Library/Framework790 {791 bool NonStandardSearchPath = false;792 const auto &Triple = getToolChain().getTriple();793 if (Triple.isDriverKit()) {794 // ld64 fixed the implicit -F and -L paths in ld64-605.1+.795 NonStandardSearchPath =796 Version.getMajor() < 605 ||797 (Version.getMajor() == 605 && Version.getMinor().value_or(0) < 1);798 }799 800 if (NonStandardSearchPath) {801 if (auto *Sysroot = Args.getLastArg(options::OPT_isysroot)) {802 auto AddSearchPath = [&](StringRef Flag, StringRef SearchPath) {803 SmallString<128> P(Sysroot->getValue());804 AppendPlatformPrefix(P, Triple);805 llvm::sys::path::append(P, SearchPath);806 if (getToolChain().getVFS().exists(P)) {807 CmdArgs.push_back(Args.MakeArgString(Flag + P));808 }809 };810 AddSearchPath("-L", "/usr/lib");811 AddSearchPath("-F", "/System/Library/Frameworks");812 }813 }814 }815 816 ResponseFileSupport ResponseSupport;817 if (Version >= VersionTuple(705) || LinkerIsLLD) {818 ResponseSupport = ResponseFileSupport::AtFileUTF8();819 } else {820 // For older versions of the linker, use the legacy filelist method instead.821 ResponseSupport = {ResponseFileSupport::RF_FileList, llvm::sys::WEM_UTF8,822 "-filelist"};823 }824 825 std::unique_ptr<Command> Cmd = std::make_unique<Command>(826 JA, *this, ResponseSupport, Exec, CmdArgs, Inputs, Output);827 Cmd->setInputFileList(std::move(InputFileList));828 C.addCommand(std::move(Cmd));829}830 831void darwin::StaticLibTool::ConstructJob(Compilation &C, const JobAction &JA,832 const InputInfo &Output,833 const InputInfoList &Inputs,834 const ArgList &Args,835 const char *LinkingOutput) const {836 const Driver &D = getToolChain().getDriver();837 838 // Silence warning for "clang -g foo.o -o foo"839 Args.ClaimAllArgs(options::OPT_g_Group);840 // and "clang -emit-llvm foo.o -o foo"841 Args.ClaimAllArgs(options::OPT_emit_llvm);842 // and for "clang -w foo.o -o foo". Other warning options are already843 // handled somewhere else.844 Args.ClaimAllArgs(options::OPT_w);845 // Silence warnings when linking C code with a C++ '-stdlib' argument.846 Args.ClaimAllArgs(options::OPT_stdlib_EQ);847 848 // libtool <options> <output_file> <input_files>849 ArgStringList CmdArgs;850 // Create and insert file members with a deterministic index.851 CmdArgs.push_back("-static");852 CmdArgs.push_back("-D");853 CmdArgs.push_back("-no_warning_for_no_symbols");854 CmdArgs.push_back("-o");855 CmdArgs.push_back(Output.getFilename());856 857 for (const auto &II : Inputs) {858 if (II.isFilename()) {859 CmdArgs.push_back(II.getFilename());860 }861 }862 863 // Delete old output archive file if it already exists before generating a new864 // archive file.865 const auto *OutputFileName = Output.getFilename();866 if (Output.isFilename() && llvm::sys::fs::exists(OutputFileName)) {867 if (std::error_code EC = llvm::sys::fs::remove(OutputFileName)) {868 D.Diag(diag::err_drv_unable_to_remove_file) << EC.message();869 return;870 }871 }872 873 const char *Exec = Args.MakeArgString(getToolChain().GetStaticLibToolPath());874 C.addCommand(std::make_unique<Command>(JA, *this,875 ResponseFileSupport::AtFileUTF8(),876 Exec, CmdArgs, Inputs, Output));877}878 879void darwin::Lipo::ConstructJob(Compilation &C, const JobAction &JA,880 const InputInfo &Output,881 const InputInfoList &Inputs,882 const ArgList &Args,883 const char *LinkingOutput) const {884 ArgStringList CmdArgs;885 886 CmdArgs.push_back("-create");887 assert(Output.isFilename() && "Unexpected lipo output.");888 889 CmdArgs.push_back("-output");890 CmdArgs.push_back(Output.getFilename());891 892 for (const auto &II : Inputs) {893 assert(II.isFilename() && "Unexpected lipo input.");894 CmdArgs.push_back(II.getFilename());895 }896 897 StringRef LipoName = Args.getLastArgValue(options::OPT_fuse_lipo_EQ, "lipo");898 const char *Exec =899 Args.MakeArgString(getToolChain().GetProgramPath(LipoName.data()));900 C.addCommand(std::make_unique<Command>(JA, *this, ResponseFileSupport::None(),901 Exec, CmdArgs, Inputs, Output));902}903 904void darwin::Dsymutil::ConstructJob(Compilation &C, const JobAction &JA,905 const InputInfo &Output,906 const InputInfoList &Inputs,907 const ArgList &Args,908 const char *LinkingOutput) const {909 ArgStringList CmdArgs;910 911 CmdArgs.push_back("-o");912 CmdArgs.push_back(Output.getFilename());913 914 assert(Inputs.size() == 1 && "Unable to handle multiple inputs.");915 const InputInfo &Input = Inputs[0];916 assert(Input.isFilename() && "Unexpected dsymutil input.");917 CmdArgs.push_back(Input.getFilename());918 919 const char *Exec =920 Args.MakeArgString(getToolChain().GetProgramPath("dsymutil"));921 C.addCommand(std::make_unique<Command>(JA, *this, ResponseFileSupport::None(),922 Exec, CmdArgs, Inputs, Output));923}924 925void darwin::VerifyDebug::ConstructJob(Compilation &C, const JobAction &JA,926 const InputInfo &Output,927 const InputInfoList &Inputs,928 const ArgList &Args,929 const char *LinkingOutput) const {930 ArgStringList CmdArgs;931 CmdArgs.push_back("--verify");932 CmdArgs.push_back("--debug-info");933 CmdArgs.push_back("--eh-frame");934 CmdArgs.push_back("--quiet");935 936 assert(Inputs.size() == 1 && "Unable to handle multiple inputs.");937 const InputInfo &Input = Inputs[0];938 assert(Input.isFilename() && "Unexpected verify input");939 940 // Grabbing the output of the earlier dsymutil run.941 CmdArgs.push_back(Input.getFilename());942 943 const char *Exec =944 Args.MakeArgString(getToolChain().GetProgramPath("dwarfdump"));945 C.addCommand(std::make_unique<Command>(JA, *this, ResponseFileSupport::None(),946 Exec, CmdArgs, Inputs, Output));947}948 949MachO::MachO(const Driver &D, const llvm::Triple &Triple, const ArgList &Args)950 : ToolChain(D, Triple, Args) {951 // We expect 'as', 'ld', etc. to be adjacent to our install dir.952 getProgramPaths().push_back(getDriver().Dir);953}954 955AppleMachO::AppleMachO(const Driver &D, const llvm::Triple &Triple,956 const ArgList &Args)957 : MachO(D, Triple, Args), CudaInstallation(D, Triple, Args),958 RocmInstallation(D, Triple, Args), SYCLInstallation(D, Triple, Args) {}959 960/// Darwin - Darwin tool chain for i386 and x86_64.961Darwin::Darwin(const Driver &D, const llvm::Triple &Triple, const ArgList &Args)962 : AppleMachO(D, Triple, Args), TargetInitialized(false) {}963 964types::ID MachO::LookupTypeForExtension(StringRef Ext) const {965 types::ID Ty = ToolChain::LookupTypeForExtension(Ext);966 967 // Darwin always preprocesses assembly files (unless -x is used explicitly).968 if (Ty == types::TY_PP_Asm)969 return types::TY_Asm;970 971 return Ty;972}973 974bool MachO::HasNativeLLVMSupport() const { return true; }975 976ToolChain::CXXStdlibType Darwin::GetDefaultCXXStdlibType() const {977 // Always use libc++ by default978 return ToolChain::CST_Libcxx;979}980 981/// Darwin provides an ARC runtime starting in MacOS X 10.7 and iOS 5.0.982ObjCRuntime Darwin::getDefaultObjCRuntime(bool isNonFragile) const {983 if (isTargetWatchOSBased())984 return ObjCRuntime(ObjCRuntime::WatchOS, TargetVersion);985 if (isTargetIOSBased())986 return ObjCRuntime(ObjCRuntime::iOS, TargetVersion);987 if (isTargetXROS()) {988 // XROS uses the iOS runtime.989 auto T = llvm::Triple(Twine("arm64-apple-") +990 llvm::Triple::getOSTypeName(llvm::Triple::XROS) +991 TargetVersion.getAsString());992 return ObjCRuntime(ObjCRuntime::iOS, T.getiOSVersion());993 }994 if (isNonFragile)995 return ObjCRuntime(ObjCRuntime::MacOSX, TargetVersion);996 return ObjCRuntime(ObjCRuntime::FragileMacOSX, TargetVersion);997}998 999/// Darwin provides a blocks runtime starting in MacOS X 10.6 and iOS 3.2.1000bool Darwin::hasBlocksRuntime() const {1001 if (isTargetWatchOSBased() || isTargetDriverKit() || isTargetXROS())1002 return true;1003 else if (isTargetIOSBased())1004 return !isIPhoneOSVersionLT(3, 2);1005 else {1006 assert(isTargetMacOSBased() && "unexpected darwin target");1007 return !isMacosxVersionLT(10, 6);1008 }1009}1010 1011void AppleMachO::AddCudaIncludeArgs(const ArgList &DriverArgs,1012 ArgStringList &CC1Args) const {1013 CudaInstallation->AddCudaIncludeArgs(DriverArgs, CC1Args);1014}1015 1016void AppleMachO::AddHIPIncludeArgs(const ArgList &DriverArgs,1017 ArgStringList &CC1Args) const {1018 RocmInstallation->AddHIPIncludeArgs(DriverArgs, CC1Args);1019}1020 1021void AppleMachO::addSYCLIncludeArgs(const ArgList &DriverArgs,1022 ArgStringList &CC1Args) const {1023 SYCLInstallation->addSYCLIncludeArgs(DriverArgs, CC1Args);1024}1025 1026// This is just a MachO name translation routine and there's no1027// way to join this into ARMTargetParser without breaking all1028// other assumptions. Maybe MachO should consider standardising1029// their nomenclature.1030static const char *ArmMachOArchName(StringRef Arch) {1031 return llvm::StringSwitch<const char *>(Arch)1032 .Case("armv6k", "armv6")1033 .Case("armv6m", "armv6m")1034 .Case("armv5tej", "armv5")1035 .Case("xscale", "xscale")1036 .Case("armv4t", "armv4t")1037 .Case("armv7", "armv7")1038 .Cases({"armv7a", "armv7-a"}, "armv7")1039 .Cases({"armv7r", "armv7-r"}, "armv7")1040 .Cases({"armv7em", "armv7e-m"}, "armv7em")1041 .Cases({"armv7k", "armv7-k"}, "armv7k")1042 .Cases({"armv7m", "armv7-m"}, "armv7m")1043 .Cases({"armv7s", "armv7-s"}, "armv7s")1044 .Default(nullptr);1045}1046 1047static const char *ArmMachOArchNameCPU(StringRef CPU) {1048 llvm::ARM::ArchKind ArchKind = llvm::ARM::parseCPUArch(CPU);1049 if (ArchKind == llvm::ARM::ArchKind::INVALID)1050 return nullptr;1051 StringRef Arch = llvm::ARM::getArchName(ArchKind);1052 1053 // FIXME: Make sure this MachO triple mangling is really necessary.1054 // ARMv5* normalises to ARMv5.1055 if (Arch.starts_with("armv5"))1056 Arch = Arch.substr(0, 5);1057 // ARMv6*, except ARMv6M, normalises to ARMv6.1058 else if (Arch.starts_with("armv6") && !Arch.ends_with("6m"))1059 Arch = Arch.substr(0, 5);1060 // ARMv7A normalises to ARMv7.1061 else if (Arch.ends_with("v7a"))1062 Arch = Arch.substr(0, 5);1063 return Arch.data();1064}1065 1066StringRef MachO::getMachOArchName(const ArgList &Args) const {1067 switch (getTriple().getArch()) {1068 default:1069 return getDefaultUniversalArchName();1070 1071 case llvm::Triple::aarch64_32:1072 return "arm64_32";1073 1074 case llvm::Triple::aarch64: {1075 if (getTriple().isArm64e())1076 return "arm64e";1077 return "arm64";1078 }1079 1080 case llvm::Triple::thumb:1081 case llvm::Triple::arm:1082 if (const Arg *A = Args.getLastArg(options::OPT_march_EQ))1083 if (const char *Arch = ArmMachOArchName(A->getValue()))1084 return Arch;1085 1086 if (const Arg *A = Args.getLastArg(options::OPT_mcpu_EQ))1087 if (const char *Arch = ArmMachOArchNameCPU(A->getValue()))1088 return Arch;1089 1090 return "arm";1091 }1092}1093 1094VersionTuple MachO::getLinkerVersion(const llvm::opt::ArgList &Args) const {1095 if (LinkerVersion) {1096#ifndef NDEBUG1097 VersionTuple NewLinkerVersion;1098 if (Arg *A = Args.getLastArg(options::OPT_mlinker_version_EQ))1099 (void)NewLinkerVersion.tryParse(A->getValue());1100 assert(NewLinkerVersion == LinkerVersion);1101#endif1102 return *LinkerVersion;1103 }1104 1105 VersionTuple NewLinkerVersion;1106 if (Arg *A = Args.getLastArg(options::OPT_mlinker_version_EQ))1107 if (NewLinkerVersion.tryParse(A->getValue()))1108 getDriver().Diag(diag::err_drv_invalid_version_number)1109 << A->getAsString(Args);1110 1111 LinkerVersion = NewLinkerVersion;1112 return *LinkerVersion;1113}1114 1115Darwin::~Darwin() {}1116 1117AppleMachO::~AppleMachO() {}1118 1119MachO::~MachO() {}1120 1121std::string Darwin::ComputeEffectiveClangTriple(const ArgList &Args,1122 types::ID InputType) const {1123 llvm::Triple Triple(ComputeLLVMTriple(Args, InputType));1124 1125 // If the target isn't initialized (e.g., an unknown Darwin platform, return1126 // the default triple).1127 if (!isTargetInitialized())1128 return Triple.getTriple();1129 1130 SmallString<16> Str;1131 if (isTargetWatchOSBased())1132 Str += "watchos";1133 else if (isTargetTvOSBased())1134 Str += "tvos";1135 else if (isTargetDriverKit())1136 Str += "driverkit";1137 else if (isTargetIOSBased() || isTargetMacCatalyst())1138 Str += "ios";1139 else if (isTargetXROS())1140 Str += llvm::Triple::getOSTypeName(llvm::Triple::XROS);1141 else1142 Str += "macosx";1143 Str += getTripleTargetVersion().getAsString();1144 Triple.setOSName(Str);1145 1146 return Triple.getTriple();1147}1148 1149Tool *MachO::getTool(Action::ActionClass AC) const {1150 switch (AC) {1151 case Action::LipoJobClass:1152 if (!Lipo)1153 Lipo.reset(new tools::darwin::Lipo(*this));1154 return Lipo.get();1155 case Action::DsymutilJobClass:1156 if (!Dsymutil)1157 Dsymutil.reset(new tools::darwin::Dsymutil(*this));1158 return Dsymutil.get();1159 case Action::VerifyDebugInfoJobClass:1160 if (!VerifyDebug)1161 VerifyDebug.reset(new tools::darwin::VerifyDebug(*this));1162 return VerifyDebug.get();1163 default:1164 return ToolChain::getTool(AC);1165 }1166}1167 1168Tool *MachO::buildLinker() const { return new tools::darwin::Linker(*this); }1169 1170Tool *MachO::buildStaticLibTool() const {1171 return new tools::darwin::StaticLibTool(*this);1172}1173 1174Tool *MachO::buildAssembler() const {1175 return new tools::darwin::Assembler(*this);1176}1177 1178DarwinClang::DarwinClang(const Driver &D, const llvm::Triple &Triple,1179 const ArgList &Args)1180 : Darwin(D, Triple, Args) {}1181 1182void DarwinClang::addClangWarningOptions(ArgStringList &CC1Args) const {1183 // Always error about undefined 'TARGET_OS_*' macros.1184 CC1Args.push_back("-Wundef-prefix=TARGET_OS_");1185 CC1Args.push_back("-Werror=undef-prefix");1186 1187 // For modern targets, promote certain warnings to errors.1188 if (isTargetWatchOSBased() || getTriple().isArch64Bit()) {1189 // Always enable -Wdeprecated-objc-isa-usage and promote it1190 // to an error.1191 CC1Args.push_back("-Wdeprecated-objc-isa-usage");1192 CC1Args.push_back("-Werror=deprecated-objc-isa-usage");1193 1194 // For iOS and watchOS, also error about implicit function declarations,1195 // as that can impact calling conventions.1196 if (!isTargetMacOS())1197 CC1Args.push_back("-Werror=implicit-function-declaration");1198 }1199}1200 1201void DarwinClang::addClangTargetOptions(1202 const llvm::opt::ArgList &DriverArgs, llvm::opt::ArgStringList &CC1Args,1203 Action::OffloadKind DeviceOffloadKind) const {1204 1205 Darwin::addClangTargetOptions(DriverArgs, CC1Args, DeviceOffloadKind);1206}1207 1208/// Take a path that speculatively points into Xcode and return the1209/// `XCODE/Contents/Developer` path if it is an Xcode path, or an empty path1210/// otherwise.1211static StringRef getXcodeDeveloperPath(StringRef PathIntoXcode) {1212 static constexpr llvm::StringLiteral XcodeAppSuffix(1213 ".app/Contents/Developer");1214 size_t Index = PathIntoXcode.find(XcodeAppSuffix);1215 if (Index == StringRef::npos)1216 return "";1217 return PathIntoXcode.take_front(Index + XcodeAppSuffix.size());1218}1219 1220void DarwinClang::AddLinkARCArgs(const ArgList &Args,1221 ArgStringList &CmdArgs) const {1222 // Avoid linking compatibility stubs on i386 mac.1223 if (isTargetMacOSBased() && getArch() == llvm::Triple::x86)1224 return;1225 if (isTargetAppleSiliconMac())1226 return;1227 // ARC runtime is supported everywhere on arm64e.1228 if (getTriple().isArm64e())1229 return;1230 if (isTargetXROS())1231 return;1232 1233 ObjCRuntime runtime = getDefaultObjCRuntime(/*nonfragile*/ true);1234 1235 if ((runtime.hasNativeARC() || !isObjCAutoRefCount(Args)) &&1236 runtime.hasSubscripting())1237 return;1238 1239 SmallString<128> P(getDriver().ClangExecutable);1240 llvm::sys::path::remove_filename(P); // 'clang'1241 llvm::sys::path::remove_filename(P); // 'bin'1242 llvm::sys::path::append(P, "lib", "arc");1243 1244 // 'libarclite' usually lives in the same toolchain as 'clang'. However, the1245 // Swift open source toolchains for macOS distribute Clang without libarclite.1246 // In that case, to allow the linker to find 'libarclite', we point to the1247 // 'libarclite' in the XcodeDefault toolchain instead.1248 if (!getVFS().exists(P)) {1249 auto updatePath = [&](const Arg *A) {1250 // Try to infer the path to 'libarclite' in the toolchain from the1251 // specified SDK path.1252 StringRef XcodePathForSDK = getXcodeDeveloperPath(A->getValue());1253 if (XcodePathForSDK.empty())1254 return false;1255 1256 P = XcodePathForSDK;1257 llvm::sys::path::append(P, "Toolchains/XcodeDefault.xctoolchain/usr",1258 "lib", "arc");1259 return getVFS().exists(P);1260 };1261 1262 bool updated = false;1263 if (const Arg *A = Args.getLastArg(options::OPT_isysroot))1264 updated = updatePath(A);1265 1266 if (!updated) {1267 if (const Arg *A = Args.getLastArg(options::OPT__sysroot_EQ))1268 updatePath(A);1269 }1270 }1271 1272 CmdArgs.push_back("-force_load");1273 llvm::sys::path::append(P, "libarclite_");1274 // Mash in the platform.1275 if (isTargetWatchOSSimulator())1276 P += "watchsimulator";1277 else if (isTargetWatchOS())1278 P += "watchos";1279 else if (isTargetTvOSSimulator())1280 P += "appletvsimulator";1281 else if (isTargetTvOS())1282 P += "appletvos";1283 else if (isTargetIOSSimulator())1284 P += "iphonesimulator";1285 else if (isTargetIPhoneOS())1286 P += "iphoneos";1287 else1288 P += "macosx";1289 P += ".a";1290 1291 if (!getVFS().exists(P))1292 getDriver().Diag(clang::diag::err_drv_darwin_sdk_missing_arclite) << P;1293 1294 CmdArgs.push_back(Args.MakeArgString(P));1295}1296 1297unsigned DarwinClang::GetDefaultDwarfVersion() const {1298 // Default to use DWARF 2 on OS X 10.10 / iOS 8 and lower.1299 if ((isTargetMacOSBased() && isMacosxVersionLT(10, 11)) ||1300 (isTargetIOSBased() && isIPhoneOSVersionLT(9)))1301 return 2;1302 // Default to use DWARF 4 on OS X 10.11 - macOS 14 / iOS 9 - iOS 17.1303 if ((isTargetMacOSBased() && isMacosxVersionLT(15)) ||1304 (isTargetIOSBased() && isIPhoneOSVersionLT(18)) ||1305 (isTargetWatchOSBased() && TargetVersion < llvm::VersionTuple(11)) ||1306 (isTargetXROS() && TargetVersion < llvm::VersionTuple(2)) ||1307 (isTargetDriverKit() && TargetVersion < llvm::VersionTuple(24)) ||1308 (isTargetMacOSBased() &&1309 TargetVersion.empty())) // apple-darwin, no version.1310 return 4;1311 return 5;1312}1313 1314void MachO::AddLinkRuntimeLib(const ArgList &Args, ArgStringList &CmdArgs,1315 StringRef Component, RuntimeLinkOptions Opts,1316 bool IsShared) const {1317 std::string P = getCompilerRT(1318 Args, Component, IsShared ? ToolChain::FT_Shared : ToolChain::FT_Static);1319 1320 // For now, allow missing resource libraries to support developers who may1321 // not have compiler-rt checked out or integrated into their build (unless1322 // we explicitly force linking with this library).1323 if ((Opts & RLO_AlwaysLink) || getVFS().exists(P)) {1324 const char *LibArg = Args.MakeArgString(P);1325 CmdArgs.push_back(LibArg);1326 }1327 1328 // Adding the rpaths might negatively interact when other rpaths are involved,1329 // so we should make sure we add the rpaths last, after all user-specified1330 // rpaths. This is currently true from this place, but we need to be1331 // careful if this function is ever called before user's rpaths are emitted.1332 if (Opts & RLO_AddRPath) {1333 assert(StringRef(P).ends_with(".dylib") && "must be a dynamic library");1334 1335 // Add @executable_path to rpath to support having the dylib copied with1336 // the executable.1337 CmdArgs.push_back("-rpath");1338 CmdArgs.push_back("@executable_path");1339 1340 // Add the compiler-rt library's directory to rpath to support using the1341 // dylib from the default location without copying.1342 CmdArgs.push_back("-rpath");1343 CmdArgs.push_back(Args.MakeArgString(llvm::sys::path::parent_path(P)));1344 }1345}1346 1347std::string MachO::getCompilerRT(const ArgList &, StringRef Component,1348 FileType Type, bool IsFortran) const {1349 assert(Type != ToolChain::FT_Object &&1350 "it doesn't make sense to ask for the compiler-rt library name as an "1351 "object file");1352 SmallString<64> MachOLibName = StringRef("libclang_rt");1353 // On MachO, the builtins component is not in the library name1354 if (Component != "builtins") {1355 MachOLibName += '.';1356 MachOLibName += Component;1357 }1358 MachOLibName += Type == ToolChain::FT_Shared ? "_dynamic.dylib" : ".a";1359 1360 SmallString<128> FullPath(getDriver().ResourceDir);1361 llvm::sys::path::append(FullPath, "lib", "darwin", "macho_embedded",1362 MachOLibName);1363 return std::string(FullPath);1364}1365 1366std::string Darwin::getCompilerRT(const ArgList &, StringRef Component,1367 FileType Type, bool IsFortran) const {1368 assert(Type != ToolChain::FT_Object &&1369 "it doesn't make sense to ask for the compiler-rt library name as an "1370 "object file");1371 SmallString<64> DarwinLibName = StringRef("libclang_rt.");1372 // On Darwin, the builtins component is not in the library name1373 if (Component != "builtins") {1374 DarwinLibName += Component;1375 DarwinLibName += '_';1376 }1377 DarwinLibName += getOSLibraryNameSuffix();1378 DarwinLibName += Type == ToolChain::FT_Shared ? "_dynamic.dylib" : ".a";1379 1380 SmallString<128> FullPath(getDriver().ResourceDir);1381 llvm::sys::path::append(FullPath, "lib", "darwin", DarwinLibName);1382 return std::string(FullPath);1383}1384 1385StringRef Darwin::getPlatformFamily() const {1386 switch (TargetPlatform) {1387 case DarwinPlatformKind::MacOS:1388 return "MacOSX";1389 case DarwinPlatformKind::IPhoneOS:1390 if (TargetEnvironment == MacCatalyst)1391 return "MacOSX";1392 return "iPhone";1393 case DarwinPlatformKind::TvOS:1394 return "AppleTV";1395 case DarwinPlatformKind::WatchOS:1396 return "Watch";1397 case DarwinPlatformKind::DriverKit:1398 return "DriverKit";1399 case DarwinPlatformKind::XROS:1400 return "XR";1401 }1402 llvm_unreachable("Unsupported platform");1403}1404 1405StringRef Darwin::getSDKName(StringRef isysroot) {1406 // Assume SDK has path: SOME_PATH/SDKs/PlatformXX.YY.sdk1407 auto BeginSDK = llvm::sys::path::rbegin(isysroot);1408 auto EndSDK = llvm::sys::path::rend(isysroot);1409 for (auto IT = BeginSDK; IT != EndSDK; ++IT) {1410 StringRef SDK = *IT;1411 if (SDK.consume_back(".sdk"))1412 return SDK;1413 }1414 return "";1415}1416 1417StringRef Darwin::getOSLibraryNameSuffix(bool IgnoreSim) const {1418 switch (TargetPlatform) {1419 case DarwinPlatformKind::MacOS:1420 return "osx";1421 case DarwinPlatformKind::IPhoneOS:1422 if (TargetEnvironment == MacCatalyst)1423 return "osx";1424 return TargetEnvironment == NativeEnvironment || IgnoreSim ? "ios"1425 : "iossim";1426 case DarwinPlatformKind::TvOS:1427 return TargetEnvironment == NativeEnvironment || IgnoreSim ? "tvos"1428 : "tvossim";1429 case DarwinPlatformKind::WatchOS:1430 return TargetEnvironment == NativeEnvironment || IgnoreSim ? "watchos"1431 : "watchossim";1432 case DarwinPlatformKind::XROS:1433 return TargetEnvironment == NativeEnvironment || IgnoreSim ? "xros"1434 : "xrossim";1435 case DarwinPlatformKind::DriverKit:1436 return "driverkit";1437 }1438 llvm_unreachable("Unsupported platform");1439}1440 1441/// Check if the link command contains a symbol export directive.1442static bool hasExportSymbolDirective(const ArgList &Args) {1443 for (Arg *A : Args) {1444 if (A->getOption().matches(options::OPT_exported__symbols__list))1445 return true;1446 if (!A->getOption().matches(options::OPT_Wl_COMMA) &&1447 !A->getOption().matches(options::OPT_Xlinker))1448 continue;1449 if (A->containsValue("-exported_symbols_list") ||1450 A->containsValue("-exported_symbol"))1451 return true;1452 }1453 return false;1454}1455 1456/// Add an export directive for \p Symbol to the link command.1457static void addExportedSymbol(ArgStringList &CmdArgs, const char *Symbol) {1458 CmdArgs.push_back("-exported_symbol");1459 CmdArgs.push_back(Symbol);1460}1461 1462/// Add a sectalign directive for \p Segment and \p Section to the maximum1463/// expected page size for Darwin.1464///1465/// On iPhone 6+ the max supported page size is 16K. On macOS, the max is 4K.1466/// Use a common alignment constant (16K) for now, and reduce the alignment on1467/// macOS if it proves important.1468static void addSectalignToPage(const ArgList &Args, ArgStringList &CmdArgs,1469 StringRef Segment, StringRef Section) {1470 for (const char *A : {"-sectalign", Args.MakeArgString(Segment),1471 Args.MakeArgString(Section), "0x4000"})1472 CmdArgs.push_back(A);1473}1474 1475void Darwin::addProfileRTLibs(const ArgList &Args,1476 ArgStringList &CmdArgs) const {1477 if (!needsProfileRT(Args) && !needsGCovInstrumentation(Args))1478 return;1479 1480 AddLinkRuntimeLib(Args, CmdArgs, "profile",1481 RuntimeLinkOptions(RLO_AlwaysLink));1482 1483 bool ForGCOV = needsGCovInstrumentation(Args);1484 1485 // If we have a symbol export directive and we're linking in the profile1486 // runtime, automatically export symbols necessary to implement some of the1487 // runtime's functionality.1488 if (hasExportSymbolDirective(Args) && ForGCOV) {1489 addExportedSymbol(CmdArgs, "___gcov_dump");1490 addExportedSymbol(CmdArgs, "___gcov_reset");1491 addExportedSymbol(CmdArgs, "_writeout_fn_list");1492 addExportedSymbol(CmdArgs, "_reset_fn_list");1493 }1494 1495 // Align __llvm_prf_{cnts,bits,data} sections to the maximum expected page1496 // alignment. This allows profile counters to be mmap()'d to disk. Note that1497 // it's not enough to just page-align __llvm_prf_cnts: the following section1498 // must also be page-aligned so that its data is not clobbered by mmap().1499 //1500 // The section alignment is only needed when continuous profile sync is1501 // enabled, but this is expected to be the default in Xcode. Specifying the1502 // extra alignment also allows the same binary to be used with/without sync1503 // enabled.1504 if (!ForGCOV) {1505 for (auto IPSK : {llvm::IPSK_cnts, llvm::IPSK_bitmap, llvm::IPSK_data}) {1506 addSectalignToPage(1507 Args, CmdArgs, "__DATA",1508 llvm::getInstrProfSectionName(IPSK, llvm::Triple::MachO,1509 /*AddSegmentInfo=*/false));1510 }1511 }1512}1513 1514void DarwinClang::AddLinkSanitizerLibArgs(const ArgList &Args,1515 ArgStringList &CmdArgs,1516 StringRef Sanitizer,1517 bool Shared) const {1518 auto RLO = RuntimeLinkOptions(RLO_AlwaysLink | (Shared ? RLO_AddRPath : 0U));1519 AddLinkRuntimeLib(Args, CmdArgs, Sanitizer, RLO, Shared);1520}1521 1522ToolChain::RuntimeLibType DarwinClang::GetRuntimeLibType(1523 const ArgList &Args) const {1524 if (Arg* A = Args.getLastArg(options::OPT_rtlib_EQ)) {1525 StringRef Value = A->getValue();1526 if (Value != "compiler-rt" && Value != "platform")1527 getDriver().Diag(clang::diag::err_drv_unsupported_rtlib_for_platform)1528 << Value << "darwin";1529 }1530 1531 return ToolChain::RLT_CompilerRT;1532}1533 1534void DarwinClang::AddLinkRuntimeLibArgs(const ArgList &Args,1535 ArgStringList &CmdArgs,1536 bool ForceLinkBuiltinRT) const {1537 // Call once to ensure diagnostic is printed if wrong value was specified1538 GetRuntimeLibType(Args);1539 1540 // Darwin doesn't support real static executables, don't link any runtime1541 // libraries with -static.1542 if (Args.hasArg(options::OPT_static) ||1543 Args.hasArg(options::OPT_fapple_kext) ||1544 Args.hasArg(options::OPT_mkernel)) {1545 if (ForceLinkBuiltinRT)1546 AddLinkRuntimeLib(Args, CmdArgs, "builtins");1547 return;1548 }1549 1550 // Reject -static-libgcc for now, we can deal with this when and if someone1551 // cares. This is useful in situations where someone wants to statically link1552 // something like libstdc++, and needs its runtime support routines.1553 if (const Arg *A = Args.getLastArg(options::OPT_static_libgcc)) {1554 getDriver().Diag(diag::err_drv_unsupported_opt) << A->getAsString(Args);1555 return;1556 }1557 1558 const SanitizerArgs &Sanitize = getSanitizerArgs(Args);1559 1560 if (!Sanitize.needsSharedRt()) {1561 const char *sanitizer = nullptr;1562 if (Sanitize.needsUbsanRt()) {1563 sanitizer = "UndefinedBehaviorSanitizer";1564 } else if (Sanitize.needsRtsanRt()) {1565 sanitizer = "RealtimeSanitizer";1566 } else if (Sanitize.needsAsanRt()) {1567 sanitizer = "AddressSanitizer";1568 } else if (Sanitize.needsTsanRt()) {1569 sanitizer = "ThreadSanitizer";1570 }1571 if (sanitizer) {1572 getDriver().Diag(diag::err_drv_unsupported_static_sanitizer_darwin)1573 << sanitizer;1574 return;1575 }1576 }1577 1578 if (Sanitize.linkRuntimes()) {1579 if (Sanitize.needsAsanRt()) {1580 if (Sanitize.needsStableAbi()) {1581 AddLinkSanitizerLibArgs(Args, CmdArgs, "asan_abi", /*shared=*/false);1582 } else {1583 assert(Sanitize.needsSharedRt() &&1584 "Static sanitizer runtimes not supported");1585 AddLinkSanitizerLibArgs(Args, CmdArgs, "asan");1586 }1587 }1588 if (Sanitize.needsRtsanRt()) {1589 assert(Sanitize.needsSharedRt() &&1590 "Static sanitizer runtimes not supported");1591 AddLinkSanitizerLibArgs(Args, CmdArgs, "rtsan");1592 }1593 if (Sanitize.needsLsanRt())1594 AddLinkSanitizerLibArgs(Args, CmdArgs, "lsan");1595 if (Sanitize.needsUbsanRt()) {1596 assert(Sanitize.needsSharedRt() &&1597 "Static sanitizer runtimes not supported");1598 AddLinkSanitizerLibArgs(1599 Args, CmdArgs,1600 Sanitize.requiresMinimalRuntime() ? "ubsan_minimal" : "ubsan");1601 }1602 if (Sanitize.needsTsanRt()) {1603 assert(Sanitize.needsSharedRt() &&1604 "Static sanitizer runtimes not supported");1605 AddLinkSanitizerLibArgs(Args, CmdArgs, "tsan");1606 }1607 if (Sanitize.needsTysanRt())1608 AddLinkSanitizerLibArgs(Args, CmdArgs, "tysan");1609 if (Sanitize.needsFuzzer() && !Args.hasArg(options::OPT_dynamiclib)) {1610 AddLinkSanitizerLibArgs(Args, CmdArgs, "fuzzer", /*shared=*/false);1611 1612 // Libfuzzer is written in C++ and requires libcxx.1613 // Since darwin::Linker::ConstructJob already adds -lc++ for clang++1614 // by default if ShouldLinkCXXStdlib(Args), we only add the option if1615 // !ShouldLinkCXXStdlib(Args). This avoids duplicate library errors1616 // on Darwin.1617 if (!ShouldLinkCXXStdlib(Args))1618 AddCXXStdlibLibArgs(Args, CmdArgs);1619 }1620 if (Sanitize.needsStatsRt()) {1621 AddLinkRuntimeLib(Args, CmdArgs, "stats_client", RLO_AlwaysLink);1622 AddLinkSanitizerLibArgs(Args, CmdArgs, "stats");1623 }1624 }1625 1626 if (Sanitize.needsMemProfRt())1627 if (hasExportSymbolDirective(Args))1628 addExportedSymbol(1629 CmdArgs,1630 llvm::memprof::getMemprofOptionsSymbolDarwinLinkageName().data());1631 1632 const XRayArgs &XRay = getXRayArgs(Args);1633 if (XRay.needsXRayRt()) {1634 AddLinkRuntimeLib(Args, CmdArgs, "xray");1635 AddLinkRuntimeLib(Args, CmdArgs, "xray-basic");1636 AddLinkRuntimeLib(Args, CmdArgs, "xray-fdr");1637 }1638 1639 if (isTargetDriverKit() && !Args.hasArg(options::OPT_nodriverkitlib)) {1640 CmdArgs.push_back("-framework");1641 CmdArgs.push_back("DriverKit");1642 }1643 1644 // Otherwise link libSystem, then the dynamic runtime library, and finally any1645 // target specific static runtime library.1646 if (!isTargetDriverKit())1647 CmdArgs.push_back("-lSystem");1648 1649 // Select the dynamic runtime library and the target specific static library.1650 // Some old Darwin versions put builtins, libunwind, and some other stuff in1651 // libgcc_s.1.dylib. MacOS X 10.6 and iOS 5 moved those functions to1652 // libSystem, and made libgcc_s.1.dylib a stub. We never link libgcc_s when1653 // building for aarch64 or iOS simulator, since libgcc_s was made obsolete1654 // before either existed.1655 if (getTriple().getArch() != llvm::Triple::aarch64 &&1656 ((isTargetIOSBased() && isIPhoneOSVersionLT(5, 0) &&1657 !isTargetIOSSimulator()) ||1658 (isTargetMacOSBased() && isMacosxVersionLT(10, 6))))1659 CmdArgs.push_back("-lgcc_s.1");1660 AddLinkRuntimeLib(Args, CmdArgs, "builtins");1661}1662 1663/// Returns the most appropriate macOS target version for the current process.1664///1665/// If the macOS SDK version is the same or earlier than the system version,1666/// then the SDK version is returned. Otherwise the system version is returned.1667static std::string getSystemOrSDKMacOSVersion(StringRef MacOSSDKVersion) {1668 llvm::Triple SystemTriple(llvm::sys::getProcessTriple());1669 if (!SystemTriple.isMacOSX())1670 return std::string(MacOSSDKVersion);1671 VersionTuple SystemVersion;1672 SystemTriple.getMacOSXVersion(SystemVersion);1673 1674 unsigned Major, Minor, Micro;1675 bool HadExtra;1676 if (!Driver::GetReleaseVersion(MacOSSDKVersion, Major, Minor, Micro,1677 HadExtra))1678 return std::string(MacOSSDKVersion);1679 VersionTuple SDKVersion(Major, Minor, Micro);1680 1681 if (SDKVersion > SystemVersion)1682 return SystemVersion.getAsString();1683 return std::string(MacOSSDKVersion);1684}1685 1686namespace {1687 1688/// The Darwin OS and version that was selected or inferred from arguments or1689/// environment.1690struct DarwinPlatform {1691 enum SourceKind {1692 /// The OS was specified using the -target argument.1693 TargetArg,1694 /// The OS was specified using the -mtargetos= argument.1695 MTargetOSArg,1696 /// The OS was specified using the -m<os>-version-min argument.1697 OSVersionArg,1698 /// The OS was specified using the OS_DEPLOYMENT_TARGET environment.1699 DeploymentTargetEnv,1700 /// The OS was inferred from the SDK.1701 InferredFromSDK,1702 /// The OS was inferred from the -arch.1703 InferredFromArch1704 };1705 1706 using DarwinPlatformKind = Darwin::DarwinPlatformKind;1707 using DarwinEnvironmentKind = Darwin::DarwinEnvironmentKind;1708 1709 DarwinPlatformKind getPlatform() const { return Platform; }1710 1711 DarwinEnvironmentKind getEnvironment() const { return Environment; }1712 1713 void setEnvironment(DarwinEnvironmentKind Kind) {1714 Environment = Kind;1715 InferSimulatorFromArch = false;1716 }1717 1718 const VersionTuple getOSVersion() const {1719 return UnderlyingOSVersion.value_or(VersionTuple());1720 }1721 1722 VersionTuple takeOSVersion() {1723 assert(UnderlyingOSVersion.has_value() &&1724 "attempting to get an unset OS version");1725 VersionTuple Result = *UnderlyingOSVersion;1726 UnderlyingOSVersion.reset();1727 return Result;1728 }1729 bool isValidOSVersion() const {1730 return llvm::Triple::isValidVersionForOS(getOSFromPlatform(Platform),1731 getOSVersion());1732 }1733 1734 VersionTuple getCanonicalOSVersion() const {1735 return llvm::Triple::getCanonicalVersionForOS(1736 getOSFromPlatform(Platform), getOSVersion(), /*IsInValidRange=*/true);1737 }1738 1739 void setOSVersion(const VersionTuple &Version) {1740 UnderlyingOSVersion = Version;1741 }1742 1743 bool hasOSVersion() const { return UnderlyingOSVersion.has_value(); }1744 1745 VersionTuple getZipperedOSVersion() const {1746 assert(Environment == DarwinEnvironmentKind::MacCatalyst &&1747 "zippered target version is specified only for Mac Catalyst");1748 return ZipperedOSVersion;1749 }1750 1751 /// Returns true if the target OS was explicitly specified.1752 bool isExplicitlySpecified() const { return Kind <= DeploymentTargetEnv; }1753 1754 /// Returns true if the simulator environment can be inferred from the arch.1755 bool canInferSimulatorFromArch() const { return InferSimulatorFromArch; }1756 1757 const std::optional<llvm::Triple> &getTargetVariantTriple() const {1758 return TargetVariantTriple;1759 }1760 1761 /// Adds the -m<os>-version-min argument to the compiler invocation.1762 void addOSVersionMinArgument(DerivedArgList &Args, const OptTable &Opts) {1763 auto &[Arg, OSVersionStr] = Arguments;1764 if (Arg)1765 return;1766 assert(Kind != TargetArg && Kind != MTargetOSArg && Kind != OSVersionArg &&1767 "Invalid kind");1768 options::ID Opt;1769 switch (Platform) {1770 case DarwinPlatformKind::MacOS:1771 Opt = options::OPT_mmacos_version_min_EQ;1772 break;1773 case DarwinPlatformKind::IPhoneOS:1774 Opt = options::OPT_mios_version_min_EQ;1775 break;1776 case DarwinPlatformKind::TvOS:1777 Opt = options::OPT_mtvos_version_min_EQ;1778 break;1779 case DarwinPlatformKind::WatchOS:1780 Opt = options::OPT_mwatchos_version_min_EQ;1781 break;1782 case DarwinPlatformKind::XROS:1783 // xrOS always explicitly provides a version in the triple.1784 return;1785 case DarwinPlatformKind::DriverKit:1786 // DriverKit always explicitly provides a version in the triple.1787 return;1788 }1789 Arg = Args.MakeJoinedArg(nullptr, Opts.getOption(Opt), OSVersionStr);1790 Args.append(Arg);1791 }1792 1793 /// Returns the OS version with the argument / environment variable that1794 /// specified it.1795 std::string getAsString(DerivedArgList &Args, const OptTable &Opts) {1796 auto &[Arg, OSVersionStr] = Arguments;1797 switch (Kind) {1798 case TargetArg:1799 case MTargetOSArg:1800 case OSVersionArg:1801 assert(Arg && "OS version argument not yet inferred");1802 return Arg->getAsString(Args);1803 case DeploymentTargetEnv:1804 return (llvm::Twine(EnvVarName) + "=" + OSVersionStr).str();1805 case InferredFromSDK:1806 case InferredFromArch:1807 llvm_unreachable("Cannot print arguments for inferred OS version");1808 }1809 llvm_unreachable("Unsupported Darwin Source Kind");1810 }1811 1812 // Returns the inferred source of how the OS version was resolved.1813 std::string getInferredSource() {1814 assert(!isExplicitlySpecified() && "OS version was not inferred");1815 return InferredSource.str();1816 }1817 1818 void setEnvironment(llvm::Triple::EnvironmentType EnvType,1819 const VersionTuple &OSVersion,1820 const std::optional<DarwinSDKInfo> &SDKInfo) {1821 switch (EnvType) {1822 case llvm::Triple::Simulator:1823 Environment = DarwinEnvironmentKind::Simulator;1824 break;1825 case llvm::Triple::MacABI: {1826 Environment = DarwinEnvironmentKind::MacCatalyst;1827 // The minimum native macOS target for MacCatalyst is macOS 10.15.1828 ZipperedOSVersion = VersionTuple(10, 15);1829 if (hasOSVersion() && SDKInfo) {1830 if (const auto *MacCatalystToMacOSMapping = SDKInfo->getVersionMapping(1831 DarwinSDKInfo::OSEnvPair::macCatalystToMacOSPair())) {1832 if (auto MacOSVersion = MacCatalystToMacOSMapping->map(1833 OSVersion, ZipperedOSVersion, std::nullopt)) {1834 ZipperedOSVersion = *MacOSVersion;1835 }1836 }1837 }1838 // In a zippered build, we could be building for a macOS target that's1839 // lower than the version that's implied by the OS version. In that case1840 // we need to use the minimum version as the native target version.1841 if (TargetVariantTriple) {1842 auto TargetVariantVersion = TargetVariantTriple->getOSVersion();1843 if (TargetVariantVersion.getMajor()) {1844 if (TargetVariantVersion < ZipperedOSVersion)1845 ZipperedOSVersion = TargetVariantVersion;1846 }1847 }1848 break;1849 }1850 default:1851 break;1852 }1853 }1854 1855 static DarwinPlatform1856 createFromTarget(const llvm::Triple &TT, Arg *A,1857 std::optional<llvm::Triple> TargetVariantTriple,1858 const std::optional<DarwinSDKInfo> &SDKInfo) {1859 DarwinPlatform Result(TargetArg, getPlatformFromOS(TT.getOS()),1860 TT.getOSVersion(), A);1861 VersionTuple OsVersion = TT.getOSVersion();1862 Result.TargetVariantTriple = TargetVariantTriple;1863 Result.setEnvironment(TT.getEnvironment(), OsVersion, SDKInfo);1864 return Result;1865 }1866 static DarwinPlatform1867 createFromMTargetOS(llvm::Triple::OSType OS, VersionTuple OSVersion,1868 llvm::Triple::EnvironmentType Environment, Arg *A,1869 const std::optional<DarwinSDKInfo> &SDKInfo) {1870 DarwinPlatform Result(MTargetOSArg, getPlatformFromOS(OS), OSVersion, A);1871 Result.InferSimulatorFromArch = false;1872 Result.setEnvironment(Environment, OSVersion, SDKInfo);1873 return Result;1874 }1875 static DarwinPlatform createOSVersionArg(DarwinPlatformKind Platform, Arg *A,1876 bool IsSimulator) {1877 DarwinPlatform Result{OSVersionArg, Platform,1878 getVersionFromString(A->getValue()), A};1879 if (IsSimulator)1880 Result.Environment = DarwinEnvironmentKind::Simulator;1881 return Result;1882 }1883 static DarwinPlatform createDeploymentTargetEnv(DarwinPlatformKind Platform,1884 StringRef EnvVarName,1885 StringRef OSVersion) {1886 DarwinPlatform Result(DeploymentTargetEnv, Platform,1887 getVersionFromString(OSVersion));1888 Result.EnvVarName = EnvVarName;1889 return Result;1890 }1891 static DarwinPlatform createFromSDK(StringRef SDKRoot,1892 DarwinPlatformKind Platform,1893 StringRef Value,1894 bool IsSimulator = false) {1895 DarwinPlatform Result(InferredFromSDK, Platform,1896 getVersionFromString(Value));1897 if (IsSimulator)1898 Result.Environment = DarwinEnvironmentKind::Simulator;1899 Result.InferSimulatorFromArch = false;1900 Result.InferredSource = SDKRoot;1901 return Result;1902 }1903 static DarwinPlatform createFromArch(StringRef Arch, llvm::Triple::OSType OS,1904 VersionTuple Version) {1905 auto Result =1906 DarwinPlatform(InferredFromArch, getPlatformFromOS(OS), Version);1907 Result.InferredSource = Arch;1908 return Result;1909 }1910 1911 /// Constructs an inferred SDKInfo value based on the version inferred from1912 /// the SDK path itself. Only works for values that were created by inferring1913 /// the platform from the SDKPath.1914 DarwinSDKInfo inferSDKInfo() {1915 assert(Kind == InferredFromSDK && "can infer SDK info only");1916 return DarwinSDKInfo(getOSVersion(),1917 /*MaximumDeploymentTarget=*/1918 VersionTuple(getOSVersion().getMajor(), 0, 99),1919 getOSFromPlatform(Platform));1920 }1921 1922private:1923 DarwinPlatform(SourceKind Kind, DarwinPlatformKind Platform, Arg *Argument)1924 : Kind(Kind), Platform(Platform),1925 Arguments({Argument, VersionTuple().getAsString()}) {}1926 DarwinPlatform(SourceKind Kind, DarwinPlatformKind Platform,1927 VersionTuple Value, Arg *Argument = nullptr)1928 : Kind(Kind), Platform(Platform),1929 Arguments({Argument, Value.getAsString()}) {1930 if (!Value.empty())1931 UnderlyingOSVersion = Value;1932 }1933 1934 static VersionTuple getVersionFromString(const StringRef Input) {1935 llvm::VersionTuple Version;1936 bool IsValid = !Version.tryParse(Input);1937 assert(IsValid && "unable to convert input version to version tuple");1938 (void)IsValid;1939 return Version;1940 }1941 1942 static DarwinPlatformKind getPlatformFromOS(llvm::Triple::OSType OS) {1943 switch (OS) {1944 case llvm::Triple::Darwin:1945 case llvm::Triple::MacOSX:1946 return DarwinPlatformKind::MacOS;1947 case llvm::Triple::IOS:1948 return DarwinPlatformKind::IPhoneOS;1949 case llvm::Triple::TvOS:1950 return DarwinPlatformKind::TvOS;1951 case llvm::Triple::WatchOS:1952 return DarwinPlatformKind::WatchOS;1953 case llvm::Triple::XROS:1954 return DarwinPlatformKind::XROS;1955 case llvm::Triple::DriverKit:1956 return DarwinPlatformKind::DriverKit;1957 default:1958 llvm_unreachable("Unable to infer Darwin variant");1959 }1960 }1961 1962 static llvm::Triple::OSType getOSFromPlatform(DarwinPlatformKind Platform) {1963 switch (Platform) {1964 case DarwinPlatformKind::MacOS:1965 return llvm::Triple::MacOSX;1966 case DarwinPlatformKind::IPhoneOS:1967 return llvm::Triple::IOS;1968 case DarwinPlatformKind::TvOS:1969 return llvm::Triple::TvOS;1970 case DarwinPlatformKind::WatchOS:1971 return llvm::Triple::WatchOS;1972 case DarwinPlatformKind::DriverKit:1973 return llvm::Triple::DriverKit;1974 case DarwinPlatformKind::XROS:1975 return llvm::Triple::XROS;1976 }1977 llvm_unreachable("Unknown DarwinPlatformKind enum");1978 }1979 1980 SourceKind Kind;1981 DarwinPlatformKind Platform;1982 DarwinEnvironmentKind Environment = DarwinEnvironmentKind::NativeEnvironment;1983 // When compiling for a zippered target, this means both target &1984 // target variant is set on the command line, ZipperedOSVersion holds the1985 // OSVersion tied to the main target value.1986 VersionTuple ZipperedOSVersion;1987 // We allow multiple ways to set or default the OS1988 // version used for compilation. When set, UnderlyingOSVersion represents1989 // the intended version to match the platform information computed from1990 // arguments.1991 std::optional<VersionTuple> UnderlyingOSVersion;1992 bool InferSimulatorFromArch = true;1993 std::pair<Arg *, std::string> Arguments;1994 StringRef EnvVarName;1995 // If the DarwinPlatform information is derived from an inferred source, this1996 // captures what that source input was for error reporting.1997 StringRef InferredSource;1998 // When compiling for a zippered target, this value represents the target1999 // triple encoded in the target variant.2000 std::optional<llvm::Triple> TargetVariantTriple;2001};2002 2003/// Returns the deployment target that's specified using the -m<os>-version-min2004/// argument.2005std::optional<DarwinPlatform>2006getDeploymentTargetFromOSVersionArg(DerivedArgList &Args,2007 const Driver &TheDriver) {2008 Arg *macOSVersion = Args.getLastArg(options::OPT_mmacos_version_min_EQ);2009 Arg *iOSVersion = Args.getLastArg(options::OPT_mios_version_min_EQ,2010 options::OPT_mios_simulator_version_min_EQ);2011 Arg *TvOSVersion =2012 Args.getLastArg(options::OPT_mtvos_version_min_EQ,2013 options::OPT_mtvos_simulator_version_min_EQ);2014 Arg *WatchOSVersion =2015 Args.getLastArg(options::OPT_mwatchos_version_min_EQ,2016 options::OPT_mwatchos_simulator_version_min_EQ);2017 2018 auto GetDarwinPlatform =2019 [&](DarwinPlatform::DarwinPlatformKind Platform, Arg *VersionArg,2020 bool IsSimulator) -> std::optional<DarwinPlatform> {2021 if (StringRef(VersionArg->getValue()).empty()) {2022 TheDriver.Diag(diag::err_drv_missing_version_number)2023 << VersionArg->getAsString(Args);2024 return std::nullopt;2025 }2026 return DarwinPlatform::createOSVersionArg(Platform, VersionArg,2027 /*IsSimulator=*/IsSimulator);2028 };2029 2030 if (macOSVersion) {2031 if (iOSVersion || TvOSVersion || WatchOSVersion) {2032 TheDriver.Diag(diag::err_drv_argument_not_allowed_with)2033 << macOSVersion->getAsString(Args)2034 << (iOSVersion ? iOSVersion2035 : TvOSVersion ? TvOSVersion : WatchOSVersion)2036 ->getAsString(Args);2037 }2038 return GetDarwinPlatform(Darwin::MacOS, macOSVersion,2039 /*IsSimulator=*/false);2040 2041 } else if (iOSVersion) {2042 if (TvOSVersion || WatchOSVersion) {2043 TheDriver.Diag(diag::err_drv_argument_not_allowed_with)2044 << iOSVersion->getAsString(Args)2045 << (TvOSVersion ? TvOSVersion : WatchOSVersion)->getAsString(Args);2046 }2047 return GetDarwinPlatform(Darwin::IPhoneOS, iOSVersion,2048 iOSVersion->getOption().getID() ==2049 options::OPT_mios_simulator_version_min_EQ);2050 } else if (TvOSVersion) {2051 if (WatchOSVersion) {2052 TheDriver.Diag(diag::err_drv_argument_not_allowed_with)2053 << TvOSVersion->getAsString(Args)2054 << WatchOSVersion->getAsString(Args);2055 }2056 return GetDarwinPlatform(Darwin::TvOS, TvOSVersion,2057 TvOSVersion->getOption().getID() ==2058 options::OPT_mtvos_simulator_version_min_EQ);2059 } else if (WatchOSVersion)2060 return GetDarwinPlatform(2061 Darwin::WatchOS, WatchOSVersion,2062 WatchOSVersion->getOption().getID() ==2063 options::OPT_mwatchos_simulator_version_min_EQ);2064 return std::nullopt;2065}2066 2067/// Returns the deployment target that's specified using the2068/// OS_DEPLOYMENT_TARGET environment variable.2069std::optional<DarwinPlatform>2070getDeploymentTargetFromEnvironmentVariables(const Driver &TheDriver,2071 const llvm::Triple &Triple) {2072 std::string Targets[Darwin::LastDarwinPlatform + 1];2073 const char *EnvVars[] = {2074 "MACOSX_DEPLOYMENT_TARGET",2075 "IPHONEOS_DEPLOYMENT_TARGET",2076 "TVOS_DEPLOYMENT_TARGET",2077 "WATCHOS_DEPLOYMENT_TARGET",2078 "DRIVERKIT_DEPLOYMENT_TARGET",2079 "XROS_DEPLOYMENT_TARGET"2080 };2081 static_assert(std::size(EnvVars) == Darwin::LastDarwinPlatform + 1,2082 "Missing platform");2083 for (const auto &I : llvm::enumerate(llvm::ArrayRef(EnvVars))) {2084 if (char *Env = ::getenv(I.value()))2085 Targets[I.index()] = Env;2086 }2087 2088 // Allow conflicts among OSX and iOS for historical reasons, but choose the2089 // default platform.2090 if (!Targets[Darwin::MacOS].empty() &&2091 (!Targets[Darwin::IPhoneOS].empty() ||2092 !Targets[Darwin::WatchOS].empty() || !Targets[Darwin::TvOS].empty() ||2093 !Targets[Darwin::XROS].empty())) {2094 if (Triple.getArch() == llvm::Triple::arm ||2095 Triple.getArch() == llvm::Triple::aarch64 ||2096 Triple.getArch() == llvm::Triple::thumb)2097 Targets[Darwin::MacOS] = "";2098 else2099 Targets[Darwin::IPhoneOS] = Targets[Darwin::WatchOS] =2100 Targets[Darwin::TvOS] = Targets[Darwin::XROS] = "";2101 } else {2102 // Don't allow conflicts in any other platform.2103 unsigned FirstTarget = std::size(Targets);2104 for (unsigned I = 0; I != std::size(Targets); ++I) {2105 if (Targets[I].empty())2106 continue;2107 if (FirstTarget == std::size(Targets))2108 FirstTarget = I;2109 else2110 TheDriver.Diag(diag::err_drv_conflicting_deployment_targets)2111 << Targets[FirstTarget] << Targets[I];2112 }2113 }2114 2115 for (const auto &Target : llvm::enumerate(llvm::ArrayRef(Targets))) {2116 if (!Target.value().empty())2117 return DarwinPlatform::createDeploymentTargetEnv(2118 (Darwin::DarwinPlatformKind)Target.index(), EnvVars[Target.index()],2119 Target.value());2120 }2121 return std::nullopt;2122}2123 2124/// Returns the SDK name without the optional prefix that ends with a '.' or an2125/// empty string otherwise.2126static StringRef dropSDKNamePrefix(StringRef SDKName) {2127 size_t PrefixPos = SDKName.find('.');2128 if (PrefixPos == StringRef::npos)2129 return "";2130 return SDKName.substr(PrefixPos + 1);2131}2132 2133/// Tries to infer the deployment target from the SDK specified by -isysroot2134/// (or SDKROOT). Uses the version specified in the SDKSettings.json file if2135/// it's available.2136std::optional<DarwinPlatform>2137inferDeploymentTargetFromSDK(DerivedArgList &Args,2138 const std::optional<DarwinSDKInfo> &SDKInfo) {2139 const Arg *A = Args.getLastArg(options::OPT_isysroot);2140 if (!A)2141 return std::nullopt;2142 StringRef isysroot = A->getValue();2143 StringRef SDK = Darwin::getSDKName(isysroot);2144 if (!SDK.size())2145 return std::nullopt;2146 2147 std::string Version;2148 if (SDKInfo) {2149 // Get the version from the SDKSettings.json if it's available.2150 Version = SDKInfo->getVersion().getAsString();2151 } else {2152 // Slice the version number out.2153 // Version number is between the first and the last number.2154 size_t StartVer = SDK.find_first_of("0123456789");2155 size_t EndVer = SDK.find_last_of("0123456789");2156 if (StartVer != StringRef::npos && EndVer > StartVer)2157 Version = std::string(SDK.slice(StartVer, EndVer + 1));2158 }2159 if (Version.empty())2160 return std::nullopt;2161 2162 auto CreatePlatformFromSDKName =2163 [&](StringRef SDK) -> std::optional<DarwinPlatform> {2164 if (SDK.starts_with("iPhoneOS") || SDK.starts_with("iPhoneSimulator"))2165 return DarwinPlatform::createFromSDK(2166 isysroot, Darwin::IPhoneOS, Version,2167 /*IsSimulator=*/SDK.starts_with("iPhoneSimulator"));2168 else if (SDK.starts_with("MacOSX"))2169 return DarwinPlatform::createFromSDK(isysroot, Darwin::MacOS,2170 getSystemOrSDKMacOSVersion(Version));2171 else if (SDK.starts_with("WatchOS") || SDK.starts_with("WatchSimulator"))2172 return DarwinPlatform::createFromSDK(2173 isysroot, Darwin::WatchOS, Version,2174 /*IsSimulator=*/SDK.starts_with("WatchSimulator"));2175 else if (SDK.starts_with("AppleTVOS") ||2176 SDK.starts_with("AppleTVSimulator"))2177 return DarwinPlatform::createFromSDK(2178 isysroot, Darwin::TvOS, Version,2179 /*IsSimulator=*/SDK.starts_with("AppleTVSimulator"));2180 else if (SDK.starts_with("XR"))2181 return DarwinPlatform::createFromSDK(2182 isysroot, Darwin::XROS, Version,2183 /*IsSimulator=*/SDK.contains("Simulator"));2184 else if (SDK.starts_with("DriverKit"))2185 return DarwinPlatform::createFromSDK(isysroot, Darwin::DriverKit,2186 Version);2187 return std::nullopt;2188 };2189 if (auto Result = CreatePlatformFromSDKName(SDK))2190 return Result;2191 // The SDK can be an SDK variant with a name like `<prefix>.<platform>`.2192 return CreatePlatformFromSDKName(dropSDKNamePrefix(SDK));2193}2194// Compute & get the OS Version when the target triple omitted one.2195VersionTuple getInferredOSVersion(llvm::Triple::OSType OS,2196 const llvm::Triple &Triple,2197 const Driver &TheDriver) {2198 VersionTuple OsVersion;2199 llvm::Triple SystemTriple(llvm::sys::getProcessTriple());2200 switch (OS) {2201 case llvm::Triple::Darwin:2202 case llvm::Triple::MacOSX:2203 // If there is no version specified on triple, and both host and target are2204 // macos, use the host triple to infer OS version.2205 if (Triple.isMacOSX() && SystemTriple.isMacOSX() &&2206 !Triple.getOSMajorVersion())2207 SystemTriple.getMacOSXVersion(OsVersion);2208 else if (!Triple.getMacOSXVersion(OsVersion))2209 TheDriver.Diag(diag::err_drv_invalid_darwin_version)2210 << Triple.getOSName();2211 break;2212 case llvm::Triple::IOS:2213 if (Triple.isMacCatalystEnvironment() && !Triple.getOSMajorVersion()) {2214 OsVersion = VersionTuple(13, 1);2215 } else2216 OsVersion = Triple.getiOSVersion();2217 break;2218 case llvm::Triple::TvOS:2219 OsVersion = Triple.getOSVersion();2220 break;2221 case llvm::Triple::WatchOS:2222 OsVersion = Triple.getWatchOSVersion();2223 break;2224 case llvm::Triple::XROS:2225 OsVersion = Triple.getOSVersion();2226 if (!OsVersion.getMajor())2227 OsVersion = OsVersion.withMajorReplaced(1);2228 break;2229 case llvm::Triple::DriverKit:2230 OsVersion = Triple.getDriverKitVersion();2231 break;2232 default:2233 llvm_unreachable("Unexpected OS type");2234 break;2235 }2236 return OsVersion;2237}2238 2239/// Tries to infer the target OS from the -arch.2240std::optional<DarwinPlatform>2241inferDeploymentTargetFromArch(DerivedArgList &Args, const Darwin &Toolchain,2242 const llvm::Triple &Triple,2243 const Driver &TheDriver) {2244 llvm::Triple::OSType OSTy = llvm::Triple::UnknownOS;2245 2246 StringRef MachOArchName = Toolchain.getMachOArchName(Args);2247 if (MachOArchName == "arm64" || MachOArchName == "arm64e")2248 OSTy = llvm::Triple::MacOSX;2249 else if (MachOArchName == "armv7" || MachOArchName == "armv7s" ||2250 MachOArchName == "armv6")2251 OSTy = llvm::Triple::IOS;2252 else if (MachOArchName == "armv7k" || MachOArchName == "arm64_32")2253 OSTy = llvm::Triple::WatchOS;2254 else if (MachOArchName != "armv6m" && MachOArchName != "armv7m" &&2255 MachOArchName != "armv7em")2256 OSTy = llvm::Triple::MacOSX;2257 if (OSTy == llvm::Triple::UnknownOS)2258 return std::nullopt;2259 return DarwinPlatform::createFromArch(2260 MachOArchName, OSTy, getInferredOSVersion(OSTy, Triple, TheDriver));2261}2262 2263/// Returns the deployment target that's specified using the -target option.2264std::optional<DarwinPlatform> getDeploymentTargetFromTargetArg(2265 DerivedArgList &Args, const llvm::Triple &Triple, const Driver &TheDriver,2266 const std::optional<DarwinSDKInfo> &SDKInfo) {2267 if (!Args.hasArg(options::OPT_target))2268 return std::nullopt;2269 if (Triple.getOS() == llvm::Triple::Darwin ||2270 Triple.getOS() == llvm::Triple::UnknownOS)2271 return std::nullopt;2272 std::optional<llvm::Triple> TargetVariantTriple;2273 for (const Arg *A : Args.filtered(options::OPT_darwin_target_variant)) {2274 llvm::Triple TVT(A->getValue());2275 // Find a matching <arch>-<vendor> target variant triple that can be used.2276 if ((Triple.getArch() == llvm::Triple::aarch64 ||2277 TVT.getArchName() == Triple.getArchName()) &&2278 TVT.getArch() == Triple.getArch() &&2279 TVT.getSubArch() == Triple.getSubArch() &&2280 TVT.getVendor() == Triple.getVendor()) {2281 if (TargetVariantTriple)2282 continue;2283 A->claim();2284 // Accept a -target-variant triple when compiling code that may run on2285 // macOS or Mac Catalyst.2286 if ((Triple.isMacOSX() && TVT.getOS() == llvm::Triple::IOS &&2287 TVT.isMacCatalystEnvironment()) ||2288 (TVT.isMacOSX() && Triple.getOS() == llvm::Triple::IOS &&2289 Triple.isMacCatalystEnvironment())) {2290 TargetVariantTriple = TVT;2291 continue;2292 }2293 TheDriver.Diag(diag::err_drv_target_variant_invalid)2294 << A->getSpelling() << A->getValue();2295 }2296 }2297 DarwinPlatform PlatformAndVersion = DarwinPlatform::createFromTarget(2298 Triple, Args.getLastArg(options::OPT_target), TargetVariantTriple,2299 SDKInfo);2300 2301 return PlatformAndVersion;2302}2303 2304/// Returns the deployment target that's specified using the -mtargetos option.2305std::optional<DarwinPlatform> getDeploymentTargetFromMTargetOSArg(2306 DerivedArgList &Args, const Driver &TheDriver,2307 const std::optional<DarwinSDKInfo> &SDKInfo) {2308 auto *A = Args.getLastArg(options::OPT_mtargetos_EQ);2309 if (!A)2310 return std::nullopt;2311 llvm::Triple TT(llvm::Twine("unknown-apple-") + A->getValue());2312 switch (TT.getOS()) {2313 case llvm::Triple::MacOSX:2314 case llvm::Triple::IOS:2315 case llvm::Triple::TvOS:2316 case llvm::Triple::WatchOS:2317 case llvm::Triple::XROS:2318 break;2319 default:2320 TheDriver.Diag(diag::err_drv_invalid_os_in_arg)2321 << TT.getOSName() << A->getAsString(Args);2322 return std::nullopt;2323 }2324 2325 VersionTuple Version = TT.getOSVersion();2326 if (!Version.getMajor()) {2327 TheDriver.Diag(diag::err_drv_invalid_version_number)2328 << A->getAsString(Args);2329 return std::nullopt;2330 }2331 return DarwinPlatform::createFromMTargetOS(TT.getOS(), Version,2332 TT.getEnvironment(), A, SDKInfo);2333}2334 2335std::optional<DarwinSDKInfo> parseSDKSettings(llvm::vfs::FileSystem &VFS,2336 const ArgList &Args,2337 const Driver &TheDriver) {2338 const Arg *A = Args.getLastArg(options::OPT_isysroot);2339 if (!A)2340 return std::nullopt;2341 StringRef isysroot = A->getValue();2342 auto SDKInfoOrErr = parseDarwinSDKInfo(VFS, isysroot);2343 if (!SDKInfoOrErr) {2344 llvm::consumeError(SDKInfoOrErr.takeError());2345 TheDriver.Diag(diag::warn_drv_darwin_sdk_invalid_settings);2346 return std::nullopt;2347 }2348 return *SDKInfoOrErr;2349}2350 2351} // namespace2352 2353void Darwin::AddDeploymentTarget(DerivedArgList &Args) const {2354 const OptTable &Opts = getDriver().getOpts();2355 2356 // Support allowing the SDKROOT environment variable used by xcrun and other2357 // Xcode tools to define the default sysroot, by making it the default for2358 // isysroot.2359 if (const Arg *A = Args.getLastArg(options::OPT_isysroot)) {2360 // Warn if the path does not exist.2361 if (!getVFS().exists(A->getValue()))2362 getDriver().Diag(clang::diag::warn_missing_sysroot) << A->getValue();2363 } else {2364 if (char *env = ::getenv("SDKROOT")) {2365 // We only use this value as the default if it is an absolute path,2366 // exists, and it is not the root path.2367 if (llvm::sys::path::is_absolute(env) && getVFS().exists(env) &&2368 StringRef(env) != "/") {2369 Args.append(Args.MakeSeparateArg(2370 nullptr, Opts.getOption(options::OPT_isysroot), env));2371 }2372 }2373 }2374 2375 // Read the SDKSettings.json file for more information, like the SDK version2376 // that we can pass down to the compiler.2377 SDKInfo = parseSDKSettings(getVFS(), Args, getDriver());2378 2379 // The OS and the version can be specified using the -target argument.2380 std::optional<DarwinPlatform> PlatformAndVersion =2381 getDeploymentTargetFromTargetArg(Args, getTriple(), getDriver(), SDKInfo);2382 if (PlatformAndVersion) {2383 // Disallow mixing -target and -mtargetos=.2384 if (const auto *MTargetOSArg = Args.getLastArg(options::OPT_mtargetos_EQ)) {2385 std::string TargetArgStr = PlatformAndVersion->getAsString(Args, Opts);2386 std::string MTargetOSArgStr = MTargetOSArg->getAsString(Args);2387 getDriver().Diag(diag::err_drv_cannot_mix_options)2388 << TargetArgStr << MTargetOSArgStr;2389 }2390 // Implicitly allow resolving the OS version when it wasn't explicitly set.2391 bool TripleProvidedOSVersion = PlatformAndVersion->hasOSVersion();2392 if (!TripleProvidedOSVersion)2393 PlatformAndVersion->setOSVersion(2394 getInferredOSVersion(getTriple().getOS(), getTriple(), getDriver()));2395 2396 std::optional<DarwinPlatform> PlatformAndVersionFromOSVersionArg =2397 getDeploymentTargetFromOSVersionArg(Args, getDriver());2398 if (PlatformAndVersionFromOSVersionArg) {2399 unsigned TargetMajor, TargetMinor, TargetMicro;2400 bool TargetExtra;2401 unsigned ArgMajor, ArgMinor, ArgMicro;2402 bool ArgExtra;2403 if (PlatformAndVersion->getPlatform() !=2404 PlatformAndVersionFromOSVersionArg->getPlatform() ||2405 (Driver::GetReleaseVersion(2406 PlatformAndVersion->getOSVersion().getAsString(), TargetMajor,2407 TargetMinor, TargetMicro, TargetExtra) &&2408 Driver::GetReleaseVersion(2409 PlatformAndVersionFromOSVersionArg->getOSVersion().getAsString(),2410 ArgMajor, ArgMinor, ArgMicro, ArgExtra) &&2411 (VersionTuple(TargetMajor, TargetMinor, TargetMicro) !=2412 VersionTuple(ArgMajor, ArgMinor, ArgMicro) ||2413 TargetExtra != ArgExtra))) {2414 // Select the OS version from the -m<os>-version-min argument when2415 // the -target does not include an OS version.2416 if (PlatformAndVersion->getPlatform() ==2417 PlatformAndVersionFromOSVersionArg->getPlatform() &&2418 !TripleProvidedOSVersion) {2419 PlatformAndVersion->setOSVersion(2420 PlatformAndVersionFromOSVersionArg->getOSVersion());2421 } else {2422 // Warn about -m<os>-version-min that doesn't match the OS version2423 // that's specified in the target.2424 std::string OSVersionArg =2425 PlatformAndVersionFromOSVersionArg->getAsString(Args, Opts);2426 std::string TargetArg = PlatformAndVersion->getAsString(Args, Opts);2427 getDriver().Diag(clang::diag::warn_drv_overriding_option)2428 << OSVersionArg << TargetArg;2429 }2430 }2431 }2432 } else if ((PlatformAndVersion = getDeploymentTargetFromMTargetOSArg(2433 Args, getDriver(), SDKInfo))) {2434 // The OS target can be specified using the -mtargetos= argument.2435 // Disallow mixing -mtargetos= and -m<os>version-min=.2436 std::optional<DarwinPlatform> PlatformAndVersionFromOSVersionArg =2437 getDeploymentTargetFromOSVersionArg(Args, getDriver());2438 if (PlatformAndVersionFromOSVersionArg) {2439 std::string MTargetOSArgStr = PlatformAndVersion->getAsString(Args, Opts);2440 std::string OSVersionArgStr =2441 PlatformAndVersionFromOSVersionArg->getAsString(Args, Opts);2442 getDriver().Diag(diag::err_drv_cannot_mix_options)2443 << MTargetOSArgStr << OSVersionArgStr;2444 }2445 } else {2446 // The OS target can be specified using the -m<os>version-min argument.2447 PlatformAndVersion = getDeploymentTargetFromOSVersionArg(Args, getDriver());2448 // If no deployment target was specified on the command line, check for2449 // environment defines.2450 if (!PlatformAndVersion) {2451 PlatformAndVersion =2452 getDeploymentTargetFromEnvironmentVariables(getDriver(), getTriple());2453 if (PlatformAndVersion) {2454 // Don't infer simulator from the arch when the SDK is also specified.2455 std::optional<DarwinPlatform> SDKTarget =2456 inferDeploymentTargetFromSDK(Args, SDKInfo);2457 if (SDKTarget)2458 PlatformAndVersion->setEnvironment(SDKTarget->getEnvironment());2459 }2460 }2461 // If there is no command-line argument to specify the Target version and2462 // no environment variable defined, see if we can set the default based2463 // on -isysroot using SDKSettings.json if it exists.2464 if (!PlatformAndVersion) {2465 PlatformAndVersion = inferDeploymentTargetFromSDK(Args, SDKInfo);2466 /// If the target was successfully constructed from the SDK path, try to2467 /// infer the SDK info if the SDK doesn't have it.2468 if (PlatformAndVersion && !SDKInfo)2469 SDKInfo = PlatformAndVersion->inferSDKInfo();2470 }2471 // If no OS targets have been specified, try to guess platform from -target2472 // or arch name and compute the version from the triple.2473 if (!PlatformAndVersion)2474 PlatformAndVersion =2475 inferDeploymentTargetFromArch(Args, *this, getTriple(), getDriver());2476 }2477 2478 assert(PlatformAndVersion && "Unable to infer Darwin variant");2479 if (!PlatformAndVersion->isValidOSVersion()) {2480 if (PlatformAndVersion->isExplicitlySpecified())2481 getDriver().Diag(diag::err_drv_invalid_version_number)2482 << PlatformAndVersion->getAsString(Args, Opts);2483 else2484 getDriver().Diag(diag::err_drv_invalid_version_number_inferred)2485 << PlatformAndVersion->getOSVersion().getAsString()2486 << PlatformAndVersion->getInferredSource();2487 }2488 // After the deployment OS version has been resolved, set it to the canonical2489 // version before further error detection and converting to a proper target2490 // triple.2491 VersionTuple CanonicalVersion = PlatformAndVersion->getCanonicalOSVersion();2492 if (CanonicalVersion != PlatformAndVersion->getOSVersion()) {2493 getDriver().Diag(diag::warn_drv_overriding_deployment_version)2494 << PlatformAndVersion->getOSVersion().getAsString()2495 << CanonicalVersion.getAsString();2496 PlatformAndVersion->setOSVersion(CanonicalVersion);2497 }2498 2499 PlatformAndVersion->addOSVersionMinArgument(Args, Opts);2500 DarwinPlatformKind Platform = PlatformAndVersion->getPlatform();2501 2502 unsigned Major, Minor, Micro;2503 bool HadExtra;2504 // The major version should not be over this number.2505 const unsigned MajorVersionLimit = 1000;2506 const VersionTuple OSVersion = PlatformAndVersion->takeOSVersion();2507 const std::string OSVersionStr = OSVersion.getAsString();2508 // Set the tool chain target information.2509 if (Platform == MacOS) {2510 if (!Driver::GetReleaseVersion(OSVersionStr, Major, Minor, Micro,2511 HadExtra) ||2512 HadExtra || Major < 10 || Major >= MajorVersionLimit || Minor >= 100 ||2513 Micro >= 100)2514 getDriver().Diag(diag::err_drv_invalid_version_number)2515 << PlatformAndVersion->getAsString(Args, Opts);2516 } else if (Platform == IPhoneOS) {2517 if (!Driver::GetReleaseVersion(OSVersionStr, Major, Minor, Micro,2518 HadExtra) ||2519 HadExtra || Major >= MajorVersionLimit || Minor >= 100 || Micro >= 100)2520 getDriver().Diag(diag::err_drv_invalid_version_number)2521 << PlatformAndVersion->getAsString(Args, Opts);2522 ;2523 if (PlatformAndVersion->getEnvironment() == MacCatalyst &&2524 (Major < 13 || (Major == 13 && Minor < 1))) {2525 getDriver().Diag(diag::err_drv_invalid_version_number)2526 << PlatformAndVersion->getAsString(Args, Opts);2527 Major = 13;2528 Minor = 1;2529 Micro = 0;2530 }2531 // For 32-bit targets, the deployment target for iOS has to be earlier than2532 // iOS 11.2533 if (getTriple().isArch32Bit() && Major >= 11) {2534 // If the deployment target is explicitly specified, print a diagnostic.2535 if (PlatformAndVersion->isExplicitlySpecified()) {2536 if (PlatformAndVersion->getEnvironment() == MacCatalyst)2537 getDriver().Diag(diag::err_invalid_macos_32bit_deployment_target);2538 else2539 getDriver().Diag(diag::warn_invalid_ios_deployment_target)2540 << PlatformAndVersion->getAsString(Args, Opts);2541 // Otherwise, set it to 10.99.99.2542 } else {2543 Major = 10;2544 Minor = 99;2545 Micro = 99;2546 }2547 }2548 } else if (Platform == TvOS) {2549 if (!Driver::GetReleaseVersion(OSVersionStr, Major, Minor, Micro,2550 HadExtra) ||2551 HadExtra || Major >= MajorVersionLimit || Minor >= 100 || Micro >= 100)2552 getDriver().Diag(diag::err_drv_invalid_version_number)2553 << PlatformAndVersion->getAsString(Args, Opts);2554 } else if (Platform == WatchOS) {2555 if (!Driver::GetReleaseVersion(OSVersionStr, Major, Minor, Micro,2556 HadExtra) ||2557 HadExtra || Major >= MajorVersionLimit || Minor >= 100 || Micro >= 100)2558 getDriver().Diag(diag::err_drv_invalid_version_number)2559 << PlatformAndVersion->getAsString(Args, Opts);2560 } else if (Platform == DriverKit) {2561 if (!Driver::GetReleaseVersion(OSVersionStr, Major, Minor, Micro,2562 HadExtra) ||2563 HadExtra || Major < 19 || Major >= MajorVersionLimit || Minor >= 100 ||2564 Micro >= 100)2565 getDriver().Diag(diag::err_drv_invalid_version_number)2566 << PlatformAndVersion->getAsString(Args, Opts);2567 } else if (Platform == XROS) {2568 if (!Driver::GetReleaseVersion(OSVersionStr, Major, Minor, Micro,2569 HadExtra) ||2570 HadExtra || Major < 1 || Major >= MajorVersionLimit || Minor >= 100 ||2571 Micro >= 100)2572 getDriver().Diag(diag::err_drv_invalid_version_number)2573 << PlatformAndVersion->getAsString(Args, Opts);2574 } else2575 llvm_unreachable("unknown kind of Darwin platform");2576 2577 DarwinEnvironmentKind Environment = PlatformAndVersion->getEnvironment();2578 // Recognize iOS targets with an x86 architecture as the iOS simulator.2579 if (Environment == NativeEnvironment && Platform != MacOS &&2580 Platform != DriverKit &&2581 PlatformAndVersion->canInferSimulatorFromArch() && getTriple().isX86())2582 Environment = Simulator;2583 2584 VersionTuple ZipperedOSVersion;2585 if (Environment == MacCatalyst)2586 ZipperedOSVersion = PlatformAndVersion->getZipperedOSVersion();2587 setTarget(Platform, Environment, Major, Minor, Micro, ZipperedOSVersion);2588 TargetVariantTriple = PlatformAndVersion->getTargetVariantTriple();2589 if (TargetVariantTriple &&2590 !llvm::Triple::isValidVersionForOS(TargetVariantTriple->getOS(),2591 TargetVariantTriple->getOSVersion())) {2592 getDriver().Diag(diag::err_drv_invalid_version_number)2593 << TargetVariantTriple->str();2594 }2595 2596 if (const Arg *A = Args.getLastArg(options::OPT_isysroot)) {2597 StringRef SDK = getSDKName(A->getValue());2598 if (SDK.size() > 0) {2599 size_t StartVer = SDK.find_first_of("0123456789");2600 StringRef SDKName = SDK.slice(0, StartVer);2601 if (!SDKName.starts_with(getPlatformFamily()) &&2602 !dropSDKNamePrefix(SDKName).starts_with(getPlatformFamily()))2603 getDriver().Diag(diag::warn_incompatible_sysroot)2604 << SDKName << getPlatformFamily();2605 }2606 }2607}2608 2609// For certain platforms/environments almost all resources (e.g., headers) are2610// located in sub-directories, e.g., for DriverKit they live in2611// <SYSROOT>/System/DriverKit/usr/include (instead of <SYSROOT>/usr/include).2612static void AppendPlatformPrefix(SmallString<128> &Path,2613 const llvm::Triple &T) {2614 if (T.isDriverKit()) {2615 llvm::sys::path::append(Path, "System", "DriverKit");2616 }2617}2618 2619// Returns the effective sysroot from either -isysroot or --sysroot, plus the2620// platform prefix (if any).2621llvm::SmallString<128>2622AppleMachO::GetEffectiveSysroot(const llvm::opt::ArgList &DriverArgs) const {2623 llvm::SmallString<128> Path("/");2624 if (DriverArgs.hasArg(options::OPT_isysroot))2625 Path = DriverArgs.getLastArgValue(options::OPT_isysroot);2626 else if (!getDriver().SysRoot.empty())2627 Path = getDriver().SysRoot;2628 2629 if (hasEffectiveTriple()) {2630 AppendPlatformPrefix(Path, getEffectiveTriple());2631 }2632 return Path;2633}2634 2635void AppleMachO::AddClangSystemIncludeArgs(2636 const llvm::opt::ArgList &DriverArgs,2637 llvm::opt::ArgStringList &CC1Args) const {2638 const Driver &D = getDriver();2639 2640 llvm::SmallString<128> Sysroot = GetEffectiveSysroot(DriverArgs);2641 2642 bool NoStdInc = DriverArgs.hasArg(options::OPT_nostdinc);2643 bool NoStdlibInc = DriverArgs.hasArg(options::OPT_nostdlibinc);2644 bool NoBuiltinInc = DriverArgs.hasFlag(2645 options::OPT_nobuiltininc, options::OPT_ibuiltininc, /*Default=*/false);2646 bool ForceBuiltinInc = DriverArgs.hasFlag(2647 options::OPT_ibuiltininc, options::OPT_nobuiltininc, /*Default=*/false);2648 2649 // Add <sysroot>/usr/local/include2650 if (!NoStdInc && !NoStdlibInc) {2651 SmallString<128> P(Sysroot);2652 llvm::sys::path::append(P, "usr", "local", "include");2653 addSystemInclude(DriverArgs, CC1Args, P);2654 }2655 2656 // Add the Clang builtin headers (<resource>/include)2657 if (!(NoStdInc && !ForceBuiltinInc) && !NoBuiltinInc) {2658 SmallString<128> P(D.ResourceDir);2659 llvm::sys::path::append(P, "include");2660 addSystemInclude(DriverArgs, CC1Args, P);2661 }2662 2663 if (NoStdInc || NoStdlibInc)2664 return;2665 2666 // Check for configure-time C include directories.2667 llvm::StringRef CIncludeDirs(C_INCLUDE_DIRS);2668 if (!CIncludeDirs.empty()) {2669 llvm::SmallVector<llvm::StringRef, 5> dirs;2670 CIncludeDirs.split(dirs, ":");2671 for (llvm::StringRef dir : dirs) {2672 llvm::StringRef Prefix =2673 llvm::sys::path::is_absolute(dir) ? "" : llvm::StringRef(Sysroot);2674 addExternCSystemInclude(DriverArgs, CC1Args, Prefix + dir);2675 }2676 } else {2677 // Otherwise, add <sysroot>/usr/include.2678 SmallString<128> P(Sysroot);2679 llvm::sys::path::append(P, "usr", "include");2680 addExternCSystemInclude(DriverArgs, CC1Args, P.str());2681 }2682}2683 2684void DarwinClang::AddClangSystemIncludeArgs(2685 const llvm::opt::ArgList &DriverArgs,2686 llvm::opt::ArgStringList &CC1Args) const {2687 AppleMachO::AddClangSystemIncludeArgs(DriverArgs, CC1Args);2688 2689 if (DriverArgs.hasArg(options::OPT_nostdinc, options::OPT_nostdlibinc))2690 return;2691 2692 llvm::SmallString<128> Sysroot = GetEffectiveSysroot(DriverArgs);2693 2694 // Add <sysroot>/System/Library/Frameworks2695 // Add <sysroot>/System/Library/SubFrameworks2696 // Add <sysroot>/Library/Frameworks2697 SmallString<128> P1(Sysroot), P2(Sysroot), P3(Sysroot);2698 llvm::sys::path::append(P1, "System", "Library", "Frameworks");2699 llvm::sys::path::append(P2, "System", "Library", "SubFrameworks");2700 llvm::sys::path::append(P3, "Library", "Frameworks");2701 addSystemFrameworkIncludes(DriverArgs, CC1Args, {P1, P2, P3});2702}2703 2704bool DarwinClang::AddGnuCPlusPlusIncludePaths(const llvm::opt::ArgList &DriverArgs,2705 llvm::opt::ArgStringList &CC1Args,2706 llvm::SmallString<128> Base,2707 llvm::StringRef Version,2708 llvm::StringRef ArchDir,2709 llvm::StringRef BitDir) const {2710 llvm::sys::path::append(Base, Version);2711 2712 // Add the base dir2713 addSystemInclude(DriverArgs, CC1Args, Base);2714 2715 // Add the multilib dirs2716 {2717 llvm::SmallString<128> P = Base;2718 if (!ArchDir.empty())2719 llvm::sys::path::append(P, ArchDir);2720 if (!BitDir.empty())2721 llvm::sys::path::append(P, BitDir);2722 addSystemInclude(DriverArgs, CC1Args, P);2723 }2724 2725 // Add the backward dir2726 {2727 llvm::SmallString<128> P = Base;2728 llvm::sys::path::append(P, "backward");2729 addSystemInclude(DriverArgs, CC1Args, P);2730 }2731 2732 return getVFS().exists(Base);2733}2734 2735void AppleMachO::AddClangCXXStdlibIncludeArgs(2736 const llvm::opt::ArgList &DriverArgs,2737 llvm::opt::ArgStringList &CC1Args) const {2738 // The implementation from a base class will pass through the -stdlib to2739 // CC1Args.2740 // FIXME: this should not be necessary, remove usages in the frontend2741 // (e.g. HeaderSearchOptions::UseLibcxx) and don't pipe -stdlib.2742 // Also check whether this is used for setting library search paths.2743 ToolChain::AddClangCXXStdlibIncludeArgs(DriverArgs, CC1Args);2744 2745 if (DriverArgs.hasArg(options::OPT_nostdinc, options::OPT_nostdlibinc,2746 options::OPT_nostdincxx))2747 return;2748 2749 llvm::SmallString<128> Sysroot = GetEffectiveSysroot(DriverArgs);2750 2751 switch (GetCXXStdlibType(DriverArgs)) {2752 case ToolChain::CST_Libcxx: {2753 // On Darwin, libc++ can be installed in one of the following places:2754 // 1. Alongside the compiler in <clang-executable-folder>/../include/c++/v12755 // 2. In a SDK (or a custom sysroot) in <sysroot>/usr/include/c++/v12756 //2757 // The precedence of paths is as listed above, i.e. we take the first path2758 // that exists. Note that we never include libc++ twice -- we take the first2759 // path that exists and don't send the other paths to CC1 (otherwise2760 // include_next could break).2761 2762 // Check for (1)2763 // Get from '<install>/bin' to '<install>/include/c++/v1'.2764 // Note that InstallBin can be relative, so we use '..' instead of2765 // parent_path.2766 llvm::SmallString<128> InstallBin(getDriver().Dir); // <install>/bin2767 llvm::sys::path::append(InstallBin, "..", "include", "c++", "v1");2768 if (getVFS().exists(InstallBin)) {2769 addSystemInclude(DriverArgs, CC1Args, InstallBin);2770 return;2771 } else if (DriverArgs.hasArg(options::OPT_v)) {2772 llvm::errs() << "ignoring nonexistent directory \"" << InstallBin2773 << "\"\n";2774 }2775 2776 // Otherwise, check for (2)2777 llvm::SmallString<128> SysrootUsr = Sysroot;2778 llvm::sys::path::append(SysrootUsr, "usr", "include", "c++", "v1");2779 if (getVFS().exists(SysrootUsr)) {2780 addSystemInclude(DriverArgs, CC1Args, SysrootUsr);2781 return;2782 } else if (DriverArgs.hasArg(options::OPT_v)) {2783 llvm::errs() << "ignoring nonexistent directory \"" << SysrootUsr2784 << "\"\n";2785 }2786 2787 // Otherwise, don't add any path.2788 break;2789 }2790 2791 case ToolChain::CST_Libstdcxx:2792 AddGnuCPlusPlusIncludePaths(DriverArgs, CC1Args);2793 break;2794 }2795}2796 2797void AppleMachO::AddGnuCPlusPlusIncludePaths(2798 const llvm::opt::ArgList &DriverArgs,2799 llvm::opt::ArgStringList &CC1Args) const {}2800 2801void DarwinClang::AddGnuCPlusPlusIncludePaths(2802 const llvm::opt::ArgList &DriverArgs,2803 llvm::opt::ArgStringList &CC1Args) const {2804 llvm::SmallString<128> UsrIncludeCxx = GetEffectiveSysroot(DriverArgs);2805 llvm::sys::path::append(UsrIncludeCxx, "usr", "include", "c++");2806 2807 llvm::Triple::ArchType arch = getTriple().getArch();2808 bool IsBaseFound = true;2809 switch (arch) {2810 default:2811 break;2812 2813 case llvm::Triple::x86:2814 case llvm::Triple::x86_64:2815 IsBaseFound = AddGnuCPlusPlusIncludePaths(2816 DriverArgs, CC1Args, UsrIncludeCxx, "4.2.1", "i686-apple-darwin10",2817 arch == llvm::Triple::x86_64 ? "x86_64" : "");2818 IsBaseFound |= AddGnuCPlusPlusIncludePaths(2819 DriverArgs, CC1Args, UsrIncludeCxx, "4.0.0", "i686-apple-darwin8", "");2820 break;2821 2822 case llvm::Triple::arm:2823 case llvm::Triple::thumb:2824 IsBaseFound =2825 AddGnuCPlusPlusIncludePaths(DriverArgs, CC1Args, UsrIncludeCxx, "4.2.1",2826 "arm-apple-darwin10", "v7");2827 IsBaseFound |=2828 AddGnuCPlusPlusIncludePaths(DriverArgs, CC1Args, UsrIncludeCxx, "4.2.1",2829 "arm-apple-darwin10", "v6");2830 break;2831 2832 case llvm::Triple::aarch64:2833 IsBaseFound =2834 AddGnuCPlusPlusIncludePaths(DriverArgs, CC1Args, UsrIncludeCxx, "4.2.1",2835 "arm64-apple-darwin10", "");2836 break;2837 }2838 2839 if (!IsBaseFound) {2840 getDriver().Diag(diag::warn_drv_libstdcxx_not_found);2841 }2842}2843 2844void AppleMachO::AddCXXStdlibLibArgs(const ArgList &Args,2845 ArgStringList &CmdArgs) const {2846 CXXStdlibType Type = GetCXXStdlibType(Args);2847 2848 switch (Type) {2849 case ToolChain::CST_Libcxx:2850 CmdArgs.push_back("-lc++");2851 if (Args.hasArg(options::OPT_fexperimental_library))2852 CmdArgs.push_back("-lc++experimental");2853 break;2854 2855 case ToolChain::CST_Libstdcxx:2856 // Unfortunately, -lstdc++ doesn't always exist in the standard search path;2857 // it was previously found in the gcc lib dir. However, for all the Darwin2858 // platforms we care about it was -lstdc++.6, so we search for that2859 // explicitly if we can't see an obvious -lstdc++ candidate.2860 2861 // Check in the sysroot first.2862 if (const Arg *A = Args.getLastArg(options::OPT_isysroot)) {2863 SmallString<128> P(A->getValue());2864 llvm::sys::path::append(P, "usr", "lib", "libstdc++.dylib");2865 2866 if (!getVFS().exists(P)) {2867 llvm::sys::path::remove_filename(P);2868 llvm::sys::path::append(P, "libstdc++.6.dylib");2869 if (getVFS().exists(P)) {2870 CmdArgs.push_back(Args.MakeArgString(P));2871 return;2872 }2873 }2874 }2875 2876 // Otherwise, look in the root.2877 // FIXME: This should be removed someday when we don't have to care about2878 // 10.6 and earlier, where /usr/lib/libstdc++.dylib does not exist.2879 if (!getVFS().exists("/usr/lib/libstdc++.dylib") &&2880 getVFS().exists("/usr/lib/libstdc++.6.dylib")) {2881 CmdArgs.push_back("/usr/lib/libstdc++.6.dylib");2882 return;2883 }2884 2885 // Otherwise, let the linker search.2886 CmdArgs.push_back("-lstdc++");2887 break;2888 }2889}2890 2891void DarwinClang::AddCCKextLibArgs(const ArgList &Args,2892 ArgStringList &CmdArgs) const {2893 // For Darwin platforms, use the compiler-rt-based support library2894 // instead of the gcc-provided one (which is also incidentally2895 // only present in the gcc lib dir, which makes it hard to find).2896 2897 SmallString<128> P(getDriver().ResourceDir);2898 llvm::sys::path::append(P, "lib", "darwin");2899 2900 // Use the newer cc_kext for iOS ARM after 6.0.2901 if (isTargetWatchOS()) {2902 llvm::sys::path::append(P, "libclang_rt.cc_kext_watchos.a");2903 } else if (isTargetTvOS()) {2904 llvm::sys::path::append(P, "libclang_rt.cc_kext_tvos.a");2905 } else if (isTargetIPhoneOS()) {2906 llvm::sys::path::append(P, "libclang_rt.cc_kext_ios.a");2907 } else if (isTargetDriverKit()) {2908 // DriverKit doesn't want extra runtime support.2909 } else if (isTargetXROSDevice()) {2910 llvm::sys::path::append(2911 P, llvm::Twine("libclang_rt.cc_kext_") +2912 llvm::Triple::getOSTypeName(llvm::Triple::XROS) + ".a");2913 } else {2914 llvm::sys::path::append(P, "libclang_rt.cc_kext.a");2915 }2916 2917 // For now, allow missing resource libraries to support developers who may2918 // not have compiler-rt checked out or integrated into their build.2919 if (getVFS().exists(P))2920 CmdArgs.push_back(Args.MakeArgString(P));2921}2922 2923DerivedArgList *MachO::TranslateArgs(const DerivedArgList &Args,2924 StringRef BoundArch,2925 Action::OffloadKind) const {2926 DerivedArgList *DAL = new DerivedArgList(Args.getBaseArgs());2927 const OptTable &Opts = getDriver().getOpts();2928 2929 // FIXME: We really want to get out of the tool chain level argument2930 // translation business, as it makes the driver functionality much2931 // more opaque. For now, we follow gcc closely solely for the2932 // purpose of easily achieving feature parity & testability. Once we2933 // have something that works, we should reevaluate each translation2934 // and try to push it down into tool specific logic.2935 2936 for (Arg *A : Args) {2937 // Sob. These is strictly gcc compatible for the time being. Apple2938 // gcc translates options twice, which means that self-expanding2939 // options add duplicates.2940 switch ((options::ID)A->getOption().getID()) {2941 default:2942 DAL->append(A);2943 break;2944 2945 case options::OPT_mkernel:2946 case options::OPT_fapple_kext:2947 DAL->append(A);2948 DAL->AddFlagArg(A, Opts.getOption(options::OPT_static));2949 break;2950 2951 case options::OPT_dependency_file:2952 DAL->AddSeparateArg(A, Opts.getOption(options::OPT_MF), A->getValue());2953 break;2954 2955 case options::OPT_gfull:2956 DAL->AddFlagArg(A, Opts.getOption(options::OPT_g_Flag));2957 DAL->AddFlagArg(2958 A, Opts.getOption(options::OPT_fno_eliminate_unused_debug_symbols));2959 break;2960 2961 case options::OPT_gused:2962 DAL->AddFlagArg(A, Opts.getOption(options::OPT_g_Flag));2963 DAL->AddFlagArg(2964 A, Opts.getOption(options::OPT_feliminate_unused_debug_symbols));2965 break;2966 2967 case options::OPT_shared:2968 DAL->AddFlagArg(A, Opts.getOption(options::OPT_dynamiclib));2969 break;2970 2971 case options::OPT_fconstant_cfstrings:2972 DAL->AddFlagArg(A, Opts.getOption(options::OPT_mconstant_cfstrings));2973 break;2974 2975 case options::OPT_fno_constant_cfstrings:2976 DAL->AddFlagArg(A, Opts.getOption(options::OPT_mno_constant_cfstrings));2977 break;2978 2979 case options::OPT_Wnonportable_cfstrings:2980 DAL->AddFlagArg(A,2981 Opts.getOption(options::OPT_mwarn_nonportable_cfstrings));2982 break;2983 2984 case options::OPT_Wno_nonportable_cfstrings:2985 DAL->AddFlagArg(2986 A, Opts.getOption(options::OPT_mno_warn_nonportable_cfstrings));2987 break;2988 }2989 }2990 2991 // Add the arch options based on the particular spelling of -arch, to match2992 // how the driver works.2993 if (!BoundArch.empty()) {2994 StringRef Name = BoundArch;2995 const Option MCpu = Opts.getOption(options::OPT_mcpu_EQ);2996 const Option MArch = Opts.getOption(options::OPT_march_EQ);2997 2998 // This code must be kept in sync with LLVM's getArchTypeForDarwinArch,2999 // which defines the list of which architectures we accept.3000 if (Name == "ppc")3001 ;3002 else if (Name == "ppc601")3003 DAL->AddJoinedArg(nullptr, MCpu, "601");3004 else if (Name == "ppc603")3005 DAL->AddJoinedArg(nullptr, MCpu, "603");3006 else if (Name == "ppc604")3007 DAL->AddJoinedArg(nullptr, MCpu, "604");3008 else if (Name == "ppc604e")3009 DAL->AddJoinedArg(nullptr, MCpu, "604e");3010 else if (Name == "ppc750")3011 DAL->AddJoinedArg(nullptr, MCpu, "750");3012 else if (Name == "ppc7400")3013 DAL->AddJoinedArg(nullptr, MCpu, "7400");3014 else if (Name == "ppc7450")3015 DAL->AddJoinedArg(nullptr, MCpu, "7450");3016 else if (Name == "ppc970")3017 DAL->AddJoinedArg(nullptr, MCpu, "970");3018 3019 else if (Name == "ppc64" || Name == "ppc64le")3020 DAL->AddFlagArg(nullptr, Opts.getOption(options::OPT_m64));3021 3022 else if (Name == "i386")3023 ;3024 else if (Name == "i486")3025 DAL->AddJoinedArg(nullptr, MArch, "i486");3026 else if (Name == "i586")3027 DAL->AddJoinedArg(nullptr, MArch, "i586");3028 else if (Name == "i686")3029 DAL->AddJoinedArg(nullptr, MArch, "i686");3030 else if (Name == "pentium")3031 DAL->AddJoinedArg(nullptr, MArch, "pentium");3032 else if (Name == "pentium2")3033 DAL->AddJoinedArg(nullptr, MArch, "pentium2");3034 else if (Name == "pentpro")3035 DAL->AddJoinedArg(nullptr, MArch, "pentiumpro");3036 else if (Name == "pentIIm3")3037 DAL->AddJoinedArg(nullptr, MArch, "pentium2");3038 3039 else if (Name == "x86_64" || Name == "x86_64h")3040 DAL->AddFlagArg(nullptr, Opts.getOption(options::OPT_m64));3041 3042 else if (Name == "arm")3043 DAL->AddJoinedArg(nullptr, MArch, "armv4t");3044 else if (Name == "armv4t")3045 DAL->AddJoinedArg(nullptr, MArch, "armv4t");3046 else if (Name == "armv5")3047 DAL->AddJoinedArg(nullptr, MArch, "armv5tej");3048 else if (Name == "xscale")3049 DAL->AddJoinedArg(nullptr, MArch, "xscale");3050 else if (Name == "armv6")3051 DAL->AddJoinedArg(nullptr, MArch, "armv6k");3052 else if (Name == "armv6m")3053 DAL->AddJoinedArg(nullptr, MArch, "armv6m");3054 else if (Name == "armv7")3055 DAL->AddJoinedArg(nullptr, MArch, "armv7a");3056 else if (Name == "armv7em")3057 DAL->AddJoinedArg(nullptr, MArch, "armv7em");3058 else if (Name == "armv7k")3059 DAL->AddJoinedArg(nullptr, MArch, "armv7k");3060 else if (Name == "armv7m")3061 DAL->AddJoinedArg(nullptr, MArch, "armv7m");3062 else if (Name == "armv7s")3063 DAL->AddJoinedArg(nullptr, MArch, "armv7s");3064 }3065 3066 return DAL;3067}3068 3069void MachO::AddLinkRuntimeLibArgs(const ArgList &Args,3070 ArgStringList &CmdArgs,3071 bool ForceLinkBuiltinRT) const {3072 // Embedded targets are simple at the moment, not supporting sanitizers and3073 // with different libraries for each member of the product { static, PIC } x3074 // { hard-float, soft-float }3075 llvm::SmallString<32> CompilerRT = StringRef("");3076 CompilerRT +=3077 (tools::arm::getARMFloatABI(*this, Args) == tools::arm::FloatABI::Hard)3078 ? "hard"3079 : "soft";3080 CompilerRT += Args.hasArg(options::OPT_fPIC) ? "_pic" : "_static";3081 3082 AddLinkRuntimeLib(Args, CmdArgs, CompilerRT, RLO_IsEmbedded);3083}3084 3085bool Darwin::isAlignedAllocationUnavailable() const {3086 llvm::Triple::OSType OS;3087 3088 if (isTargetMacCatalyst())3089 return TargetVersion < alignedAllocMinVersion(llvm::Triple::MacOSX);3090 switch (TargetPlatform) {3091 case MacOS: // Earlier than 10.13.3092 OS = llvm::Triple::MacOSX;3093 break;3094 case IPhoneOS:3095 OS = llvm::Triple::IOS;3096 break;3097 case TvOS: // Earlier than 11.0.3098 OS = llvm::Triple::TvOS;3099 break;3100 case WatchOS: // Earlier than 4.0.3101 OS = llvm::Triple::WatchOS;3102 break;3103 case XROS: // Always available.3104 return false;3105 case DriverKit: // Always available.3106 return false;3107 }3108 3109 return TargetVersion < alignedAllocMinVersion(OS);3110}3111 3112static bool3113sdkSupportsBuiltinModules(const std::optional<DarwinSDKInfo> &SDKInfo) {3114 if (!SDKInfo)3115 // If there is no SDK info, assume this is building against a3116 // pre-SDK version of macOS (i.e. before Mac OS X 10.4). Those3117 // don't support modules anyway, but the headers definitely3118 // don't support builtin modules either. It might also be some3119 // kind of degenerate build environment, err on the side of3120 // the old behavior which is to not use builtin modules.3121 return false;3122 3123 VersionTuple SDKVersion = SDKInfo->getVersion();3124 switch (SDKInfo->getOS()) {3125 // Existing SDKs added support for builtin modules in the fall3126 // 2024 major releases.3127 case llvm::Triple::MacOSX:3128 return SDKVersion >= VersionTuple(15U);3129 case llvm::Triple::IOS:3130 return SDKVersion >= VersionTuple(18U);3131 case llvm::Triple::TvOS:3132 return SDKVersion >= VersionTuple(18U);3133 case llvm::Triple::WatchOS:3134 return SDKVersion >= VersionTuple(11U);3135 case llvm::Triple::XROS:3136 return SDKVersion >= VersionTuple(2U);3137 3138 // New SDKs support builtin modules from the start.3139 default:3140 return true;3141 }3142}3143 3144static inline llvm::VersionTuple3145sizedDeallocMinVersion(llvm::Triple::OSType OS) {3146 switch (OS) {3147 default:3148 break;3149 case llvm::Triple::Darwin:3150 case llvm::Triple::MacOSX: // Earliest supporting version is 10.12.3151 return llvm::VersionTuple(10U, 12U);3152 case llvm::Triple::IOS:3153 case llvm::Triple::TvOS: // Earliest supporting version is 10.0.0.3154 return llvm::VersionTuple(10U);3155 case llvm::Triple::WatchOS: // Earliest supporting version is 3.0.0.3156 return llvm::VersionTuple(3U);3157 }3158 3159 llvm_unreachable("Unexpected OS");3160}3161 3162bool Darwin::isSizedDeallocationUnavailable() const {3163 llvm::Triple::OSType OS;3164 3165 if (isTargetMacCatalyst())3166 return TargetVersion < sizedDeallocMinVersion(llvm::Triple::MacOSX);3167 switch (TargetPlatform) {3168 case MacOS: // Earlier than 10.12.3169 OS = llvm::Triple::MacOSX;3170 break;3171 case IPhoneOS:3172 OS = llvm::Triple::IOS;3173 break;3174 case TvOS: // Earlier than 10.0.3175 OS = llvm::Triple::TvOS;3176 break;3177 case WatchOS: // Earlier than 3.0.3178 OS = llvm::Triple::WatchOS;3179 break;3180 case DriverKit:3181 case XROS:3182 // Always available.3183 return false;3184 }3185 3186 return TargetVersion < sizedDeallocMinVersion(OS);3187}3188 3189void MachO::addClangTargetOptions(const llvm::opt::ArgList &DriverArgs,3190 llvm::opt::ArgStringList &CC1Args,3191 Action::OffloadKind DeviceOffloadKind) const {3192 3193 ToolChain::addClangTargetOptions(DriverArgs, CC1Args, DeviceOffloadKind);3194 3195 // On arm64e, we enable all the features required for the Darwin userspace3196 // ABI3197 if (getTriple().isArm64e()) {3198 // Core platform ABI3199 if (!DriverArgs.hasArg(options::OPT_fptrauth_calls,3200 options::OPT_fno_ptrauth_calls))3201 CC1Args.push_back("-fptrauth-calls");3202 if (!DriverArgs.hasArg(options::OPT_fptrauth_returns,3203 options::OPT_fno_ptrauth_returns))3204 CC1Args.push_back("-fptrauth-returns");3205 if (!DriverArgs.hasArg(options::OPT_fptrauth_intrinsics,3206 options::OPT_fno_ptrauth_intrinsics))3207 CC1Args.push_back("-fptrauth-intrinsics");3208 if (!DriverArgs.hasArg(options::OPT_fptrauth_indirect_gotos,3209 options::OPT_fno_ptrauth_indirect_gotos))3210 CC1Args.push_back("-fptrauth-indirect-gotos");3211 if (!DriverArgs.hasArg(options::OPT_fptrauth_auth_traps,3212 options::OPT_fno_ptrauth_auth_traps))3213 CC1Args.push_back("-fptrauth-auth-traps");3214 3215 // C++ v-table ABI3216 if (!DriverArgs.hasArg(3217 options::OPT_fptrauth_vtable_pointer_address_discrimination,3218 options::OPT_fno_ptrauth_vtable_pointer_address_discrimination))3219 CC1Args.push_back("-fptrauth-vtable-pointer-address-discrimination");3220 if (!DriverArgs.hasArg(3221 options::OPT_fptrauth_vtable_pointer_type_discrimination,3222 options::OPT_fno_ptrauth_vtable_pointer_type_discrimination))3223 CC1Args.push_back("-fptrauth-vtable-pointer-type-discrimination");3224 3225 // Objective-C ABI3226 if (!DriverArgs.hasArg(options::OPT_fptrauth_objc_isa,3227 options::OPT_fno_ptrauth_objc_isa))3228 CC1Args.push_back("-fptrauth-objc-isa");3229 if (!DriverArgs.hasArg(options::OPT_fptrauth_objc_class_ro,3230 options::OPT_fno_ptrauth_objc_class_ro))3231 CC1Args.push_back("-fptrauth-objc-class-ro");3232 if (!DriverArgs.hasArg(options::OPT_fptrauth_objc_interface_sel,3233 options::OPT_fno_ptrauth_objc_interface_sel))3234 CC1Args.push_back("-fptrauth-objc-interface-sel");3235 }3236}3237 3238void Darwin::addClangTargetOptions(3239 const llvm::opt::ArgList &DriverArgs, llvm::opt::ArgStringList &CC1Args,3240 Action::OffloadKind DeviceOffloadKind) const {3241 3242 MachO::addClangTargetOptions(DriverArgs, CC1Args, DeviceOffloadKind);3243 3244 // Pass "-faligned-alloc-unavailable" only when the user hasn't manually3245 // enabled or disabled aligned allocations.3246 if (!DriverArgs.hasArgNoClaim(options::OPT_faligned_allocation,3247 options::OPT_fno_aligned_allocation) &&3248 isAlignedAllocationUnavailable())3249 CC1Args.push_back("-faligned-alloc-unavailable");3250 3251 // Pass "-fno-sized-deallocation" only when the user hasn't manually enabled3252 // or disabled sized deallocations.3253 if (!DriverArgs.hasArgNoClaim(options::OPT_fsized_deallocation,3254 options::OPT_fno_sized_deallocation) &&3255 isSizedDeallocationUnavailable())3256 CC1Args.push_back("-fno-sized-deallocation");3257 3258 addClangCC1ASTargetOptions(DriverArgs, CC1Args);3259 3260 // Enable compatibility mode for NSItemProviderCompletionHandler in3261 // Foundation/NSItemProvider.h.3262 CC1Args.push_back("-fcompatibility-qualified-id-block-type-checking");3263 3264 // Give static local variables in inline functions hidden visibility when3265 // -fvisibility-inlines-hidden is enabled.3266 if (!DriverArgs.getLastArgNoClaim(3267 options::OPT_fvisibility_inlines_hidden_static_local_var,3268 options::OPT_fno_visibility_inlines_hidden_static_local_var))3269 CC1Args.push_back("-fvisibility-inlines-hidden-static-local-var");3270 3271 // Earlier versions of the darwin SDK have the C standard library headers3272 // all together in the Darwin module. That leads to module cycles with3273 // the _Builtin_ modules. e.g. <inttypes.h> on darwin includes <stdint.h>.3274 // The builtin <stdint.h> include-nexts <stdint.h>. When both of those3275 // darwin headers are in the Darwin module, there's a module cycle Darwin ->3276 // _Builtin_stdint -> Darwin (i.e. inttypes.h (darwin) -> stdint.h (builtin) ->3277 // stdint.h (darwin)). This is fixed in later versions of the darwin SDK,3278 // but until then, the builtin headers need to join the system modules.3279 // i.e. when the builtin stdint.h is in the Darwin module too, the cycle3280 // goes away. Note that -fbuiltin-headers-in-system-modules does nothing3281 // to fix the same problem with C++ headers, and is generally fragile.3282 if (!sdkSupportsBuiltinModules(SDKInfo))3283 CC1Args.push_back("-fbuiltin-headers-in-system-modules");3284 3285 if (!DriverArgs.hasArgNoClaim(options::OPT_fdefine_target_os_macros,3286 options::OPT_fno_define_target_os_macros))3287 CC1Args.push_back("-fdefine-target-os-macros");3288 3289 // Disable subdirectory modulemap search on sufficiently recent SDKs.3290 if (SDKInfo &&3291 !DriverArgs.hasFlag(options::OPT_fmodulemap_allow_subdirectory_search,3292 options::OPT_fno_modulemap_allow_subdirectory_search,3293 false)) {3294 bool RequiresSubdirectorySearch;3295 VersionTuple SDKVersion = SDKInfo->getVersion();3296 switch (TargetPlatform) {3297 default:3298 RequiresSubdirectorySearch = true;3299 break;3300 case MacOS:3301 RequiresSubdirectorySearch = SDKVersion < VersionTuple(15, 0);3302 break;3303 case IPhoneOS:3304 case TvOS:3305 RequiresSubdirectorySearch = SDKVersion < VersionTuple(18, 0);3306 break;3307 case WatchOS:3308 RequiresSubdirectorySearch = SDKVersion < VersionTuple(11, 0);3309 break;3310 case XROS:3311 RequiresSubdirectorySearch = SDKVersion < VersionTuple(2, 0);3312 break;3313 }3314 if (!RequiresSubdirectorySearch)3315 CC1Args.push_back("-fno-modulemap-allow-subdirectory-search");3316 }3317}3318 3319void Darwin::addClangCC1ASTargetOptions(3320 const llvm::opt::ArgList &Args, llvm::opt::ArgStringList &CC1ASArgs) const {3321 if (TargetVariantTriple) {3322 CC1ASArgs.push_back("-darwin-target-variant-triple");3323 CC1ASArgs.push_back(Args.MakeArgString(TargetVariantTriple->getTriple()));3324 }3325 3326 if (SDKInfo) {3327 /// Pass the SDK version to the compiler when the SDK information is3328 /// available.3329 auto EmitTargetSDKVersionArg = [&](const VersionTuple &V) {3330 std::string Arg;3331 llvm::raw_string_ostream OS(Arg);3332 OS << "-target-sdk-version=" << V;3333 CC1ASArgs.push_back(Args.MakeArgString(Arg));3334 };3335 3336 if (isTargetMacCatalyst()) {3337 if (const auto *MacOStoMacCatalystMapping = SDKInfo->getVersionMapping(3338 DarwinSDKInfo::OSEnvPair::macOStoMacCatalystPair())) {3339 std::optional<VersionTuple> SDKVersion = MacOStoMacCatalystMapping->map(3340 SDKInfo->getVersion(), minimumMacCatalystDeploymentTarget(),3341 std::nullopt);3342 EmitTargetSDKVersionArg(3343 SDKVersion ? *SDKVersion : minimumMacCatalystDeploymentTarget());3344 }3345 } else {3346 EmitTargetSDKVersionArg(SDKInfo->getVersion());3347 }3348 3349 /// Pass the target variant SDK version to the compiler when the SDK3350 /// information is available and is required for target variant.3351 if (TargetVariantTriple) {3352 if (isTargetMacCatalyst()) {3353 std::string Arg;3354 llvm::raw_string_ostream OS(Arg);3355 OS << "-darwin-target-variant-sdk-version=" << SDKInfo->getVersion();3356 CC1ASArgs.push_back(Args.MakeArgString(Arg));3357 } else if (const auto *MacOStoMacCatalystMapping =3358 SDKInfo->getVersionMapping(3359 DarwinSDKInfo::OSEnvPair::macOStoMacCatalystPair())) {3360 if (std::optional<VersionTuple> SDKVersion =3361 MacOStoMacCatalystMapping->map(3362 SDKInfo->getVersion(), minimumMacCatalystDeploymentTarget(),3363 std::nullopt)) {3364 std::string Arg;3365 llvm::raw_string_ostream OS(Arg);3366 OS << "-darwin-target-variant-sdk-version=" << *SDKVersion;3367 CC1ASArgs.push_back(Args.MakeArgString(Arg));3368 }3369 }3370 }3371 }3372}3373 3374DerivedArgList *3375Darwin::TranslateArgs(const DerivedArgList &Args, StringRef BoundArch,3376 Action::OffloadKind DeviceOffloadKind) const {3377 // First get the generic Apple args, before moving onto Darwin-specific ones.3378 DerivedArgList *DAL =3379 MachO::TranslateArgs(Args, BoundArch, DeviceOffloadKind);3380 3381 // If no architecture is bound, none of the translations here are relevant.3382 if (BoundArch.empty())3383 return DAL;3384 3385 // Add an explicit version min argument for the deployment target. We do this3386 // after argument translation because -Xarch_ arguments may add a version min3387 // argument.3388 AddDeploymentTarget(*DAL);3389 3390 // For iOS 6, undo the translation to add -static for -mkernel/-fapple-kext.3391 // FIXME: It would be far better to avoid inserting those -static arguments,3392 // but we can't check the deployment target in the translation code until3393 // it is set here.3394 if (isTargetWatchOSBased() || isTargetDriverKit() || isTargetXROS() ||3395 (isTargetIOSBased() && !isIPhoneOSVersionLT(6, 0))) {3396 for (ArgList::iterator it = DAL->begin(), ie = DAL->end(); it != ie; ) {3397 Arg *A = *it;3398 ++it;3399 if (A->getOption().getID() != options::OPT_mkernel &&3400 A->getOption().getID() != options::OPT_fapple_kext)3401 continue;3402 assert(it != ie && "unexpected argument translation");3403 A = *it;3404 assert(A->getOption().getID() == options::OPT_static &&3405 "missing expected -static argument");3406 *it = nullptr;3407 ++it;3408 }3409 }3410 3411 auto Arch = tools::darwin::getArchTypeForMachOArchName(BoundArch);3412 if ((Arch == llvm::Triple::arm || Arch == llvm::Triple::thumb)) {3413 if (Args.hasFlag(options::OPT_fomit_frame_pointer,3414 options::OPT_fno_omit_frame_pointer, false))3415 getDriver().Diag(clang::diag::warn_drv_unsupported_opt_for_target)3416 << "-fomit-frame-pointer" << BoundArch;3417 }3418 3419 return DAL;3420}3421 3422ToolChain::UnwindTableLevel MachO::getDefaultUnwindTableLevel(const ArgList &Args) const {3423 // Unwind tables are not emitted if -fno-exceptions is supplied (except when3424 // targeting x86_64).3425 if (getArch() == llvm::Triple::x86_64 ||3426 (GetExceptionModel(Args) != llvm::ExceptionHandling::SjLj &&3427 Args.hasFlag(options::OPT_fexceptions, options::OPT_fno_exceptions,3428 true)))3429 return (getArch() == llvm::Triple::aarch64 ||3430 getArch() == llvm::Triple::aarch64_32)3431 ? UnwindTableLevel::Synchronous3432 : UnwindTableLevel::Asynchronous;3433 3434 return UnwindTableLevel::None;3435}3436 3437bool MachO::UseDwarfDebugFlags() const {3438 if (const char *S = ::getenv("RC_DEBUG_OPTIONS"))3439 return S[0] != '\0';3440 return false;3441}3442 3443std::string MachO::GetGlobalDebugPathRemapping() const {3444 if (const char *S = ::getenv("RC_DEBUG_PREFIX_MAP"))3445 return S;3446 return {};3447}3448 3449llvm::ExceptionHandling Darwin::GetExceptionModel(const ArgList &Args) const {3450 // Darwin uses SjLj exceptions on ARM.3451 if (getTriple().getArch() != llvm::Triple::arm &&3452 getTriple().getArch() != llvm::Triple::thumb)3453 return llvm::ExceptionHandling::None;3454 3455 // Only watchOS uses the new DWARF/Compact unwinding method.3456 llvm::Triple Triple(ComputeLLVMTriple(Args));3457 if (Triple.isWatchABI())3458 return llvm::ExceptionHandling::DwarfCFI;3459 3460 return llvm::ExceptionHandling::SjLj;3461}3462 3463bool Darwin::SupportsEmbeddedBitcode() const {3464 assert(TargetInitialized && "Target not initialized!");3465 if (isTargetIPhoneOS() && isIPhoneOSVersionLT(6, 0))3466 return false;3467 return true;3468}3469 3470bool MachO::isPICDefault() const { return true; }3471 3472bool MachO::isPIEDefault(const llvm::opt::ArgList &Args) const { return false; }3473 3474bool MachO::isPICDefaultForced() const {3475 return (getArch() == llvm::Triple::x86_64 ||3476 getArch() == llvm::Triple::aarch64);3477}3478 3479bool MachO::SupportsProfiling() const {3480 // Profiling instrumentation is only supported on x86.3481 return getTriple().isX86();3482}3483 3484void Darwin::addMinVersionArgs(const ArgList &Args,3485 ArgStringList &CmdArgs) const {3486 VersionTuple TargetVersion = getTripleTargetVersion();3487 3488 assert(!isTargetXROS() && "xrOS always uses -platform-version");3489 3490 if (isTargetWatchOS())3491 CmdArgs.push_back("-watchos_version_min");3492 else if (isTargetWatchOSSimulator())3493 CmdArgs.push_back("-watchos_simulator_version_min");3494 else if (isTargetTvOS())3495 CmdArgs.push_back("-tvos_version_min");3496 else if (isTargetTvOSSimulator())3497 CmdArgs.push_back("-tvos_simulator_version_min");3498 else if (isTargetDriverKit())3499 CmdArgs.push_back("-driverkit_version_min");3500 else if (isTargetIOSSimulator())3501 CmdArgs.push_back("-ios_simulator_version_min");3502 else if (isTargetIOSBased())3503 CmdArgs.push_back("-iphoneos_version_min");3504 else if (isTargetMacCatalyst())3505 CmdArgs.push_back("-maccatalyst_version_min");3506 else {3507 assert(isTargetMacOS() && "unexpected target");3508 CmdArgs.push_back("-macosx_version_min");3509 }3510 3511 VersionTuple MinTgtVers = getEffectiveTriple().getMinimumSupportedOSVersion();3512 if (!MinTgtVers.empty() && MinTgtVers > TargetVersion)3513 TargetVersion = MinTgtVers;3514 CmdArgs.push_back(Args.MakeArgString(TargetVersion.getAsString()));3515 if (TargetVariantTriple) {3516 assert(isTargetMacOSBased() && "unexpected target");3517 VersionTuple VariantTargetVersion;3518 if (TargetVariantTriple->isMacOSX()) {3519 CmdArgs.push_back("-macosx_version_min");3520 TargetVariantTriple->getMacOSXVersion(VariantTargetVersion);3521 } else {3522 assert(TargetVariantTriple->isiOS() &&3523 TargetVariantTriple->isMacCatalystEnvironment() &&3524 "unexpected target variant triple");3525 CmdArgs.push_back("-maccatalyst_version_min");3526 VariantTargetVersion = TargetVariantTriple->getiOSVersion();3527 }3528 VersionTuple MinTgtVers =3529 TargetVariantTriple->getMinimumSupportedOSVersion();3530 if (MinTgtVers.getMajor() && MinTgtVers > VariantTargetVersion)3531 VariantTargetVersion = MinTgtVers;3532 CmdArgs.push_back(Args.MakeArgString(VariantTargetVersion.getAsString()));3533 }3534}3535 3536static const char *getPlatformName(Darwin::DarwinPlatformKind Platform,3537 Darwin::DarwinEnvironmentKind Environment) {3538 switch (Platform) {3539 case Darwin::MacOS:3540 return "macos";3541 case Darwin::IPhoneOS:3542 if (Environment == Darwin::MacCatalyst)3543 return "mac catalyst";3544 return "ios";3545 case Darwin::TvOS:3546 return "tvos";3547 case Darwin::WatchOS:3548 return "watchos";3549 case Darwin::XROS:3550 return "xros";3551 case Darwin::DriverKit:3552 return "driverkit";3553 }3554 llvm_unreachable("invalid platform");3555}3556 3557void Darwin::addPlatformVersionArgs(const llvm::opt::ArgList &Args,3558 llvm::opt::ArgStringList &CmdArgs) const {3559 auto EmitPlatformVersionArg =3560 [&](const VersionTuple &TV, Darwin::DarwinPlatformKind TargetPlatform,3561 Darwin::DarwinEnvironmentKind TargetEnvironment,3562 const llvm::Triple &TT) {3563 // -platform_version <platform> <target_version> <sdk_version>3564 // Both the target and SDK version support only up to 3 components.3565 CmdArgs.push_back("-platform_version");3566 std::string PlatformName =3567 getPlatformName(TargetPlatform, TargetEnvironment);3568 if (TargetEnvironment == Darwin::Simulator)3569 PlatformName += "-simulator";3570 CmdArgs.push_back(Args.MakeArgString(PlatformName));3571 VersionTuple TargetVersion = TV.withoutBuild();3572 if ((TargetPlatform == Darwin::IPhoneOS ||3573 TargetPlatform == Darwin::TvOS) &&3574 getTriple().getArchName() == "arm64e" &&3575 TargetVersion.getMajor() < 14) {3576 // arm64e slice is supported on iOS/tvOS 14+ only.3577 TargetVersion = VersionTuple(14, 0);3578 }3579 VersionTuple MinTgtVers = TT.getMinimumSupportedOSVersion();3580 if (!MinTgtVers.empty() && MinTgtVers > TargetVersion)3581 TargetVersion = MinTgtVers;3582 CmdArgs.push_back(Args.MakeArgString(TargetVersion.getAsString()));3583 3584 if (TargetPlatform == IPhoneOS && TargetEnvironment == MacCatalyst) {3585 // Mac Catalyst programs must use the appropriate iOS SDK version3586 // that corresponds to the macOS SDK version used for the compilation.3587 std::optional<VersionTuple> iOSSDKVersion;3588 if (SDKInfo) {3589 if (const auto *MacOStoMacCatalystMapping =3590 SDKInfo->getVersionMapping(3591 DarwinSDKInfo::OSEnvPair::macOStoMacCatalystPair())) {3592 iOSSDKVersion = MacOStoMacCatalystMapping->map(3593 SDKInfo->getVersion().withoutBuild(),3594 minimumMacCatalystDeploymentTarget(), std::nullopt);3595 }3596 }3597 CmdArgs.push_back(Args.MakeArgString(3598 (iOSSDKVersion ? *iOSSDKVersion3599 : minimumMacCatalystDeploymentTarget())3600 .getAsString()));3601 return;3602 }3603 3604 if (SDKInfo) {3605 VersionTuple SDKVersion = SDKInfo->getVersion().withoutBuild();3606 if (!SDKVersion.getMinor())3607 SDKVersion = VersionTuple(SDKVersion.getMajor(), 0);3608 CmdArgs.push_back(Args.MakeArgString(SDKVersion.getAsString()));3609 } else {3610 // Use an SDK version that's matching the deployment target if the SDK3611 // version is missing. This is preferred over an empty SDK version3612 // (0.0.0) as the system's runtime might expect the linked binary to3613 // contain a valid SDK version in order for the binary to work3614 // correctly. It's reasonable to use the deployment target version as3615 // a proxy for the SDK version because older SDKs don't guarantee3616 // support for deployment targets newer than the SDK versions, so that3617 // rules out using some predetermined older SDK version, which leaves3618 // the deployment target version as the only reasonable choice.3619 CmdArgs.push_back(Args.MakeArgString(TargetVersion.getAsString()));3620 }3621 };3622 EmitPlatformVersionArg(getTripleTargetVersion(), TargetPlatform,3623 TargetEnvironment, getEffectiveTriple());3624 if (!TargetVariantTriple)3625 return;3626 Darwin::DarwinPlatformKind Platform;3627 Darwin::DarwinEnvironmentKind Environment;3628 VersionTuple TargetVariantVersion;3629 if (TargetVariantTriple->isMacOSX()) {3630 TargetVariantTriple->getMacOSXVersion(TargetVariantVersion);3631 Platform = Darwin::MacOS;3632 Environment = Darwin::NativeEnvironment;3633 } else {3634 assert(TargetVariantTriple->isiOS() &&3635 TargetVariantTriple->isMacCatalystEnvironment() &&3636 "unexpected target variant triple");3637 TargetVariantVersion = TargetVariantTriple->getiOSVersion();3638 Platform = Darwin::IPhoneOS;3639 Environment = Darwin::MacCatalyst;3640 }3641 EmitPlatformVersionArg(TargetVariantVersion, Platform, Environment,3642 *TargetVariantTriple);3643}3644 3645// Add additional link args for the -dynamiclib option.3646static void addDynamicLibLinkArgs(const Darwin &D, const ArgList &Args,3647 ArgStringList &CmdArgs) {3648 // Derived from darwin_dylib1 spec.3649 if (D.isTargetIPhoneOS()) {3650 if (D.isIPhoneOSVersionLT(3, 1))3651 CmdArgs.push_back("-ldylib1.o");3652 return;3653 }3654 3655 if (!D.isTargetMacOS())3656 return;3657 if (D.isMacosxVersionLT(10, 5))3658 CmdArgs.push_back("-ldylib1.o");3659 else if (D.isMacosxVersionLT(10, 6))3660 CmdArgs.push_back("-ldylib1.10.5.o");3661}3662 3663// Add additional link args for the -bundle option.3664static void addBundleLinkArgs(const Darwin &D, const ArgList &Args,3665 ArgStringList &CmdArgs) {3666 if (Args.hasArg(options::OPT_static))3667 return;3668 // Derived from darwin_bundle1 spec.3669 if ((D.isTargetIPhoneOS() && D.isIPhoneOSVersionLT(3, 1)) ||3670 (D.isTargetMacOS() && D.isMacosxVersionLT(10, 6)))3671 CmdArgs.push_back("-lbundle1.o");3672}3673 3674// Add additional link args for the -pg option.3675static void addPgProfilingLinkArgs(const Darwin &D, const ArgList &Args,3676 ArgStringList &CmdArgs) {3677 if (D.isTargetMacOS() && D.isMacosxVersionLT(10, 9)) {3678 if (Args.hasArg(options::OPT_static) || Args.hasArg(options::OPT_object) ||3679 Args.hasArg(options::OPT_preload)) {3680 CmdArgs.push_back("-lgcrt0.o");3681 } else {3682 CmdArgs.push_back("-lgcrt1.o");3683 3684 // darwin_crt2 spec is empty.3685 }3686 // By default on OS X 10.8 and later, we don't link with a crt1.o3687 // file and the linker knows to use _main as the entry point. But,3688 // when compiling with -pg, we need to link with the gcrt1.o file,3689 // so pass the -no_new_main option to tell the linker to use the3690 // "start" symbol as the entry point.3691 if (!D.isMacosxVersionLT(10, 8))3692 CmdArgs.push_back("-no_new_main");3693 } else {3694 D.getDriver().Diag(diag::err_drv_clang_unsupported_opt_pg_darwin)3695 << D.isTargetMacOSBased();3696 }3697}3698 3699static void addDefaultCRTLinkArgs(const Darwin &D, const ArgList &Args,3700 ArgStringList &CmdArgs) {3701 // Derived from darwin_crt1 spec.3702 if (D.isTargetIPhoneOS()) {3703 if (D.getArch() == llvm::Triple::aarch64)3704 ; // iOS does not need any crt1 files for arm643705 else if (D.isIPhoneOSVersionLT(3, 1))3706 CmdArgs.push_back("-lcrt1.o");3707 else if (D.isIPhoneOSVersionLT(6, 0))3708 CmdArgs.push_back("-lcrt1.3.1.o");3709 return;3710 }3711 3712 if (!D.isTargetMacOS())3713 return;3714 if (D.isMacosxVersionLT(10, 5))3715 CmdArgs.push_back("-lcrt1.o");3716 else if (D.isMacosxVersionLT(10, 6))3717 CmdArgs.push_back("-lcrt1.10.5.o");3718 else if (D.isMacosxVersionLT(10, 8))3719 CmdArgs.push_back("-lcrt1.10.6.o");3720 // darwin_crt2 spec is empty.3721}3722 3723void Darwin::addStartObjectFileArgs(const ArgList &Args,3724 ArgStringList &CmdArgs) const {3725 // Derived from startfile spec.3726 if (Args.hasArg(options::OPT_dynamiclib))3727 addDynamicLibLinkArgs(*this, Args, CmdArgs);3728 else if (Args.hasArg(options::OPT_bundle))3729 addBundleLinkArgs(*this, Args, CmdArgs);3730 else if (Args.hasArg(options::OPT_pg) && SupportsProfiling())3731 addPgProfilingLinkArgs(*this, Args, CmdArgs);3732 else if (Args.hasArg(options::OPT_static) ||3733 Args.hasArg(options::OPT_object) ||3734 Args.hasArg(options::OPT_preload))3735 CmdArgs.push_back("-lcrt0.o");3736 else3737 addDefaultCRTLinkArgs(*this, Args, CmdArgs);3738 3739 if (isTargetMacOS() && Args.hasArg(options::OPT_shared_libgcc) &&3740 isMacosxVersionLT(10, 5)) {3741 const char *Str = Args.MakeArgString(GetFilePath("crt3.o"));3742 CmdArgs.push_back(Str);3743 }3744}3745 3746void Darwin::CheckObjCARC() const {3747 if (isTargetIOSBased() || isTargetWatchOSBased() || isTargetXROS() ||3748 (isTargetMacOSBased() && !isMacosxVersionLT(10, 6)))3749 return;3750 getDriver().Diag(diag::err_arc_unsupported_on_toolchain);3751}3752 3753SanitizerMask Darwin::getSupportedSanitizers() const {3754 const bool IsX86_64 = getTriple().getArch() == llvm::Triple::x86_64;3755 const bool IsAArch64 = getTriple().getArch() == llvm::Triple::aarch64;3756 SanitizerMask Res = ToolChain::getSupportedSanitizers();3757 Res |= SanitizerKind::Address;3758 Res |= SanitizerKind::PointerCompare;3759 Res |= SanitizerKind::PointerSubtract;3760 Res |= SanitizerKind::Realtime;3761 Res |= SanitizerKind::Leak;3762 Res |= SanitizerKind::Fuzzer;3763 Res |= SanitizerKind::FuzzerNoLink;3764 Res |= SanitizerKind::ObjCCast;3765 3766 // Prior to 10.9, macOS shipped a version of the C++ standard library without3767 // C++11 support. The same is true of iOS prior to version 5. These OS'es are3768 // incompatible with -fsanitize=vptr.3769 if (!(isTargetMacOSBased() && isMacosxVersionLT(10, 9)) &&3770 !(isTargetIPhoneOS() && isIPhoneOSVersionLT(5, 0)))3771 Res |= SanitizerKind::Vptr;3772 3773 if ((IsX86_64 || IsAArch64) &&3774 (isTargetMacOSBased() || isTargetIOSSimulator() ||3775 isTargetTvOSSimulator() || isTargetWatchOSSimulator())) {3776 Res |= SanitizerKind::Thread;3777 }3778 3779 if ((IsX86_64 || IsAArch64) && isTargetMacOSBased()) {3780 Res |= SanitizerKind::Type;3781 }3782 3783 if (IsX86_64)3784 Res |= SanitizerKind::NumericalStability;3785 3786 return Res;3787}3788 3789void AppleMachO::printVerboseInfo(raw_ostream &OS) const {3790 CudaInstallation->print(OS);3791 RocmInstallation->print(OS);3792}3793