Darwin.h revision 360784
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
18namespace clang {
19namespace driver {
20
21namespace toolchains {
22class MachO;
23} // end namespace toolchains
24
25namespace tools {
26
27namespace darwin {
28llvm::Triple::ArchType getArchTypeForMachOArchName(StringRef Str);
29void setTripleTypeForMachOArchName(llvm::Triple &T, StringRef Str);
30
31class LLVM_LIBRARY_VISIBILITY MachOTool : public Tool {
32  virtual void anchor();
33
34protected:
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
42public:
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
52class LLVM_LIBRARY_VISIBILITY Assembler : public MachOTool {
53public:
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
65class 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
71public:
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
85class LLVM_LIBRARY_VISIBILITY Lipo : public MachOTool {
86public:
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
97class LLVM_LIBRARY_VISIBILITY Dsymutil : public MachOTool {
98public:
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
111class LLVM_LIBRARY_VISIBILITY VerifyDebug : public MachOTool {
112public:
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
126namespace toolchains {
127
128class LLVM_LIBRARY_VISIBILITY MachO : public ToolChain {
129protected:
130  Tool *buildAssembler() const override;
131  Tool *buildLinker() const override;
132  Tool *getTool(Action::ActionClass AC) const override;
133
134private:
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
139public:
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.
272class LLVM_LIBRARY_VISIBILITY Darwin : public MachO {
273public:
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
304private:
305  void AddDeploymentTarget(llvm::opt::DerivedArgList &Args) const;
306
307public:
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
335protected:
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
442public:
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.
498class LLVM_LIBRARY_VISIBILITY DarwinClang : public Darwin {
499public:
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
540private:
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