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