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