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