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