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-exception 6 // 7 //===----------------------------------------------------------------------===// 8 9 #include "Darwin.h" 10 #include "Arch/AArch64.h" 11 #include "Arch/ARM.h" 12 #include "CommonArgs.h" 13 #include "clang/Basic/AlignedAllocation.h" 14 #include "clang/Basic/ObjCRuntime.h" 15 #include "clang/Config/config.h" 16 #include "clang/Driver/Compilation.h" 17 #include "clang/Driver/Driver.h" 18 #include "clang/Driver/DriverDiagnostic.h" 19 #include "clang/Driver/Options.h" 20 #include "clang/Driver/SanitizerArgs.h" 21 #include "llvm/ADT/StringSwitch.h" 22 #include "llvm/Option/ArgList.h" 23 #include "llvm/ProfileData/InstrProf.h" 24 #include "llvm/Support/Path.h" 25 #include "llvm/Support/ScopedPrinter.h" 26 #include "llvm/Support/Threading.h" 27 #include "llvm/Support/VirtualFileSystem.h" 28 #include "llvm/TargetParser/TargetParser.h" 29 #include "llvm/TargetParser/Triple.h" 30 #include <cstdlib> // ::getenv 31 32 using namespace clang::driver; 33 using namespace clang::driver::tools; 34 using namespace clang::driver::toolchains; 35 using namespace clang; 36 using namespace llvm::opt; 37 38 static VersionTuple minimumMacCatalystDeploymentTarget() { 39 return VersionTuple(13, 1); 40 } 41 42 llvm::Triple::ArchType darwin::getArchTypeForMachOArchName(StringRef Str) { 43 // See arch(3) and llvm-gcc's driver-driver.c. We don't implement support for 44 // archs which Darwin doesn't use. 45 46 // The matching this routine does is fairly pointless, since it is neither the 47 // complete architecture list, nor a reasonable subset. The problem is that 48 // historically the driver accepts this and also ties its -march= 49 // handling to the architecture name, so we need to be careful before removing 50 // support for it. 51 52 // This code must be kept in sync with Clang's Darwin specific argument 53 // translation. 54 55 return llvm::StringSwitch<llvm::Triple::ArchType>(Str) 56 .Cases("ppc", "ppc601", "ppc603", "ppc604", "ppc604e", llvm::Triple::ppc) 57 .Cases("ppc750", "ppc7400", "ppc7450", "ppc970", llvm::Triple::ppc) 58 .Case("ppc64", llvm::Triple::ppc64) 59 .Cases("i386", "i486", "i486SX", "i586", "i686", llvm::Triple::x86) 60 .Cases("pentium", "pentpro", "pentIIm3", "pentIIm5", "pentium4", 61 llvm::Triple::x86) 62 .Cases("x86_64", "x86_64h", llvm::Triple::x86_64) 63 // This is derived from the driver. 64 .Cases("arm", "armv4t", "armv5", "armv6", "armv6m", llvm::Triple::arm) 65 .Cases("armv7", "armv7em", "armv7k", "armv7m", llvm::Triple::arm) 66 .Cases("armv7s", "xscale", llvm::Triple::arm) 67 .Cases("arm64", "arm64e", llvm::Triple::aarch64) 68 .Case("arm64_32", llvm::Triple::aarch64_32) 69 .Case("r600", llvm::Triple::r600) 70 .Case("amdgcn", llvm::Triple::amdgcn) 71 .Case("nvptx", llvm::Triple::nvptx) 72 .Case("nvptx64", llvm::Triple::nvptx64) 73 .Case("amdil", llvm::Triple::amdil) 74 .Case("spir", llvm::Triple::spir) 75 .Default(llvm::Triple::UnknownArch); 76 } 77 78 void darwin::setTripleTypeForMachOArchName(llvm::Triple &T, StringRef Str, 79 const ArgList &Args) { 80 const llvm::Triple::ArchType Arch = getArchTypeForMachOArchName(Str); 81 llvm::ARM::ArchKind ArchKind = llvm::ARM::parseArch(Str); 82 T.setArch(Arch); 83 if (Arch != llvm::Triple::UnknownArch) 84 T.setArchName(Str); 85 86 if (ArchKind == llvm::ARM::ArchKind::ARMV6M || 87 ArchKind == llvm::ARM::ArchKind::ARMV7M || 88 ArchKind == llvm::ARM::ArchKind::ARMV7EM) { 89 // Don't reject these -version-min= if we have the appropriate triple. 90 if (T.getOS() == llvm::Triple::IOS) 91 for (Arg *A : Args.filtered(options::OPT_mios_version_min_EQ)) 92 A->ignoreTargetSpecific(); 93 if (T.getOS() == llvm::Triple::WatchOS) 94 for (Arg *A : Args.filtered(options::OPT_mwatchos_version_min_EQ)) 95 A->ignoreTargetSpecific(); 96 if (T.getOS() == llvm::Triple::TvOS) 97 for (Arg *A : Args.filtered(options::OPT_mtvos_version_min_EQ)) 98 A->ignoreTargetSpecific(); 99 100 T.setOS(llvm::Triple::UnknownOS); 101 T.setObjectFormat(llvm::Triple::MachO); 102 } 103 } 104 105 void darwin::Assembler::ConstructJob(Compilation &C, const JobAction &JA, 106 const InputInfo &Output, 107 const InputInfoList &Inputs, 108 const ArgList &Args, 109 const char *LinkingOutput) const { 110 const llvm::Triple &T(getToolChain().getTriple()); 111 112 ArgStringList CmdArgs; 113 114 assert(Inputs.size() == 1 && "Unexpected number of inputs."); 115 const InputInfo &Input = Inputs[0]; 116 117 // Determine the original source input. 118 const Action *SourceAction = &JA; 119 while (SourceAction->getKind() != Action::InputClass) { 120 assert(!SourceAction->getInputs().empty() && "unexpected root action!"); 121 SourceAction = SourceAction->getInputs()[0]; 122 } 123 124 // If -fno-integrated-as is used add -Q to the darwin assembler driver to make 125 // sure it runs its system assembler not clang's integrated assembler. 126 // Applicable to darwin11+ and Xcode 4+. darwin<10 lacked integrated-as. 127 // FIXME: at run-time detect assembler capabilities or rely on version 128 // information forwarded by -target-assembler-version. 129 if (Args.hasArg(options::OPT_fno_integrated_as)) { 130 if (!(T.isMacOSX() && T.isMacOSXVersionLT(10, 7))) 131 CmdArgs.push_back("-Q"); 132 } 133 134 // Forward -g, assuming we are dealing with an actual assembly file. 135 if (SourceAction->getType() == types::TY_Asm || 136 SourceAction->getType() == types::TY_PP_Asm) { 137 if (Args.hasArg(options::OPT_gstabs)) 138 CmdArgs.push_back("--gstabs"); 139 else if (Args.hasArg(options::OPT_g_Group)) 140 CmdArgs.push_back("-g"); 141 } 142 143 // Derived from asm spec. 144 AddMachOArch(Args, CmdArgs); 145 146 // Use -force_cpusubtype_ALL on x86 by default. 147 if (T.isX86() || Args.hasArg(options::OPT_force__cpusubtype__ALL)) 148 CmdArgs.push_back("-force_cpusubtype_ALL"); 149 150 if (getToolChain().getArch() != llvm::Triple::x86_64 && 151 (((Args.hasArg(options::OPT_mkernel) || 152 Args.hasArg(options::OPT_fapple_kext)) && 153 getMachOToolChain().isKernelStatic()) || 154 Args.hasArg(options::OPT_static))) 155 CmdArgs.push_back("-static"); 156 157 Args.AddAllArgValues(CmdArgs, options::OPT_Wa_COMMA, options::OPT_Xassembler); 158 159 assert(Output.isFilename() && "Unexpected lipo output."); 160 CmdArgs.push_back("-o"); 161 CmdArgs.push_back(Output.getFilename()); 162 163 assert(Input.isFilename() && "Invalid input."); 164 CmdArgs.push_back(Input.getFilename()); 165 166 // asm_final spec is empty. 167 168 const char *Exec = Args.MakeArgString(getToolChain().GetProgramPath("as")); 169 C.addCommand(std::make_unique<Command>(JA, *this, ResponseFileSupport::None(), 170 Exec, CmdArgs, Inputs, Output)); 171 } 172 173 void darwin::MachOTool::anchor() {} 174 175 void darwin::MachOTool::AddMachOArch(const ArgList &Args, 176 ArgStringList &CmdArgs) const { 177 StringRef ArchName = getMachOToolChain().getMachOArchName(Args); 178 179 // Derived from darwin_arch spec. 180 CmdArgs.push_back("-arch"); 181 CmdArgs.push_back(Args.MakeArgString(ArchName)); 182 183 // FIXME: Is this needed anymore? 184 if (ArchName == "arm") 185 CmdArgs.push_back("-force_cpusubtype_ALL"); 186 } 187 188 bool darwin::Linker::NeedsTempPath(const InputInfoList &Inputs) const { 189 // We only need to generate a temp path for LTO if we aren't compiling object 190 // files. When compiling source files, we run 'dsymutil' after linking. We 191 // don't run 'dsymutil' when compiling object files. 192 for (const auto &Input : Inputs) 193 if (Input.getType() != types::TY_Object) 194 return true; 195 196 return false; 197 } 198 199 /// Pass -no_deduplicate to ld64 under certain conditions: 200 /// 201 /// - Either -O0 or -O1 is explicitly specified 202 /// - No -O option is specified *and* this is a compile+link (implicit -O0) 203 /// 204 /// Also do *not* add -no_deduplicate when no -O option is specified and this 205 /// is just a link (we can't imply -O0) 206 static bool shouldLinkerNotDedup(bool IsLinkerOnlyAction, const ArgList &Args) { 207 if (Arg *A = Args.getLastArg(options::OPT_O_Group)) { 208 if (A->getOption().matches(options::OPT_O0)) 209 return true; 210 if (A->getOption().matches(options::OPT_O)) 211 return llvm::StringSwitch<bool>(A->getValue()) 212 .Case("1", true) 213 .Default(false); 214 return false; // OPT_Ofast & OPT_O4 215 } 216 217 if (!IsLinkerOnlyAction) // Implicit -O0 for compile+linker only. 218 return true; 219 return false; 220 } 221 222 void darwin::Linker::AddLinkArgs(Compilation &C, const ArgList &Args, 223 ArgStringList &CmdArgs, 224 const InputInfoList &Inputs, 225 VersionTuple Version, bool LinkerIsLLD) const { 226 const Driver &D = getToolChain().getDriver(); 227 const toolchains::MachO &MachOTC = getMachOToolChain(); 228 229 // Newer linkers support -demangle. Pass it if supported and not disabled by 230 // the user. 231 if ((Version >= VersionTuple(100) || LinkerIsLLD) && 232 !Args.hasArg(options::OPT_Z_Xlinker__no_demangle)) 233 CmdArgs.push_back("-demangle"); 234 235 if (Args.hasArg(options::OPT_rdynamic) && 236 (Version >= VersionTuple(137) || LinkerIsLLD)) 237 CmdArgs.push_back("-export_dynamic"); 238 239 // If we are using App Extension restrictions, pass a flag to the linker 240 // telling it that the compiled code has been audited. 241 if (Args.hasFlag(options::OPT_fapplication_extension, 242 options::OPT_fno_application_extension, false)) 243 CmdArgs.push_back("-application_extension"); 244 245 if (D.isUsingLTO() && (Version >= VersionTuple(116) || LinkerIsLLD) && 246 NeedsTempPath(Inputs)) { 247 std::string TmpPathName; 248 if (D.getLTOMode() == LTOK_Full) { 249 // If we are using full LTO, then automatically create a temporary file 250 // path for the linker to use, so that it's lifetime will extend past a 251 // possible dsymutil step. 252 TmpPathName = 253 D.GetTemporaryPath("cc", types::getTypeTempSuffix(types::TY_Object)); 254 } else if (D.getLTOMode() == LTOK_Thin) 255 // If we are using thin LTO, then create a directory instead. 256 TmpPathName = D.GetTemporaryDirectory("thinlto"); 257 258 if (!TmpPathName.empty()) { 259 auto *TmpPath = C.getArgs().MakeArgString(TmpPathName); 260 C.addTempFile(TmpPath); 261 CmdArgs.push_back("-object_path_lto"); 262 CmdArgs.push_back(TmpPath); 263 } 264 } 265 266 // Use -lto_library option to specify the libLTO.dylib path. Try to find 267 // it in clang installed libraries. ld64 will only look at this argument 268 // when it actually uses LTO, so libLTO.dylib only needs to exist at link 269 // time if ld64 decides that it needs to use LTO. 270 // Since this is passed unconditionally, ld64 will never look for libLTO.dylib 271 // next to it. That's ok since ld64 using a libLTO.dylib not matching the 272 // clang version won't work anyways. 273 // lld is built at the same revision as clang and statically links in 274 // LLVM libraries, so it doesn't need libLTO.dylib. 275 if (Version >= VersionTuple(133) && !LinkerIsLLD) { 276 // Search for libLTO in <InstalledDir>/../lib/libLTO.dylib 277 StringRef P = llvm::sys::path::parent_path(D.Dir); 278 SmallString<128> LibLTOPath(P); 279 llvm::sys::path::append(LibLTOPath, "lib"); 280 llvm::sys::path::append(LibLTOPath, "libLTO.dylib"); 281 CmdArgs.push_back("-lto_library"); 282 CmdArgs.push_back(C.getArgs().MakeArgString(LibLTOPath)); 283 } 284 285 // ld64 version 262 and above runs the deduplicate pass by default. 286 // FIXME: lld doesn't dedup by default. Should we pass `--icf=safe` 287 // if `!shouldLinkerNotDedup()` if LinkerIsLLD here? 288 if (Version >= VersionTuple(262) && 289 shouldLinkerNotDedup(C.getJobs().empty(), Args)) 290 CmdArgs.push_back("-no_deduplicate"); 291 292 // Derived from the "link" spec. 293 Args.AddAllArgs(CmdArgs, options::OPT_static); 294 if (!Args.hasArg(options::OPT_static)) 295 CmdArgs.push_back("-dynamic"); 296 if (Args.hasArg(options::OPT_fgnu_runtime)) { 297 // FIXME: gcc replaces -lobjc in forward args with -lobjc-gnu 298 // here. How do we wish to handle such things? 299 } 300 301 if (!Args.hasArg(options::OPT_dynamiclib)) { 302 AddMachOArch(Args, CmdArgs); 303 // FIXME: Why do this only on this path? 304 Args.AddLastArg(CmdArgs, options::OPT_force__cpusubtype__ALL); 305 306 Args.AddLastArg(CmdArgs, options::OPT_bundle); 307 Args.AddAllArgs(CmdArgs, options::OPT_bundle__loader); 308 Args.AddAllArgs(CmdArgs, options::OPT_client__name); 309 310 Arg *A; 311 if ((A = Args.getLastArg(options::OPT_compatibility__version)) || 312 (A = Args.getLastArg(options::OPT_current__version)) || 313 (A = Args.getLastArg(options::OPT_install__name))) 314 D.Diag(diag::err_drv_argument_only_allowed_with) << A->getAsString(Args) 315 << "-dynamiclib"; 316 317 Args.AddLastArg(CmdArgs, options::OPT_force__flat__namespace); 318 Args.AddLastArg(CmdArgs, options::OPT_keep__private__externs); 319 Args.AddLastArg(CmdArgs, options::OPT_private__bundle); 320 } else { 321 CmdArgs.push_back("-dylib"); 322 323 Arg *A; 324 if ((A = Args.getLastArg(options::OPT_bundle)) || 325 (A = Args.getLastArg(options::OPT_bundle__loader)) || 326 (A = Args.getLastArg(options::OPT_client__name)) || 327 (A = Args.getLastArg(options::OPT_force__flat__namespace)) || 328 (A = Args.getLastArg(options::OPT_keep__private__externs)) || 329 (A = Args.getLastArg(options::OPT_private__bundle))) 330 D.Diag(diag::err_drv_argument_not_allowed_with) << A->getAsString(Args) 331 << "-dynamiclib"; 332 333 Args.AddAllArgsTranslated(CmdArgs, options::OPT_compatibility__version, 334 "-dylib_compatibility_version"); 335 Args.AddAllArgsTranslated(CmdArgs, options::OPT_current__version, 336 "-dylib_current_version"); 337 338 AddMachOArch(Args, CmdArgs); 339 340 Args.AddAllArgsTranslated(CmdArgs, options::OPT_install__name, 341 "-dylib_install_name"); 342 } 343 344 Args.AddLastArg(CmdArgs, options::OPT_all__load); 345 Args.AddAllArgs(CmdArgs, options::OPT_allowable__client); 346 Args.AddLastArg(CmdArgs, options::OPT_bind__at__load); 347 if (MachOTC.isTargetIOSBased()) 348 Args.AddLastArg(CmdArgs, options::OPT_arch__errors__fatal); 349 Args.AddLastArg(CmdArgs, options::OPT_dead__strip); 350 Args.AddLastArg(CmdArgs, options::OPT_no__dead__strip__inits__and__terms); 351 Args.AddAllArgs(CmdArgs, options::OPT_dylib__file); 352 Args.AddLastArg(CmdArgs, options::OPT_dynamic); 353 Args.AddAllArgs(CmdArgs, options::OPT_exported__symbols__list); 354 Args.AddLastArg(CmdArgs, options::OPT_flat__namespace); 355 Args.AddAllArgs(CmdArgs, options::OPT_force__load); 356 Args.AddAllArgs(CmdArgs, options::OPT_headerpad__max__install__names); 357 Args.AddAllArgs(CmdArgs, options::OPT_image__base); 358 Args.AddAllArgs(CmdArgs, options::OPT_init); 359 360 // Add the deployment target. 361 if (Version >= VersionTuple(520) || LinkerIsLLD) 362 MachOTC.addPlatformVersionArgs(Args, CmdArgs); 363 else 364 MachOTC.addMinVersionArgs(Args, CmdArgs); 365 366 Args.AddLastArg(CmdArgs, options::OPT_nomultidefs); 367 Args.AddLastArg(CmdArgs, options::OPT_multi__module); 368 Args.AddLastArg(CmdArgs, options::OPT_single__module); 369 Args.AddAllArgs(CmdArgs, options::OPT_multiply__defined); 370 Args.AddAllArgs(CmdArgs, options::OPT_multiply__defined__unused); 371 372 if (const Arg *A = 373 Args.getLastArg(options::OPT_fpie, options::OPT_fPIE, 374 options::OPT_fno_pie, options::OPT_fno_PIE)) { 375 if (A->getOption().matches(options::OPT_fpie) || 376 A->getOption().matches(options::OPT_fPIE)) 377 CmdArgs.push_back("-pie"); 378 else 379 CmdArgs.push_back("-no_pie"); 380 } 381 382 // for embed-bitcode, use -bitcode_bundle in linker command 383 if (C.getDriver().embedBitcodeEnabled()) { 384 // Check if the toolchain supports bitcode build flow. 385 if (MachOTC.SupportsEmbeddedBitcode()) { 386 CmdArgs.push_back("-bitcode_bundle"); 387 // FIXME: Pass this if LinkerIsLLD too, once it implements this flag. 388 if (C.getDriver().embedBitcodeMarkerOnly() && 389 Version >= VersionTuple(278)) { 390 CmdArgs.push_back("-bitcode_process_mode"); 391 CmdArgs.push_back("marker"); 392 } 393 } else 394 D.Diag(diag::err_drv_bitcode_unsupported_on_toolchain); 395 } 396 397 // If GlobalISel is enabled, pass it through to LLVM. 398 if (Arg *A = Args.getLastArg(options::OPT_fglobal_isel, 399 options::OPT_fno_global_isel)) { 400 if (A->getOption().matches(options::OPT_fglobal_isel)) { 401 CmdArgs.push_back("-mllvm"); 402 CmdArgs.push_back("-global-isel"); 403 // Disable abort and fall back to SDAG silently. 404 CmdArgs.push_back("-mllvm"); 405 CmdArgs.push_back("-global-isel-abort=0"); 406 } 407 } 408 409 if (Args.hasArg(options::OPT_mkernel) || 410 Args.hasArg(options::OPT_fapple_kext) || 411 Args.hasArg(options::OPT_ffreestanding)) { 412 CmdArgs.push_back("-mllvm"); 413 CmdArgs.push_back("-disable-atexit-based-global-dtor-lowering"); 414 } 415 416 Args.AddLastArg(CmdArgs, options::OPT_prebind); 417 Args.AddLastArg(CmdArgs, options::OPT_noprebind); 418 Args.AddLastArg(CmdArgs, options::OPT_nofixprebinding); 419 Args.AddLastArg(CmdArgs, options::OPT_prebind__all__twolevel__modules); 420 Args.AddLastArg(CmdArgs, options::OPT_read__only__relocs); 421 Args.AddAllArgs(CmdArgs, options::OPT_sectcreate); 422 Args.AddAllArgs(CmdArgs, options::OPT_sectorder); 423 Args.AddAllArgs(CmdArgs, options::OPT_seg1addr); 424 Args.AddAllArgs(CmdArgs, options::OPT_segprot); 425 Args.AddAllArgs(CmdArgs, options::OPT_segaddr); 426 Args.AddAllArgs(CmdArgs, options::OPT_segs__read__only__addr); 427 Args.AddAllArgs(CmdArgs, options::OPT_segs__read__write__addr); 428 Args.AddAllArgs(CmdArgs, options::OPT_seg__addr__table); 429 Args.AddAllArgs(CmdArgs, options::OPT_seg__addr__table__filename); 430 Args.AddAllArgs(CmdArgs, options::OPT_sub__library); 431 Args.AddAllArgs(CmdArgs, options::OPT_sub__umbrella); 432 433 // Give --sysroot= preference, over the Apple specific behavior to also use 434 // --isysroot as the syslibroot. 435 StringRef sysroot = C.getSysRoot(); 436 if (sysroot != "") { 437 CmdArgs.push_back("-syslibroot"); 438 CmdArgs.push_back(C.getArgs().MakeArgString(sysroot)); 439 } else if (const Arg *A = Args.getLastArg(options::OPT_isysroot)) { 440 CmdArgs.push_back("-syslibroot"); 441 CmdArgs.push_back(A->getValue()); 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() == 0 469 ? "" 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 } 483 484 /// Determine whether we are linking the ObjC runtime. 485 static bool isObjCRuntimeLinked(const ArgList &Args) { 486 if (isObjCAutoRefCount(Args)) { 487 Args.ClaimAllArgs(options::OPT_fobjc_link_runtime); 488 return true; 489 } 490 return Args.hasArg(options::OPT_fobjc_link_runtime); 491 } 492 493 static bool checkRemarksOptions(const Driver &D, const ArgList &Args, 494 const llvm::Triple &Triple) { 495 // When enabling remarks, we need to error if: 496 // * The remark file is specified but we're targeting multiple architectures, 497 // which means more than one remark file is being generated. 498 bool hasMultipleInvocations = 499 Args.getAllArgValues(options::OPT_arch).size() > 1; 500 bool hasExplicitOutputFile = 501 Args.getLastArg(options::OPT_foptimization_record_file_EQ); 502 if (hasMultipleInvocations && hasExplicitOutputFile) { 503 D.Diag(diag::err_drv_invalid_output_with_multiple_archs) 504 << "-foptimization-record-file"; 505 return false; 506 } 507 return true; 508 } 509 510 static void renderRemarksOptions(const ArgList &Args, ArgStringList &CmdArgs, 511 const llvm::Triple &Triple, 512 const InputInfo &Output, const JobAction &JA) { 513 StringRef Format = "yaml"; 514 if (const Arg *A = Args.getLastArg(options::OPT_fsave_optimization_record_EQ)) 515 Format = A->getValue(); 516 517 CmdArgs.push_back("-mllvm"); 518 CmdArgs.push_back("-lto-pass-remarks-output"); 519 CmdArgs.push_back("-mllvm"); 520 521 const Arg *A = Args.getLastArg(options::OPT_foptimization_record_file_EQ); 522 if (A) { 523 CmdArgs.push_back(A->getValue()); 524 } else { 525 assert(Output.isFilename() && "Unexpected ld output."); 526 SmallString<128> F; 527 F = Output.getFilename(); 528 F += ".opt."; 529 F += Format; 530 531 CmdArgs.push_back(Args.MakeArgString(F)); 532 } 533 534 if (const Arg *A = 535 Args.getLastArg(options::OPT_foptimization_record_passes_EQ)) { 536 CmdArgs.push_back("-mllvm"); 537 std::string Passes = 538 std::string("-lto-pass-remarks-filter=") + A->getValue(); 539 CmdArgs.push_back(Args.MakeArgString(Passes)); 540 } 541 542 if (!Format.empty()) { 543 CmdArgs.push_back("-mllvm"); 544 Twine FormatArg = Twine("-lto-pass-remarks-format=") + Format; 545 CmdArgs.push_back(Args.MakeArgString(FormatArg)); 546 } 547 548 if (getLastProfileUseArg(Args)) { 549 CmdArgs.push_back("-mllvm"); 550 CmdArgs.push_back("-lto-pass-remarks-with-hotness"); 551 552 if (const Arg *A = 553 Args.getLastArg(options::OPT_fdiagnostics_hotness_threshold_EQ)) { 554 CmdArgs.push_back("-mllvm"); 555 std::string Opt = 556 std::string("-lto-pass-remarks-hotness-threshold=") + A->getValue(); 557 CmdArgs.push_back(Args.MakeArgString(Opt)); 558 } 559 } 560 } 561 562 static void AppendPlatformPrefix(SmallString<128> &Path, const llvm::Triple &T); 563 564 void darwin::Linker::ConstructJob(Compilation &C, const JobAction &JA, 565 const InputInfo &Output, 566 const InputInfoList &Inputs, 567 const ArgList &Args, 568 const char *LinkingOutput) const { 569 assert(Output.getType() == types::TY_Image && "Invalid linker output type."); 570 571 // If the number of arguments surpasses the system limits, we will encode the 572 // input files in a separate file, shortening the command line. To this end, 573 // build a list of input file names that can be passed via a file with the 574 // -filelist linker option. 575 llvm::opt::ArgStringList InputFileList; 576 577 // The logic here is derived from gcc's behavior; most of which 578 // comes from specs (starting with link_command). Consult gcc for 579 // more information. 580 ArgStringList CmdArgs; 581 582 /// Hack(tm) to ignore linking errors when we are doing ARC migration. 583 if (Args.hasArg(options::OPT_ccc_arcmt_check, 584 options::OPT_ccc_arcmt_migrate)) { 585 for (const auto &Arg : Args) 586 Arg->claim(); 587 const char *Exec = 588 Args.MakeArgString(getToolChain().GetProgramPath("touch")); 589 CmdArgs.push_back(Output.getFilename()); 590 C.addCommand(std::make_unique<Command>(JA, *this, 591 ResponseFileSupport::None(), Exec, 592 CmdArgs, std::nullopt, Output)); 593 return; 594 } 595 596 VersionTuple Version = getMachOToolChain().getLinkerVersion(Args); 597 598 bool LinkerIsLLD; 599 const char *Exec = 600 Args.MakeArgString(getToolChain().GetLinkerPath(&LinkerIsLLD)); 601 602 // I'm not sure why this particular decomposition exists in gcc, but 603 // we follow suite for ease of comparison. 604 AddLinkArgs(C, Args, CmdArgs, Inputs, Version, LinkerIsLLD); 605 606 if (willEmitRemarks(Args) && 607 checkRemarksOptions(getToolChain().getDriver(), Args, 608 getToolChain().getTriple())) 609 renderRemarksOptions(Args, CmdArgs, getToolChain().getTriple(), Output, JA); 610 611 // Propagate the -moutline flag to the linker in LTO. 612 if (Arg *A = 613 Args.getLastArg(options::OPT_moutline, options::OPT_mno_outline)) { 614 if (A->getOption().matches(options::OPT_moutline)) { 615 if (getMachOToolChain().getMachOArchName(Args) == "arm64") { 616 CmdArgs.push_back("-mllvm"); 617 CmdArgs.push_back("-enable-machine-outliner"); 618 619 // Outline from linkonceodr functions by default in LTO. 620 CmdArgs.push_back("-mllvm"); 621 CmdArgs.push_back("-enable-linkonceodr-outlining"); 622 } 623 } else { 624 // Disable all outlining behaviour if we have mno-outline. We need to do 625 // this explicitly, because targets which support default outlining will 626 // try to do work if we don't. 627 CmdArgs.push_back("-mllvm"); 628 CmdArgs.push_back("-enable-machine-outliner=never"); 629 } 630 } 631 632 // Setup statistics file output. 633 SmallString<128> StatsFile = 634 getStatsFileName(Args, Output, Inputs[0], getToolChain().getDriver()); 635 if (!StatsFile.empty()) { 636 CmdArgs.push_back("-mllvm"); 637 CmdArgs.push_back(Args.MakeArgString("-lto-stats-file=" + StatsFile.str())); 638 } 639 640 // It seems that the 'e' option is completely ignored for dynamic executables 641 // (the default), and with static executables, the last one wins, as expected. 642 Args.AddAllArgs(CmdArgs, 643 {options::OPT_d_Flag, options::OPT_s, options::OPT_t, 644 options::OPT_Z_Flag, options::OPT_u_Group, options::OPT_r}); 645 646 // Forward -ObjC when either -ObjC or -ObjC++ is used, to force loading 647 // members of static archive libraries which implement Objective-C classes or 648 // categories. 649 if (Args.hasArg(options::OPT_ObjC) || Args.hasArg(options::OPT_ObjCXX)) 650 CmdArgs.push_back("-ObjC"); 651 652 CmdArgs.push_back("-o"); 653 CmdArgs.push_back(Output.getFilename()); 654 655 if (!Args.hasArg(options::OPT_nostdlib, options::OPT_nostartfiles)) 656 getMachOToolChain().addStartObjectFileArgs(Args, CmdArgs); 657 658 Args.AddAllArgs(CmdArgs, options::OPT_L); 659 660 AddLinkerInputs(getToolChain(), Inputs, Args, CmdArgs, JA); 661 // Build the input file for -filelist (list of linker input files) in case we 662 // need it later 663 for (const auto &II : Inputs) { 664 if (!II.isFilename()) { 665 // This is a linker input argument. 666 // We cannot mix input arguments and file names in a -filelist input, thus 667 // we prematurely stop our list (remaining files shall be passed as 668 // arguments). 669 if (InputFileList.size() > 0) 670 break; 671 672 continue; 673 } 674 675 InputFileList.push_back(II.getFilename()); 676 } 677 678 // Additional linker set-up and flags for Fortran. This is required in order 679 // to generate executables. 680 if (getToolChain().getDriver().IsFlangMode()) { 681 addFortranRuntimeLibraryPath(getToolChain(), Args, CmdArgs); 682 addFortranRuntimeLibs(getToolChain(), CmdArgs); 683 } 684 685 if (!Args.hasArg(options::OPT_nostdlib, options::OPT_nodefaultlibs)) 686 addOpenMPRuntime(CmdArgs, getToolChain(), Args); 687 688 if (isObjCRuntimeLinked(Args) && 689 !Args.hasArg(options::OPT_nostdlib, options::OPT_nodefaultlibs)) { 690 // We use arclite library for both ARC and subscripting support. 691 getMachOToolChain().AddLinkARCArgs(Args, CmdArgs); 692 693 CmdArgs.push_back("-framework"); 694 CmdArgs.push_back("Foundation"); 695 // Link libobj. 696 CmdArgs.push_back("-lobjc"); 697 } 698 699 if (LinkingOutput) { 700 CmdArgs.push_back("-arch_multiple"); 701 CmdArgs.push_back("-final_output"); 702 CmdArgs.push_back(LinkingOutput); 703 } 704 705 if (Args.hasArg(options::OPT_fnested_functions)) 706 CmdArgs.push_back("-allow_stack_execute"); 707 708 getMachOToolChain().addProfileRTLibs(Args, CmdArgs); 709 710 StringRef Parallelism = getLTOParallelism(Args, getToolChain().getDriver()); 711 if (!Parallelism.empty()) { 712 CmdArgs.push_back("-mllvm"); 713 unsigned NumThreads = 714 llvm::get_threadpool_strategy(Parallelism)->compute_thread_count(); 715 CmdArgs.push_back(Args.MakeArgString("-threads=" + Twine(NumThreads))); 716 } 717 718 if (getToolChain().ShouldLinkCXXStdlib(Args)) 719 getToolChain().AddCXXStdlibLibArgs(Args, CmdArgs); 720 721 bool NoStdOrDefaultLibs = 722 Args.hasArg(options::OPT_nostdlib, options::OPT_nodefaultlibs); 723 bool ForceLinkBuiltins = Args.hasArg(options::OPT_fapple_link_rtlib); 724 if (!NoStdOrDefaultLibs || ForceLinkBuiltins) { 725 // link_ssp spec is empty. 726 727 // If we have both -nostdlib/nodefaultlibs and -fapple-link-rtlib then 728 // we just want to link the builtins, not the other libs like libSystem. 729 if (NoStdOrDefaultLibs && ForceLinkBuiltins) { 730 getMachOToolChain().AddLinkRuntimeLib(Args, CmdArgs, "builtins"); 731 } else { 732 // Let the tool chain choose which runtime library to link. 733 getMachOToolChain().AddLinkRuntimeLibArgs(Args, CmdArgs, 734 ForceLinkBuiltins); 735 736 // No need to do anything for pthreads. Claim argument to avoid warning. 737 Args.ClaimAllArgs(options::OPT_pthread); 738 Args.ClaimAllArgs(options::OPT_pthreads); 739 } 740 } 741 742 if (!Args.hasArg(options::OPT_nostdlib, options::OPT_nostartfiles)) { 743 // endfile_spec is empty. 744 } 745 746 Args.AddAllArgs(CmdArgs, options::OPT_T_Group); 747 Args.AddAllArgs(CmdArgs, options::OPT_F); 748 749 // -iframework should be forwarded as -F. 750 for (const Arg *A : Args.filtered(options::OPT_iframework)) 751 CmdArgs.push_back(Args.MakeArgString(std::string("-F") + A->getValue())); 752 753 if (!Args.hasArg(options::OPT_nostdlib, options::OPT_nodefaultlibs)) { 754 if (Arg *A = Args.getLastArg(options::OPT_fveclib)) { 755 if (A->getValue() == StringRef("Accelerate")) { 756 CmdArgs.push_back("-framework"); 757 CmdArgs.push_back("Accelerate"); 758 } 759 } 760 } 761 762 // Add non-standard, platform-specific search paths, e.g., for DriverKit: 763 // -L<sysroot>/System/DriverKit/usr/lib 764 // -F<sysroot>/System/DriverKit/System/Library/Framework 765 { 766 bool NonStandardSearchPath = false; 767 const auto &Triple = getToolChain().getTriple(); 768 if (Triple.isDriverKit()) { 769 // ld64 fixed the implicit -F and -L paths in ld64-605.1+. 770 NonStandardSearchPath = 771 Version.getMajor() < 605 || 772 (Version.getMajor() == 605 && Version.getMinor().value_or(0) < 1); 773 } 774 775 if (NonStandardSearchPath) { 776 if (auto *Sysroot = Args.getLastArg(options::OPT_isysroot)) { 777 auto AddSearchPath = [&](StringRef Flag, StringRef SearchPath) { 778 SmallString<128> P(Sysroot->getValue()); 779 AppendPlatformPrefix(P, Triple); 780 llvm::sys::path::append(P, SearchPath); 781 if (getToolChain().getVFS().exists(P)) { 782 CmdArgs.push_back(Args.MakeArgString(Flag + P)); 783 } 784 }; 785 AddSearchPath("-L", "/usr/lib"); 786 AddSearchPath("-F", "/System/Library/Frameworks"); 787 } 788 } 789 } 790 791 ResponseFileSupport ResponseSupport; 792 if (Version >= VersionTuple(705) || LinkerIsLLD) { 793 ResponseSupport = ResponseFileSupport::AtFileUTF8(); 794 } else { 795 // For older versions of the linker, use the legacy filelist method instead. 796 ResponseSupport = {ResponseFileSupport::RF_FileList, llvm::sys::WEM_UTF8, 797 "-filelist"}; 798 } 799 800 std::unique_ptr<Command> Cmd = std::make_unique<Command>( 801 JA, *this, ResponseSupport, Exec, CmdArgs, Inputs, Output); 802 Cmd->setInputFileList(std::move(InputFileList)); 803 C.addCommand(std::move(Cmd)); 804 } 805 806 void darwin::StaticLibTool::ConstructJob(Compilation &C, const JobAction &JA, 807 const InputInfo &Output, 808 const InputInfoList &Inputs, 809 const ArgList &Args, 810 const char *LinkingOutput) const { 811 const Driver &D = getToolChain().getDriver(); 812 813 // Silence warning for "clang -g foo.o -o foo" 814 Args.ClaimAllArgs(options::OPT_g_Group); 815 // and "clang -emit-llvm foo.o -o foo" 816 Args.ClaimAllArgs(options::OPT_emit_llvm); 817 // and for "clang -w foo.o -o foo". Other warning options are already 818 // handled somewhere else. 819 Args.ClaimAllArgs(options::OPT_w); 820 // Silence warnings when linking C code with a C++ '-stdlib' argument. 821 Args.ClaimAllArgs(options::OPT_stdlib_EQ); 822 823 // libtool <options> <output_file> <input_files> 824 ArgStringList CmdArgs; 825 // Create and insert file members with a deterministic index. 826 CmdArgs.push_back("-static"); 827 CmdArgs.push_back("-D"); 828 CmdArgs.push_back("-no_warning_for_no_symbols"); 829 CmdArgs.push_back("-o"); 830 CmdArgs.push_back(Output.getFilename()); 831 832 for (const auto &II : Inputs) { 833 if (II.isFilename()) { 834 CmdArgs.push_back(II.getFilename()); 835 } 836 } 837 838 // Delete old output archive file if it already exists before generating a new 839 // archive file. 840 const auto *OutputFileName = Output.getFilename(); 841 if (Output.isFilename() && llvm::sys::fs::exists(OutputFileName)) { 842 if (std::error_code EC = llvm::sys::fs::remove(OutputFileName)) { 843 D.Diag(diag::err_drv_unable_to_remove_file) << EC.message(); 844 return; 845 } 846 } 847 848 const char *Exec = Args.MakeArgString(getToolChain().GetStaticLibToolPath()); 849 C.addCommand(std::make_unique<Command>(JA, *this, 850 ResponseFileSupport::AtFileUTF8(), 851 Exec, CmdArgs, Inputs, Output)); 852 } 853 854 void darwin::Lipo::ConstructJob(Compilation &C, const JobAction &JA, 855 const InputInfo &Output, 856 const InputInfoList &Inputs, 857 const ArgList &Args, 858 const char *LinkingOutput) const { 859 ArgStringList CmdArgs; 860 861 CmdArgs.push_back("-create"); 862 assert(Output.isFilename() && "Unexpected lipo output."); 863 864 CmdArgs.push_back("-output"); 865 CmdArgs.push_back(Output.getFilename()); 866 867 for (const auto &II : Inputs) { 868 assert(II.isFilename() && "Unexpected lipo input."); 869 CmdArgs.push_back(II.getFilename()); 870 } 871 872 const char *Exec = Args.MakeArgString(getToolChain().GetProgramPath("lipo")); 873 C.addCommand(std::make_unique<Command>(JA, *this, ResponseFileSupport::None(), 874 Exec, CmdArgs, Inputs, Output)); 875 } 876 877 void darwin::Dsymutil::ConstructJob(Compilation &C, const JobAction &JA, 878 const InputInfo &Output, 879 const InputInfoList &Inputs, 880 const ArgList &Args, 881 const char *LinkingOutput) const { 882 ArgStringList CmdArgs; 883 884 CmdArgs.push_back("-o"); 885 CmdArgs.push_back(Output.getFilename()); 886 887 assert(Inputs.size() == 1 && "Unable to handle multiple inputs."); 888 const InputInfo &Input = Inputs[0]; 889 assert(Input.isFilename() && "Unexpected dsymutil input."); 890 CmdArgs.push_back(Input.getFilename()); 891 892 const char *Exec = 893 Args.MakeArgString(getToolChain().GetProgramPath("dsymutil")); 894 C.addCommand(std::make_unique<Command>(JA, *this, ResponseFileSupport::None(), 895 Exec, CmdArgs, Inputs, Output)); 896 } 897 898 void darwin::VerifyDebug::ConstructJob(Compilation &C, const JobAction &JA, 899 const InputInfo &Output, 900 const InputInfoList &Inputs, 901 const ArgList &Args, 902 const char *LinkingOutput) const { 903 ArgStringList CmdArgs; 904 CmdArgs.push_back("--verify"); 905 CmdArgs.push_back("--debug-info"); 906 CmdArgs.push_back("--eh-frame"); 907 CmdArgs.push_back("--quiet"); 908 909 assert(Inputs.size() == 1 && "Unable to handle multiple inputs."); 910 const InputInfo &Input = Inputs[0]; 911 assert(Input.isFilename() && "Unexpected verify input"); 912 913 // Grabbing the output of the earlier dsymutil run. 914 CmdArgs.push_back(Input.getFilename()); 915 916 const char *Exec = 917 Args.MakeArgString(getToolChain().GetProgramPath("dwarfdump")); 918 C.addCommand(std::make_unique<Command>(JA, *this, ResponseFileSupport::None(), 919 Exec, CmdArgs, Inputs, Output)); 920 } 921 922 MachO::MachO(const Driver &D, const llvm::Triple &Triple, const ArgList &Args) 923 : ToolChain(D, Triple, Args) { 924 // We expect 'as', 'ld', etc. to be adjacent to our install dir. 925 getProgramPaths().push_back(getDriver().getInstalledDir()); 926 if (getDriver().getInstalledDir() != getDriver().Dir) 927 getProgramPaths().push_back(getDriver().Dir); 928 } 929 930 /// Darwin - Darwin tool chain for i386 and x86_64. 931 Darwin::Darwin(const Driver &D, const llvm::Triple &Triple, const ArgList &Args) 932 : MachO(D, Triple, Args), TargetInitialized(false), 933 CudaInstallation(D, Triple, Args), RocmInstallation(D, Triple, Args) {} 934 935 types::ID MachO::LookupTypeForExtension(StringRef Ext) const { 936 types::ID Ty = ToolChain::LookupTypeForExtension(Ext); 937 938 // Darwin always preprocesses assembly files (unless -x is used explicitly). 939 if (Ty == types::TY_PP_Asm) 940 return types::TY_Asm; 941 942 return Ty; 943 } 944 945 bool MachO::HasNativeLLVMSupport() const { return true; } 946 947 ToolChain::CXXStdlibType Darwin::GetDefaultCXXStdlibType() const { 948 // Always use libc++ by default 949 return ToolChain::CST_Libcxx; 950 } 951 952 /// Darwin provides an ARC runtime starting in MacOS X 10.7 and iOS 5.0. 953 ObjCRuntime Darwin::getDefaultObjCRuntime(bool isNonFragile) const { 954 if (isTargetWatchOSBased()) 955 return ObjCRuntime(ObjCRuntime::WatchOS, TargetVersion); 956 if (isTargetIOSBased()) 957 return ObjCRuntime(ObjCRuntime::iOS, TargetVersion); 958 if (isNonFragile) 959 return ObjCRuntime(ObjCRuntime::MacOSX, TargetVersion); 960 return ObjCRuntime(ObjCRuntime::FragileMacOSX, TargetVersion); 961 } 962 963 /// Darwin provides a blocks runtime starting in MacOS X 10.6 and iOS 3.2. 964 bool Darwin::hasBlocksRuntime() const { 965 if (isTargetWatchOSBased() || isTargetDriverKit()) 966 return true; 967 else if (isTargetIOSBased()) 968 return !isIPhoneOSVersionLT(3, 2); 969 else { 970 assert(isTargetMacOSBased() && "unexpected darwin target"); 971 return !isMacosxVersionLT(10, 6); 972 } 973 } 974 975 void Darwin::AddCudaIncludeArgs(const ArgList &DriverArgs, 976 ArgStringList &CC1Args) const { 977 CudaInstallation.AddCudaIncludeArgs(DriverArgs, CC1Args); 978 } 979 980 void Darwin::AddHIPIncludeArgs(const ArgList &DriverArgs, 981 ArgStringList &CC1Args) const { 982 RocmInstallation.AddHIPIncludeArgs(DriverArgs, CC1Args); 983 } 984 985 // This is just a MachO name translation routine and there's no 986 // way to join this into ARMTargetParser without breaking all 987 // other assumptions. Maybe MachO should consider standardising 988 // their nomenclature. 989 static const char *ArmMachOArchName(StringRef Arch) { 990 return llvm::StringSwitch<const char *>(Arch) 991 .Case("armv6k", "armv6") 992 .Case("armv6m", "armv6m") 993 .Case("armv5tej", "armv5") 994 .Case("xscale", "xscale") 995 .Case("armv4t", "armv4t") 996 .Case("armv7", "armv7") 997 .Cases("armv7a", "armv7-a", "armv7") 998 .Cases("armv7r", "armv7-r", "armv7") 999 .Cases("armv7em", "armv7e-m", "armv7em") 1000 .Cases("armv7k", "armv7-k", "armv7k") 1001 .Cases("armv7m", "armv7-m", "armv7m") 1002 .Cases("armv7s", "armv7-s", "armv7s") 1003 .Default(nullptr); 1004 } 1005 1006 static const char *ArmMachOArchNameCPU(StringRef CPU) { 1007 llvm::ARM::ArchKind ArchKind = llvm::ARM::parseCPUArch(CPU); 1008 if (ArchKind == llvm::ARM::ArchKind::INVALID) 1009 return nullptr; 1010 StringRef Arch = llvm::ARM::getArchName(ArchKind); 1011 1012 // FIXME: Make sure this MachO triple mangling is really necessary. 1013 // ARMv5* normalises to ARMv5. 1014 if (Arch.startswith("armv5")) 1015 Arch = Arch.substr(0, 5); 1016 // ARMv6*, except ARMv6M, normalises to ARMv6. 1017 else if (Arch.startswith("armv6") && !Arch.endswith("6m")) 1018 Arch = Arch.substr(0, 5); 1019 // ARMv7A normalises to ARMv7. 1020 else if (Arch.endswith("v7a")) 1021 Arch = Arch.substr(0, 5); 1022 return Arch.data(); 1023 } 1024 1025 StringRef MachO::getMachOArchName(const ArgList &Args) const { 1026 switch (getTriple().getArch()) { 1027 default: 1028 return getDefaultUniversalArchName(); 1029 1030 case llvm::Triple::aarch64_32: 1031 return "arm64_32"; 1032 1033 case llvm::Triple::aarch64: { 1034 if (getTriple().isArm64e()) 1035 return "arm64e"; 1036 return "arm64"; 1037 } 1038 1039 case llvm::Triple::thumb: 1040 case llvm::Triple::arm: 1041 if (const Arg *A = Args.getLastArg(clang::driver::options::OPT_march_EQ)) 1042 if (const char *Arch = ArmMachOArchName(A->getValue())) 1043 return Arch; 1044 1045 if (const Arg *A = Args.getLastArg(options::OPT_mcpu_EQ)) 1046 if (const char *Arch = ArmMachOArchNameCPU(A->getValue())) 1047 return Arch; 1048 1049 return "arm"; 1050 } 1051 } 1052 1053 VersionTuple MachO::getLinkerVersion(const llvm::opt::ArgList &Args) const { 1054 if (LinkerVersion) { 1055 #ifndef NDEBUG 1056 VersionTuple NewLinkerVersion; 1057 if (Arg *A = Args.getLastArg(options::OPT_mlinker_version_EQ)) 1058 (void)NewLinkerVersion.tryParse(A->getValue()); 1059 assert(NewLinkerVersion == LinkerVersion); 1060 #endif 1061 return *LinkerVersion; 1062 } 1063 1064 VersionTuple NewLinkerVersion; 1065 if (Arg *A = Args.getLastArg(options::OPT_mlinker_version_EQ)) 1066 if (NewLinkerVersion.tryParse(A->getValue())) 1067 getDriver().Diag(diag::err_drv_invalid_version_number) 1068 << A->getAsString(Args); 1069 1070 LinkerVersion = NewLinkerVersion; 1071 return *LinkerVersion; 1072 } 1073 1074 Darwin::~Darwin() {} 1075 1076 MachO::~MachO() {} 1077 1078 std::string Darwin::ComputeEffectiveClangTriple(const ArgList &Args, 1079 types::ID InputType) const { 1080 llvm::Triple Triple(ComputeLLVMTriple(Args, InputType)); 1081 1082 // If the target isn't initialized (e.g., an unknown Darwin platform, return 1083 // the default triple). 1084 if (!isTargetInitialized()) 1085 return Triple.getTriple(); 1086 1087 SmallString<16> Str; 1088 if (isTargetWatchOSBased()) 1089 Str += "watchos"; 1090 else if (isTargetTvOSBased()) 1091 Str += "tvos"; 1092 else if (isTargetDriverKit()) 1093 Str += "driverkit"; 1094 else if (isTargetIOSBased() || isTargetMacCatalyst()) 1095 Str += "ios"; 1096 else 1097 Str += "macosx"; 1098 Str += getTripleTargetVersion().getAsString(); 1099 Triple.setOSName(Str); 1100 1101 return Triple.getTriple(); 1102 } 1103 1104 Tool *MachO::getTool(Action::ActionClass AC) const { 1105 switch (AC) { 1106 case Action::LipoJobClass: 1107 if (!Lipo) 1108 Lipo.reset(new tools::darwin::Lipo(*this)); 1109 return Lipo.get(); 1110 case Action::DsymutilJobClass: 1111 if (!Dsymutil) 1112 Dsymutil.reset(new tools::darwin::Dsymutil(*this)); 1113 return Dsymutil.get(); 1114 case Action::VerifyDebugInfoJobClass: 1115 if (!VerifyDebug) 1116 VerifyDebug.reset(new tools::darwin::VerifyDebug(*this)); 1117 return VerifyDebug.get(); 1118 default: 1119 return ToolChain::getTool(AC); 1120 } 1121 } 1122 1123 Tool *MachO::buildLinker() const { return new tools::darwin::Linker(*this); } 1124 1125 Tool *MachO::buildStaticLibTool() const { 1126 return new tools::darwin::StaticLibTool(*this); 1127 } 1128 1129 Tool *MachO::buildAssembler() const { 1130 return new tools::darwin::Assembler(*this); 1131 } 1132 1133 DarwinClang::DarwinClang(const Driver &D, const llvm::Triple &Triple, 1134 const ArgList &Args) 1135 : Darwin(D, Triple, Args) {} 1136 1137 void DarwinClang::addClangWarningOptions(ArgStringList &CC1Args) const { 1138 // Always error about undefined 'TARGET_OS_*' macros. 1139 CC1Args.push_back("-Wundef-prefix=TARGET_OS_"); 1140 CC1Args.push_back("-Werror=undef-prefix"); 1141 1142 // For modern targets, promote certain warnings to errors. 1143 if (isTargetWatchOSBased() || getTriple().isArch64Bit()) { 1144 // Always enable -Wdeprecated-objc-isa-usage and promote it 1145 // to an error. 1146 CC1Args.push_back("-Wdeprecated-objc-isa-usage"); 1147 CC1Args.push_back("-Werror=deprecated-objc-isa-usage"); 1148 1149 // For iOS and watchOS, also error about implicit function declarations, 1150 // as that can impact calling conventions. 1151 if (!isTargetMacOS()) 1152 CC1Args.push_back("-Werror=implicit-function-declaration"); 1153 } 1154 } 1155 1156 /// Take a path that speculatively points into Xcode and return the 1157 /// `XCODE/Contents/Developer` path if it is an Xcode path, or an empty path 1158 /// otherwise. 1159 static StringRef getXcodeDeveloperPath(StringRef PathIntoXcode) { 1160 static constexpr llvm::StringLiteral XcodeAppSuffix( 1161 ".app/Contents/Developer"); 1162 size_t Index = PathIntoXcode.find(XcodeAppSuffix); 1163 if (Index == StringRef::npos) 1164 return ""; 1165 return PathIntoXcode.take_front(Index + XcodeAppSuffix.size()); 1166 } 1167 1168 void DarwinClang::AddLinkARCArgs(const ArgList &Args, 1169 ArgStringList &CmdArgs) const { 1170 // Avoid linking compatibility stubs on i386 mac. 1171 if (isTargetMacOSBased() && getArch() == llvm::Triple::x86) 1172 return; 1173 if (isTargetAppleSiliconMac()) 1174 return; 1175 // ARC runtime is supported everywhere on arm64e. 1176 if (getTriple().isArm64e()) 1177 return; 1178 1179 ObjCRuntime runtime = getDefaultObjCRuntime(/*nonfragile*/ true); 1180 1181 if ((runtime.hasNativeARC() || !isObjCAutoRefCount(Args)) && 1182 runtime.hasSubscripting()) 1183 return; 1184 1185 SmallString<128> P(getDriver().ClangExecutable); 1186 llvm::sys::path::remove_filename(P); // 'clang' 1187 llvm::sys::path::remove_filename(P); // 'bin' 1188 llvm::sys::path::append(P, "lib", "arc"); 1189 1190 // 'libarclite' usually lives in the same toolchain as 'clang'. However, the 1191 // Swift open source toolchains for macOS distribute Clang without libarclite. 1192 // In that case, to allow the linker to find 'libarclite', we point to the 1193 // 'libarclite' in the XcodeDefault toolchain instead. 1194 if (!getVFS().exists(P)) { 1195 auto updatePath = [&](const Arg *A) { 1196 // Try to infer the path to 'libarclite' in the toolchain from the 1197 // specified SDK path. 1198 StringRef XcodePathForSDK = getXcodeDeveloperPath(A->getValue()); 1199 if (XcodePathForSDK.empty()) 1200 return false; 1201 1202 P = XcodePathForSDK; 1203 llvm::sys::path::append(P, "Toolchains/XcodeDefault.xctoolchain/usr", 1204 "lib", "arc"); 1205 return getVFS().exists(P); 1206 }; 1207 1208 bool updated = false; 1209 if (const Arg *A = Args.getLastArg(options::OPT_isysroot)) 1210 updated = updatePath(A); 1211 1212 if (!updated) { 1213 if (const Arg *A = Args.getLastArg(options::OPT__sysroot_EQ)) 1214 updatePath(A); 1215 } 1216 } 1217 1218 CmdArgs.push_back("-force_load"); 1219 llvm::sys::path::append(P, "libarclite_"); 1220 // Mash in the platform. 1221 if (isTargetWatchOSSimulator()) 1222 P += "watchsimulator"; 1223 else if (isTargetWatchOS()) 1224 P += "watchos"; 1225 else if (isTargetTvOSSimulator()) 1226 P += "appletvsimulator"; 1227 else if (isTargetTvOS()) 1228 P += "appletvos"; 1229 else if (isTargetIOSSimulator()) 1230 P += "iphonesimulator"; 1231 else if (isTargetIPhoneOS()) 1232 P += "iphoneos"; 1233 else 1234 P += "macosx"; 1235 P += ".a"; 1236 1237 if (!getVFS().exists(P)) 1238 getDriver().Diag(clang::diag::err_drv_darwin_sdk_missing_arclite) << P; 1239 1240 CmdArgs.push_back(Args.MakeArgString(P)); 1241 } 1242 1243 unsigned DarwinClang::GetDefaultDwarfVersion() const { 1244 // Default to use DWARF 2 on OS X 10.10 / iOS 8 and lower. 1245 if ((isTargetMacOSBased() && isMacosxVersionLT(10, 11)) || 1246 (isTargetIOSBased() && isIPhoneOSVersionLT(9))) 1247 return 2; 1248 return 4; 1249 } 1250 1251 void MachO::AddLinkRuntimeLib(const ArgList &Args, ArgStringList &CmdArgs, 1252 StringRef Component, RuntimeLinkOptions Opts, 1253 bool IsShared) const { 1254 SmallString<64> DarwinLibName = StringRef("libclang_rt."); 1255 // an Darwin the builtins compomnent is not in the library name 1256 if (Component != "builtins") { 1257 DarwinLibName += Component; 1258 if (!(Opts & RLO_IsEmbedded)) 1259 DarwinLibName += "_"; 1260 } 1261 1262 DarwinLibName += getOSLibraryNameSuffix(); 1263 DarwinLibName += IsShared ? "_dynamic.dylib" : ".a"; 1264 SmallString<128> Dir(getDriver().ResourceDir); 1265 llvm::sys::path::append(Dir, "lib", "darwin"); 1266 if (Opts & RLO_IsEmbedded) 1267 llvm::sys::path::append(Dir, "macho_embedded"); 1268 1269 SmallString<128> P(Dir); 1270 llvm::sys::path::append(P, DarwinLibName); 1271 1272 // For now, allow missing resource libraries to support developers who may 1273 // not have compiler-rt checked out or integrated into their build (unless 1274 // we explicitly force linking with this library). 1275 if ((Opts & RLO_AlwaysLink) || getVFS().exists(P)) { 1276 const char *LibArg = Args.MakeArgString(P); 1277 CmdArgs.push_back(LibArg); 1278 } 1279 1280 // Adding the rpaths might negatively interact when other rpaths are involved, 1281 // so we should make sure we add the rpaths last, after all user-specified 1282 // rpaths. This is currently true from this place, but we need to be 1283 // careful if this function is ever called before user's rpaths are emitted. 1284 if (Opts & RLO_AddRPath) { 1285 assert(DarwinLibName.endswith(".dylib") && "must be a dynamic library"); 1286 1287 // Add @executable_path to rpath to support having the dylib copied with 1288 // the executable. 1289 CmdArgs.push_back("-rpath"); 1290 CmdArgs.push_back("@executable_path"); 1291 1292 // Add the path to the resource dir to rpath to support using the dylib 1293 // from the default location without copying. 1294 CmdArgs.push_back("-rpath"); 1295 CmdArgs.push_back(Args.MakeArgString(Dir)); 1296 } 1297 } 1298 1299 StringRef Darwin::getPlatformFamily() const { 1300 switch (TargetPlatform) { 1301 case DarwinPlatformKind::MacOS: 1302 return "MacOSX"; 1303 case DarwinPlatformKind::IPhoneOS: 1304 if (TargetEnvironment == MacCatalyst) 1305 return "MacOSX"; 1306 return "iPhone"; 1307 case DarwinPlatformKind::TvOS: 1308 return "AppleTV"; 1309 case DarwinPlatformKind::WatchOS: 1310 return "Watch"; 1311 case DarwinPlatformKind::DriverKit: 1312 return "DriverKit"; 1313 } 1314 llvm_unreachable("Unsupported platform"); 1315 } 1316 1317 StringRef Darwin::getSDKName(StringRef isysroot) { 1318 // Assume SDK has path: SOME_PATH/SDKs/PlatformXX.YY.sdk 1319 auto BeginSDK = llvm::sys::path::rbegin(isysroot); 1320 auto EndSDK = llvm::sys::path::rend(isysroot); 1321 for (auto IT = BeginSDK; IT != EndSDK; ++IT) { 1322 StringRef SDK = *IT; 1323 if (SDK.endswith(".sdk")) 1324 return SDK.slice(0, SDK.size() - 4); 1325 } 1326 return ""; 1327 } 1328 1329 StringRef Darwin::getOSLibraryNameSuffix(bool IgnoreSim) const { 1330 switch (TargetPlatform) { 1331 case DarwinPlatformKind::MacOS: 1332 return "osx"; 1333 case DarwinPlatformKind::IPhoneOS: 1334 if (TargetEnvironment == MacCatalyst) 1335 return "osx"; 1336 return TargetEnvironment == NativeEnvironment || IgnoreSim ? "ios" 1337 : "iossim"; 1338 case DarwinPlatformKind::TvOS: 1339 return TargetEnvironment == NativeEnvironment || IgnoreSim ? "tvos" 1340 : "tvossim"; 1341 case DarwinPlatformKind::WatchOS: 1342 return TargetEnvironment == NativeEnvironment || IgnoreSim ? "watchos" 1343 : "watchossim"; 1344 case DarwinPlatformKind::DriverKit: 1345 return "driverkit"; 1346 } 1347 llvm_unreachable("Unsupported platform"); 1348 } 1349 1350 /// Check if the link command contains a symbol export directive. 1351 static bool hasExportSymbolDirective(const ArgList &Args) { 1352 for (Arg *A : Args) { 1353 if (A->getOption().matches(options::OPT_exported__symbols__list)) 1354 return true; 1355 if (!A->getOption().matches(options::OPT_Wl_COMMA) && 1356 !A->getOption().matches(options::OPT_Xlinker)) 1357 continue; 1358 if (A->containsValue("-exported_symbols_list") || 1359 A->containsValue("-exported_symbol")) 1360 return true; 1361 } 1362 return false; 1363 } 1364 1365 /// Add an export directive for \p Symbol to the link command. 1366 static void addExportedSymbol(ArgStringList &CmdArgs, const char *Symbol) { 1367 CmdArgs.push_back("-exported_symbol"); 1368 CmdArgs.push_back(Symbol); 1369 } 1370 1371 /// Add a sectalign directive for \p Segment and \p Section to the maximum 1372 /// expected page size for Darwin. 1373 /// 1374 /// On iPhone 6+ the max supported page size is 16K. On macOS, the max is 4K. 1375 /// Use a common alignment constant (16K) for now, and reduce the alignment on 1376 /// macOS if it proves important. 1377 static void addSectalignToPage(const ArgList &Args, ArgStringList &CmdArgs, 1378 StringRef Segment, StringRef Section) { 1379 for (const char *A : {"-sectalign", Args.MakeArgString(Segment), 1380 Args.MakeArgString(Section), "0x4000"}) 1381 CmdArgs.push_back(A); 1382 } 1383 1384 void Darwin::addProfileRTLibs(const ArgList &Args, 1385 ArgStringList &CmdArgs) const { 1386 if (!needsProfileRT(Args) && !needsGCovInstrumentation(Args)) 1387 return; 1388 1389 AddLinkRuntimeLib(Args, CmdArgs, "profile", 1390 RuntimeLinkOptions(RLO_AlwaysLink)); 1391 1392 bool ForGCOV = needsGCovInstrumentation(Args); 1393 1394 // If we have a symbol export directive and we're linking in the profile 1395 // runtime, automatically export symbols necessary to implement some of the 1396 // runtime's functionality. 1397 if (hasExportSymbolDirective(Args) && ForGCOV) { 1398 addExportedSymbol(CmdArgs, "___gcov_dump"); 1399 addExportedSymbol(CmdArgs, "___gcov_reset"); 1400 addExportedSymbol(CmdArgs, "_writeout_fn_list"); 1401 addExportedSymbol(CmdArgs, "_reset_fn_list"); 1402 } 1403 1404 // Align __llvm_prf_{cnts,data} sections to the maximum expected page 1405 // alignment. This allows profile counters to be mmap()'d to disk. Note that 1406 // it's not enough to just page-align __llvm_prf_cnts: the following section 1407 // must also be page-aligned so that its data is not clobbered by mmap(). 1408 // 1409 // The section alignment is only needed when continuous profile sync is 1410 // enabled, but this is expected to be the default in Xcode. Specifying the 1411 // extra alignment also allows the same binary to be used with/without sync 1412 // enabled. 1413 if (!ForGCOV) { 1414 for (auto IPSK : {llvm::IPSK_cnts, llvm::IPSK_data}) { 1415 addSectalignToPage( 1416 Args, CmdArgs, "__DATA", 1417 llvm::getInstrProfSectionName(IPSK, llvm::Triple::MachO, 1418 /*AddSegmentInfo=*/false)); 1419 } 1420 } 1421 } 1422 1423 void DarwinClang::AddLinkSanitizerLibArgs(const ArgList &Args, 1424 ArgStringList &CmdArgs, 1425 StringRef Sanitizer, 1426 bool Shared) const { 1427 auto RLO = RuntimeLinkOptions(RLO_AlwaysLink | (Shared ? RLO_AddRPath : 0U)); 1428 AddLinkRuntimeLib(Args, CmdArgs, Sanitizer, RLO, Shared); 1429 } 1430 1431 ToolChain::RuntimeLibType DarwinClang::GetRuntimeLibType( 1432 const ArgList &Args) const { 1433 if (Arg* A = Args.getLastArg(options::OPT_rtlib_EQ)) { 1434 StringRef Value = A->getValue(); 1435 if (Value != "compiler-rt" && Value != "platform") 1436 getDriver().Diag(clang::diag::err_drv_unsupported_rtlib_for_platform) 1437 << Value << "darwin"; 1438 } 1439 1440 return ToolChain::RLT_CompilerRT; 1441 } 1442 1443 void DarwinClang::AddLinkRuntimeLibArgs(const ArgList &Args, 1444 ArgStringList &CmdArgs, 1445 bool ForceLinkBuiltinRT) const { 1446 // Call once to ensure diagnostic is printed if wrong value was specified 1447 GetRuntimeLibType(Args); 1448 1449 // Darwin doesn't support real static executables, don't link any runtime 1450 // libraries with -static. 1451 if (Args.hasArg(options::OPT_static) || 1452 Args.hasArg(options::OPT_fapple_kext) || 1453 Args.hasArg(options::OPT_mkernel)) { 1454 if (ForceLinkBuiltinRT) 1455 AddLinkRuntimeLib(Args, CmdArgs, "builtins"); 1456 return; 1457 } 1458 1459 // Reject -static-libgcc for now, we can deal with this when and if someone 1460 // cares. This is useful in situations where someone wants to statically link 1461 // something like libstdc++, and needs its runtime support routines. 1462 if (const Arg *A = Args.getLastArg(options::OPT_static_libgcc)) { 1463 getDriver().Diag(diag::err_drv_unsupported_opt) << A->getAsString(Args); 1464 return; 1465 } 1466 1467 const SanitizerArgs &Sanitize = getSanitizerArgs(Args); 1468 1469 if (!Sanitize.needsSharedRt()) { 1470 const char *sanitizer = nullptr; 1471 if (Sanitize.needsUbsanRt()) { 1472 sanitizer = "UndefinedBehaviorSanitizer"; 1473 } else if (Sanitize.needsAsanRt()) { 1474 sanitizer = "AddressSanitizer"; 1475 } else if (Sanitize.needsTsanRt()) { 1476 sanitizer = "ThreadSanitizer"; 1477 } 1478 if (sanitizer) { 1479 getDriver().Diag(diag::err_drv_unsupported_static_sanitizer_darwin) 1480 << sanitizer; 1481 return; 1482 } 1483 } 1484 1485 if (Sanitize.linkRuntimes()) { 1486 if (Sanitize.needsAsanRt()) { 1487 assert(Sanitize.needsSharedRt() && 1488 "Static sanitizer runtimes not supported"); 1489 AddLinkSanitizerLibArgs(Args, CmdArgs, "asan"); 1490 } 1491 if (Sanitize.needsLsanRt()) 1492 AddLinkSanitizerLibArgs(Args, CmdArgs, "lsan"); 1493 if (Sanitize.needsUbsanRt()) { 1494 assert(Sanitize.needsSharedRt() && 1495 "Static sanitizer runtimes not supported"); 1496 AddLinkSanitizerLibArgs( 1497 Args, CmdArgs, 1498 Sanitize.requiresMinimalRuntime() ? "ubsan_minimal" : "ubsan"); 1499 } 1500 if (Sanitize.needsTsanRt()) { 1501 assert(Sanitize.needsSharedRt() && 1502 "Static sanitizer runtimes not supported"); 1503 AddLinkSanitizerLibArgs(Args, CmdArgs, "tsan"); 1504 } 1505 if (Sanitize.needsFuzzer() && !Args.hasArg(options::OPT_dynamiclib)) { 1506 AddLinkSanitizerLibArgs(Args, CmdArgs, "fuzzer", /*shared=*/false); 1507 1508 // Libfuzzer is written in C++ and requires libcxx. 1509 AddCXXStdlibLibArgs(Args, CmdArgs); 1510 } 1511 if (Sanitize.needsStatsRt()) { 1512 AddLinkRuntimeLib(Args, CmdArgs, "stats_client", RLO_AlwaysLink); 1513 AddLinkSanitizerLibArgs(Args, CmdArgs, "stats"); 1514 } 1515 } 1516 1517 const XRayArgs &XRay = getXRayArgs(); 1518 if (XRay.needsXRayRt()) { 1519 AddLinkRuntimeLib(Args, CmdArgs, "xray"); 1520 AddLinkRuntimeLib(Args, CmdArgs, "xray-basic"); 1521 AddLinkRuntimeLib(Args, CmdArgs, "xray-fdr"); 1522 } 1523 1524 if (isTargetDriverKit() && !Args.hasArg(options::OPT_nodriverkitlib)) { 1525 CmdArgs.push_back("-framework"); 1526 CmdArgs.push_back("DriverKit"); 1527 } 1528 1529 // Otherwise link libSystem, then the dynamic runtime library, and finally any 1530 // target specific static runtime library. 1531 if (!isTargetDriverKit()) 1532 CmdArgs.push_back("-lSystem"); 1533 1534 // Select the dynamic runtime library and the target specific static library. 1535 if (isTargetIOSBased()) { 1536 // If we are compiling as iOS / simulator, don't attempt to link libgcc_s.1, 1537 // it never went into the SDK. 1538 // Linking against libgcc_s.1 isn't needed for iOS 5.0+ 1539 if (isIPhoneOSVersionLT(5, 0) && !isTargetIOSSimulator() && 1540 getTriple().getArch() != llvm::Triple::aarch64) 1541 CmdArgs.push_back("-lgcc_s.1"); 1542 } 1543 AddLinkRuntimeLib(Args, CmdArgs, "builtins"); 1544 } 1545 1546 /// Returns the most appropriate macOS target version for the current process. 1547 /// 1548 /// If the macOS SDK version is the same or earlier than the system version, 1549 /// then the SDK version is returned. Otherwise the system version is returned. 1550 static std::string getSystemOrSDKMacOSVersion(StringRef MacOSSDKVersion) { 1551 llvm::Triple SystemTriple(llvm::sys::getProcessTriple()); 1552 if (!SystemTriple.isMacOSX()) 1553 return std::string(MacOSSDKVersion); 1554 VersionTuple SystemVersion; 1555 SystemTriple.getMacOSXVersion(SystemVersion); 1556 1557 unsigned Major, Minor, Micro; 1558 bool HadExtra; 1559 if (!Driver::GetReleaseVersion(MacOSSDKVersion, Major, Minor, Micro, 1560 HadExtra)) 1561 return std::string(MacOSSDKVersion); 1562 VersionTuple SDKVersion(Major, Minor, Micro); 1563 1564 if (SDKVersion > SystemVersion) 1565 return SystemVersion.getAsString(); 1566 return std::string(MacOSSDKVersion); 1567 } 1568 1569 namespace { 1570 1571 /// The Darwin OS that was selected or inferred from arguments / environment. 1572 struct DarwinPlatform { 1573 enum SourceKind { 1574 /// The OS was specified using the -target argument. 1575 TargetArg, 1576 /// The OS was specified using the -mtargetos= argument. 1577 MTargetOSArg, 1578 /// The OS was specified using the -m<os>-version-min argument. 1579 OSVersionArg, 1580 /// The OS was specified using the OS_DEPLOYMENT_TARGET environment. 1581 DeploymentTargetEnv, 1582 /// The OS was inferred from the SDK. 1583 InferredFromSDK, 1584 /// The OS was inferred from the -arch. 1585 InferredFromArch 1586 }; 1587 1588 using DarwinPlatformKind = Darwin::DarwinPlatformKind; 1589 using DarwinEnvironmentKind = Darwin::DarwinEnvironmentKind; 1590 1591 DarwinPlatformKind getPlatform() const { return Platform; } 1592 1593 DarwinEnvironmentKind getEnvironment() const { return Environment; } 1594 1595 void setEnvironment(DarwinEnvironmentKind Kind) { 1596 Environment = Kind; 1597 InferSimulatorFromArch = false; 1598 } 1599 1600 StringRef getOSVersion() const { 1601 if (Kind == OSVersionArg) 1602 return Argument->getValue(); 1603 return OSVersion; 1604 } 1605 1606 void setOSVersion(StringRef S) { 1607 assert(Kind == TargetArg && "Unexpected kind!"); 1608 OSVersion = std::string(S); 1609 } 1610 1611 bool hasOSVersion() const { return HasOSVersion; } 1612 1613 VersionTuple getNativeTargetVersion() const { 1614 assert(Environment == DarwinEnvironmentKind::MacCatalyst && 1615 "native target version is specified only for Mac Catalyst"); 1616 return NativeTargetVersion; 1617 } 1618 1619 /// Returns true if the target OS was explicitly specified. 1620 bool isExplicitlySpecified() const { return Kind <= DeploymentTargetEnv; } 1621 1622 /// Returns true if the simulator environment can be inferred from the arch. 1623 bool canInferSimulatorFromArch() const { return InferSimulatorFromArch; } 1624 1625 const std::optional<llvm::Triple> &getTargetVariantTriple() const { 1626 return TargetVariantTriple; 1627 } 1628 1629 /// Adds the -m<os>-version-min argument to the compiler invocation. 1630 void addOSVersionMinArgument(DerivedArgList &Args, const OptTable &Opts) { 1631 if (Argument) 1632 return; 1633 assert(Kind != TargetArg && Kind != MTargetOSArg && Kind != OSVersionArg && 1634 "Invalid kind"); 1635 options::ID Opt; 1636 switch (Platform) { 1637 case DarwinPlatformKind::MacOS: 1638 Opt = options::OPT_mmacos_version_min_EQ; 1639 break; 1640 case DarwinPlatformKind::IPhoneOS: 1641 Opt = options::OPT_mios_version_min_EQ; 1642 break; 1643 case DarwinPlatformKind::TvOS: 1644 Opt = options::OPT_mtvos_version_min_EQ; 1645 break; 1646 case DarwinPlatformKind::WatchOS: 1647 Opt = options::OPT_mwatchos_version_min_EQ; 1648 break; 1649 case DarwinPlatformKind::DriverKit: 1650 // DriverKit always explicitly provides a version in the triple. 1651 return; 1652 } 1653 Argument = Args.MakeJoinedArg(nullptr, Opts.getOption(Opt), OSVersion); 1654 Args.append(Argument); 1655 } 1656 1657 /// Returns the OS version with the argument / environment variable that 1658 /// specified it. 1659 std::string getAsString(DerivedArgList &Args, const OptTable &Opts) { 1660 switch (Kind) { 1661 case TargetArg: 1662 case MTargetOSArg: 1663 case OSVersionArg: 1664 case InferredFromSDK: 1665 case InferredFromArch: 1666 assert(Argument && "OS version argument not yet inferred"); 1667 return Argument->getAsString(Args); 1668 case DeploymentTargetEnv: 1669 return (llvm::Twine(EnvVarName) + "=" + OSVersion).str(); 1670 } 1671 llvm_unreachable("Unsupported Darwin Source Kind"); 1672 } 1673 1674 void setEnvironment(llvm::Triple::EnvironmentType EnvType, 1675 const VersionTuple &OSVersion, 1676 const std::optional<DarwinSDKInfo> &SDKInfo) { 1677 switch (EnvType) { 1678 case llvm::Triple::Simulator: 1679 Environment = DarwinEnvironmentKind::Simulator; 1680 break; 1681 case llvm::Triple::MacABI: { 1682 Environment = DarwinEnvironmentKind::MacCatalyst; 1683 // The minimum native macOS target for MacCatalyst is macOS 10.15. 1684 NativeTargetVersion = VersionTuple(10, 15); 1685 if (HasOSVersion && SDKInfo) { 1686 if (const auto *MacCatalystToMacOSMapping = SDKInfo->getVersionMapping( 1687 DarwinSDKInfo::OSEnvPair::macCatalystToMacOSPair())) { 1688 if (auto MacOSVersion = MacCatalystToMacOSMapping->map( 1689 OSVersion, NativeTargetVersion, std::nullopt)) { 1690 NativeTargetVersion = *MacOSVersion; 1691 } 1692 } 1693 } 1694 // In a zippered build, we could be building for a macOS target that's 1695 // lower than the version that's implied by the OS version. In that case 1696 // we need to use the minimum version as the native target version. 1697 if (TargetVariantTriple) { 1698 auto TargetVariantVersion = TargetVariantTriple->getOSVersion(); 1699 if (TargetVariantVersion.getMajor()) { 1700 if (TargetVariantVersion < NativeTargetVersion) 1701 NativeTargetVersion = TargetVariantVersion; 1702 } 1703 } 1704 break; 1705 } 1706 default: 1707 break; 1708 } 1709 } 1710 1711 static DarwinPlatform 1712 createFromTarget(const llvm::Triple &TT, StringRef OSVersion, Arg *A, 1713 std::optional<llvm::Triple> TargetVariantTriple, 1714 const std::optional<DarwinSDKInfo> &SDKInfo) { 1715 DarwinPlatform Result(TargetArg, getPlatformFromOS(TT.getOS()), OSVersion, 1716 A); 1717 VersionTuple OsVersion = TT.getOSVersion(); 1718 if (OsVersion.getMajor() == 0) 1719 Result.HasOSVersion = false; 1720 Result.TargetVariantTriple = TargetVariantTriple; 1721 Result.setEnvironment(TT.getEnvironment(), OsVersion, SDKInfo); 1722 return Result; 1723 } 1724 static DarwinPlatform 1725 createFromMTargetOS(llvm::Triple::OSType OS, VersionTuple OSVersion, 1726 llvm::Triple::EnvironmentType Environment, Arg *A, 1727 const std::optional<DarwinSDKInfo> &SDKInfo) { 1728 DarwinPlatform Result(MTargetOSArg, getPlatformFromOS(OS), 1729 OSVersion.getAsString(), A); 1730 Result.InferSimulatorFromArch = false; 1731 Result.setEnvironment(Environment, OSVersion, SDKInfo); 1732 return Result; 1733 } 1734 static DarwinPlatform createOSVersionArg(DarwinPlatformKind Platform, Arg *A, 1735 bool IsSimulator) { 1736 DarwinPlatform Result{OSVersionArg, Platform, A}; 1737 if (IsSimulator) 1738 Result.Environment = DarwinEnvironmentKind::Simulator; 1739 return Result; 1740 } 1741 static DarwinPlatform createDeploymentTargetEnv(DarwinPlatformKind Platform, 1742 StringRef EnvVarName, 1743 StringRef Value) { 1744 DarwinPlatform Result(DeploymentTargetEnv, Platform, Value); 1745 Result.EnvVarName = EnvVarName; 1746 return Result; 1747 } 1748 static DarwinPlatform createFromSDK(DarwinPlatformKind Platform, 1749 StringRef Value, 1750 bool IsSimulator = false) { 1751 DarwinPlatform Result(InferredFromSDK, Platform, Value); 1752 if (IsSimulator) 1753 Result.Environment = DarwinEnvironmentKind::Simulator; 1754 Result.InferSimulatorFromArch = false; 1755 return Result; 1756 } 1757 static DarwinPlatform createFromArch(llvm::Triple::OSType OS, 1758 StringRef Value) { 1759 return DarwinPlatform(InferredFromArch, getPlatformFromOS(OS), Value); 1760 } 1761 1762 /// Constructs an inferred SDKInfo value based on the version inferred from 1763 /// the SDK path itself. Only works for values that were created by inferring 1764 /// the platform from the SDKPath. 1765 DarwinSDKInfo inferSDKInfo() { 1766 assert(Kind == InferredFromSDK && "can infer SDK info only"); 1767 llvm::VersionTuple Version; 1768 bool IsValid = !Version.tryParse(OSVersion); 1769 (void)IsValid; 1770 assert(IsValid && "invalid SDK version"); 1771 return DarwinSDKInfo( 1772 Version, 1773 /*MaximumDeploymentTarget=*/VersionTuple(Version.getMajor(), 0, 99)); 1774 } 1775 1776 private: 1777 DarwinPlatform(SourceKind Kind, DarwinPlatformKind Platform, Arg *Argument) 1778 : Kind(Kind), Platform(Platform), Argument(Argument) {} 1779 DarwinPlatform(SourceKind Kind, DarwinPlatformKind Platform, StringRef Value, 1780 Arg *Argument = nullptr) 1781 : Kind(Kind), Platform(Platform), OSVersion(Value), Argument(Argument) {} 1782 1783 static DarwinPlatformKind getPlatformFromOS(llvm::Triple::OSType OS) { 1784 switch (OS) { 1785 case llvm::Triple::Darwin: 1786 case llvm::Triple::MacOSX: 1787 return DarwinPlatformKind::MacOS; 1788 case llvm::Triple::IOS: 1789 return DarwinPlatformKind::IPhoneOS; 1790 case llvm::Triple::TvOS: 1791 return DarwinPlatformKind::TvOS; 1792 case llvm::Triple::WatchOS: 1793 return DarwinPlatformKind::WatchOS; 1794 case llvm::Triple::DriverKit: 1795 return DarwinPlatformKind::DriverKit; 1796 default: 1797 llvm_unreachable("Unable to infer Darwin variant"); 1798 } 1799 } 1800 1801 SourceKind Kind; 1802 DarwinPlatformKind Platform; 1803 DarwinEnvironmentKind Environment = DarwinEnvironmentKind::NativeEnvironment; 1804 VersionTuple NativeTargetVersion; 1805 std::string OSVersion; 1806 bool HasOSVersion = true, InferSimulatorFromArch = true; 1807 Arg *Argument; 1808 StringRef EnvVarName; 1809 std::optional<llvm::Triple> TargetVariantTriple; 1810 }; 1811 1812 /// Returns the deployment target that's specified using the -m<os>-version-min 1813 /// argument. 1814 std::optional<DarwinPlatform> 1815 getDeploymentTargetFromOSVersionArg(DerivedArgList &Args, 1816 const Driver &TheDriver) { 1817 Arg *macOSVersion = Args.getLastArg(options::OPT_mmacos_version_min_EQ); 1818 Arg *iOSVersion = Args.getLastArg(options::OPT_mios_version_min_EQ, 1819 options::OPT_mios_simulator_version_min_EQ); 1820 Arg *TvOSVersion = 1821 Args.getLastArg(options::OPT_mtvos_version_min_EQ, 1822 options::OPT_mtvos_simulator_version_min_EQ); 1823 Arg *WatchOSVersion = 1824 Args.getLastArg(options::OPT_mwatchos_version_min_EQ, 1825 options::OPT_mwatchos_simulator_version_min_EQ); 1826 if (macOSVersion) { 1827 if (iOSVersion || TvOSVersion || WatchOSVersion) { 1828 TheDriver.Diag(diag::err_drv_argument_not_allowed_with) 1829 << macOSVersion->getAsString(Args) 1830 << (iOSVersion ? iOSVersion 1831 : TvOSVersion ? TvOSVersion : WatchOSVersion) 1832 ->getAsString(Args); 1833 } 1834 return DarwinPlatform::createOSVersionArg(Darwin::MacOS, macOSVersion, 1835 /*IsSimulator=*/false); 1836 } else if (iOSVersion) { 1837 if (TvOSVersion || WatchOSVersion) { 1838 TheDriver.Diag(diag::err_drv_argument_not_allowed_with) 1839 << iOSVersion->getAsString(Args) 1840 << (TvOSVersion ? TvOSVersion : WatchOSVersion)->getAsString(Args); 1841 } 1842 return DarwinPlatform::createOSVersionArg( 1843 Darwin::IPhoneOS, iOSVersion, 1844 iOSVersion->getOption().getID() == 1845 options::OPT_mios_simulator_version_min_EQ); 1846 } else if (TvOSVersion) { 1847 if (WatchOSVersion) { 1848 TheDriver.Diag(diag::err_drv_argument_not_allowed_with) 1849 << TvOSVersion->getAsString(Args) 1850 << WatchOSVersion->getAsString(Args); 1851 } 1852 return DarwinPlatform::createOSVersionArg( 1853 Darwin::TvOS, TvOSVersion, 1854 TvOSVersion->getOption().getID() == 1855 options::OPT_mtvos_simulator_version_min_EQ); 1856 } else if (WatchOSVersion) 1857 return DarwinPlatform::createOSVersionArg( 1858 Darwin::WatchOS, WatchOSVersion, 1859 WatchOSVersion->getOption().getID() == 1860 options::OPT_mwatchos_simulator_version_min_EQ); 1861 return std::nullopt; 1862 } 1863 1864 /// Returns the deployment target that's specified using the 1865 /// OS_DEPLOYMENT_TARGET environment variable. 1866 std::optional<DarwinPlatform> 1867 getDeploymentTargetFromEnvironmentVariables(const Driver &TheDriver, 1868 const llvm::Triple &Triple) { 1869 std::string Targets[Darwin::LastDarwinPlatform + 1]; 1870 const char *EnvVars[] = { 1871 "MACOSX_DEPLOYMENT_TARGET", 1872 "IPHONEOS_DEPLOYMENT_TARGET", 1873 "TVOS_DEPLOYMENT_TARGET", 1874 "WATCHOS_DEPLOYMENT_TARGET", 1875 "DRIVERKIT_DEPLOYMENT_TARGET", 1876 }; 1877 static_assert(std::size(EnvVars) == Darwin::LastDarwinPlatform + 1, 1878 "Missing platform"); 1879 for (const auto &I : llvm::enumerate(llvm::ArrayRef(EnvVars))) { 1880 if (char *Env = ::getenv(I.value())) 1881 Targets[I.index()] = Env; 1882 } 1883 1884 // Allow conflicts among OSX and iOS for historical reasons, but choose the 1885 // default platform. 1886 if (!Targets[Darwin::MacOS].empty() && 1887 (!Targets[Darwin::IPhoneOS].empty() || 1888 !Targets[Darwin::WatchOS].empty() || !Targets[Darwin::TvOS].empty())) { 1889 if (Triple.getArch() == llvm::Triple::arm || 1890 Triple.getArch() == llvm::Triple::aarch64 || 1891 Triple.getArch() == llvm::Triple::thumb) 1892 Targets[Darwin::MacOS] = ""; 1893 else 1894 Targets[Darwin::IPhoneOS] = Targets[Darwin::WatchOS] = 1895 Targets[Darwin::TvOS] = ""; 1896 } else { 1897 // Don't allow conflicts in any other platform. 1898 unsigned FirstTarget = std::size(Targets); 1899 for (unsigned I = 0; I != std::size(Targets); ++I) { 1900 if (Targets[I].empty()) 1901 continue; 1902 if (FirstTarget == std::size(Targets)) 1903 FirstTarget = I; 1904 else 1905 TheDriver.Diag(diag::err_drv_conflicting_deployment_targets) 1906 << Targets[FirstTarget] << Targets[I]; 1907 } 1908 } 1909 1910 for (const auto &Target : llvm::enumerate(llvm::ArrayRef(Targets))) { 1911 if (!Target.value().empty()) 1912 return DarwinPlatform::createDeploymentTargetEnv( 1913 (Darwin::DarwinPlatformKind)Target.index(), EnvVars[Target.index()], 1914 Target.value()); 1915 } 1916 return std::nullopt; 1917 } 1918 1919 /// Returns the SDK name without the optional prefix that ends with a '.' or an 1920 /// empty string otherwise. 1921 static StringRef dropSDKNamePrefix(StringRef SDKName) { 1922 size_t PrefixPos = SDKName.find('.'); 1923 if (PrefixPos == StringRef::npos) 1924 return ""; 1925 return SDKName.substr(PrefixPos + 1); 1926 } 1927 1928 /// Tries to infer the deployment target from the SDK specified by -isysroot 1929 /// (or SDKROOT). Uses the version specified in the SDKSettings.json file if 1930 /// it's available. 1931 std::optional<DarwinPlatform> 1932 inferDeploymentTargetFromSDK(DerivedArgList &Args, 1933 const std::optional<DarwinSDKInfo> &SDKInfo) { 1934 const Arg *A = Args.getLastArg(options::OPT_isysroot); 1935 if (!A) 1936 return std::nullopt; 1937 StringRef isysroot = A->getValue(); 1938 StringRef SDK = Darwin::getSDKName(isysroot); 1939 if (!SDK.size()) 1940 return std::nullopt; 1941 1942 std::string Version; 1943 if (SDKInfo) { 1944 // Get the version from the SDKSettings.json if it's available. 1945 Version = SDKInfo->getVersion().getAsString(); 1946 } else { 1947 // Slice the version number out. 1948 // Version number is between the first and the last number. 1949 size_t StartVer = SDK.find_first_of("0123456789"); 1950 size_t EndVer = SDK.find_last_of("0123456789"); 1951 if (StartVer != StringRef::npos && EndVer > StartVer) 1952 Version = std::string(SDK.slice(StartVer, EndVer + 1)); 1953 } 1954 if (Version.empty()) 1955 return std::nullopt; 1956 1957 auto CreatePlatformFromSDKName = 1958 [&](StringRef SDK) -> std::optional<DarwinPlatform> { 1959 if (SDK.startswith("iPhoneOS") || SDK.startswith("iPhoneSimulator")) 1960 return DarwinPlatform::createFromSDK( 1961 Darwin::IPhoneOS, Version, 1962 /*IsSimulator=*/SDK.startswith("iPhoneSimulator")); 1963 else if (SDK.startswith("MacOSX")) 1964 return DarwinPlatform::createFromSDK(Darwin::MacOS, 1965 getSystemOrSDKMacOSVersion(Version)); 1966 else if (SDK.startswith("WatchOS") || SDK.startswith("WatchSimulator")) 1967 return DarwinPlatform::createFromSDK( 1968 Darwin::WatchOS, Version, 1969 /*IsSimulator=*/SDK.startswith("WatchSimulator")); 1970 else if (SDK.startswith("AppleTVOS") || SDK.startswith("AppleTVSimulator")) 1971 return DarwinPlatform::createFromSDK( 1972 Darwin::TvOS, Version, 1973 /*IsSimulator=*/SDK.startswith("AppleTVSimulator")); 1974 else if (SDK.startswith("DriverKit")) 1975 return DarwinPlatform::createFromSDK(Darwin::DriverKit, Version); 1976 return std::nullopt; 1977 }; 1978 if (auto Result = CreatePlatformFromSDKName(SDK)) 1979 return Result; 1980 // The SDK can be an SDK variant with a name like `<prefix>.<platform>`. 1981 return CreatePlatformFromSDKName(dropSDKNamePrefix(SDK)); 1982 } 1983 1984 std::string getOSVersion(llvm::Triple::OSType OS, const llvm::Triple &Triple, 1985 const Driver &TheDriver) { 1986 VersionTuple OsVersion; 1987 llvm::Triple SystemTriple(llvm::sys::getProcessTriple()); 1988 switch (OS) { 1989 case llvm::Triple::Darwin: 1990 case llvm::Triple::MacOSX: 1991 // If there is no version specified on triple, and both host and target are 1992 // macos, use the host triple to infer OS version. 1993 if (Triple.isMacOSX() && SystemTriple.isMacOSX() && 1994 !Triple.getOSMajorVersion()) 1995 SystemTriple.getMacOSXVersion(OsVersion); 1996 else if (!Triple.getMacOSXVersion(OsVersion)) 1997 TheDriver.Diag(diag::err_drv_invalid_darwin_version) 1998 << Triple.getOSName(); 1999 break; 2000 case llvm::Triple::IOS: 2001 if (Triple.isMacCatalystEnvironment() && !Triple.getOSMajorVersion()) { 2002 OsVersion = VersionTuple(13, 1); 2003 } else 2004 OsVersion = Triple.getiOSVersion(); 2005 break; 2006 case llvm::Triple::TvOS: 2007 OsVersion = Triple.getOSVersion(); 2008 break; 2009 case llvm::Triple::WatchOS: 2010 OsVersion = Triple.getWatchOSVersion(); 2011 break; 2012 case llvm::Triple::DriverKit: 2013 OsVersion = Triple.getDriverKitVersion(); 2014 break; 2015 default: 2016 llvm_unreachable("Unexpected OS type"); 2017 break; 2018 } 2019 2020 std::string OSVersion; 2021 llvm::raw_string_ostream(OSVersion) 2022 << OsVersion.getMajor() << '.' << OsVersion.getMinor().value_or(0) << '.' 2023 << OsVersion.getSubminor().value_or(0); 2024 return OSVersion; 2025 } 2026 2027 /// Tries to infer the target OS from the -arch. 2028 std::optional<DarwinPlatform> 2029 inferDeploymentTargetFromArch(DerivedArgList &Args, const Darwin &Toolchain, 2030 const llvm::Triple &Triple, 2031 const Driver &TheDriver) { 2032 llvm::Triple::OSType OSTy = llvm::Triple::UnknownOS; 2033 2034 StringRef MachOArchName = Toolchain.getMachOArchName(Args); 2035 if (MachOArchName == "arm64" || MachOArchName == "arm64e") 2036 OSTy = llvm::Triple::MacOSX; 2037 else if (MachOArchName == "armv7" || MachOArchName == "armv7s") 2038 OSTy = llvm::Triple::IOS; 2039 else if (MachOArchName == "armv7k" || MachOArchName == "arm64_32") 2040 OSTy = llvm::Triple::WatchOS; 2041 else if (MachOArchName != "armv6m" && MachOArchName != "armv7m" && 2042 MachOArchName != "armv7em") 2043 OSTy = llvm::Triple::MacOSX; 2044 if (OSTy == llvm::Triple::UnknownOS) 2045 return std::nullopt; 2046 return DarwinPlatform::createFromArch(OSTy, 2047 getOSVersion(OSTy, Triple, TheDriver)); 2048 } 2049 2050 /// Returns the deployment target that's specified using the -target option. 2051 std::optional<DarwinPlatform> getDeploymentTargetFromTargetArg( 2052 DerivedArgList &Args, const llvm::Triple &Triple, const Driver &TheDriver, 2053 const std::optional<DarwinSDKInfo> &SDKInfo) { 2054 if (!Args.hasArg(options::OPT_target)) 2055 return std::nullopt; 2056 if (Triple.getOS() == llvm::Triple::Darwin || 2057 Triple.getOS() == llvm::Triple::UnknownOS) 2058 return std::nullopt; 2059 std::string OSVersion = getOSVersion(Triple.getOS(), Triple, TheDriver); 2060 std::optional<llvm::Triple> TargetVariantTriple; 2061 for (const Arg *A : Args.filtered(options::OPT_darwin_target_variant)) { 2062 llvm::Triple TVT(A->getValue()); 2063 // Find a matching <arch>-<vendor> target variant triple that can be used. 2064 if ((Triple.getArch() == llvm::Triple::aarch64 || 2065 TVT.getArchName() == Triple.getArchName()) && 2066 TVT.getArch() == Triple.getArch() && 2067 TVT.getSubArch() == Triple.getSubArch() && 2068 TVT.getVendor() == Triple.getVendor()) { 2069 if (TargetVariantTriple) 2070 continue; 2071 A->claim(); 2072 // Accept a -target-variant triple when compiling code that may run on 2073 // macOS or Mac Catalust. 2074 if ((Triple.isMacOSX() && TVT.getOS() == llvm::Triple::IOS && 2075 TVT.isMacCatalystEnvironment()) || 2076 (TVT.isMacOSX() && Triple.getOS() == llvm::Triple::IOS && 2077 Triple.isMacCatalystEnvironment())) { 2078 TargetVariantTriple = TVT; 2079 continue; 2080 } 2081 TheDriver.Diag(diag::err_drv_target_variant_invalid) 2082 << A->getSpelling() << A->getValue(); 2083 } 2084 } 2085 return DarwinPlatform::createFromTarget(Triple, OSVersion, 2086 Args.getLastArg(options::OPT_target), 2087 TargetVariantTriple, SDKInfo); 2088 } 2089 2090 /// Returns the deployment target that's specified using the -mtargetos option. 2091 std::optional<DarwinPlatform> getDeploymentTargetFromMTargetOSArg( 2092 DerivedArgList &Args, const Driver &TheDriver, 2093 const std::optional<DarwinSDKInfo> &SDKInfo) { 2094 auto *A = Args.getLastArg(options::OPT_mtargetos_EQ); 2095 if (!A) 2096 return std::nullopt; 2097 llvm::Triple TT(llvm::Twine("unknown-apple-") + A->getValue()); 2098 switch (TT.getOS()) { 2099 case llvm::Triple::MacOSX: 2100 case llvm::Triple::IOS: 2101 case llvm::Triple::TvOS: 2102 case llvm::Triple::WatchOS: 2103 break; 2104 default: 2105 TheDriver.Diag(diag::err_drv_invalid_os_in_arg) 2106 << TT.getOSName() << A->getAsString(Args); 2107 return std::nullopt; 2108 } 2109 2110 VersionTuple Version = TT.getOSVersion(); 2111 if (!Version.getMajor()) { 2112 TheDriver.Diag(diag::err_drv_invalid_version_number) 2113 << A->getAsString(Args); 2114 return std::nullopt; 2115 } 2116 return DarwinPlatform::createFromMTargetOS(TT.getOS(), Version, 2117 TT.getEnvironment(), A, SDKInfo); 2118 } 2119 2120 std::optional<DarwinSDKInfo> parseSDKSettings(llvm::vfs::FileSystem &VFS, 2121 const ArgList &Args, 2122 const Driver &TheDriver) { 2123 const Arg *A = Args.getLastArg(options::OPT_isysroot); 2124 if (!A) 2125 return std::nullopt; 2126 StringRef isysroot = A->getValue(); 2127 auto SDKInfoOrErr = parseDarwinSDKInfo(VFS, isysroot); 2128 if (!SDKInfoOrErr) { 2129 llvm::consumeError(SDKInfoOrErr.takeError()); 2130 TheDriver.Diag(diag::warn_drv_darwin_sdk_invalid_settings); 2131 return std::nullopt; 2132 } 2133 return *SDKInfoOrErr; 2134 } 2135 2136 } // namespace 2137 2138 void Darwin::AddDeploymentTarget(DerivedArgList &Args) const { 2139 const OptTable &Opts = getDriver().getOpts(); 2140 2141 // Support allowing the SDKROOT environment variable used by xcrun and other 2142 // Xcode tools to define the default sysroot, by making it the default for 2143 // isysroot. 2144 if (const Arg *A = Args.getLastArg(options::OPT_isysroot)) { 2145 // Warn if the path does not exist. 2146 if (!getVFS().exists(A->getValue())) 2147 getDriver().Diag(clang::diag::warn_missing_sysroot) << A->getValue(); 2148 } else { 2149 if (char *env = ::getenv("SDKROOT")) { 2150 // We only use this value as the default if it is an absolute path, 2151 // exists, and it is not the root path. 2152 if (llvm::sys::path::is_absolute(env) && getVFS().exists(env) && 2153 StringRef(env) != "/") { 2154 Args.append(Args.MakeSeparateArg( 2155 nullptr, Opts.getOption(options::OPT_isysroot), env)); 2156 } 2157 } 2158 } 2159 2160 // Read the SDKSettings.json file for more information, like the SDK version 2161 // that we can pass down to the compiler. 2162 SDKInfo = parseSDKSettings(getVFS(), Args, getDriver()); 2163 2164 // The OS and the version can be specified using the -target argument. 2165 std::optional<DarwinPlatform> OSTarget = 2166 getDeploymentTargetFromTargetArg(Args, getTriple(), getDriver(), SDKInfo); 2167 if (OSTarget) { 2168 // Disallow mixing -target and -mtargetos=. 2169 if (const auto *MTargetOSArg = Args.getLastArg(options::OPT_mtargetos_EQ)) { 2170 std::string TargetArgStr = OSTarget->getAsString(Args, Opts); 2171 std::string MTargetOSArgStr = MTargetOSArg->getAsString(Args); 2172 getDriver().Diag(diag::err_drv_cannot_mix_options) 2173 << TargetArgStr << MTargetOSArgStr; 2174 } 2175 std::optional<DarwinPlatform> OSVersionArgTarget = 2176 getDeploymentTargetFromOSVersionArg(Args, getDriver()); 2177 if (OSVersionArgTarget) { 2178 unsigned TargetMajor, TargetMinor, TargetMicro; 2179 bool TargetExtra; 2180 unsigned ArgMajor, ArgMinor, ArgMicro; 2181 bool ArgExtra; 2182 if (OSTarget->getPlatform() != OSVersionArgTarget->getPlatform() || 2183 (Driver::GetReleaseVersion(OSTarget->getOSVersion(), TargetMajor, 2184 TargetMinor, TargetMicro, TargetExtra) && 2185 Driver::GetReleaseVersion(OSVersionArgTarget->getOSVersion(), 2186 ArgMajor, ArgMinor, ArgMicro, ArgExtra) && 2187 (VersionTuple(TargetMajor, TargetMinor, TargetMicro) != 2188 VersionTuple(ArgMajor, ArgMinor, ArgMicro) || 2189 TargetExtra != ArgExtra))) { 2190 // Select the OS version from the -m<os>-version-min argument when 2191 // the -target does not include an OS version. 2192 if (OSTarget->getPlatform() == OSVersionArgTarget->getPlatform() && 2193 !OSTarget->hasOSVersion()) { 2194 OSTarget->setOSVersion(OSVersionArgTarget->getOSVersion()); 2195 } else { 2196 // Warn about -m<os>-version-min that doesn't match the OS version 2197 // that's specified in the target. 2198 std::string OSVersionArg = 2199 OSVersionArgTarget->getAsString(Args, Opts); 2200 std::string TargetArg = OSTarget->getAsString(Args, Opts); 2201 getDriver().Diag(clang::diag::warn_drv_overriding_flag_option) 2202 << OSVersionArg << TargetArg; 2203 } 2204 } 2205 } 2206 } else if ((OSTarget = getDeploymentTargetFromMTargetOSArg(Args, getDriver(), 2207 SDKInfo))) { 2208 // The OS target can be specified using the -mtargetos= argument. 2209 // Disallow mixing -mtargetos= and -m<os>version-min=. 2210 std::optional<DarwinPlatform> OSVersionArgTarget = 2211 getDeploymentTargetFromOSVersionArg(Args, getDriver()); 2212 if (OSVersionArgTarget) { 2213 std::string MTargetOSArgStr = OSTarget->getAsString(Args, Opts); 2214 std::string OSVersionArgStr = OSVersionArgTarget->getAsString(Args, Opts); 2215 getDriver().Diag(diag::err_drv_cannot_mix_options) 2216 << MTargetOSArgStr << OSVersionArgStr; 2217 } 2218 } else { 2219 // The OS target can be specified using the -m<os>version-min argument. 2220 OSTarget = getDeploymentTargetFromOSVersionArg(Args, getDriver()); 2221 // If no deployment target was specified on the command line, check for 2222 // environment defines. 2223 if (!OSTarget) { 2224 OSTarget = 2225 getDeploymentTargetFromEnvironmentVariables(getDriver(), getTriple()); 2226 if (OSTarget) { 2227 // Don't infer simulator from the arch when the SDK is also specified. 2228 std::optional<DarwinPlatform> SDKTarget = 2229 inferDeploymentTargetFromSDK(Args, SDKInfo); 2230 if (SDKTarget) 2231 OSTarget->setEnvironment(SDKTarget->getEnvironment()); 2232 } 2233 } 2234 // If there is no command-line argument to specify the Target version and 2235 // no environment variable defined, see if we can set the default based 2236 // on -isysroot using SDKSettings.json if it exists. 2237 if (!OSTarget) { 2238 OSTarget = inferDeploymentTargetFromSDK(Args, SDKInfo); 2239 /// If the target was successfully constructed from the SDK path, try to 2240 /// infer the SDK info if the SDK doesn't have it. 2241 if (OSTarget && !SDKInfo) 2242 SDKInfo = OSTarget->inferSDKInfo(); 2243 } 2244 // If no OS targets have been specified, try to guess platform from -target 2245 // or arch name and compute the version from the triple. 2246 if (!OSTarget) 2247 OSTarget = 2248 inferDeploymentTargetFromArch(Args, *this, getTriple(), getDriver()); 2249 } 2250 2251 assert(OSTarget && "Unable to infer Darwin variant"); 2252 OSTarget->addOSVersionMinArgument(Args, Opts); 2253 DarwinPlatformKind Platform = OSTarget->getPlatform(); 2254 2255 unsigned Major, Minor, Micro; 2256 bool HadExtra; 2257 // The major version should not be over this number. 2258 const unsigned MajorVersionLimit = 1000; 2259 // Set the tool chain target information. 2260 if (Platform == MacOS) { 2261 if (!Driver::GetReleaseVersion(OSTarget->getOSVersion(), Major, Minor, 2262 Micro, HadExtra) || 2263 HadExtra || Major < 10 || Major >= MajorVersionLimit || Minor >= 100 || 2264 Micro >= 100) 2265 getDriver().Diag(diag::err_drv_invalid_version_number) 2266 << OSTarget->getAsString(Args, Opts); 2267 } else if (Platform == IPhoneOS) { 2268 if (!Driver::GetReleaseVersion(OSTarget->getOSVersion(), Major, Minor, 2269 Micro, HadExtra) || 2270 HadExtra || Major >= MajorVersionLimit || Minor >= 100 || Micro >= 100) 2271 getDriver().Diag(diag::err_drv_invalid_version_number) 2272 << OSTarget->getAsString(Args, Opts); 2273 ; 2274 if (OSTarget->getEnvironment() == MacCatalyst && 2275 (Major < 13 || (Major == 13 && Minor < 1))) { 2276 getDriver().Diag(diag::err_drv_invalid_version_number) 2277 << OSTarget->getAsString(Args, Opts); 2278 Major = 13; 2279 Minor = 1; 2280 Micro = 0; 2281 } 2282 // For 32-bit targets, the deployment target for iOS has to be earlier than 2283 // iOS 11. 2284 if (getTriple().isArch32Bit() && Major >= 11) { 2285 // If the deployment target is explicitly specified, print a diagnostic. 2286 if (OSTarget->isExplicitlySpecified()) { 2287 if (OSTarget->getEnvironment() == MacCatalyst) 2288 getDriver().Diag(diag::err_invalid_macos_32bit_deployment_target); 2289 else 2290 getDriver().Diag(diag::warn_invalid_ios_deployment_target) 2291 << OSTarget->getAsString(Args, Opts); 2292 // Otherwise, set it to 10.99.99. 2293 } else { 2294 Major = 10; 2295 Minor = 99; 2296 Micro = 99; 2297 } 2298 } 2299 } else if (Platform == TvOS) { 2300 if (!Driver::GetReleaseVersion(OSTarget->getOSVersion(), Major, Minor, 2301 Micro, HadExtra) || 2302 HadExtra || Major >= MajorVersionLimit || Minor >= 100 || Micro >= 100) 2303 getDriver().Diag(diag::err_drv_invalid_version_number) 2304 << OSTarget->getAsString(Args, Opts); 2305 } else if (Platform == WatchOS) { 2306 if (!Driver::GetReleaseVersion(OSTarget->getOSVersion(), Major, Minor, 2307 Micro, HadExtra) || 2308 HadExtra || Major >= MajorVersionLimit || Minor >= 100 || Micro >= 100) 2309 getDriver().Diag(diag::err_drv_invalid_version_number) 2310 << OSTarget->getAsString(Args, Opts); 2311 } else if (Platform == DriverKit) { 2312 if (!Driver::GetReleaseVersion(OSTarget->getOSVersion(), Major, Minor, 2313 Micro, HadExtra) || 2314 HadExtra || Major < 19 || Major >= MajorVersionLimit || Minor >= 100 || 2315 Micro >= 100) 2316 getDriver().Diag(diag::err_drv_invalid_version_number) 2317 << OSTarget->getAsString(Args, Opts); 2318 } else 2319 llvm_unreachable("unknown kind of Darwin platform"); 2320 2321 DarwinEnvironmentKind Environment = OSTarget->getEnvironment(); 2322 // Recognize iOS targets with an x86 architecture as the iOS simulator. 2323 if (Environment == NativeEnvironment && Platform != MacOS && 2324 Platform != DriverKit && OSTarget->canInferSimulatorFromArch() && 2325 getTriple().isX86()) 2326 Environment = Simulator; 2327 2328 VersionTuple NativeTargetVersion; 2329 if (Environment == MacCatalyst) 2330 NativeTargetVersion = OSTarget->getNativeTargetVersion(); 2331 setTarget(Platform, Environment, Major, Minor, Micro, NativeTargetVersion); 2332 TargetVariantTriple = OSTarget->getTargetVariantTriple(); 2333 2334 if (const Arg *A = Args.getLastArg(options::OPT_isysroot)) { 2335 StringRef SDK = getSDKName(A->getValue()); 2336 if (SDK.size() > 0) { 2337 size_t StartVer = SDK.find_first_of("0123456789"); 2338 StringRef SDKName = SDK.slice(0, StartVer); 2339 if (!SDKName.startswith(getPlatformFamily()) && 2340 !dropSDKNamePrefix(SDKName).startswith(getPlatformFamily())) 2341 getDriver().Diag(diag::warn_incompatible_sysroot) 2342 << SDKName << getPlatformFamily(); 2343 } 2344 } 2345 } 2346 2347 // For certain platforms/environments almost all resources (e.g., headers) are 2348 // located in sub-directories, e.g., for DriverKit they live in 2349 // <SYSROOT>/System/DriverKit/usr/include (instead of <SYSROOT>/usr/include). 2350 static void AppendPlatformPrefix(SmallString<128> &Path, 2351 const llvm::Triple &T) { 2352 if (T.isDriverKit()) { 2353 llvm::sys::path::append(Path, "System", "DriverKit"); 2354 } 2355 } 2356 2357 // Returns the effective sysroot from either -isysroot or --sysroot, plus the 2358 // platform prefix (if any). 2359 llvm::SmallString<128> 2360 DarwinClang::GetEffectiveSysroot(const llvm::opt::ArgList &DriverArgs) const { 2361 llvm::SmallString<128> Path("/"); 2362 if (DriverArgs.hasArg(options::OPT_isysroot)) 2363 Path = DriverArgs.getLastArgValue(options::OPT_isysroot); 2364 else if (!getDriver().SysRoot.empty()) 2365 Path = getDriver().SysRoot; 2366 2367 if (hasEffectiveTriple()) { 2368 AppendPlatformPrefix(Path, getEffectiveTriple()); 2369 } 2370 return Path; 2371 } 2372 2373 void DarwinClang::AddClangSystemIncludeArgs(const llvm::opt::ArgList &DriverArgs, 2374 llvm::opt::ArgStringList &CC1Args) const { 2375 const Driver &D = getDriver(); 2376 2377 llvm::SmallString<128> Sysroot = GetEffectiveSysroot(DriverArgs); 2378 2379 bool NoStdInc = DriverArgs.hasArg(options::OPT_nostdinc); 2380 bool NoStdlibInc = DriverArgs.hasArg(options::OPT_nostdlibinc); 2381 bool NoBuiltinInc = DriverArgs.hasFlag( 2382 options::OPT_nobuiltininc, options::OPT_ibuiltininc, /*Default=*/false); 2383 bool ForceBuiltinInc = DriverArgs.hasFlag( 2384 options::OPT_ibuiltininc, options::OPT_nobuiltininc, /*Default=*/false); 2385 2386 // Add <sysroot>/usr/local/include 2387 if (!NoStdInc && !NoStdlibInc) { 2388 SmallString<128> P(Sysroot); 2389 llvm::sys::path::append(P, "usr", "local", "include"); 2390 addSystemInclude(DriverArgs, CC1Args, P); 2391 } 2392 2393 // Add the Clang builtin headers (<resource>/include) 2394 if (!(NoStdInc && !ForceBuiltinInc) && !NoBuiltinInc) { 2395 SmallString<128> P(D.ResourceDir); 2396 llvm::sys::path::append(P, "include"); 2397 addSystemInclude(DriverArgs, CC1Args, P); 2398 } 2399 2400 if (NoStdInc || NoStdlibInc) 2401 return; 2402 2403 // Check for configure-time C include directories. 2404 llvm::StringRef CIncludeDirs(C_INCLUDE_DIRS); 2405 if (!CIncludeDirs.empty()) { 2406 llvm::SmallVector<llvm::StringRef, 5> dirs; 2407 CIncludeDirs.split(dirs, ":"); 2408 for (llvm::StringRef dir : dirs) { 2409 llvm::StringRef Prefix = 2410 llvm::sys::path::is_absolute(dir) ? "" : llvm::StringRef(Sysroot); 2411 addExternCSystemInclude(DriverArgs, CC1Args, Prefix + dir); 2412 } 2413 } else { 2414 // Otherwise, add <sysroot>/usr/include. 2415 SmallString<128> P(Sysroot); 2416 llvm::sys::path::append(P, "usr", "include"); 2417 addExternCSystemInclude(DriverArgs, CC1Args, P.str()); 2418 } 2419 } 2420 2421 bool DarwinClang::AddGnuCPlusPlusIncludePaths(const llvm::opt::ArgList &DriverArgs, 2422 llvm::opt::ArgStringList &CC1Args, 2423 llvm::SmallString<128> Base, 2424 llvm::StringRef Version, 2425 llvm::StringRef ArchDir, 2426 llvm::StringRef BitDir) const { 2427 llvm::sys::path::append(Base, Version); 2428 2429 // Add the base dir 2430 addSystemInclude(DriverArgs, CC1Args, Base); 2431 2432 // Add the multilib dirs 2433 { 2434 llvm::SmallString<128> P = Base; 2435 if (!ArchDir.empty()) 2436 llvm::sys::path::append(P, ArchDir); 2437 if (!BitDir.empty()) 2438 llvm::sys::path::append(P, BitDir); 2439 addSystemInclude(DriverArgs, CC1Args, P); 2440 } 2441 2442 // Add the backward dir 2443 { 2444 llvm::SmallString<128> P = Base; 2445 llvm::sys::path::append(P, "backward"); 2446 addSystemInclude(DriverArgs, CC1Args, P); 2447 } 2448 2449 return getVFS().exists(Base); 2450 } 2451 2452 void DarwinClang::AddClangCXXStdlibIncludeArgs( 2453 const llvm::opt::ArgList &DriverArgs, 2454 llvm::opt::ArgStringList &CC1Args) const { 2455 // The implementation from a base class will pass through the -stdlib to 2456 // CC1Args. 2457 // FIXME: this should not be necessary, remove usages in the frontend 2458 // (e.g. HeaderSearchOptions::UseLibcxx) and don't pipe -stdlib. 2459 // Also check whether this is used for setting library search paths. 2460 ToolChain::AddClangCXXStdlibIncludeArgs(DriverArgs, CC1Args); 2461 2462 if (DriverArgs.hasArg(options::OPT_nostdinc, options::OPT_nostdlibinc, 2463 options::OPT_nostdincxx)) 2464 return; 2465 2466 llvm::SmallString<128> Sysroot = GetEffectiveSysroot(DriverArgs); 2467 2468 switch (GetCXXStdlibType(DriverArgs)) { 2469 case ToolChain::CST_Libcxx: { 2470 // On Darwin, libc++ can be installed in one of the following two places: 2471 // 1. Alongside the compiler in <install>/include/c++/v1 2472 // 2. In a SDK (or a custom sysroot) in <sysroot>/usr/include/c++/v1 2473 // 2474 // The precendence of paths is as listed above, i.e. we take the first path 2475 // that exists. Also note that we never include libc++ twice -- we take the 2476 // first path that exists and don't send the other paths to CC1 (otherwise 2477 // include_next could break). 2478 2479 // Check for (1) 2480 // Get from '<install>/bin' to '<install>/include/c++/v1'. 2481 // Note that InstallBin can be relative, so we use '..' instead of 2482 // parent_path. 2483 llvm::SmallString<128> InstallBin = 2484 llvm::StringRef(getDriver().getInstalledDir()); // <install>/bin 2485 llvm::sys::path::append(InstallBin, "..", "include", "c++", "v1"); 2486 if (getVFS().exists(InstallBin)) { 2487 addSystemInclude(DriverArgs, CC1Args, InstallBin); 2488 return; 2489 } else if (DriverArgs.hasArg(options::OPT_v)) { 2490 llvm::errs() << "ignoring nonexistent directory \"" << InstallBin 2491 << "\"\n"; 2492 } 2493 2494 // Otherwise, check for (2) 2495 llvm::SmallString<128> SysrootUsr = Sysroot; 2496 llvm::sys::path::append(SysrootUsr, "usr", "include", "c++", "v1"); 2497 if (getVFS().exists(SysrootUsr)) { 2498 addSystemInclude(DriverArgs, CC1Args, SysrootUsr); 2499 return; 2500 } else if (DriverArgs.hasArg(options::OPT_v)) { 2501 llvm::errs() << "ignoring nonexistent directory \"" << SysrootUsr 2502 << "\"\n"; 2503 } 2504 2505 // Otherwise, don't add any path. 2506 break; 2507 } 2508 2509 case ToolChain::CST_Libstdcxx: 2510 llvm::SmallString<128> UsrIncludeCxx = Sysroot; 2511 llvm::sys::path::append(UsrIncludeCxx, "usr", "include", "c++"); 2512 2513 llvm::Triple::ArchType arch = getTriple().getArch(); 2514 bool IsBaseFound = true; 2515 switch (arch) { 2516 default: break; 2517 2518 case llvm::Triple::x86: 2519 case llvm::Triple::x86_64: 2520 IsBaseFound = AddGnuCPlusPlusIncludePaths(DriverArgs, CC1Args, UsrIncludeCxx, 2521 "4.2.1", 2522 "i686-apple-darwin10", 2523 arch == llvm::Triple::x86_64 ? "x86_64" : ""); 2524 IsBaseFound |= AddGnuCPlusPlusIncludePaths(DriverArgs, CC1Args, UsrIncludeCxx, 2525 "4.0.0", "i686-apple-darwin8", 2526 ""); 2527 break; 2528 2529 case llvm::Triple::arm: 2530 case llvm::Triple::thumb: 2531 IsBaseFound = AddGnuCPlusPlusIncludePaths(DriverArgs, CC1Args, UsrIncludeCxx, 2532 "4.2.1", 2533 "arm-apple-darwin10", 2534 "v7"); 2535 IsBaseFound |= AddGnuCPlusPlusIncludePaths(DriverArgs, CC1Args, UsrIncludeCxx, 2536 "4.2.1", 2537 "arm-apple-darwin10", 2538 "v6"); 2539 break; 2540 2541 case llvm::Triple::aarch64: 2542 IsBaseFound = AddGnuCPlusPlusIncludePaths(DriverArgs, CC1Args, UsrIncludeCxx, 2543 "4.2.1", 2544 "arm64-apple-darwin10", 2545 ""); 2546 break; 2547 } 2548 2549 if (!IsBaseFound) { 2550 getDriver().Diag(diag::warn_drv_libstdcxx_not_found); 2551 } 2552 2553 break; 2554 } 2555 } 2556 2557 void DarwinClang::AddCXXStdlibLibArgs(const ArgList &Args, 2558 ArgStringList &CmdArgs) const { 2559 CXXStdlibType Type = GetCXXStdlibType(Args); 2560 2561 switch (Type) { 2562 case ToolChain::CST_Libcxx: 2563 CmdArgs.push_back("-lc++"); 2564 if (Args.hasArg(options::OPT_fexperimental_library)) 2565 CmdArgs.push_back("-lc++experimental"); 2566 break; 2567 2568 case ToolChain::CST_Libstdcxx: 2569 // Unfortunately, -lstdc++ doesn't always exist in the standard search path; 2570 // it was previously found in the gcc lib dir. However, for all the Darwin 2571 // platforms we care about it was -lstdc++.6, so we search for that 2572 // explicitly if we can't see an obvious -lstdc++ candidate. 2573 2574 // Check in the sysroot first. 2575 if (const Arg *A = Args.getLastArg(options::OPT_isysroot)) { 2576 SmallString<128> P(A->getValue()); 2577 llvm::sys::path::append(P, "usr", "lib", "libstdc++.dylib"); 2578 2579 if (!getVFS().exists(P)) { 2580 llvm::sys::path::remove_filename(P); 2581 llvm::sys::path::append(P, "libstdc++.6.dylib"); 2582 if (getVFS().exists(P)) { 2583 CmdArgs.push_back(Args.MakeArgString(P)); 2584 return; 2585 } 2586 } 2587 } 2588 2589 // Otherwise, look in the root. 2590 // FIXME: This should be removed someday when we don't have to care about 2591 // 10.6 and earlier, where /usr/lib/libstdc++.dylib does not exist. 2592 if (!getVFS().exists("/usr/lib/libstdc++.dylib") && 2593 getVFS().exists("/usr/lib/libstdc++.6.dylib")) { 2594 CmdArgs.push_back("/usr/lib/libstdc++.6.dylib"); 2595 return; 2596 } 2597 2598 // Otherwise, let the linker search. 2599 CmdArgs.push_back("-lstdc++"); 2600 break; 2601 } 2602 } 2603 2604 void DarwinClang::AddCCKextLibArgs(const ArgList &Args, 2605 ArgStringList &CmdArgs) const { 2606 // For Darwin platforms, use the compiler-rt-based support library 2607 // instead of the gcc-provided one (which is also incidentally 2608 // only present in the gcc lib dir, which makes it hard to find). 2609 2610 SmallString<128> P(getDriver().ResourceDir); 2611 llvm::sys::path::append(P, "lib", "darwin"); 2612 2613 // Use the newer cc_kext for iOS ARM after 6.0. 2614 if (isTargetWatchOS()) { 2615 llvm::sys::path::append(P, "libclang_rt.cc_kext_watchos.a"); 2616 } else if (isTargetTvOS()) { 2617 llvm::sys::path::append(P, "libclang_rt.cc_kext_tvos.a"); 2618 } else if (isTargetIPhoneOS()) { 2619 llvm::sys::path::append(P, "libclang_rt.cc_kext_ios.a"); 2620 } else if (isTargetDriverKit()) { 2621 // DriverKit doesn't want extra runtime support. 2622 } else { 2623 llvm::sys::path::append(P, "libclang_rt.cc_kext.a"); 2624 } 2625 2626 // For now, allow missing resource libraries to support developers who may 2627 // not have compiler-rt checked out or integrated into their build. 2628 if (getVFS().exists(P)) 2629 CmdArgs.push_back(Args.MakeArgString(P)); 2630 } 2631 2632 DerivedArgList *MachO::TranslateArgs(const DerivedArgList &Args, 2633 StringRef BoundArch, 2634 Action::OffloadKind) const { 2635 DerivedArgList *DAL = new DerivedArgList(Args.getBaseArgs()); 2636 const OptTable &Opts = getDriver().getOpts(); 2637 2638 // FIXME: We really want to get out of the tool chain level argument 2639 // translation business, as it makes the driver functionality much 2640 // more opaque. For now, we follow gcc closely solely for the 2641 // purpose of easily achieving feature parity & testability. Once we 2642 // have something that works, we should reevaluate each translation 2643 // and try to push it down into tool specific logic. 2644 2645 for (Arg *A : Args) { 2646 if (A->getOption().matches(options::OPT_Xarch__)) { 2647 // Skip this argument unless the architecture matches either the toolchain 2648 // triple arch, or the arch being bound. 2649 StringRef XarchArch = A->getValue(0); 2650 if (!(XarchArch == getArchName() || 2651 (!BoundArch.empty() && XarchArch == BoundArch))) 2652 continue; 2653 2654 Arg *OriginalArg = A; 2655 TranslateXarchArgs(Args, A, DAL); 2656 2657 // Linker input arguments require custom handling. The problem is that we 2658 // have already constructed the phase actions, so we can not treat them as 2659 // "input arguments". 2660 if (A->getOption().hasFlag(options::LinkerInput)) { 2661 // Convert the argument into individual Zlinker_input_args. 2662 for (const char *Value : A->getValues()) { 2663 DAL->AddSeparateArg( 2664 OriginalArg, Opts.getOption(options::OPT_Zlinker_input), Value); 2665 } 2666 continue; 2667 } 2668 } 2669 2670 // Sob. These is strictly gcc compatible for the time being. Apple 2671 // gcc translates options twice, which means that self-expanding 2672 // options add duplicates. 2673 switch ((options::ID)A->getOption().getID()) { 2674 default: 2675 DAL->append(A); 2676 break; 2677 2678 case options::OPT_mkernel: 2679 case options::OPT_fapple_kext: 2680 DAL->append(A); 2681 DAL->AddFlagArg(A, Opts.getOption(options::OPT_static)); 2682 break; 2683 2684 case options::OPT_dependency_file: 2685 DAL->AddSeparateArg(A, Opts.getOption(options::OPT_MF), A->getValue()); 2686 break; 2687 2688 case options::OPT_gfull: 2689 DAL->AddFlagArg(A, Opts.getOption(options::OPT_g_Flag)); 2690 DAL->AddFlagArg( 2691 A, Opts.getOption(options::OPT_fno_eliminate_unused_debug_symbols)); 2692 break; 2693 2694 case options::OPT_gused: 2695 DAL->AddFlagArg(A, Opts.getOption(options::OPT_g_Flag)); 2696 DAL->AddFlagArg( 2697 A, Opts.getOption(options::OPT_feliminate_unused_debug_symbols)); 2698 break; 2699 2700 case options::OPT_shared: 2701 DAL->AddFlagArg(A, Opts.getOption(options::OPT_dynamiclib)); 2702 break; 2703 2704 case options::OPT_fconstant_cfstrings: 2705 DAL->AddFlagArg(A, Opts.getOption(options::OPT_mconstant_cfstrings)); 2706 break; 2707 2708 case options::OPT_fno_constant_cfstrings: 2709 DAL->AddFlagArg(A, Opts.getOption(options::OPT_mno_constant_cfstrings)); 2710 break; 2711 2712 case options::OPT_Wnonportable_cfstrings: 2713 DAL->AddFlagArg(A, 2714 Opts.getOption(options::OPT_mwarn_nonportable_cfstrings)); 2715 break; 2716 2717 case options::OPT_Wno_nonportable_cfstrings: 2718 DAL->AddFlagArg( 2719 A, Opts.getOption(options::OPT_mno_warn_nonportable_cfstrings)); 2720 break; 2721 } 2722 } 2723 2724 // Add the arch options based on the particular spelling of -arch, to match 2725 // how the driver works. 2726 if (!BoundArch.empty()) { 2727 StringRef Name = BoundArch; 2728 const Option MCpu = Opts.getOption(options::OPT_mcpu_EQ); 2729 const Option MArch = Opts.getOption(clang::driver::options::OPT_march_EQ); 2730 2731 // This code must be kept in sync with LLVM's getArchTypeForDarwinArch, 2732 // which defines the list of which architectures we accept. 2733 if (Name == "ppc") 2734 ; 2735 else if (Name == "ppc601") 2736 DAL->AddJoinedArg(nullptr, MCpu, "601"); 2737 else if (Name == "ppc603") 2738 DAL->AddJoinedArg(nullptr, MCpu, "603"); 2739 else if (Name == "ppc604") 2740 DAL->AddJoinedArg(nullptr, MCpu, "604"); 2741 else if (Name == "ppc604e") 2742 DAL->AddJoinedArg(nullptr, MCpu, "604e"); 2743 else if (Name == "ppc750") 2744 DAL->AddJoinedArg(nullptr, MCpu, "750"); 2745 else if (Name == "ppc7400") 2746 DAL->AddJoinedArg(nullptr, MCpu, "7400"); 2747 else if (Name == "ppc7450") 2748 DAL->AddJoinedArg(nullptr, MCpu, "7450"); 2749 else if (Name == "ppc970") 2750 DAL->AddJoinedArg(nullptr, MCpu, "970"); 2751 2752 else if (Name == "ppc64" || Name == "ppc64le") 2753 DAL->AddFlagArg(nullptr, Opts.getOption(options::OPT_m64)); 2754 2755 else if (Name == "i386") 2756 ; 2757 else if (Name == "i486") 2758 DAL->AddJoinedArg(nullptr, MArch, "i486"); 2759 else if (Name == "i586") 2760 DAL->AddJoinedArg(nullptr, MArch, "i586"); 2761 else if (Name == "i686") 2762 DAL->AddJoinedArg(nullptr, MArch, "i686"); 2763 else if (Name == "pentium") 2764 DAL->AddJoinedArg(nullptr, MArch, "pentium"); 2765 else if (Name == "pentium2") 2766 DAL->AddJoinedArg(nullptr, MArch, "pentium2"); 2767 else if (Name == "pentpro") 2768 DAL->AddJoinedArg(nullptr, MArch, "pentiumpro"); 2769 else if (Name == "pentIIm3") 2770 DAL->AddJoinedArg(nullptr, MArch, "pentium2"); 2771 2772 else if (Name == "x86_64" || Name == "x86_64h") 2773 DAL->AddFlagArg(nullptr, Opts.getOption(options::OPT_m64)); 2774 2775 else if (Name == "arm") 2776 DAL->AddJoinedArg(nullptr, MArch, "armv4t"); 2777 else if (Name == "armv4t") 2778 DAL->AddJoinedArg(nullptr, MArch, "armv4t"); 2779 else if (Name == "armv5") 2780 DAL->AddJoinedArg(nullptr, MArch, "armv5tej"); 2781 else if (Name == "xscale") 2782 DAL->AddJoinedArg(nullptr, MArch, "xscale"); 2783 else if (Name == "armv6") 2784 DAL->AddJoinedArg(nullptr, MArch, "armv6k"); 2785 else if (Name == "armv6m") 2786 DAL->AddJoinedArg(nullptr, MArch, "armv6m"); 2787 else if (Name == "armv7") 2788 DAL->AddJoinedArg(nullptr, MArch, "armv7a"); 2789 else if (Name == "armv7em") 2790 DAL->AddJoinedArg(nullptr, MArch, "armv7em"); 2791 else if (Name == "armv7k") 2792 DAL->AddJoinedArg(nullptr, MArch, "armv7k"); 2793 else if (Name == "armv7m") 2794 DAL->AddJoinedArg(nullptr, MArch, "armv7m"); 2795 else if (Name == "armv7s") 2796 DAL->AddJoinedArg(nullptr, MArch, "armv7s"); 2797 } 2798 2799 return DAL; 2800 } 2801 2802 void MachO::AddLinkRuntimeLibArgs(const ArgList &Args, 2803 ArgStringList &CmdArgs, 2804 bool ForceLinkBuiltinRT) const { 2805 // Embedded targets are simple at the moment, not supporting sanitizers and 2806 // with different libraries for each member of the product { static, PIC } x 2807 // { hard-float, soft-float } 2808 llvm::SmallString<32> CompilerRT = StringRef(""); 2809 CompilerRT += 2810 (tools::arm::getARMFloatABI(*this, Args) == tools::arm::FloatABI::Hard) 2811 ? "hard" 2812 : "soft"; 2813 CompilerRT += Args.hasArg(options::OPT_fPIC) ? "_pic" : "_static"; 2814 2815 AddLinkRuntimeLib(Args, CmdArgs, CompilerRT, RLO_IsEmbedded); 2816 } 2817 2818 bool Darwin::isAlignedAllocationUnavailable() const { 2819 llvm::Triple::OSType OS; 2820 2821 if (isTargetMacCatalyst()) 2822 return TargetVersion < alignedAllocMinVersion(llvm::Triple::MacOSX); 2823 switch (TargetPlatform) { 2824 case MacOS: // Earlier than 10.13. 2825 OS = llvm::Triple::MacOSX; 2826 break; 2827 case IPhoneOS: 2828 OS = llvm::Triple::IOS; 2829 break; 2830 case TvOS: // Earlier than 11.0. 2831 OS = llvm::Triple::TvOS; 2832 break; 2833 case WatchOS: // Earlier than 4.0. 2834 OS = llvm::Triple::WatchOS; 2835 break; 2836 case DriverKit: // Always available. 2837 return false; 2838 } 2839 2840 return TargetVersion < alignedAllocMinVersion(OS); 2841 } 2842 2843 void Darwin::addClangTargetOptions(const llvm::opt::ArgList &DriverArgs, 2844 llvm::opt::ArgStringList &CC1Args, 2845 Action::OffloadKind DeviceOffloadKind) const { 2846 // Pass "-faligned-alloc-unavailable" only when the user hasn't manually 2847 // enabled or disabled aligned allocations. 2848 if (!DriverArgs.hasArgNoClaim(options::OPT_faligned_allocation, 2849 options::OPT_fno_aligned_allocation) && 2850 isAlignedAllocationUnavailable()) 2851 CC1Args.push_back("-faligned-alloc-unavailable"); 2852 2853 addClangCC1ASTargetOptions(DriverArgs, CC1Args); 2854 2855 // Enable compatibility mode for NSItemProviderCompletionHandler in 2856 // Foundation/NSItemProvider.h. 2857 CC1Args.push_back("-fcompatibility-qualified-id-block-type-checking"); 2858 2859 // Give static local variables in inline functions hidden visibility when 2860 // -fvisibility-inlines-hidden is enabled. 2861 if (!DriverArgs.getLastArgNoClaim( 2862 options::OPT_fvisibility_inlines_hidden_static_local_var, 2863 options::OPT_fno_visibility_inlines_hidden_static_local_var)) 2864 CC1Args.push_back("-fvisibility-inlines-hidden-static-local-var"); 2865 } 2866 2867 void Darwin::addClangCC1ASTargetOptions( 2868 const llvm::opt::ArgList &Args, llvm::opt::ArgStringList &CC1ASArgs) const { 2869 if (TargetVariantTriple) { 2870 CC1ASArgs.push_back("-darwin-target-variant-triple"); 2871 CC1ASArgs.push_back(Args.MakeArgString(TargetVariantTriple->getTriple())); 2872 } 2873 2874 if (SDKInfo) { 2875 /// Pass the SDK version to the compiler when the SDK information is 2876 /// available. 2877 auto EmitTargetSDKVersionArg = [&](const VersionTuple &V) { 2878 std::string Arg; 2879 llvm::raw_string_ostream OS(Arg); 2880 OS << "-target-sdk-version=" << V; 2881 CC1ASArgs.push_back(Args.MakeArgString(OS.str())); 2882 }; 2883 2884 if (isTargetMacCatalyst()) { 2885 if (const auto *MacOStoMacCatalystMapping = SDKInfo->getVersionMapping( 2886 DarwinSDKInfo::OSEnvPair::macOStoMacCatalystPair())) { 2887 std::optional<VersionTuple> SDKVersion = MacOStoMacCatalystMapping->map( 2888 SDKInfo->getVersion(), minimumMacCatalystDeploymentTarget(), 2889 std::nullopt); 2890 EmitTargetSDKVersionArg( 2891 SDKVersion ? *SDKVersion : minimumMacCatalystDeploymentTarget()); 2892 } 2893 } else { 2894 EmitTargetSDKVersionArg(SDKInfo->getVersion()); 2895 } 2896 2897 /// Pass the target variant SDK version to the compiler when the SDK 2898 /// information is available and is required for target variant. 2899 if (TargetVariantTriple) { 2900 if (isTargetMacCatalyst()) { 2901 std::string Arg; 2902 llvm::raw_string_ostream OS(Arg); 2903 OS << "-darwin-target-variant-sdk-version=" << SDKInfo->getVersion(); 2904 CC1ASArgs.push_back(Args.MakeArgString(OS.str())); 2905 } else if (const auto *MacOStoMacCatalystMapping = 2906 SDKInfo->getVersionMapping( 2907 DarwinSDKInfo::OSEnvPair::macOStoMacCatalystPair())) { 2908 if (std::optional<VersionTuple> SDKVersion = 2909 MacOStoMacCatalystMapping->map( 2910 SDKInfo->getVersion(), minimumMacCatalystDeploymentTarget(), 2911 std::nullopt)) { 2912 std::string Arg; 2913 llvm::raw_string_ostream OS(Arg); 2914 OS << "-darwin-target-variant-sdk-version=" << *SDKVersion; 2915 CC1ASArgs.push_back(Args.MakeArgString(OS.str())); 2916 } 2917 } 2918 } 2919 } 2920 } 2921 2922 DerivedArgList * 2923 Darwin::TranslateArgs(const DerivedArgList &Args, StringRef BoundArch, 2924 Action::OffloadKind DeviceOffloadKind) const { 2925 // First get the generic Apple args, before moving onto Darwin-specific ones. 2926 DerivedArgList *DAL = 2927 MachO::TranslateArgs(Args, BoundArch, DeviceOffloadKind); 2928 2929 // If no architecture is bound, none of the translations here are relevant. 2930 if (BoundArch.empty()) 2931 return DAL; 2932 2933 // Add an explicit version min argument for the deployment target. We do this 2934 // after argument translation because -Xarch_ arguments may add a version min 2935 // argument. 2936 AddDeploymentTarget(*DAL); 2937 2938 // For iOS 6, undo the translation to add -static for -mkernel/-fapple-kext. 2939 // FIXME: It would be far better to avoid inserting those -static arguments, 2940 // but we can't check the deployment target in the translation code until 2941 // it is set here. 2942 if (isTargetWatchOSBased() || isTargetDriverKit() || 2943 (isTargetIOSBased() && !isIPhoneOSVersionLT(6, 0))) { 2944 for (ArgList::iterator it = DAL->begin(), ie = DAL->end(); it != ie; ) { 2945 Arg *A = *it; 2946 ++it; 2947 if (A->getOption().getID() != options::OPT_mkernel && 2948 A->getOption().getID() != options::OPT_fapple_kext) 2949 continue; 2950 assert(it != ie && "unexpected argument translation"); 2951 A = *it; 2952 assert(A->getOption().getID() == options::OPT_static && 2953 "missing expected -static argument"); 2954 *it = nullptr; 2955 ++it; 2956 } 2957 } 2958 2959 auto Arch = tools::darwin::getArchTypeForMachOArchName(BoundArch); 2960 if ((Arch == llvm::Triple::arm || Arch == llvm::Triple::thumb)) { 2961 if (Args.hasFlag(options::OPT_fomit_frame_pointer, 2962 options::OPT_fno_omit_frame_pointer, false)) 2963 getDriver().Diag(clang::diag::warn_drv_unsupported_opt_for_target) 2964 << "-fomit-frame-pointer" << BoundArch; 2965 } 2966 2967 return DAL; 2968 } 2969 2970 ToolChain::UnwindTableLevel MachO::getDefaultUnwindTableLevel(const ArgList &Args) const { 2971 // Unwind tables are not emitted if -fno-exceptions is supplied (except when 2972 // targeting x86_64). 2973 if (getArch() == llvm::Triple::x86_64 || 2974 (GetExceptionModel(Args) != llvm::ExceptionHandling::SjLj && 2975 Args.hasFlag(options::OPT_fexceptions, options::OPT_fno_exceptions, 2976 true))) 2977 return (getArch() == llvm::Triple::aarch64 || 2978 getArch() == llvm::Triple::aarch64_32) 2979 ? UnwindTableLevel::Synchronous 2980 : UnwindTableLevel::Asynchronous; 2981 2982 return UnwindTableLevel::None; 2983 } 2984 2985 bool MachO::UseDwarfDebugFlags() const { 2986 if (const char *S = ::getenv("RC_DEBUG_OPTIONS")) 2987 return S[0] != '\0'; 2988 return false; 2989 } 2990 2991 std::string MachO::GetGlobalDebugPathRemapping() const { 2992 if (const char *S = ::getenv("RC_DEBUG_PREFIX_MAP")) 2993 return S; 2994 return {}; 2995 } 2996 2997 llvm::ExceptionHandling Darwin::GetExceptionModel(const ArgList &Args) const { 2998 // Darwin uses SjLj exceptions on ARM. 2999 if (getTriple().getArch() != llvm::Triple::arm && 3000 getTriple().getArch() != llvm::Triple::thumb) 3001 return llvm::ExceptionHandling::None; 3002 3003 // Only watchOS uses the new DWARF/Compact unwinding method. 3004 llvm::Triple Triple(ComputeLLVMTriple(Args)); 3005 if (Triple.isWatchABI()) 3006 return llvm::ExceptionHandling::DwarfCFI; 3007 3008 return llvm::ExceptionHandling::SjLj; 3009 } 3010 3011 bool Darwin::SupportsEmbeddedBitcode() const { 3012 assert(TargetInitialized && "Target not initialized!"); 3013 if (isTargetIPhoneOS() && isIPhoneOSVersionLT(6, 0)) 3014 return false; 3015 return true; 3016 } 3017 3018 bool MachO::isPICDefault() const { return true; } 3019 3020 bool MachO::isPIEDefault(const llvm::opt::ArgList &Args) const { return false; } 3021 3022 bool MachO::isPICDefaultForced() const { 3023 return (getArch() == llvm::Triple::x86_64 || 3024 getArch() == llvm::Triple::aarch64); 3025 } 3026 3027 bool MachO::SupportsProfiling() const { 3028 // Profiling instrumentation is only supported on x86. 3029 return getTriple().isX86(); 3030 } 3031 3032 void Darwin::addMinVersionArgs(const ArgList &Args, 3033 ArgStringList &CmdArgs) const { 3034 VersionTuple TargetVersion = getTripleTargetVersion(); 3035 3036 if (isTargetWatchOS()) 3037 CmdArgs.push_back("-watchos_version_min"); 3038 else if (isTargetWatchOSSimulator()) 3039 CmdArgs.push_back("-watchos_simulator_version_min"); 3040 else if (isTargetTvOS()) 3041 CmdArgs.push_back("-tvos_version_min"); 3042 else if (isTargetTvOSSimulator()) 3043 CmdArgs.push_back("-tvos_simulator_version_min"); 3044 else if (isTargetDriverKit()) 3045 CmdArgs.push_back("-driverkit_version_min"); 3046 else if (isTargetIOSSimulator()) 3047 CmdArgs.push_back("-ios_simulator_version_min"); 3048 else if (isTargetIOSBased()) 3049 CmdArgs.push_back("-iphoneos_version_min"); 3050 else if (isTargetMacCatalyst()) 3051 CmdArgs.push_back("-maccatalyst_version_min"); 3052 else { 3053 assert(isTargetMacOS() && "unexpected target"); 3054 CmdArgs.push_back("-macosx_version_min"); 3055 } 3056 3057 VersionTuple MinTgtVers = getEffectiveTriple().getMinimumSupportedOSVersion(); 3058 if (!MinTgtVers.empty() && MinTgtVers > TargetVersion) 3059 TargetVersion = MinTgtVers; 3060 CmdArgs.push_back(Args.MakeArgString(TargetVersion.getAsString())); 3061 if (TargetVariantTriple) { 3062 assert(isTargetMacOSBased() && "unexpected target"); 3063 VersionTuple VariantTargetVersion; 3064 if (TargetVariantTriple->isMacOSX()) { 3065 CmdArgs.push_back("-macosx_version_min"); 3066 TargetVariantTriple->getMacOSXVersion(VariantTargetVersion); 3067 } else { 3068 assert(TargetVariantTriple->isiOS() && 3069 TargetVariantTriple->isMacCatalystEnvironment() && 3070 "unexpected target variant triple"); 3071 CmdArgs.push_back("-maccatalyst_version_min"); 3072 VariantTargetVersion = TargetVariantTriple->getiOSVersion(); 3073 } 3074 VersionTuple MinTgtVers = 3075 TargetVariantTriple->getMinimumSupportedOSVersion(); 3076 if (MinTgtVers.getMajor() && MinTgtVers > VariantTargetVersion) 3077 VariantTargetVersion = MinTgtVers; 3078 CmdArgs.push_back(Args.MakeArgString(VariantTargetVersion.getAsString())); 3079 } 3080 } 3081 3082 static const char *getPlatformName(Darwin::DarwinPlatformKind Platform, 3083 Darwin::DarwinEnvironmentKind Environment) { 3084 switch (Platform) { 3085 case Darwin::MacOS: 3086 return "macos"; 3087 case Darwin::IPhoneOS: 3088 if (Environment == Darwin::MacCatalyst) 3089 return "mac catalyst"; 3090 return "ios"; 3091 case Darwin::TvOS: 3092 return "tvos"; 3093 case Darwin::WatchOS: 3094 return "watchos"; 3095 case Darwin::DriverKit: 3096 return "driverkit"; 3097 } 3098 llvm_unreachable("invalid platform"); 3099 } 3100 3101 void Darwin::addPlatformVersionArgs(const llvm::opt::ArgList &Args, 3102 llvm::opt::ArgStringList &CmdArgs) const { 3103 auto EmitPlatformVersionArg = 3104 [&](const VersionTuple &TV, Darwin::DarwinPlatformKind TargetPlatform, 3105 Darwin::DarwinEnvironmentKind TargetEnvironment, 3106 const llvm::Triple &TT) { 3107 // -platform_version <platform> <target_version> <sdk_version> 3108 // Both the target and SDK version support only up to 3 components. 3109 CmdArgs.push_back("-platform_version"); 3110 std::string PlatformName = 3111 getPlatformName(TargetPlatform, TargetEnvironment); 3112 if (TargetEnvironment == Darwin::Simulator) 3113 PlatformName += "-simulator"; 3114 CmdArgs.push_back(Args.MakeArgString(PlatformName)); 3115 VersionTuple TargetVersion = TV.withoutBuild(); 3116 if ((TargetPlatform == Darwin::IPhoneOS || 3117 TargetPlatform == Darwin::TvOS) && 3118 getTriple().getArchName() == "arm64e" && 3119 TargetVersion.getMajor() < 14) { 3120 // arm64e slice is supported on iOS/tvOS 14+ only. 3121 TargetVersion = VersionTuple(14, 0); 3122 } 3123 VersionTuple MinTgtVers = TT.getMinimumSupportedOSVersion(); 3124 if (!MinTgtVers.empty() && MinTgtVers > TargetVersion) 3125 TargetVersion = MinTgtVers; 3126 CmdArgs.push_back(Args.MakeArgString(TargetVersion.getAsString())); 3127 3128 if (TargetPlatform == IPhoneOS && TargetEnvironment == MacCatalyst) { 3129 // Mac Catalyst programs must use the appropriate iOS SDK version 3130 // that corresponds to the macOS SDK version used for the compilation. 3131 std::optional<VersionTuple> iOSSDKVersion; 3132 if (SDKInfo) { 3133 if (const auto *MacOStoMacCatalystMapping = 3134 SDKInfo->getVersionMapping( 3135 DarwinSDKInfo::OSEnvPair::macOStoMacCatalystPair())) { 3136 iOSSDKVersion = MacOStoMacCatalystMapping->map( 3137 SDKInfo->getVersion().withoutBuild(), 3138 minimumMacCatalystDeploymentTarget(), std::nullopt); 3139 } 3140 } 3141 CmdArgs.push_back(Args.MakeArgString( 3142 (iOSSDKVersion ? *iOSSDKVersion 3143 : minimumMacCatalystDeploymentTarget()) 3144 .getAsString())); 3145 return; 3146 } 3147 3148 if (SDKInfo) { 3149 VersionTuple SDKVersion = SDKInfo->getVersion().withoutBuild(); 3150 if (!SDKVersion.getMinor()) 3151 SDKVersion = VersionTuple(SDKVersion.getMajor(), 0); 3152 CmdArgs.push_back(Args.MakeArgString(SDKVersion.getAsString())); 3153 } else { 3154 // Use an SDK version that's matching the deployment target if the SDK 3155 // version is missing. This is preferred over an empty SDK version 3156 // (0.0.0) as the system's runtime might expect the linked binary to 3157 // contain a valid SDK version in order for the binary to work 3158 // correctly. It's reasonable to use the deployment target version as 3159 // a proxy for the SDK version because older SDKs don't guarantee 3160 // support for deployment targets newer than the SDK versions, so that 3161 // rules out using some predetermined older SDK version, which leaves 3162 // the deployment target version as the only reasonable choice. 3163 CmdArgs.push_back(Args.MakeArgString(TargetVersion.getAsString())); 3164 } 3165 }; 3166 EmitPlatformVersionArg(getTripleTargetVersion(), TargetPlatform, 3167 TargetEnvironment, getEffectiveTriple()); 3168 if (!TargetVariantTriple) 3169 return; 3170 Darwin::DarwinPlatformKind Platform; 3171 Darwin::DarwinEnvironmentKind Environment; 3172 VersionTuple TargetVariantVersion; 3173 if (TargetVariantTriple->isMacOSX()) { 3174 TargetVariantTriple->getMacOSXVersion(TargetVariantVersion); 3175 Platform = Darwin::MacOS; 3176 Environment = Darwin::NativeEnvironment; 3177 } else { 3178 assert(TargetVariantTriple->isiOS() && 3179 TargetVariantTriple->isMacCatalystEnvironment() && 3180 "unexpected target variant triple"); 3181 TargetVariantVersion = TargetVariantTriple->getiOSVersion(); 3182 Platform = Darwin::IPhoneOS; 3183 Environment = Darwin::MacCatalyst; 3184 } 3185 EmitPlatformVersionArg(TargetVariantVersion, Platform, Environment, 3186 *TargetVariantTriple); 3187 } 3188 3189 // Add additional link args for the -dynamiclib option. 3190 static void addDynamicLibLinkArgs(const Darwin &D, const ArgList &Args, 3191 ArgStringList &CmdArgs) { 3192 // Derived from darwin_dylib1 spec. 3193 if (D.isTargetIPhoneOS()) { 3194 if (D.isIPhoneOSVersionLT(3, 1)) 3195 CmdArgs.push_back("-ldylib1.o"); 3196 return; 3197 } 3198 3199 if (!D.isTargetMacOS()) 3200 return; 3201 if (D.isMacosxVersionLT(10, 5)) 3202 CmdArgs.push_back("-ldylib1.o"); 3203 else if (D.isMacosxVersionLT(10, 6)) 3204 CmdArgs.push_back("-ldylib1.10.5.o"); 3205 } 3206 3207 // Add additional link args for the -bundle option. 3208 static void addBundleLinkArgs(const Darwin &D, const ArgList &Args, 3209 ArgStringList &CmdArgs) { 3210 if (Args.hasArg(options::OPT_static)) 3211 return; 3212 // Derived from darwin_bundle1 spec. 3213 if ((D.isTargetIPhoneOS() && D.isIPhoneOSVersionLT(3, 1)) || 3214 (D.isTargetMacOS() && D.isMacosxVersionLT(10, 6))) 3215 CmdArgs.push_back("-lbundle1.o"); 3216 } 3217 3218 // Add additional link args for the -pg option. 3219 static void addPgProfilingLinkArgs(const Darwin &D, const ArgList &Args, 3220 ArgStringList &CmdArgs) { 3221 if (D.isTargetMacOS() && D.isMacosxVersionLT(10, 9)) { 3222 if (Args.hasArg(options::OPT_static) || Args.hasArg(options::OPT_object) || 3223 Args.hasArg(options::OPT_preload)) { 3224 CmdArgs.push_back("-lgcrt0.o"); 3225 } else { 3226 CmdArgs.push_back("-lgcrt1.o"); 3227 3228 // darwin_crt2 spec is empty. 3229 } 3230 // By default on OS X 10.8 and later, we don't link with a crt1.o 3231 // file and the linker knows to use _main as the entry point. But, 3232 // when compiling with -pg, we need to link with the gcrt1.o file, 3233 // so pass the -no_new_main option to tell the linker to use the 3234 // "start" symbol as the entry point. 3235 if (!D.isMacosxVersionLT(10, 8)) 3236 CmdArgs.push_back("-no_new_main"); 3237 } else { 3238 D.getDriver().Diag(diag::err_drv_clang_unsupported_opt_pg_darwin) 3239 << D.isTargetMacOSBased(); 3240 } 3241 } 3242 3243 static void addDefaultCRTLinkArgs(const Darwin &D, const ArgList &Args, 3244 ArgStringList &CmdArgs) { 3245 // Derived from darwin_crt1 spec. 3246 if (D.isTargetIPhoneOS()) { 3247 if (D.getArch() == llvm::Triple::aarch64) 3248 ; // iOS does not need any crt1 files for arm64 3249 else if (D.isIPhoneOSVersionLT(3, 1)) 3250 CmdArgs.push_back("-lcrt1.o"); 3251 else if (D.isIPhoneOSVersionLT(6, 0)) 3252 CmdArgs.push_back("-lcrt1.3.1.o"); 3253 return; 3254 } 3255 3256 if (!D.isTargetMacOS()) 3257 return; 3258 if (D.isMacosxVersionLT(10, 5)) 3259 CmdArgs.push_back("-lcrt1.o"); 3260 else if (D.isMacosxVersionLT(10, 6)) 3261 CmdArgs.push_back("-lcrt1.10.5.o"); 3262 else if (D.isMacosxVersionLT(10, 8)) 3263 CmdArgs.push_back("-lcrt1.10.6.o"); 3264 // darwin_crt2 spec is empty. 3265 } 3266 3267 void Darwin::addStartObjectFileArgs(const ArgList &Args, 3268 ArgStringList &CmdArgs) const { 3269 // Derived from startfile spec. 3270 if (Args.hasArg(options::OPT_dynamiclib)) 3271 addDynamicLibLinkArgs(*this, Args, CmdArgs); 3272 else if (Args.hasArg(options::OPT_bundle)) 3273 addBundleLinkArgs(*this, Args, CmdArgs); 3274 else if (Args.hasArg(options::OPT_pg) && SupportsProfiling()) 3275 addPgProfilingLinkArgs(*this, Args, CmdArgs); 3276 else if (Args.hasArg(options::OPT_static) || 3277 Args.hasArg(options::OPT_object) || 3278 Args.hasArg(options::OPT_preload)) 3279 CmdArgs.push_back("-lcrt0.o"); 3280 else 3281 addDefaultCRTLinkArgs(*this, Args, CmdArgs); 3282 3283 if (isTargetMacOS() && Args.hasArg(options::OPT_shared_libgcc) && 3284 isMacosxVersionLT(10, 5)) { 3285 const char *Str = Args.MakeArgString(GetFilePath("crt3.o")); 3286 CmdArgs.push_back(Str); 3287 } 3288 } 3289 3290 void Darwin::CheckObjCARC() const { 3291 if (isTargetIOSBased() || isTargetWatchOSBased() || 3292 (isTargetMacOSBased() && !isMacosxVersionLT(10, 6))) 3293 return; 3294 getDriver().Diag(diag::err_arc_unsupported_on_toolchain); 3295 } 3296 3297 SanitizerMask Darwin::getSupportedSanitizers() const { 3298 const bool IsX86_64 = getTriple().getArch() == llvm::Triple::x86_64; 3299 const bool IsAArch64 = getTriple().getArch() == llvm::Triple::aarch64; 3300 SanitizerMask Res = ToolChain::getSupportedSanitizers(); 3301 Res |= SanitizerKind::Address; 3302 Res |= SanitizerKind::PointerCompare; 3303 Res |= SanitizerKind::PointerSubtract; 3304 Res |= SanitizerKind::Leak; 3305 Res |= SanitizerKind::Fuzzer; 3306 Res |= SanitizerKind::FuzzerNoLink; 3307 Res |= SanitizerKind::ObjCCast; 3308 3309 // Prior to 10.9, macOS shipped a version of the C++ standard library without 3310 // C++11 support. The same is true of iOS prior to version 5. These OS'es are 3311 // incompatible with -fsanitize=vptr. 3312 if (!(isTargetMacOSBased() && isMacosxVersionLT(10, 9)) && 3313 !(isTargetIPhoneOS() && isIPhoneOSVersionLT(5, 0))) 3314 Res |= SanitizerKind::Vptr; 3315 3316 if ((IsX86_64 || IsAArch64) && 3317 (isTargetMacOSBased() || isTargetIOSSimulator() || 3318 isTargetTvOSSimulator() || isTargetWatchOSSimulator())) { 3319 Res |= SanitizerKind::Thread; 3320 } 3321 return Res; 3322 } 3323 3324 void Darwin::printVerboseInfo(raw_ostream &OS) const { 3325 CudaInstallation.print(OS); 3326 RocmInstallation.print(OS); 3327 } 3328