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