1 //===--- Darwin.h - Darwin ToolChain Implementations ------------*- C++ -*-===// 2 // 3 // The LLVM Compiler Infrastructure 4 // 5 // This file is distributed under the University of Illinois Open Source 6 // License. See LICENSE.TXT for details. 7 // 8 //===----------------------------------------------------------------------===// 9 10 #ifndef LLVM_CLANG_LIB_DRIVER_TOOLCHAINS_DARWIN_H 11 #define LLVM_CLANG_LIB_DRIVER_TOOLCHAINS_DARWIN_H 12 13 #include "Cuda.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 getMachOToolChain()39 const toolchains::MachO &getMachOToolChain() const { 40 return reinterpret_cast<const toolchains::MachO &>(getToolChain()); 41 } 42 43 public: 44 MachOTool( 45 const char *Name, const char *ShortName, const ToolChain &TC, 46 ResponseFileSupport ResponseSupport = RF_None, 47 llvm::sys::WindowsEncodingMethod ResponseEncoding = llvm::sys::WEM_UTF8, 48 const char *ResponseFlag = "@") Tool(Name,ShortName,TC,ResponseSupport,ResponseEncoding,ResponseFlag)49 : Tool(Name, ShortName, TC, ResponseSupport, ResponseEncoding, 50 ResponseFlag) {} 51 }; 52 53 class LLVM_LIBRARY_VISIBILITY Assembler : public MachOTool { 54 public: Assembler(const ToolChain & TC)55 Assembler(const ToolChain &TC) 56 : MachOTool("darwin::Assembler", "assembler", TC) {} 57 hasIntegratedCPP()58 bool hasIntegratedCPP() const override { return false; } 59 60 void ConstructJob(Compilation &C, const JobAction &JA, 61 const InputInfo &Output, const InputInfoList &Inputs, 62 const llvm::opt::ArgList &TCArgs, 63 const char *LinkingOutput) const override; 64 }; 65 66 class LLVM_LIBRARY_VISIBILITY Linker : public MachOTool { 67 bool NeedsTempPath(const InputInfoList &Inputs) const; 68 void AddLinkArgs(Compilation &C, const llvm::opt::ArgList &Args, 69 llvm::opt::ArgStringList &CmdArgs, 70 const InputInfoList &Inputs) const; 71 72 public: Linker(const ToolChain & TC)73 Linker(const ToolChain &TC) 74 : MachOTool("darwin::Linker", "linker", TC, RF_FileList, 75 llvm::sys::WEM_UTF8, "-filelist") {} 76 hasIntegratedCPP()77 bool hasIntegratedCPP() const override { return false; } isLinkJob()78 bool isLinkJob() const override { return true; } 79 80 void ConstructJob(Compilation &C, const JobAction &JA, 81 const InputInfo &Output, const InputInfoList &Inputs, 82 const llvm::opt::ArgList &TCArgs, 83 const char *LinkingOutput) const override; 84 }; 85 86 class LLVM_LIBRARY_VISIBILITY Lipo : public MachOTool { 87 public: Lipo(const ToolChain & TC)88 Lipo(const ToolChain &TC) : MachOTool("darwin::Lipo", "lipo", TC) {} 89 hasIntegratedCPP()90 bool hasIntegratedCPP() const override { return false; } 91 92 void ConstructJob(Compilation &C, const JobAction &JA, 93 const InputInfo &Output, const InputInfoList &Inputs, 94 const llvm::opt::ArgList &TCArgs, 95 const char *LinkingOutput) const override; 96 }; 97 98 class LLVM_LIBRARY_VISIBILITY Dsymutil : public MachOTool { 99 public: Dsymutil(const ToolChain & TC)100 Dsymutil(const ToolChain &TC) 101 : MachOTool("darwin::Dsymutil", "dsymutil", TC) {} 102 hasIntegratedCPP()103 bool hasIntegratedCPP() const override { return false; } isDsymutilJob()104 bool isDsymutilJob() const override { return true; } 105 106 void ConstructJob(Compilation &C, const JobAction &JA, 107 const InputInfo &Output, const InputInfoList &Inputs, 108 const llvm::opt::ArgList &TCArgs, 109 const char *LinkingOutput) const override; 110 }; 111 112 class LLVM_LIBRARY_VISIBILITY VerifyDebug : public MachOTool { 113 public: VerifyDebug(const ToolChain & TC)114 VerifyDebug(const ToolChain &TC) 115 : MachOTool("darwin::VerifyDebug", "dwarfdump", TC) {} 116 hasIntegratedCPP()117 bool hasIntegratedCPP() const override { return false; } 118 119 void ConstructJob(Compilation &C, const JobAction &JA, 120 const InputInfo &Output, const InputInfoList &Inputs, 121 const llvm::opt::ArgList &TCArgs, 122 const char *LinkingOutput) const override; 123 }; 124 } // end namespace darwin 125 } // end namespace tools 126 127 namespace toolchains { 128 129 class LLVM_LIBRARY_VISIBILITY MachO : public ToolChain { 130 protected: 131 Tool *buildAssembler() const override; 132 Tool *buildLinker() const override; 133 Tool *getTool(Action::ActionClass AC) const override; 134 135 private: 136 mutable std::unique_ptr<tools::darwin::Lipo> Lipo; 137 mutable std::unique_ptr<tools::darwin::Dsymutil> Dsymutil; 138 mutable std::unique_ptr<tools::darwin::VerifyDebug> VerifyDebug; 139 140 public: 141 MachO(const Driver &D, const llvm::Triple &Triple, 142 const llvm::opt::ArgList &Args); 143 ~MachO() override; 144 145 /// @name MachO specific toolchain API 146 /// { 147 148 /// Get the "MachO" arch name for a particular compiler invocation. For 149 /// example, Apple treats different ARM variations as distinct architectures. 150 StringRef getMachOArchName(const llvm::opt::ArgList &Args) const; 151 152 /// Add the linker arguments to link the ARC runtime library. AddLinkARCArgs(const llvm::opt::ArgList & Args,llvm::opt::ArgStringList & CmdArgs)153 virtual void AddLinkARCArgs(const llvm::opt::ArgList &Args, 154 llvm::opt::ArgStringList &CmdArgs) const {} 155 156 /// Add the linker arguments to link the compiler runtime library. 157 /// 158 /// FIXME: This API is intended for use with embedded libraries only, and is 159 /// misleadingly named. 160 virtual void AddLinkRuntimeLibArgs(const llvm::opt::ArgList &Args, 161 llvm::opt::ArgStringList &CmdArgs) const; 162 addStartObjectFileArgs(const llvm::opt::ArgList & Args,llvm::opt::ArgStringList & CmdArgs)163 virtual void addStartObjectFileArgs(const llvm::opt::ArgList &Args, 164 llvm::opt::ArgStringList &CmdArgs) const { 165 } 166 addMinVersionArgs(const llvm::opt::ArgList & Args,llvm::opt::ArgStringList & CmdArgs)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? isKernelStatic()172 virtual bool isKernelStatic() const { return false; } 173 174 /// Is the target either iOS or an iOS simulator? isTargetIOSBased()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. addProfileRTLibs(const llvm::opt::ArgList & Args,llvm::opt::ArgStringList & CmdArgs)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 IsBlocksDefault()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 } IsIntegratedAssemblerDefault()222 bool IsIntegratedAssemblerDefault() const override { 223 // Default integrated assembler to on for Apple's MachO targets. 224 return true; 225 } 226 IsMathErrnoDefault()227 bool IsMathErrnoDefault() const override { return false; } 228 IsEncodeExtendedBlockSignatureDefault()229 bool IsEncodeExtendedBlockSignatureDefault() const override { return true; } 230 IsObjCNonFragileABIDefault()231 bool IsObjCNonFragileABIDefault() const override { 232 // Non-fragile ABI is default for everything but i386. 233 return getTriple().getArch() != llvm::Triple::x86; 234 } 235 UseObjCMixedDispatch()236 bool UseObjCMixedDispatch() const override { return true; } 237 238 bool IsUnwindTablesDefault(const llvm::opt::ArgList &Args) const override; 239 GetDefaultRuntimeLibType()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 GetExceptionModel(const llvm::opt::ArgList & Args)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 isKernelStatic()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. setTarget(DarwinPlatformKind Platform,DarwinEnvironmentKind Environment,unsigned Major,unsigned Minor,unsigned Micro)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 isTargetIPhoneOS()350 bool isTargetIPhoneOS() const { 351 assert(TargetInitialized && "Target not initialized!"); 352 return (TargetPlatform == IPhoneOS || TargetPlatform == TvOS) && 353 TargetEnvironment == NativeEnvironment; 354 } 355 isTargetIOSSimulator()356 bool isTargetIOSSimulator() const { 357 assert(TargetInitialized && "Target not initialized!"); 358 return (TargetPlatform == IPhoneOS || TargetPlatform == TvOS) && 359 TargetEnvironment == Simulator; 360 } 361 isTargetIOSBased()362 bool isTargetIOSBased() const { 363 assert(TargetInitialized && "Target not initialized!"); 364 return isTargetIPhoneOS() || isTargetIOSSimulator(); 365 } 366 isTargetTvOS()367 bool isTargetTvOS() const { 368 assert(TargetInitialized && "Target not initialized!"); 369 return TargetPlatform == TvOS && TargetEnvironment == NativeEnvironment; 370 } 371 isTargetTvOSSimulator()372 bool isTargetTvOSSimulator() const { 373 assert(TargetInitialized && "Target not initialized!"); 374 return TargetPlatform == TvOS && TargetEnvironment == Simulator; 375 } 376 isTargetTvOSBased()377 bool isTargetTvOSBased() const { 378 assert(TargetInitialized && "Target not initialized!"); 379 return TargetPlatform == TvOS; 380 } 381 isTargetWatchOS()382 bool isTargetWatchOS() const { 383 assert(TargetInitialized && "Target not initialized!"); 384 return TargetPlatform == WatchOS && TargetEnvironment == NativeEnvironment; 385 } 386 isTargetWatchOSSimulator()387 bool isTargetWatchOSSimulator() const { 388 assert(TargetInitialized && "Target not initialized!"); 389 return TargetPlatform == WatchOS && TargetEnvironment == Simulator; 390 } 391 isTargetWatchOSBased()392 bool isTargetWatchOSBased() const { 393 assert(TargetInitialized && "Target not initialized!"); 394 return TargetPlatform == WatchOS; 395 } 396 isTargetMacOS()397 bool isTargetMacOS() const { 398 assert(TargetInitialized && "Target not initialized!"); 399 return TargetPlatform == MacOS; 400 } 401 isTargetInitialized()402 bool isTargetInitialized() const { return TargetInitialized; } 403 getTargetVersion()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. isCrossCompiling()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 UseObjCMixedDispatch()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 GetDefaultStackProtectorLevel(bool KernelOrKext)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) const override; 500 501 void AddClangCXXStdlibIncludeArgs( 502 const llvm::opt::ArgList &DriverArgs, 503 llvm::opt::ArgStringList &CC1Args) const override; 504 505 void AddCXXStdlibLibArgs(const llvm::opt::ArgList &Args, 506 llvm::opt::ArgStringList &CmdArgs) const override; 507 508 void AddCCKextLibArgs(const llvm::opt::ArgList &Args, 509 llvm::opt::ArgStringList &CmdArgs) const override; 510 511 void addClangWarningOptions(llvm::opt::ArgStringList &CC1Args) const override; 512 513 void AddLinkARCArgs(const llvm::opt::ArgList &Args, 514 llvm::opt::ArgStringList &CmdArgs) const override; 515 516 unsigned GetDefaultDwarfVersion() const override; 517 // Until dtrace (via CTF) and LLDB can deal with distributed debug info, 518 // Darwin defaults to standalone/full debug info. GetDefaultStandaloneDebug()519 bool GetDefaultStandaloneDebug() const override { return true; } getDefaultDebuggerTuning()520 llvm::DebuggerKind getDefaultDebuggerTuning() const override { 521 return llvm::DebuggerKind::LLDB; 522 } 523 524 /// } 525 526 private: 527 void AddLinkSanitizerLibArgs(const llvm::opt::ArgList &Args, 528 llvm::opt::ArgStringList &CmdArgs, 529 StringRef Sanitizer, 530 bool shared = true) const; 531 }; 532 533 } // end namespace toolchains 534 } // end namespace driver 535 } // end namespace clang 536 537 #endif // LLVM_CLANG_LIB_DRIVER_TOOLCHAINS_DARWIN_H 538