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 /// 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 /// Link the library in before any others. 189 RLO_FirstLink = 1 << 3, 190 }; 191 192 /// Add a runtime library to the list of items to link. 193 void AddLinkRuntimeLib(const llvm::opt::ArgList &Args, 194 llvm::opt::ArgStringList &CmdArgs, StringRef Component, 195 RuntimeLinkOptions Opts = RuntimeLinkOptions(), 196 bool IsShared = false) const; 197 198 /// Add any profiling runtime libraries that are needed. This is essentially a 199 /// MachO specific version of addProfileRT in Tools.cpp. 200 void addProfileRTLibs(const llvm::opt::ArgList &Args, 201 llvm::opt::ArgStringList &CmdArgs) const override { 202 // There aren't any profiling libs for embedded targets currently. 203 } 204 205 /// } 206 /// @name ToolChain Implementation 207 /// { 208 209 types::ID LookupTypeForExtension(StringRef Ext) const override; 210 211 bool HasNativeLLVMSupport() const override; 212 213 llvm::opt::DerivedArgList * 214 TranslateArgs(const llvm::opt::DerivedArgList &Args, StringRef BoundArch, 215 Action::OffloadKind DeviceOffloadKind) const override; 216 217 bool IsBlocksDefault() const override { 218 // Always allow blocks on Apple; users interested in versioning are 219 // expected to use /usr/include/Block.h. 220 return true; 221 } 222 bool IsIntegratedAssemblerDefault() const override { 223 // Default integrated assembler to on for Apple's MachO targets. 224 return true; 225 } 226 227 bool IsMathErrnoDefault() const override { return false; } 228 229 bool IsEncodeExtendedBlockSignatureDefault() const override { return true; } 230 231 bool IsObjCNonFragileABIDefault() const override { 232 // Non-fragile ABI is default for everything but i386. 233 return getTriple().getArch() != llvm::Triple::x86; 234 } 235 236 bool UseObjCMixedDispatch() const override { return true; } 237 238 bool IsUnwindTablesDefault(const llvm::opt::ArgList &Args) const override; 239 240 RuntimeLibType GetDefaultRuntimeLibType() const override { 241 return ToolChain::RLT_CompilerRT; 242 } 243 244 bool isPICDefault() const override; 245 bool isPIEDefault() const override; 246 bool isPICDefaultForced() const override; 247 248 bool SupportsProfiling() const override; 249 250 bool UseDwarfDebugFlags() const override; 251 252 llvm::ExceptionHandling 253 GetExceptionModel(const llvm::opt::ArgList &Args) const override { 254 return llvm::ExceptionHandling::None; 255 } 256 257 virtual StringRef getOSLibraryNameSuffix(bool IgnoreSim = false) const { 258 return ""; 259 } 260 261 // Darwin toolchain uses legacy thin LTO API, which is not 262 // capable of unit splitting. 263 bool canSplitThinLTOUnit() const override { return false; } 264 /// } 265 }; 266 267 /// Darwin - The base Darwin tool chain. 268 class LLVM_LIBRARY_VISIBILITY Darwin : public MachO { 269 public: 270 /// Whether the information on the target has been initialized. 271 // 272 // FIXME: This should be eliminated. What we want to do is make this part of 273 // the "default target for arguments" selection process, once we get out of 274 // the argument translation business. 275 mutable bool TargetInitialized; 276 277 enum DarwinPlatformKind { 278 MacOS, 279 IPhoneOS, 280 TvOS, 281 WatchOS, 282 LastDarwinPlatform = WatchOS 283 }; 284 enum DarwinEnvironmentKind { 285 NativeEnvironment, 286 Simulator, 287 }; 288 289 mutable DarwinPlatformKind TargetPlatform; 290 mutable DarwinEnvironmentKind TargetEnvironment; 291 292 /// The OS version we are targeting. 293 mutable VersionTuple TargetVersion; 294 295 /// The information about the darwin SDK that was used. 296 mutable Optional<DarwinSDKInfo> SDKInfo; 297 298 CudaInstallationDetector CudaInstallation; 299 300 private: 301 void AddDeploymentTarget(llvm::opt::DerivedArgList &Args) const; 302 303 public: 304 Darwin(const Driver &D, const llvm::Triple &Triple, 305 const llvm::opt::ArgList &Args); 306 ~Darwin() override; 307 308 std::string ComputeEffectiveClangTriple(const llvm::opt::ArgList &Args, 309 types::ID InputType) const override; 310 311 /// @name Apple Specific Toolchain Implementation 312 /// { 313 314 void addMinVersionArgs(const llvm::opt::ArgList &Args, 315 llvm::opt::ArgStringList &CmdArgs) const override; 316 317 void addStartObjectFileArgs(const llvm::opt::ArgList &Args, 318 llvm::opt::ArgStringList &CmdArgs) const override; 319 320 bool isKernelStatic() const override { 321 return (!(isTargetIPhoneOS() && !isIPhoneOSVersionLT(6, 0)) && 322 !isTargetWatchOS()); 323 } 324 325 void addProfileRTLibs(const llvm::opt::ArgList &Args, 326 llvm::opt::ArgStringList &CmdArgs) const override; 327 328 protected: 329 /// } 330 /// @name Darwin specific Toolchain functions 331 /// { 332 333 // FIXME: Eliminate these ...Target functions and derive separate tool chains 334 // for these targets and put version in constructor. 335 void setTarget(DarwinPlatformKind Platform, DarwinEnvironmentKind Environment, 336 unsigned Major, unsigned Minor, unsigned Micro) const { 337 // FIXME: For now, allow reinitialization as long as values don't 338 // change. This will go away when we move away from argument translation. 339 if (TargetInitialized && TargetPlatform == Platform && 340 TargetEnvironment == Environment && 341 TargetVersion == VersionTuple(Major, Minor, Micro)) 342 return; 343 344 assert(!TargetInitialized && "Target already initialized!"); 345 TargetInitialized = true; 346 TargetPlatform = Platform; 347 TargetEnvironment = Environment; 348 TargetVersion = VersionTuple(Major, Minor, Micro); 349 if (Environment == Simulator) 350 const_cast<Darwin *>(this)->setTripleEnvironment(llvm::Triple::Simulator); 351 } 352 353 bool isTargetIPhoneOS() const { 354 assert(TargetInitialized && "Target not initialized!"); 355 return (TargetPlatform == IPhoneOS || TargetPlatform == TvOS) && 356 TargetEnvironment == NativeEnvironment; 357 } 358 359 bool isTargetIOSSimulator() const { 360 assert(TargetInitialized && "Target not initialized!"); 361 return (TargetPlatform == IPhoneOS || TargetPlatform == TvOS) && 362 TargetEnvironment == Simulator; 363 } 364 365 bool isTargetIOSBased() const { 366 assert(TargetInitialized && "Target not initialized!"); 367 return isTargetIPhoneOS() || isTargetIOSSimulator(); 368 } 369 370 bool isTargetTvOS() const { 371 assert(TargetInitialized && "Target not initialized!"); 372 return TargetPlatform == TvOS && TargetEnvironment == NativeEnvironment; 373 } 374 375 bool isTargetTvOSSimulator() const { 376 assert(TargetInitialized && "Target not initialized!"); 377 return TargetPlatform == TvOS && TargetEnvironment == Simulator; 378 } 379 380 bool isTargetTvOSBased() const { 381 assert(TargetInitialized && "Target not initialized!"); 382 return TargetPlatform == TvOS; 383 } 384 385 bool isTargetWatchOS() const { 386 assert(TargetInitialized && "Target not initialized!"); 387 return TargetPlatform == WatchOS && TargetEnvironment == NativeEnvironment; 388 } 389 390 bool isTargetWatchOSSimulator() const { 391 assert(TargetInitialized && "Target not initialized!"); 392 return TargetPlatform == WatchOS && TargetEnvironment == Simulator; 393 } 394 395 bool isTargetWatchOSBased() const { 396 assert(TargetInitialized && "Target not initialized!"); 397 return TargetPlatform == WatchOS; 398 } 399 400 bool isTargetMacOS() const { 401 assert(TargetInitialized && "Target not initialized!"); 402 return TargetPlatform == MacOS; 403 } 404 405 bool isTargetInitialized() const { return TargetInitialized; } 406 407 VersionTuple getTargetVersion() const { 408 assert(TargetInitialized && "Target not initialized!"); 409 return TargetVersion; 410 } 411 412 bool isIPhoneOSVersionLT(unsigned V0, unsigned V1 = 0, 413 unsigned V2 = 0) const { 414 assert(isTargetIOSBased() && "Unexpected call for non iOS target!"); 415 return TargetVersion < VersionTuple(V0, V1, V2); 416 } 417 418 bool isMacosxVersionLT(unsigned V0, unsigned V1 = 0, unsigned V2 = 0) const { 419 assert(isTargetMacOS() && "Unexpected call for non OS X target!"); 420 return TargetVersion < VersionTuple(V0, V1, V2); 421 } 422 423 /// Return true if c++17 aligned allocation/deallocation functions are not 424 /// implemented in the c++ standard library of the deployment target we are 425 /// targeting. 426 bool isAlignedAllocationUnavailable() const; 427 428 void addClangTargetOptions(const llvm::opt::ArgList &DriverArgs, 429 llvm::opt::ArgStringList &CC1Args, 430 Action::OffloadKind DeviceOffloadKind) const override; 431 432 StringRef getPlatformFamily() const; 433 StringRef getOSLibraryNameSuffix(bool IgnoreSim = false) const override; 434 435 public: 436 static StringRef getSDKName(StringRef isysroot); 437 438 /// } 439 /// @name ToolChain Implementation 440 /// { 441 442 // Darwin tools support multiple architecture (e.g., i386 and x86_64) and 443 // most development is done against SDKs, so compiling for a different 444 // architecture should not get any special treatment. 445 bool isCrossCompiling() const override { return false; } 446 447 llvm::opt::DerivedArgList * 448 TranslateArgs(const llvm::opt::DerivedArgList &Args, StringRef BoundArch, 449 Action::OffloadKind DeviceOffloadKind) const override; 450 451 CXXStdlibType GetDefaultCXXStdlibType() const override; 452 ObjCRuntime getDefaultObjCRuntime(bool isNonFragile) const override; 453 bool hasBlocksRuntime() const override; 454 455 void AddCudaIncludeArgs(const llvm::opt::ArgList &DriverArgs, 456 llvm::opt::ArgStringList &CC1Args) const override; 457 458 bool UseObjCMixedDispatch() const override { 459 // This is only used with the non-fragile ABI and non-legacy dispatch. 460 461 // Mixed dispatch is used everywhere except OS X before 10.6. 462 return !(isTargetMacOS() && isMacosxVersionLT(10, 6)); 463 } 464 465 unsigned GetDefaultStackProtectorLevel(bool KernelOrKext) const override { 466 // Stack protectors default to on for user code on 10.5, 467 // and for everything in 10.6 and beyond 468 if (isTargetIOSBased() || isTargetWatchOSBased()) 469 return 1; 470 else if (isTargetMacOS() && !isMacosxVersionLT(10, 6)) 471 return 1; 472 else if (isTargetMacOS() && !isMacosxVersionLT(10, 5) && !KernelOrKext) 473 return 1; 474 475 return 0; 476 } 477 478 void CheckObjCARC() const override; 479 480 llvm::ExceptionHandling GetExceptionModel( 481 const llvm::opt::ArgList &Args) const override; 482 483 bool SupportsEmbeddedBitcode() const override; 484 485 SanitizerMask getSupportedSanitizers() const override; 486 487 void printVerboseInfo(raw_ostream &OS) const override; 488 }; 489 490 /// DarwinClang - The Darwin toolchain used by Clang. 491 class LLVM_LIBRARY_VISIBILITY DarwinClang : public Darwin { 492 public: 493 DarwinClang(const Driver &D, const llvm::Triple &Triple, 494 const llvm::opt::ArgList &Args); 495 496 /// @name Apple ToolChain Implementation 497 /// { 498 499 RuntimeLibType GetRuntimeLibType(const llvm::opt::ArgList &Args) const override; 500 501 void AddLinkRuntimeLibArgs(const llvm::opt::ArgList &Args, 502 llvm::opt::ArgStringList &CmdArgs, 503 bool ForceLinkBuiltinRT = false) const override; 504 505 void AddClangCXXStdlibIncludeArgs( 506 const llvm::opt::ArgList &DriverArgs, 507 llvm::opt::ArgStringList &CC1Args) const override; 508 509 void AddClangSystemIncludeArgs(const llvm::opt::ArgList &DriverArgs, 510 llvm::opt::ArgStringList &CC1Args) const override; 511 512 void AddCXXStdlibLibArgs(const llvm::opt::ArgList &Args, 513 llvm::opt::ArgStringList &CmdArgs) const override; 514 515 void AddCCKextLibArgs(const llvm::opt::ArgList &Args, 516 llvm::opt::ArgStringList &CmdArgs) const override; 517 518 void addClangWarningOptions(llvm::opt::ArgStringList &CC1Args) const override; 519 520 void AddLinkARCArgs(const llvm::opt::ArgList &Args, 521 llvm::opt::ArgStringList &CmdArgs) const override; 522 523 unsigned GetDefaultDwarfVersion() const override; 524 // Until dtrace (via CTF) and LLDB can deal with distributed debug info, 525 // Darwin defaults to standalone/full debug info. 526 bool GetDefaultStandaloneDebug() const override { return true; } 527 llvm::DebuggerKind getDefaultDebuggerTuning() const override { 528 return llvm::DebuggerKind::LLDB; 529 } 530 531 /// } 532 533 private: 534 void AddLinkSanitizerLibArgs(const llvm::opt::ArgList &Args, 535 llvm::opt::ArgStringList &CmdArgs, 536 StringRef Sanitizer, 537 bool shared = true) const; 538 539 bool AddGnuCPlusPlusIncludePaths(const llvm::opt::ArgList &DriverArgs, 540 llvm::opt::ArgStringList &CC1Args, 541 llvm::SmallString<128> Base, 542 llvm::StringRef Version, 543 llvm::StringRef ArchDir, 544 llvm::StringRef BitDir) const; 545 546 llvm::StringRef GetHeaderSysroot(const llvm::opt::ArgList &DriverArgs) const; 547 }; 548 549 } // end namespace toolchains 550 } // end namespace driver 551 } // end namespace clang 552 553 #endif // LLVM_CLANG_LIB_DRIVER_TOOLCHAINS_DARWIN_H 554