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