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 /// } 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 }; 285 286 mutable DarwinPlatformKind TargetPlatform; 287 mutable DarwinEnvironmentKind TargetEnvironment; 288 289 /// The OS version we are targeting. 290 mutable VersionTuple TargetVersion; 291 292 /// The information about the darwin SDK that was used. 293 mutable Optional<DarwinSDKInfo> SDKInfo; 294 295 CudaInstallationDetector CudaInstallation; 296 297 private: 298 void AddDeploymentTarget(llvm::opt::DerivedArgList &Args) const; 299 300 public: 301 Darwin(const Driver &D, const llvm::Triple &Triple, 302 const llvm::opt::ArgList &Args); 303 ~Darwin() override; 304 305 std::string ComputeEffectiveClangTriple(const llvm::opt::ArgList &Args, 306 types::ID InputType) const override; 307 308 /// @name Apple Specific Toolchain Implementation 309 /// { 310 311 void addMinVersionArgs(const llvm::opt::ArgList &Args, 312 llvm::opt::ArgStringList &CmdArgs) const override; 313 314 void addStartObjectFileArgs(const llvm::opt::ArgList &Args, 315 llvm::opt::ArgStringList &CmdArgs) const override; 316 317 bool isKernelStatic() const override { 318 return (!(isTargetIPhoneOS() && !isIPhoneOSVersionLT(6, 0)) && 319 !isTargetWatchOS()); 320 } 321 322 void addProfileRTLibs(const llvm::opt::ArgList &Args, 323 llvm::opt::ArgStringList &CmdArgs) const override; 324 325 protected: 326 /// } 327 /// @name Darwin specific Toolchain functions 328 /// { 329 330 // FIXME: Eliminate these ...Target functions and derive separate tool chains 331 // for these targets and put version in constructor. 332 void setTarget(DarwinPlatformKind Platform, DarwinEnvironmentKind Environment, 333 unsigned Major, unsigned Minor, unsigned Micro) const { 334 // FIXME: For now, allow reinitialization as long as values don't 335 // change. This will go away when we move away from argument translation. 336 if (TargetInitialized && TargetPlatform == Platform && 337 TargetEnvironment == Environment && 338 TargetVersion == VersionTuple(Major, Minor, Micro)) 339 return; 340 341 assert(!TargetInitialized && "Target already initialized!"); 342 TargetInitialized = true; 343 TargetPlatform = Platform; 344 TargetEnvironment = Environment; 345 TargetVersion = VersionTuple(Major, Minor, Micro); 346 if (Environment == Simulator) 347 const_cast<Darwin *>(this)->setTripleEnvironment(llvm::Triple::Simulator); 348 } 349 350 bool isTargetIPhoneOS() const { 351 assert(TargetInitialized && "Target not initialized!"); 352 return (TargetPlatform == IPhoneOS || TargetPlatform == TvOS) && 353 TargetEnvironment == NativeEnvironment; 354 } 355 356 bool isTargetIOSSimulator() const { 357 assert(TargetInitialized && "Target not initialized!"); 358 return (TargetPlatform == IPhoneOS || TargetPlatform == TvOS) && 359 TargetEnvironment == Simulator; 360 } 361 362 bool isTargetIOSBased() const { 363 assert(TargetInitialized && "Target not initialized!"); 364 return isTargetIPhoneOS() || isTargetIOSSimulator(); 365 } 366 367 bool isTargetTvOS() const { 368 assert(TargetInitialized && "Target not initialized!"); 369 return TargetPlatform == TvOS && TargetEnvironment == NativeEnvironment; 370 } 371 372 bool isTargetTvOSSimulator() const { 373 assert(TargetInitialized && "Target not initialized!"); 374 return TargetPlatform == TvOS && TargetEnvironment == Simulator; 375 } 376 377 bool isTargetTvOSBased() const { 378 assert(TargetInitialized && "Target not initialized!"); 379 return TargetPlatform == TvOS; 380 } 381 382 bool isTargetWatchOS() const { 383 assert(TargetInitialized && "Target not initialized!"); 384 return TargetPlatform == WatchOS && TargetEnvironment == NativeEnvironment; 385 } 386 387 bool isTargetWatchOSSimulator() const { 388 assert(TargetInitialized && "Target not initialized!"); 389 return TargetPlatform == WatchOS && TargetEnvironment == Simulator; 390 } 391 392 bool isTargetWatchOSBased() const { 393 assert(TargetInitialized && "Target not initialized!"); 394 return TargetPlatform == WatchOS; 395 } 396 397 bool isTargetMacOS() const { 398 assert(TargetInitialized && "Target not initialized!"); 399 return TargetPlatform == MacOS; 400 } 401 402 bool isTargetInitialized() const { return TargetInitialized; } 403 404 VersionTuple getTargetVersion() const { 405 assert(TargetInitialized && "Target not initialized!"); 406 return TargetVersion; 407 } 408 409 bool isIPhoneOSVersionLT(unsigned V0, unsigned V1 = 0, 410 unsigned V2 = 0) const { 411 assert(isTargetIOSBased() && "Unexpected call for non iOS target!"); 412 return TargetVersion < VersionTuple(V0, V1, V2); 413 } 414 415 bool isMacosxVersionLT(unsigned V0, unsigned V1 = 0, unsigned V2 = 0) const { 416 assert(isTargetMacOS() && "Unexpected call for non OS X target!"); 417 return TargetVersion < VersionTuple(V0, V1, V2); 418 } 419 420 /// Return true if c++17 aligned allocation/deallocation functions are not 421 /// implemented in the c++ standard library of the deployment target we are 422 /// targeting. 423 bool isAlignedAllocationUnavailable() const; 424 425 void addClangTargetOptions(const llvm::opt::ArgList &DriverArgs, 426 llvm::opt::ArgStringList &CC1Args, 427 Action::OffloadKind DeviceOffloadKind) const override; 428 429 StringRef getPlatformFamily() const; 430 StringRef getOSLibraryNameSuffix(bool IgnoreSim = false) const override; 431 432 public: 433 static StringRef getSDKName(StringRef isysroot); 434 435 /// } 436 /// @name ToolChain Implementation 437 /// { 438 439 // Darwin tools support multiple architecture (e.g., i386 and x86_64) and 440 // most development is done against SDKs, so compiling for a different 441 // architecture should not get any special treatment. 442 bool isCrossCompiling() const override { return false; } 443 444 llvm::opt::DerivedArgList * 445 TranslateArgs(const llvm::opt::DerivedArgList &Args, StringRef BoundArch, 446 Action::OffloadKind DeviceOffloadKind) const override; 447 448 CXXStdlibType GetDefaultCXXStdlibType() const override; 449 ObjCRuntime getDefaultObjCRuntime(bool isNonFragile) const override; 450 bool hasBlocksRuntime() const override; 451 452 void AddCudaIncludeArgs(const llvm::opt::ArgList &DriverArgs, 453 llvm::opt::ArgStringList &CC1Args) const override; 454 455 bool UseObjCMixedDispatch() const override { 456 // This is only used with the non-fragile ABI and non-legacy dispatch. 457 458 // Mixed dispatch is used everywhere except OS X before 10.6. 459 return !(isTargetMacOS() && isMacosxVersionLT(10, 6)); 460 } 461 462 unsigned GetDefaultStackProtectorLevel(bool KernelOrKext) const override { 463 // Stack protectors default to on for user code on 10.5, 464 // and for everything in 10.6 and beyond 465 if (isTargetIOSBased() || isTargetWatchOSBased()) 466 return 1; 467 else if (isTargetMacOS() && !isMacosxVersionLT(10, 6)) 468 return 1; 469 else if (isTargetMacOS() && !isMacosxVersionLT(10, 5) && !KernelOrKext) 470 return 1; 471 472 return 0; 473 } 474 475 void CheckObjCARC() const override; 476 477 llvm::ExceptionHandling GetExceptionModel( 478 const llvm::opt::ArgList &Args) const override; 479 480 bool SupportsEmbeddedBitcode() const override; 481 482 SanitizerMask getSupportedSanitizers() const override; 483 484 void printVerboseInfo(raw_ostream &OS) const override; 485 }; 486 487 /// DarwinClang - The Darwin toolchain used by Clang. 488 class LLVM_LIBRARY_VISIBILITY DarwinClang : public Darwin { 489 public: 490 DarwinClang(const Driver &D, const llvm::Triple &Triple, 491 const llvm::opt::ArgList &Args); 492 493 /// @name Apple ToolChain Implementation 494 /// { 495 496 RuntimeLibType GetRuntimeLibType(const llvm::opt::ArgList &Args) const override; 497 498 void AddLinkRuntimeLibArgs(const llvm::opt::ArgList &Args, 499 llvm::opt::ArgStringList &CmdArgs, 500 bool ForceLinkBuiltinRT = false) const override; 501 502 void AddClangCXXStdlibIncludeArgs( 503 const llvm::opt::ArgList &DriverArgs, 504 llvm::opt::ArgStringList &CC1Args) const override; 505 506 void AddClangSystemIncludeArgs(const llvm::opt::ArgList &DriverArgs, 507 llvm::opt::ArgStringList &CC1Args) const override; 508 509 void AddCXXStdlibLibArgs(const llvm::opt::ArgList &Args, 510 llvm::opt::ArgStringList &CmdArgs) const override; 511 512 void AddCCKextLibArgs(const llvm::opt::ArgList &Args, 513 llvm::opt::ArgStringList &CmdArgs) const override; 514 515 void addClangWarningOptions(llvm::opt::ArgStringList &CC1Args) const override; 516 517 void AddLinkARCArgs(const llvm::opt::ArgList &Args, 518 llvm::opt::ArgStringList &CmdArgs) const override; 519 520 unsigned GetDefaultDwarfVersion() const override; 521 // Until dtrace (via CTF) and LLDB can deal with distributed debug info, 522 // Darwin defaults to standalone/full debug info. 523 bool GetDefaultStandaloneDebug() const override { return true; } 524 llvm::DebuggerKind getDefaultDebuggerTuning() const override { 525 return llvm::DebuggerKind::LLDB; 526 } 527 528 /// } 529 530 private: 531 void AddLinkSanitizerLibArgs(const llvm::opt::ArgList &Args, 532 llvm::opt::ArgStringList &CmdArgs, 533 StringRef Sanitizer, 534 bool shared = true) const; 535 536 bool AddGnuCPlusPlusIncludePaths(const llvm::opt::ArgList &DriverArgs, 537 llvm::opt::ArgStringList &CC1Args, 538 llvm::SmallString<128> Base, 539 llvm::StringRef Version, 540 llvm::StringRef ArchDir, 541 llvm::StringRef BitDir) const; 542 543 llvm::StringRef GetHeaderSysroot(const llvm::opt::ArgList &DriverArgs) const; 544 }; 545 546 } // end namespace toolchains 547 } // end namespace driver 548 } // end namespace clang 549 550 #endif // LLVM_CLANG_LIB_DRIVER_TOOLCHAINS_DARWIN_H 551