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