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