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