1 //===--- Darwin.h - Darwin 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 #ifndef LLVM_CLANG_LIB_DRIVER_TOOLCHAINS_DARWIN_H 10 #define LLVM_CLANG_LIB_DRIVER_TOOLCHAINS_DARWIN_H 11 12 #include "Cuda.h" 13 #include "ROCm.h" 14 #include "clang/Basic/DarwinSDKInfo.h" 15 #include "clang/Basic/LangOptions.h" 16 #include "clang/Driver/Tool.h" 17 #include "clang/Driver/ToolChain.h" 18 #include "clang/Driver/XRayArgs.h" 19 20 namespace clang { 21 namespace driver { 22 23 namespace toolchains { 24 class MachO; 25 } // end namespace toolchains 26 27 namespace tools { 28 29 namespace darwin { 30 llvm::Triple::ArchType getArchTypeForMachOArchName(StringRef Str); 31 void setTripleTypeForMachOArchName(llvm::Triple &T, StringRef Str); 32 33 class LLVM_LIBRARY_VISIBILITY MachOTool : public Tool { 34 virtual void anchor(); 35 36 protected: 37 void AddMachOArch(const llvm::opt::ArgList &Args, 38 llvm::opt::ArgStringList &CmdArgs) const; 39 40 const toolchains::MachO &getMachOToolChain() const { 41 return reinterpret_cast<const toolchains::MachO &>(getToolChain()); 42 } 43 44 public: 45 MachOTool(const char *Name, const char *ShortName, const ToolChain &TC) 46 : Tool(Name, ShortName, TC) {} 47 }; 48 49 class LLVM_LIBRARY_VISIBILITY Assembler : public MachOTool { 50 public: 51 Assembler(const ToolChain &TC) 52 : MachOTool("darwin::Assembler", "assembler", TC) {} 53 54 bool hasIntegratedCPP() const override { return false; } 55 56 void ConstructJob(Compilation &C, const JobAction &JA, 57 const InputInfo &Output, const InputInfoList &Inputs, 58 const llvm::opt::ArgList &TCArgs, 59 const char *LinkingOutput) const override; 60 }; 61 62 class LLVM_LIBRARY_VISIBILITY Linker : public MachOTool { 63 bool NeedsTempPath(const InputInfoList &Inputs) const; 64 void AddLinkArgs(Compilation &C, const llvm::opt::ArgList &Args, 65 llvm::opt::ArgStringList &CmdArgs, 66 const InputInfoList &Inputs, unsigned Version[5], 67 bool LinkerIsLLD, bool LinkerIsLLDDarwinNew) const; 68 69 public: 70 Linker(const ToolChain &TC) : MachOTool("darwin::Linker", "linker", TC) {} 71 72 bool hasIntegratedCPP() const override { return false; } 73 bool isLinkJob() const override { return true; } 74 75 void ConstructJob(Compilation &C, const JobAction &JA, 76 const InputInfo &Output, const InputInfoList &Inputs, 77 const llvm::opt::ArgList &TCArgs, 78 const char *LinkingOutput) const override; 79 }; 80 81 class LLVM_LIBRARY_VISIBILITY Lipo : public MachOTool { 82 public: 83 Lipo(const ToolChain &TC) : MachOTool("darwin::Lipo", "lipo", TC) {} 84 85 bool hasIntegratedCPP() const override { return false; } 86 87 void ConstructJob(Compilation &C, const JobAction &JA, 88 const InputInfo &Output, const InputInfoList &Inputs, 89 const llvm::opt::ArgList &TCArgs, 90 const char *LinkingOutput) const override; 91 }; 92 93 class LLVM_LIBRARY_VISIBILITY Dsymutil : public MachOTool { 94 public: 95 Dsymutil(const ToolChain &TC) 96 : MachOTool("darwin::Dsymutil", "dsymutil", TC) {} 97 98 bool hasIntegratedCPP() const override { return false; } 99 bool isDsymutilJob() const override { return true; } 100 101 void ConstructJob(Compilation &C, const JobAction &JA, 102 const InputInfo &Output, const InputInfoList &Inputs, 103 const llvm::opt::ArgList &TCArgs, 104 const char *LinkingOutput) const override; 105 }; 106 107 class LLVM_LIBRARY_VISIBILITY VerifyDebug : public MachOTool { 108 public: 109 VerifyDebug(const ToolChain &TC) 110 : MachOTool("darwin::VerifyDebug", "dwarfdump", TC) {} 111 112 bool hasIntegratedCPP() const override { return false; } 113 114 void ConstructJob(Compilation &C, const JobAction &JA, 115 const InputInfo &Output, const InputInfoList &Inputs, 116 const llvm::opt::ArgList &TCArgs, 117 const char *LinkingOutput) const override; 118 }; 119 } // end namespace darwin 120 } // end namespace tools 121 122 namespace toolchains { 123 124 class LLVM_LIBRARY_VISIBILITY MachO : public ToolChain { 125 protected: 126 Tool *buildAssembler() const override; 127 Tool *buildLinker() const override; 128 Tool *getTool(Action::ActionClass AC) const override; 129 130 private: 131 mutable std::unique_ptr<tools::darwin::Lipo> Lipo; 132 mutable std::unique_ptr<tools::darwin::Dsymutil> Dsymutil; 133 mutable std::unique_ptr<tools::darwin::VerifyDebug> VerifyDebug; 134 135 public: 136 MachO(const Driver &D, const llvm::Triple &Triple, 137 const llvm::opt::ArgList &Args); 138 ~MachO() override; 139 140 /// @name MachO specific toolchain API 141 /// { 142 143 /// Get the "MachO" arch name for a particular compiler invocation. For 144 /// example, Apple treats different ARM variations as distinct architectures. 145 StringRef getMachOArchName(const llvm::opt::ArgList &Args) const; 146 147 /// Add the linker arguments to link the ARC runtime library. 148 virtual void AddLinkARCArgs(const llvm::opt::ArgList &Args, 149 llvm::opt::ArgStringList &CmdArgs) const {} 150 151 /// Add the linker arguments to link the compiler runtime library. 152 /// 153 /// FIXME: This API is intended for use with embedded libraries only, and is 154 /// misleadingly named. 155 virtual void AddLinkRuntimeLibArgs(const llvm::opt::ArgList &Args, 156 llvm::opt::ArgStringList &CmdArgs, 157 bool ForceLinkBuiltinRT = false) const; 158 159 virtual void addStartObjectFileArgs(const llvm::opt::ArgList &Args, 160 llvm::opt::ArgStringList &CmdArgs) const { 161 } 162 163 virtual void addMinVersionArgs(const llvm::opt::ArgList &Args, 164 llvm::opt::ArgStringList &CmdArgs) const {} 165 166 virtual void addPlatformVersionArgs(const llvm::opt::ArgList &Args, 167 llvm::opt::ArgStringList &CmdArgs) const { 168 } 169 170 /// On some iOS platforms, kernel and kernel modules were built statically. Is 171 /// this such a target? 172 virtual bool isKernelStatic() const { return false; } 173 174 /// Is the target either iOS or an iOS simulator? 175 bool isTargetIOSBased() const { return false; } 176 177 /// Options to control how a runtime library is linked. 178 enum RuntimeLinkOptions : unsigned { 179 /// Link the library in even if it can't be found in the VFS. 180 RLO_AlwaysLink = 1 << 0, 181 182 /// Use the embedded runtime from the macho_embedded directory. 183 RLO_IsEmbedded = 1 << 1, 184 185 /// Emit rpaths for @executable_path as well as the resource directory. 186 RLO_AddRPath = 1 << 2, 187 }; 188 189 /// Add a runtime library to the list of items to link. 190 void AddLinkRuntimeLib(const llvm::opt::ArgList &Args, 191 llvm::opt::ArgStringList &CmdArgs, StringRef Component, 192 RuntimeLinkOptions Opts = RuntimeLinkOptions(), 193 bool IsShared = false) const; 194 195 /// Add any profiling runtime libraries that are needed. This is essentially a 196 /// MachO specific version of addProfileRT in Tools.cpp. 197 void addProfileRTLibs(const llvm::opt::ArgList &Args, 198 llvm::opt::ArgStringList &CmdArgs) const override { 199 // There aren't any profiling libs for embedded targets currently. 200 } 201 202 /// } 203 /// @name ToolChain Implementation 204 /// { 205 206 types::ID LookupTypeForExtension(StringRef Ext) const override; 207 208 bool HasNativeLLVMSupport() const override; 209 210 llvm::opt::DerivedArgList * 211 TranslateArgs(const llvm::opt::DerivedArgList &Args, StringRef BoundArch, 212 Action::OffloadKind DeviceOffloadKind) const override; 213 214 bool IsBlocksDefault() const override { 215 // Always allow blocks on Apple; users interested in versioning are 216 // expected to use /usr/include/Block.h. 217 return true; 218 } 219 bool IsIntegratedAssemblerDefault() const override { 220 // Default integrated assembler to on for Apple's MachO targets. 221 return true; 222 } 223 224 bool IsMathErrnoDefault() const override { return false; } 225 226 bool IsEncodeExtendedBlockSignatureDefault() const override { return true; } 227 228 bool IsObjCNonFragileABIDefault() const override { 229 // Non-fragile ABI is default for everything but i386. 230 return getTriple().getArch() != llvm::Triple::x86; 231 } 232 233 bool UseObjCMixedDispatch() const override { return true; } 234 235 bool IsUnwindTablesDefault(const llvm::opt::ArgList &Args) const override; 236 237 RuntimeLibType GetDefaultRuntimeLibType() const override { 238 return ToolChain::RLT_CompilerRT; 239 } 240 241 bool isPICDefault() const override; 242 bool isPIEDefault() const override; 243 bool isPICDefaultForced() const override; 244 245 bool SupportsProfiling() const override; 246 247 bool UseDwarfDebugFlags() const override; 248 249 llvm::ExceptionHandling 250 GetExceptionModel(const llvm::opt::ArgList &Args) const override { 251 return llvm::ExceptionHandling::None; 252 } 253 254 virtual StringRef getOSLibraryNameSuffix(bool IgnoreSim = false) const { 255 return ""; 256 } 257 258 // Darwin toolchain uses legacy thin LTO API, which is not 259 // capable of unit splitting. 260 bool canSplitThinLTOUnit() const override { return false; } 261 /// } 262 }; 263 264 /// Darwin - The base Darwin tool chain. 265 class LLVM_LIBRARY_VISIBILITY Darwin : public MachO { 266 public: 267 /// Whether the information on the target has been initialized. 268 // 269 // FIXME: This should be eliminated. What we want to do is make this part of 270 // the "default target for arguments" selection process, once we get out of 271 // the argument translation business. 272 mutable bool TargetInitialized; 273 274 enum DarwinPlatformKind { 275 MacOS, 276 IPhoneOS, 277 TvOS, 278 WatchOS, 279 LastDarwinPlatform = WatchOS 280 }; 281 enum DarwinEnvironmentKind { 282 NativeEnvironment, 283 Simulator, 284 MacCatalyst, 285 }; 286 287 mutable DarwinPlatformKind TargetPlatform; 288 mutable DarwinEnvironmentKind TargetEnvironment; 289 290 /// The native OS version we are targeting. 291 mutable VersionTuple TargetVersion; 292 /// The OS version we are targeting as specified in the triple. 293 mutable VersionTuple OSTargetVersion; 294 295 /// The information about the darwin SDK that was used. 296 mutable Optional<DarwinSDKInfo> SDKInfo; 297 298 CudaInstallationDetector CudaInstallation; 299 RocmInstallationDetector RocmInstallation; 300 301 private: 302 void AddDeploymentTarget(llvm::opt::DerivedArgList &Args) const; 303 304 public: 305 Darwin(const Driver &D, const llvm::Triple &Triple, 306 const llvm::opt::ArgList &Args); 307 ~Darwin() override; 308 309 std::string ComputeEffectiveClangTriple(const llvm::opt::ArgList &Args, 310 types::ID InputType) const override; 311 312 /// @name Apple Specific Toolchain Implementation 313 /// { 314 315 void addMinVersionArgs(const llvm::opt::ArgList &Args, 316 llvm::opt::ArgStringList &CmdArgs) const override; 317 318 void addPlatformVersionArgs(const llvm::opt::ArgList &Args, 319 llvm::opt::ArgStringList &CmdArgs) const override; 320 321 void addStartObjectFileArgs(const llvm::opt::ArgList &Args, 322 llvm::opt::ArgStringList &CmdArgs) const override; 323 324 bool isKernelStatic() const override { 325 return (!(isTargetIPhoneOS() && !isIPhoneOSVersionLT(6, 0)) && 326 !isTargetWatchOS()); 327 } 328 329 void addProfileRTLibs(const llvm::opt::ArgList &Args, 330 llvm::opt::ArgStringList &CmdArgs) const override; 331 332 protected: 333 /// } 334 /// @name Darwin specific Toolchain functions 335 /// { 336 337 // FIXME: Eliminate these ...Target functions and derive separate tool chains 338 // for these targets and put version in constructor. 339 void setTarget(DarwinPlatformKind Platform, DarwinEnvironmentKind Environment, 340 unsigned Major, unsigned Minor, unsigned Micro, 341 VersionTuple NativeTargetVersion) const { 342 // FIXME: For now, allow reinitialization as long as values don't 343 // change. This will go away when we move away from argument translation. 344 if (TargetInitialized && TargetPlatform == Platform && 345 TargetEnvironment == Environment && 346 (Environment == MacCatalyst ? OSTargetVersion : TargetVersion) == 347 VersionTuple(Major, Minor, Micro)) 348 return; 349 350 assert(!TargetInitialized && "Target already initialized!"); 351 TargetInitialized = true; 352 TargetPlatform = Platform; 353 TargetEnvironment = Environment; 354 TargetVersion = VersionTuple(Major, Minor, Micro); 355 if (Environment == Simulator) 356 const_cast<Darwin *>(this)->setTripleEnvironment(llvm::Triple::Simulator); 357 else if (Environment == MacCatalyst) { 358 const_cast<Darwin *>(this)->setTripleEnvironment(llvm::Triple::MacABI); 359 TargetVersion = NativeTargetVersion; 360 OSTargetVersion = VersionTuple(Major, Minor, Micro); 361 } 362 } 363 364 public: 365 bool isTargetIPhoneOS() const { 366 assert(TargetInitialized && "Target not initialized!"); 367 return (TargetPlatform == IPhoneOS || TargetPlatform == TvOS) && 368 TargetEnvironment == NativeEnvironment; 369 } 370 371 bool isTargetIOSSimulator() const { 372 assert(TargetInitialized && "Target not initialized!"); 373 return (TargetPlatform == IPhoneOS || TargetPlatform == TvOS) && 374 TargetEnvironment == Simulator; 375 } 376 377 bool isTargetIOSBased() const { 378 assert(TargetInitialized && "Target not initialized!"); 379 return isTargetIPhoneOS() || isTargetIOSSimulator(); 380 } 381 382 bool isTargetTvOS() const { 383 assert(TargetInitialized && "Target not initialized!"); 384 return TargetPlatform == TvOS && TargetEnvironment == NativeEnvironment; 385 } 386 387 bool isTargetTvOSSimulator() const { 388 assert(TargetInitialized && "Target not initialized!"); 389 return TargetPlatform == TvOS && TargetEnvironment == Simulator; 390 } 391 392 bool isTargetTvOSBased() const { 393 assert(TargetInitialized && "Target not initialized!"); 394 return TargetPlatform == TvOS; 395 } 396 397 bool isTargetWatchOS() const { 398 assert(TargetInitialized && "Target not initialized!"); 399 return TargetPlatform == WatchOS && TargetEnvironment == NativeEnvironment; 400 } 401 402 bool isTargetWatchOSSimulator() const { 403 assert(TargetInitialized && "Target not initialized!"); 404 return TargetPlatform == WatchOS && TargetEnvironment == Simulator; 405 } 406 407 bool isTargetWatchOSBased() const { 408 assert(TargetInitialized && "Target not initialized!"); 409 return TargetPlatform == WatchOS; 410 } 411 412 bool isTargetMacCatalyst() const { 413 return TargetPlatform == IPhoneOS && TargetEnvironment == MacCatalyst; 414 } 415 416 bool isTargetMacOS() const { 417 assert(TargetInitialized && "Target not initialized!"); 418 return TargetPlatform == MacOS; 419 } 420 421 bool isTargetMacOSBased() const { 422 assert(TargetInitialized && "Target not initialized!"); 423 return TargetPlatform == MacOS || isTargetMacCatalyst(); 424 } 425 426 bool isTargetAppleSiliconMac() const { 427 assert(TargetInitialized && "Target not initialized!"); 428 return isTargetMacOSBased() && getArch() == llvm::Triple::aarch64; 429 } 430 431 bool isTargetInitialized() const { return TargetInitialized; } 432 433 /// The version of the OS that's used by the OS specified in the target 434 /// triple. It might be different from the actual target OS on which the 435 /// program will run, e.g. MacCatalyst code runs on a macOS target, but its 436 /// target triple is iOS. 437 VersionTuple getTripleTargetVersion() const { 438 assert(TargetInitialized && "Target not initialized!"); 439 return isTargetMacCatalyst() ? OSTargetVersion : TargetVersion; 440 } 441 442 bool isIPhoneOSVersionLT(unsigned V0, unsigned V1 = 0, 443 unsigned V2 = 0) const { 444 assert(isTargetIOSBased() && "Unexpected call for non iOS target!"); 445 return TargetVersion < VersionTuple(V0, V1, V2); 446 } 447 448 /// Returns true if the minimum supported macOS version for the slice that's 449 /// being built is less than the specified version. If there's no minimum 450 /// supported macOS version, the deployment target version is compared to the 451 /// specifed version instead. 452 bool isMacosxVersionLT(unsigned V0, unsigned V1 = 0, unsigned V2 = 0) const { 453 assert(isTargetMacOSBased() && 454 (getTriple().isMacOSX() || getTriple().isMacCatalystEnvironment()) && 455 "Unexpected call for non OS X target!"); 456 // The effective triple might not be initialized yet, so construct a 457 // pseudo-effective triple to get the minimum supported OS version. 458 VersionTuple MinVers = 459 llvm::Triple(getTriple().getArchName(), "apple", "macos") 460 .getMinimumSupportedOSVersion(); 461 return (!MinVers.empty() && MinVers > TargetVersion 462 ? MinVers 463 : TargetVersion) < VersionTuple(V0, V1, V2); 464 } 465 466 protected: 467 /// Return true if c++17 aligned allocation/deallocation functions are not 468 /// implemented in the c++ standard library of the deployment target we are 469 /// targeting. 470 bool isAlignedAllocationUnavailable() const; 471 472 void addClangTargetOptions(const llvm::opt::ArgList &DriverArgs, 473 llvm::opt::ArgStringList &CC1Args, 474 Action::OffloadKind DeviceOffloadKind) const override; 475 476 StringRef getPlatformFamily() const; 477 StringRef getOSLibraryNameSuffix(bool IgnoreSim = false) const override; 478 479 public: 480 static StringRef getSDKName(StringRef isysroot); 481 482 /// } 483 /// @name ToolChain Implementation 484 /// { 485 486 // Darwin tools support multiple architecture (e.g., i386 and x86_64) and 487 // most development is done against SDKs, so compiling for a different 488 // architecture should not get any special treatment. 489 bool isCrossCompiling() const override { return false; } 490 491 llvm::opt::DerivedArgList * 492 TranslateArgs(const llvm::opt::DerivedArgList &Args, StringRef BoundArch, 493 Action::OffloadKind DeviceOffloadKind) const override; 494 495 CXXStdlibType GetDefaultCXXStdlibType() const override; 496 ObjCRuntime getDefaultObjCRuntime(bool isNonFragile) const override; 497 bool hasBlocksRuntime() const override; 498 499 void AddCudaIncludeArgs(const llvm::opt::ArgList &DriverArgs, 500 llvm::opt::ArgStringList &CC1Args) const override; 501 void AddHIPIncludeArgs(const llvm::opt::ArgList &DriverArgs, 502 llvm::opt::ArgStringList &CC1Args) const override; 503 504 bool UseObjCMixedDispatch() const override { 505 // This is only used with the non-fragile ABI and non-legacy dispatch. 506 507 // Mixed dispatch is used everywhere except OS X before 10.6. 508 return !(isTargetMacOSBased() && isMacosxVersionLT(10, 6)); 509 } 510 511 LangOptions::StackProtectorMode 512 GetDefaultStackProtectorLevel(bool KernelOrKext) const override { 513 // Stack protectors default to on for user code on 10.5, 514 // and for everything in 10.6 and beyond 515 if (isTargetIOSBased() || isTargetWatchOSBased()) 516 return LangOptions::SSPOn; 517 else if (isTargetMacOSBased() && !isMacosxVersionLT(10, 6)) 518 return LangOptions::SSPOn; 519 else if (isTargetMacOSBased() && !isMacosxVersionLT(10, 5) && !KernelOrKext) 520 return LangOptions::SSPOn; 521 522 return LangOptions::SSPOff; 523 } 524 525 void CheckObjCARC() const override; 526 527 llvm::ExceptionHandling GetExceptionModel( 528 const llvm::opt::ArgList &Args) const override; 529 530 bool SupportsEmbeddedBitcode() const override; 531 532 SanitizerMask getSupportedSanitizers() const override; 533 534 void printVerboseInfo(raw_ostream &OS) const override; 535 }; 536 537 /// DarwinClang - The Darwin toolchain used by Clang. 538 class LLVM_LIBRARY_VISIBILITY DarwinClang : public Darwin { 539 public: 540 DarwinClang(const Driver &D, const llvm::Triple &Triple, 541 const llvm::opt::ArgList &Args); 542 543 /// @name Apple ToolChain Implementation 544 /// { 545 546 RuntimeLibType GetRuntimeLibType(const llvm::opt::ArgList &Args) const override; 547 548 void AddLinkRuntimeLibArgs(const llvm::opt::ArgList &Args, 549 llvm::opt::ArgStringList &CmdArgs, 550 bool ForceLinkBuiltinRT = false) const override; 551 552 void AddClangCXXStdlibIncludeArgs( 553 const llvm::opt::ArgList &DriverArgs, 554 llvm::opt::ArgStringList &CC1Args) const override; 555 556 void AddClangSystemIncludeArgs(const llvm::opt::ArgList &DriverArgs, 557 llvm::opt::ArgStringList &CC1Args) const override; 558 559 void AddCXXStdlibLibArgs(const llvm::opt::ArgList &Args, 560 llvm::opt::ArgStringList &CmdArgs) const override; 561 562 void AddCCKextLibArgs(const llvm::opt::ArgList &Args, 563 llvm::opt::ArgStringList &CmdArgs) const override; 564 565 void addClangWarningOptions(llvm::opt::ArgStringList &CC1Args) const override; 566 567 void AddLinkARCArgs(const llvm::opt::ArgList &Args, 568 llvm::opt::ArgStringList &CmdArgs) const override; 569 570 unsigned GetDefaultDwarfVersion() const override; 571 // Until dtrace (via CTF) and LLDB can deal with distributed debug info, 572 // Darwin defaults to standalone/full debug info. 573 bool GetDefaultStandaloneDebug() const override { return true; } 574 llvm::DebuggerKind getDefaultDebuggerTuning() const override { 575 return llvm::DebuggerKind::LLDB; 576 } 577 578 /// } 579 580 private: 581 void AddLinkSanitizerLibArgs(const llvm::opt::ArgList &Args, 582 llvm::opt::ArgStringList &CmdArgs, 583 StringRef Sanitizer, 584 bool shared = true) const; 585 586 bool AddGnuCPlusPlusIncludePaths(const llvm::opt::ArgList &DriverArgs, 587 llvm::opt::ArgStringList &CC1Args, 588 llvm::SmallString<128> Base, 589 llvm::StringRef Version, 590 llvm::StringRef ArchDir, 591 llvm::StringRef BitDir) const; 592 593 llvm::StringRef GetHeaderSysroot(const llvm::opt::ArgList &DriverArgs) const; 594 }; 595 596 } // end namespace toolchains 597 } // end namespace driver 598 } // end namespace clang 599 600 #endif // LLVM_CLANG_LIB_DRIVER_TOOLCHAINS_DARWIN_H 601