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