xref: /freebsd/contrib/llvm-project/clang/lib/Driver/ToolChains/Darwin.h (revision 6966ac055c3b7a39266fb982493330df7a097997)
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   /// }
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   };
285 
286   mutable DarwinPlatformKind TargetPlatform;
287   mutable DarwinEnvironmentKind TargetEnvironment;
288 
289   /// The OS version we are targeting.
290   mutable VersionTuple TargetVersion;
291 
292   /// The information about the darwin SDK that was used.
293   mutable Optional<DarwinSDKInfo> SDKInfo;
294 
295   CudaInstallationDetector CudaInstallation;
296 
297 private:
298   void AddDeploymentTarget(llvm::opt::DerivedArgList &Args) const;
299 
300 public:
301   Darwin(const Driver &D, const llvm::Triple &Triple,
302          const llvm::opt::ArgList &Args);
303   ~Darwin() override;
304 
305   std::string ComputeEffectiveClangTriple(const llvm::opt::ArgList &Args,
306                                           types::ID InputType) const override;
307 
308   /// @name Apple Specific Toolchain Implementation
309   /// {
310 
311   void addMinVersionArgs(const llvm::opt::ArgList &Args,
312                          llvm::opt::ArgStringList &CmdArgs) const override;
313 
314   void addStartObjectFileArgs(const llvm::opt::ArgList &Args,
315                               llvm::opt::ArgStringList &CmdArgs) const override;
316 
317   bool isKernelStatic() const override {
318     return (!(isTargetIPhoneOS() && !isIPhoneOSVersionLT(6, 0)) &&
319             !isTargetWatchOS());
320   }
321 
322   void addProfileRTLibs(const llvm::opt::ArgList &Args,
323                         llvm::opt::ArgStringList &CmdArgs) const override;
324 
325 protected:
326   /// }
327   /// @name Darwin specific Toolchain functions
328   /// {
329 
330   // FIXME: Eliminate these ...Target functions and derive separate tool chains
331   // for these targets and put version in constructor.
332   void setTarget(DarwinPlatformKind Platform, DarwinEnvironmentKind Environment,
333                  unsigned Major, unsigned Minor, unsigned Micro) const {
334     // FIXME: For now, allow reinitialization as long as values don't
335     // change. This will go away when we move away from argument translation.
336     if (TargetInitialized && TargetPlatform == Platform &&
337         TargetEnvironment == Environment &&
338         TargetVersion == VersionTuple(Major, Minor, Micro))
339       return;
340 
341     assert(!TargetInitialized && "Target already initialized!");
342     TargetInitialized = true;
343     TargetPlatform = Platform;
344     TargetEnvironment = Environment;
345     TargetVersion = VersionTuple(Major, Minor, Micro);
346     if (Environment == Simulator)
347       const_cast<Darwin *>(this)->setTripleEnvironment(llvm::Triple::Simulator);
348   }
349 
350   bool isTargetIPhoneOS() const {
351     assert(TargetInitialized && "Target not initialized!");
352     return (TargetPlatform == IPhoneOS || TargetPlatform == TvOS) &&
353            TargetEnvironment == NativeEnvironment;
354   }
355 
356   bool isTargetIOSSimulator() const {
357     assert(TargetInitialized && "Target not initialized!");
358     return (TargetPlatform == IPhoneOS || TargetPlatform == TvOS) &&
359            TargetEnvironment == Simulator;
360   }
361 
362   bool isTargetIOSBased() const {
363     assert(TargetInitialized && "Target not initialized!");
364     return isTargetIPhoneOS() || isTargetIOSSimulator();
365   }
366 
367   bool isTargetTvOS() const {
368     assert(TargetInitialized && "Target not initialized!");
369     return TargetPlatform == TvOS && TargetEnvironment == NativeEnvironment;
370   }
371 
372   bool isTargetTvOSSimulator() const {
373     assert(TargetInitialized && "Target not initialized!");
374     return TargetPlatform == TvOS && TargetEnvironment == Simulator;
375   }
376 
377   bool isTargetTvOSBased() const {
378     assert(TargetInitialized && "Target not initialized!");
379     return TargetPlatform == TvOS;
380   }
381 
382   bool isTargetWatchOS() const {
383     assert(TargetInitialized && "Target not initialized!");
384     return TargetPlatform == WatchOS && TargetEnvironment == NativeEnvironment;
385   }
386 
387   bool isTargetWatchOSSimulator() const {
388     assert(TargetInitialized && "Target not initialized!");
389     return TargetPlatform == WatchOS && TargetEnvironment == Simulator;
390   }
391 
392   bool isTargetWatchOSBased() const {
393     assert(TargetInitialized && "Target not initialized!");
394     return TargetPlatform == WatchOS;
395   }
396 
397   bool isTargetMacOS() const {
398     assert(TargetInitialized && "Target not initialized!");
399     return TargetPlatform == MacOS;
400   }
401 
402   bool isTargetInitialized() const { return TargetInitialized; }
403 
404   VersionTuple getTargetVersion() const {
405     assert(TargetInitialized && "Target not initialized!");
406     return TargetVersion;
407   }
408 
409   bool isIPhoneOSVersionLT(unsigned V0, unsigned V1 = 0,
410                            unsigned V2 = 0) const {
411     assert(isTargetIOSBased() && "Unexpected call for non iOS target!");
412     return TargetVersion < VersionTuple(V0, V1, V2);
413   }
414 
415   bool isMacosxVersionLT(unsigned V0, unsigned V1 = 0, unsigned V2 = 0) const {
416     assert(isTargetMacOS() && "Unexpected call for non OS X target!");
417     return TargetVersion < VersionTuple(V0, V1, V2);
418   }
419 
420   /// Return true if c++17 aligned allocation/deallocation functions are not
421   /// implemented in the c++ standard library of the deployment target we are
422   /// targeting.
423   bool isAlignedAllocationUnavailable() const;
424 
425   void addClangTargetOptions(const llvm::opt::ArgList &DriverArgs,
426                              llvm::opt::ArgStringList &CC1Args,
427                              Action::OffloadKind DeviceOffloadKind) const override;
428 
429   StringRef getPlatformFamily() const;
430   StringRef getOSLibraryNameSuffix(bool IgnoreSim = false) const override;
431 
432 public:
433   static StringRef getSDKName(StringRef isysroot);
434 
435   /// }
436   /// @name ToolChain Implementation
437   /// {
438 
439   // Darwin tools support multiple architecture (e.g., i386 and x86_64) and
440   // most development is done against SDKs, so compiling for a different
441   // architecture should not get any special treatment.
442   bool isCrossCompiling() const override { return false; }
443 
444   llvm::opt::DerivedArgList *
445   TranslateArgs(const llvm::opt::DerivedArgList &Args, StringRef BoundArch,
446                 Action::OffloadKind DeviceOffloadKind) const override;
447 
448   CXXStdlibType GetDefaultCXXStdlibType() const override;
449   ObjCRuntime getDefaultObjCRuntime(bool isNonFragile) const override;
450   bool hasBlocksRuntime() const override;
451 
452   void AddCudaIncludeArgs(const llvm::opt::ArgList &DriverArgs,
453                           llvm::opt::ArgStringList &CC1Args) const override;
454 
455   bool UseObjCMixedDispatch() const override {
456     // This is only used with the non-fragile ABI and non-legacy dispatch.
457 
458     // Mixed dispatch is used everywhere except OS X before 10.6.
459     return !(isTargetMacOS() && isMacosxVersionLT(10, 6));
460   }
461 
462   unsigned GetDefaultStackProtectorLevel(bool KernelOrKext) const override {
463     // Stack protectors default to on for user code on 10.5,
464     // and for everything in 10.6 and beyond
465     if (isTargetIOSBased() || isTargetWatchOSBased())
466       return 1;
467     else if (isTargetMacOS() && !isMacosxVersionLT(10, 6))
468       return 1;
469     else if (isTargetMacOS() && !isMacosxVersionLT(10, 5) && !KernelOrKext)
470       return 1;
471 
472     return 0;
473   }
474 
475   void CheckObjCARC() const override;
476 
477   llvm::ExceptionHandling GetExceptionModel(
478       const llvm::opt::ArgList &Args) const override;
479 
480   bool SupportsEmbeddedBitcode() const override;
481 
482   SanitizerMask getSupportedSanitizers() const override;
483 
484   void printVerboseInfo(raw_ostream &OS) const override;
485 };
486 
487 /// DarwinClang - The Darwin toolchain used by Clang.
488 class LLVM_LIBRARY_VISIBILITY DarwinClang : public Darwin {
489 public:
490   DarwinClang(const Driver &D, const llvm::Triple &Triple,
491               const llvm::opt::ArgList &Args);
492 
493   /// @name Apple ToolChain Implementation
494   /// {
495 
496   RuntimeLibType GetRuntimeLibType(const llvm::opt::ArgList &Args) const override;
497 
498   void AddLinkRuntimeLibArgs(const llvm::opt::ArgList &Args,
499                              llvm::opt::ArgStringList &CmdArgs,
500                              bool ForceLinkBuiltinRT = false) const override;
501 
502   void AddClangCXXStdlibIncludeArgs(
503       const llvm::opt::ArgList &DriverArgs,
504       llvm::opt::ArgStringList &CC1Args) const override;
505 
506   void AddClangSystemIncludeArgs(const llvm::opt::ArgList &DriverArgs,
507                                  llvm::opt::ArgStringList &CC1Args) const override;
508 
509   void AddCXXStdlibLibArgs(const llvm::opt::ArgList &Args,
510                            llvm::opt::ArgStringList &CmdArgs) const override;
511 
512   void AddCCKextLibArgs(const llvm::opt::ArgList &Args,
513                         llvm::opt::ArgStringList &CmdArgs) const override;
514 
515   void addClangWarningOptions(llvm::opt::ArgStringList &CC1Args) const override;
516 
517   void AddLinkARCArgs(const llvm::opt::ArgList &Args,
518                       llvm::opt::ArgStringList &CmdArgs) const override;
519 
520   unsigned GetDefaultDwarfVersion() const override;
521   // Until dtrace (via CTF) and LLDB can deal with distributed debug info,
522   // Darwin defaults to standalone/full debug info.
523   bool GetDefaultStandaloneDebug() const override { return true; }
524   llvm::DebuggerKind getDefaultDebuggerTuning() const override {
525     return llvm::DebuggerKind::LLDB;
526   }
527 
528   /// }
529 
530 private:
531   void AddLinkSanitizerLibArgs(const llvm::opt::ArgList &Args,
532                                llvm::opt::ArgStringList &CmdArgs,
533                                StringRef Sanitizer,
534                                bool shared = true) const;
535 
536   bool AddGnuCPlusPlusIncludePaths(const llvm::opt::ArgList &DriverArgs,
537                                    llvm::opt::ArgStringList &CC1Args,
538                                    llvm::SmallString<128> Base,
539                                    llvm::StringRef Version,
540                                    llvm::StringRef ArchDir,
541                                    llvm::StringRef BitDir) const;
542 
543   llvm::StringRef GetHeaderSysroot(const llvm::opt::ArgList &DriverArgs) const;
544 };
545 
546 } // end namespace toolchains
547 } // end namespace driver
548 } // end namespace clang
549 
550 #endif // LLVM_CLANG_LIB_DRIVER_TOOLCHAINS_DARWIN_H
551