xref: /netbsd-src/external/apache2/llvm/dist/clang/lib/Driver/ToolChains/Darwin.h (revision 9fb66d812c00ebfb445c0b47dea128f32aa6fe96)
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   /// 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     /// Link the library in before any others.
189     RLO_FirstLink = 1 << 3,
190   };
191 
192   /// Add a runtime library to the list of items to link.
193   void AddLinkRuntimeLib(const llvm::opt::ArgList &Args,
194                          llvm::opt::ArgStringList &CmdArgs, StringRef Component,
195                          RuntimeLinkOptions Opts = RuntimeLinkOptions(),
196                          bool IsShared = false) const;
197 
198   /// Add any profiling runtime libraries that are needed. This is essentially a
199   /// MachO specific version of addProfileRT in Tools.cpp.
200   void addProfileRTLibs(const llvm::opt::ArgList &Args,
201                         llvm::opt::ArgStringList &CmdArgs) const override {
202     // There aren't any profiling libs for embedded targets currently.
203   }
204 
205   /// }
206   /// @name ToolChain Implementation
207   /// {
208 
209   types::ID LookupTypeForExtension(StringRef Ext) const override;
210 
211   bool HasNativeLLVMSupport() const override;
212 
213   llvm::opt::DerivedArgList *
214   TranslateArgs(const llvm::opt::DerivedArgList &Args, StringRef BoundArch,
215                 Action::OffloadKind DeviceOffloadKind) const override;
216 
217   bool IsBlocksDefault() const override {
218     // Always allow blocks on Apple; users interested in versioning are
219     // expected to use /usr/include/Block.h.
220     return true;
221   }
222   bool IsIntegratedAssemblerDefault() const override {
223     // Default integrated assembler to on for Apple's MachO targets.
224     return true;
225   }
226 
227   bool IsMathErrnoDefault() const override { return false; }
228 
229   bool IsEncodeExtendedBlockSignatureDefault() const override { return true; }
230 
231   bool IsObjCNonFragileABIDefault() const override {
232     // Non-fragile ABI is default for everything but i386.
233     return getTriple().getArch() != llvm::Triple::x86;
234   }
235 
236   bool UseObjCMixedDispatch() const override { return true; }
237 
238   bool IsUnwindTablesDefault(const llvm::opt::ArgList &Args) const override;
239 
240   RuntimeLibType GetDefaultRuntimeLibType() const override {
241     return ToolChain::RLT_CompilerRT;
242   }
243 
244   bool isPICDefault() const override;
245   bool isPIEDefault() const override;
246   bool isPICDefaultForced() const override;
247 
248   bool SupportsProfiling() const override;
249 
250   bool UseDwarfDebugFlags() const override;
251 
252   llvm::ExceptionHandling
253   GetExceptionModel(const llvm::opt::ArgList &Args) const override {
254     return llvm::ExceptionHandling::None;
255   }
256 
257   virtual StringRef getOSLibraryNameSuffix(bool IgnoreSim = false) const {
258     return "";
259   }
260 
261   // Darwin toolchain uses legacy thin LTO API, which is not
262   // capable of unit splitting.
263   bool canSplitThinLTOUnit() const override { return false; }
264   /// }
265 };
266 
267 /// Darwin - The base Darwin tool chain.
268 class LLVM_LIBRARY_VISIBILITY Darwin : public MachO {
269 public:
270   /// Whether the information on the target has been initialized.
271   //
272   // FIXME: This should be eliminated. What we want to do is make this part of
273   // the "default target for arguments" selection process, once we get out of
274   // the argument translation business.
275   mutable bool TargetInitialized;
276 
277   enum DarwinPlatformKind {
278     MacOS,
279     IPhoneOS,
280     TvOS,
281     WatchOS,
282     LastDarwinPlatform = WatchOS
283   };
284   enum DarwinEnvironmentKind {
285     NativeEnvironment,
286     Simulator,
287   };
288 
289   mutable DarwinPlatformKind TargetPlatform;
290   mutable DarwinEnvironmentKind TargetEnvironment;
291 
292   /// The OS version we are targeting.
293   mutable VersionTuple TargetVersion;
294 
295   /// The information about the darwin SDK that was used.
296   mutable Optional<DarwinSDKInfo> SDKInfo;
297 
298   CudaInstallationDetector CudaInstallation;
299 
300 private:
301   void AddDeploymentTarget(llvm::opt::DerivedArgList &Args) const;
302 
303 public:
304   Darwin(const Driver &D, const llvm::Triple &Triple,
305          const llvm::opt::ArgList &Args);
306   ~Darwin() override;
307 
308   std::string ComputeEffectiveClangTriple(const llvm::opt::ArgList &Args,
309                                           types::ID InputType) const override;
310 
311   /// @name Apple Specific Toolchain Implementation
312   /// {
313 
314   void addMinVersionArgs(const llvm::opt::ArgList &Args,
315                          llvm::opt::ArgStringList &CmdArgs) const override;
316 
317   void addStartObjectFileArgs(const llvm::opt::ArgList &Args,
318                               llvm::opt::ArgStringList &CmdArgs) const override;
319 
320   bool isKernelStatic() const override {
321     return (!(isTargetIPhoneOS() && !isIPhoneOSVersionLT(6, 0)) &&
322             !isTargetWatchOS());
323   }
324 
325   void addProfileRTLibs(const llvm::opt::ArgList &Args,
326                         llvm::opt::ArgStringList &CmdArgs) const override;
327 
328 protected:
329   /// }
330   /// @name Darwin specific Toolchain functions
331   /// {
332 
333   // FIXME: Eliminate these ...Target functions and derive separate tool chains
334   // for these targets and put version in constructor.
335   void setTarget(DarwinPlatformKind Platform, DarwinEnvironmentKind Environment,
336                  unsigned Major, unsigned Minor, unsigned Micro) const {
337     // FIXME: For now, allow reinitialization as long as values don't
338     // change. This will go away when we move away from argument translation.
339     if (TargetInitialized && TargetPlatform == Platform &&
340         TargetEnvironment == Environment &&
341         TargetVersion == VersionTuple(Major, Minor, Micro))
342       return;
343 
344     assert(!TargetInitialized && "Target already initialized!");
345     TargetInitialized = true;
346     TargetPlatform = Platform;
347     TargetEnvironment = Environment;
348     TargetVersion = VersionTuple(Major, Minor, Micro);
349     if (Environment == Simulator)
350       const_cast<Darwin *>(this)->setTripleEnvironment(llvm::Triple::Simulator);
351   }
352 
353   bool isTargetIPhoneOS() const {
354     assert(TargetInitialized && "Target not initialized!");
355     return (TargetPlatform == IPhoneOS || TargetPlatform == TvOS) &&
356            TargetEnvironment == NativeEnvironment;
357   }
358 
359   bool isTargetIOSSimulator() const {
360     assert(TargetInitialized && "Target not initialized!");
361     return (TargetPlatform == IPhoneOS || TargetPlatform == TvOS) &&
362            TargetEnvironment == Simulator;
363   }
364 
365   bool isTargetIOSBased() const {
366     assert(TargetInitialized && "Target not initialized!");
367     return isTargetIPhoneOS() || isTargetIOSSimulator();
368   }
369 
370   bool isTargetTvOS() const {
371     assert(TargetInitialized && "Target not initialized!");
372     return TargetPlatform == TvOS && TargetEnvironment == NativeEnvironment;
373   }
374 
375   bool isTargetTvOSSimulator() const {
376     assert(TargetInitialized && "Target not initialized!");
377     return TargetPlatform == TvOS && TargetEnvironment == Simulator;
378   }
379 
380   bool isTargetTvOSBased() const {
381     assert(TargetInitialized && "Target not initialized!");
382     return TargetPlatform == TvOS;
383   }
384 
385   bool isTargetWatchOS() const {
386     assert(TargetInitialized && "Target not initialized!");
387     return TargetPlatform == WatchOS && TargetEnvironment == NativeEnvironment;
388   }
389 
390   bool isTargetWatchOSSimulator() const {
391     assert(TargetInitialized && "Target not initialized!");
392     return TargetPlatform == WatchOS && TargetEnvironment == Simulator;
393   }
394 
395   bool isTargetWatchOSBased() const {
396     assert(TargetInitialized && "Target not initialized!");
397     return TargetPlatform == WatchOS;
398   }
399 
400   bool isTargetMacOS() const {
401     assert(TargetInitialized && "Target not initialized!");
402     return TargetPlatform == MacOS;
403   }
404 
405   bool isTargetInitialized() const { return TargetInitialized; }
406 
407   VersionTuple getTargetVersion() const {
408     assert(TargetInitialized && "Target not initialized!");
409     return TargetVersion;
410   }
411 
412   bool isIPhoneOSVersionLT(unsigned V0, unsigned V1 = 0,
413                            unsigned V2 = 0) const {
414     assert(isTargetIOSBased() && "Unexpected call for non iOS target!");
415     return TargetVersion < VersionTuple(V0, V1, V2);
416   }
417 
418   bool isMacosxVersionLT(unsigned V0, unsigned V1 = 0, unsigned V2 = 0) const {
419     assert(isTargetMacOS() && "Unexpected call for non OS X target!");
420     return TargetVersion < VersionTuple(V0, V1, V2);
421   }
422 
423   /// Return true if c++17 aligned allocation/deallocation functions are not
424   /// implemented in the c++ standard library of the deployment target we are
425   /// targeting.
426   bool isAlignedAllocationUnavailable() const;
427 
428   void addClangTargetOptions(const llvm::opt::ArgList &DriverArgs,
429                              llvm::opt::ArgStringList &CC1Args,
430                              Action::OffloadKind DeviceOffloadKind) const override;
431 
432   StringRef getPlatformFamily() const;
433   StringRef getOSLibraryNameSuffix(bool IgnoreSim = false) const override;
434 
435 public:
436   static StringRef getSDKName(StringRef isysroot);
437 
438   /// }
439   /// @name ToolChain Implementation
440   /// {
441 
442   // Darwin tools support multiple architecture (e.g., i386 and x86_64) and
443   // most development is done against SDKs, so compiling for a different
444   // architecture should not get any special treatment.
445   bool isCrossCompiling() const override { return false; }
446 
447   llvm::opt::DerivedArgList *
448   TranslateArgs(const llvm::opt::DerivedArgList &Args, StringRef BoundArch,
449                 Action::OffloadKind DeviceOffloadKind) const override;
450 
451   CXXStdlibType GetDefaultCXXStdlibType() const override;
452   ObjCRuntime getDefaultObjCRuntime(bool isNonFragile) const override;
453   bool hasBlocksRuntime() const override;
454 
455   void AddCudaIncludeArgs(const llvm::opt::ArgList &DriverArgs,
456                           llvm::opt::ArgStringList &CC1Args) const override;
457 
458   bool UseObjCMixedDispatch() const override {
459     // This is only used with the non-fragile ABI and non-legacy dispatch.
460 
461     // Mixed dispatch is used everywhere except OS X before 10.6.
462     return !(isTargetMacOS() && isMacosxVersionLT(10, 6));
463   }
464 
465   unsigned GetDefaultStackProtectorLevel(bool KernelOrKext) const override {
466     // Stack protectors default to on for user code on 10.5,
467     // and for everything in 10.6 and beyond
468     if (isTargetIOSBased() || isTargetWatchOSBased())
469       return 1;
470     else if (isTargetMacOS() && !isMacosxVersionLT(10, 6))
471       return 1;
472     else if (isTargetMacOS() && !isMacosxVersionLT(10, 5) && !KernelOrKext)
473       return 1;
474 
475     return 0;
476   }
477 
478   void CheckObjCARC() const override;
479 
480   llvm::ExceptionHandling GetExceptionModel(
481       const llvm::opt::ArgList &Args) const override;
482 
483   bool SupportsEmbeddedBitcode() const override;
484 
485   SanitizerMask getSupportedSanitizers() const override;
486 
487   void printVerboseInfo(raw_ostream &OS) const override;
488 };
489 
490 /// DarwinClang - The Darwin toolchain used by Clang.
491 class LLVM_LIBRARY_VISIBILITY DarwinClang : public Darwin {
492 public:
493   DarwinClang(const Driver &D, const llvm::Triple &Triple,
494               const llvm::opt::ArgList &Args);
495 
496   /// @name Apple ToolChain Implementation
497   /// {
498 
499   RuntimeLibType GetRuntimeLibType(const llvm::opt::ArgList &Args) const override;
500 
501   void AddLinkRuntimeLibArgs(const llvm::opt::ArgList &Args,
502                              llvm::opt::ArgStringList &CmdArgs,
503                              bool ForceLinkBuiltinRT = false) const override;
504 
505   void AddClangCXXStdlibIncludeArgs(
506       const llvm::opt::ArgList &DriverArgs,
507       llvm::opt::ArgStringList &CC1Args) const override;
508 
509   void AddClangSystemIncludeArgs(const llvm::opt::ArgList &DriverArgs,
510                                  llvm::opt::ArgStringList &CC1Args) const override;
511 
512   void AddCXXStdlibLibArgs(const llvm::opt::ArgList &Args,
513                            llvm::opt::ArgStringList &CmdArgs) const override;
514 
515   void AddCCKextLibArgs(const llvm::opt::ArgList &Args,
516                         llvm::opt::ArgStringList &CmdArgs) const override;
517 
518   void addClangWarningOptions(llvm::opt::ArgStringList &CC1Args) const override;
519 
520   void AddLinkARCArgs(const llvm::opt::ArgList &Args,
521                       llvm::opt::ArgStringList &CmdArgs) const override;
522 
523   unsigned GetDefaultDwarfVersion() const override;
524   // Until dtrace (via CTF) and LLDB can deal with distributed debug info,
525   // Darwin defaults to standalone/full debug info.
526   bool GetDefaultStandaloneDebug() const override { return true; }
527   llvm::DebuggerKind getDefaultDebuggerTuning() const override {
528     return llvm::DebuggerKind::LLDB;
529   }
530 
531   /// }
532 
533 private:
534   void AddLinkSanitizerLibArgs(const llvm::opt::ArgList &Args,
535                                llvm::opt::ArgStringList &CmdArgs,
536                                StringRef Sanitizer,
537                                bool shared = true) const;
538 
539   bool AddGnuCPlusPlusIncludePaths(const llvm::opt::ArgList &DriverArgs,
540                                    llvm::opt::ArgStringList &CC1Args,
541                                    llvm::SmallString<128> Base,
542                                    llvm::StringRef Version,
543                                    llvm::StringRef ArchDir,
544                                    llvm::StringRef BitDir) const;
545 
546   llvm::StringRef GetHeaderSysroot(const llvm::opt::ArgList &DriverArgs) const;
547 };
548 
549 } // end namespace toolchains
550 } // end namespace driver
551 } // end namespace clang
552 
553 #endif // LLVM_CLANG_LIB_DRIVER_TOOLCHAINS_DARWIN_H
554