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/Basic/LangOptions.h"
15#include "clang/Driver/DarwinSDKInfo.h"
16#include "clang/Driver/Tool.h"
17#include "clang/Driver/ToolChain.h"
18#include "clang/Driver/XRayArgs.h"
19
20namespace clang {
21namespace driver {
22
23namespace toolchains {
24class MachO;
25} // end namespace toolchains
26
27namespace tools {
28
29namespace darwin {
30llvm::Triple::ArchType getArchTypeForMachOArchName(StringRef Str);
31void setTripleTypeForMachOArchName(llvm::Triple &T, StringRef Str);
32
33class LLVM_LIBRARY_VISIBILITY MachOTool : public Tool {
34  virtual void anchor();
35
36protected:
37  void AddMachOArch(const llvm::opt::ArgList &Args,
38                    llvm::opt::ArgStringList &CmdArgs) const;
39
40  const toolchains::MachO &getMachOToolChain() const {
41    return reinterpret_cast<const toolchains::MachO &>(getToolChain());
42  }
43
44public:
45  MachOTool(const char *Name, const char *ShortName, const ToolChain &TC)
46      : Tool(Name, ShortName, TC) {}
47};
48
49class LLVM_LIBRARY_VISIBILITY Assembler : public MachOTool {
50public:
51  Assembler(const ToolChain &TC)
52      : MachOTool("darwin::Assembler", "assembler", TC) {}
53
54  bool hasIntegratedCPP() const override { return false; }
55
56  void ConstructJob(Compilation &C, const JobAction &JA,
57                    const InputInfo &Output, const InputInfoList &Inputs,
58                    const llvm::opt::ArgList &TCArgs,
59                    const char *LinkingOutput) const override;
60};
61
62class LLVM_LIBRARY_VISIBILITY Linker : public MachOTool {
63  bool NeedsTempPath(const InputInfoList &Inputs) const;
64  void AddLinkArgs(Compilation &C, const llvm::opt::ArgList &Args,
65                   llvm::opt::ArgStringList &CmdArgs,
66                   const InputInfoList &Inputs, unsigned Version[5],
67                   bool LinkerIsLLD, bool LinkerIsLLDDarwinNew) const;
68
69public:
70  Linker(const ToolChain &TC) : MachOTool("darwin::Linker", "linker", TC) {}
71
72  bool hasIntegratedCPP() const override { return false; }
73  bool isLinkJob() const override { return true; }
74
75  void ConstructJob(Compilation &C, const JobAction &JA,
76                    const InputInfo &Output, const InputInfoList &Inputs,
77                    const llvm::opt::ArgList &TCArgs,
78                    const char *LinkingOutput) const override;
79};
80
81class LLVM_LIBRARY_VISIBILITY Lipo : public MachOTool {
82public:
83  Lipo(const ToolChain &TC) : MachOTool("darwin::Lipo", "lipo", TC) {}
84
85  bool hasIntegratedCPP() const override { return false; }
86
87  void ConstructJob(Compilation &C, const JobAction &JA,
88                    const InputInfo &Output, const InputInfoList &Inputs,
89                    const llvm::opt::ArgList &TCArgs,
90                    const char *LinkingOutput) const override;
91};
92
93class LLVM_LIBRARY_VISIBILITY Dsymutil : public MachOTool {
94public:
95  Dsymutil(const ToolChain &TC)
96      : MachOTool("darwin::Dsymutil", "dsymutil", TC) {}
97
98  bool hasIntegratedCPP() const override { return false; }
99  bool isDsymutilJob() const override { return true; }
100
101  void ConstructJob(Compilation &C, const JobAction &JA,
102                    const InputInfo &Output, const InputInfoList &Inputs,
103                    const llvm::opt::ArgList &TCArgs,
104                    const char *LinkingOutput) const override;
105};
106
107class LLVM_LIBRARY_VISIBILITY VerifyDebug : public MachOTool {
108public:
109  VerifyDebug(const ToolChain &TC)
110      : MachOTool("darwin::VerifyDebug", "dwarfdump", TC) {}
111
112  bool hasIntegratedCPP() const override { return false; }
113
114  void ConstructJob(Compilation &C, const JobAction &JA,
115                    const InputInfo &Output, const InputInfoList &Inputs,
116                    const llvm::opt::ArgList &TCArgs,
117                    const char *LinkingOutput) const override;
118};
119} // end namespace darwin
120} // end namespace tools
121
122namespace toolchains {
123
124class LLVM_LIBRARY_VISIBILITY MachO : public ToolChain {
125protected:
126  Tool *buildAssembler() const override;
127  Tool *buildLinker() const override;
128  Tool *getTool(Action::ActionClass AC) const override;
129
130private:
131  mutable std::unique_ptr<tools::darwin::Lipo> Lipo;
132  mutable std::unique_ptr<tools::darwin::Dsymutil> Dsymutil;
133  mutable std::unique_ptr<tools::darwin::VerifyDebug> VerifyDebug;
134
135public:
136  MachO(const Driver &D, const llvm::Triple &Triple,
137        const llvm::opt::ArgList &Args);
138  ~MachO() override;
139
140  /// @name MachO specific toolchain API
141  /// {
142
143  /// Get the "MachO" arch name for a particular compiler invocation. For
144  /// example, Apple treats different ARM variations as distinct architectures.
145  StringRef getMachOArchName(const llvm::opt::ArgList &Args) const;
146
147  /// Add the linker arguments to link the ARC runtime library.
148  virtual void AddLinkARCArgs(const llvm::opt::ArgList &Args,
149                              llvm::opt::ArgStringList &CmdArgs) const {}
150
151  /// Add the linker arguments to link the compiler runtime library.
152  ///
153  /// FIXME: This API is intended for use with embedded libraries only, and is
154  /// misleadingly named.
155  virtual void AddLinkRuntimeLibArgs(const llvm::opt::ArgList &Args,
156                                     llvm::opt::ArgStringList &CmdArgs,
157                                     bool ForceLinkBuiltinRT = false) const;
158
159  virtual void addStartObjectFileArgs(const llvm::opt::ArgList &Args,
160                                      llvm::opt::ArgStringList &CmdArgs) const {
161  }
162
163  virtual void addMinVersionArgs(const llvm::opt::ArgList &Args,
164                                 llvm::opt::ArgStringList &CmdArgs) const {}
165
166  virtual void addPlatformVersionArgs(const llvm::opt::ArgList &Args,
167                                      llvm::opt::ArgStringList &CmdArgs) const {
168  }
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.
268class LLVM_LIBRARY_VISIBILITY Darwin : public MachO {
269public:
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  RocmInstallationDetector RocmInstallation;
300
301private:
302  void AddDeploymentTarget(llvm::opt::DerivedArgList &Args) const;
303
304public:
305  Darwin(const Driver &D, const llvm::Triple &Triple,
306         const llvm::opt::ArgList &Args);
307  ~Darwin() override;
308
309  std::string ComputeEffectiveClangTriple(const llvm::opt::ArgList &Args,
310                                          types::ID InputType) const override;
311
312  /// @name Apple Specific Toolchain Implementation
313  /// {
314
315  void addMinVersionArgs(const llvm::opt::ArgList &Args,
316                         llvm::opt::ArgStringList &CmdArgs) const override;
317
318  void addPlatformVersionArgs(const llvm::opt::ArgList &Args,
319                              llvm::opt::ArgStringList &CmdArgs) const override;
320
321  void addStartObjectFileArgs(const llvm::opt::ArgList &Args,
322                              llvm::opt::ArgStringList &CmdArgs) const override;
323
324  bool isKernelStatic() const override {
325    return (!(isTargetIPhoneOS() && !isIPhoneOSVersionLT(6, 0)) &&
326            !isTargetWatchOS());
327  }
328
329  void addProfileRTLibs(const llvm::opt::ArgList &Args,
330                        llvm::opt::ArgStringList &CmdArgs) const override;
331
332protected:
333  /// }
334  /// @name Darwin specific Toolchain functions
335  /// {
336
337  // FIXME: Eliminate these ...Target functions and derive separate tool chains
338  // for these targets and put version in constructor.
339  void setTarget(DarwinPlatformKind Platform, DarwinEnvironmentKind Environment,
340                 unsigned Major, unsigned Minor, unsigned Micro) const {
341    // FIXME: For now, allow reinitialization as long as values don't
342    // change. This will go away when we move away from argument translation.
343    if (TargetInitialized && TargetPlatform == Platform &&
344        TargetEnvironment == Environment &&
345        TargetVersion == VersionTuple(Major, Minor, Micro))
346      return;
347
348    assert(!TargetInitialized && "Target already initialized!");
349    TargetInitialized = true;
350    TargetPlatform = Platform;
351    TargetEnvironment = Environment;
352    TargetVersion = VersionTuple(Major, Minor, Micro);
353    if (Environment == Simulator)
354      const_cast<Darwin *>(this)->setTripleEnvironment(llvm::Triple::Simulator);
355  }
356
357public:
358  bool isTargetIPhoneOS() const {
359    assert(TargetInitialized && "Target not initialized!");
360    return (TargetPlatform == IPhoneOS || TargetPlatform == TvOS) &&
361           TargetEnvironment == NativeEnvironment;
362  }
363
364  bool isTargetIOSSimulator() const {
365    assert(TargetInitialized && "Target not initialized!");
366    return (TargetPlatform == IPhoneOS || TargetPlatform == TvOS) &&
367           TargetEnvironment == Simulator;
368  }
369
370  bool isTargetIOSBased() const {
371    assert(TargetInitialized && "Target not initialized!");
372    return isTargetIPhoneOS() || isTargetIOSSimulator();
373  }
374
375  bool isTargetTvOS() const {
376    assert(TargetInitialized && "Target not initialized!");
377    return TargetPlatform == TvOS && TargetEnvironment == NativeEnvironment;
378  }
379
380  bool isTargetTvOSSimulator() const {
381    assert(TargetInitialized && "Target not initialized!");
382    return TargetPlatform == TvOS && TargetEnvironment == Simulator;
383  }
384
385  bool isTargetTvOSBased() const {
386    assert(TargetInitialized && "Target not initialized!");
387    return TargetPlatform == TvOS;
388  }
389
390  bool isTargetWatchOS() const {
391    assert(TargetInitialized && "Target not initialized!");
392    return TargetPlatform == WatchOS && TargetEnvironment == NativeEnvironment;
393  }
394
395  bool isTargetWatchOSSimulator() const {
396    assert(TargetInitialized && "Target not initialized!");
397    return TargetPlatform == WatchOS && TargetEnvironment == Simulator;
398  }
399
400  bool isTargetWatchOSBased() const {
401    assert(TargetInitialized && "Target not initialized!");
402    return TargetPlatform == WatchOS;
403  }
404
405  bool isTargetMacOS() const {
406    assert(TargetInitialized && "Target not initialized!");
407    return TargetPlatform == MacOS;
408  }
409
410  bool isTargetMacOSBased() const {
411    assert(TargetInitialized && "Target not initialized!");
412    // FIXME (Alex L): Add remaining MacCatalyst suppport.
413    return TargetPlatform == MacOS;
414  }
415
416  bool isTargetAppleSiliconMac() const {
417    assert(TargetInitialized && "Target not initialized!");
418    return isTargetMacOSBased() && getArch() == llvm::Triple::aarch64;
419  }
420
421  bool isTargetInitialized() const { return TargetInitialized; }
422
423  VersionTuple getTargetVersion() const {
424    assert(TargetInitialized && "Target not initialized!");
425    return TargetVersion;
426  }
427
428  bool isIPhoneOSVersionLT(unsigned V0, unsigned V1 = 0,
429                           unsigned V2 = 0) const {
430    assert(isTargetIOSBased() && "Unexpected call for non iOS target!");
431    return TargetVersion < VersionTuple(V0, V1, V2);
432  }
433
434  /// Returns true if the minimum supported macOS version for the slice that's
435  /// being built is less than the specified version. If there's no minimum
436  /// supported macOS version, the deployment target version is compared to the
437  /// specifed version instead.
438  bool isMacosxVersionLT(unsigned V0, unsigned V1 = 0, unsigned V2 = 0) const {
439    assert(isTargetMacOS() && getTriple().isMacOSX() &&
440           "Unexpected call for non OS X target!");
441    // The effective triple might not be initialized yet, so construct a
442    // pseudo-effective triple to get the minimum supported OS version.
443    VersionTuple MinVers =
444        llvm::Triple(getTriple().getArchName(), "apple", "macos")
445            .getMinimumSupportedOSVersion();
446    return (!MinVers.empty() && MinVers > TargetVersion
447                ? MinVers
448                : TargetVersion) < VersionTuple(V0, V1, V2);
449  }
450
451protected:
452  /// Return true if c++17 aligned allocation/deallocation functions are not
453  /// implemented in the c++ standard library of the deployment target we are
454  /// targeting.
455  bool isAlignedAllocationUnavailable() const;
456
457  void addClangTargetOptions(const llvm::opt::ArgList &DriverArgs,
458                             llvm::opt::ArgStringList &CC1Args,
459                             Action::OffloadKind DeviceOffloadKind) const override;
460
461  StringRef getPlatformFamily() const;
462  StringRef getOSLibraryNameSuffix(bool IgnoreSim = false) const override;
463
464public:
465  static StringRef getSDKName(StringRef isysroot);
466
467  /// }
468  /// @name ToolChain Implementation
469  /// {
470
471  // Darwin tools support multiple architecture (e.g., i386 and x86_64) and
472  // most development is done against SDKs, so compiling for a different
473  // architecture should not get any special treatment.
474  bool isCrossCompiling() const override { return false; }
475
476  llvm::opt::DerivedArgList *
477  TranslateArgs(const llvm::opt::DerivedArgList &Args, StringRef BoundArch,
478                Action::OffloadKind DeviceOffloadKind) const override;
479
480  CXXStdlibType GetDefaultCXXStdlibType() const override;
481  ObjCRuntime getDefaultObjCRuntime(bool isNonFragile) const override;
482  bool hasBlocksRuntime() const override;
483
484  void AddCudaIncludeArgs(const llvm::opt::ArgList &DriverArgs,
485                          llvm::opt::ArgStringList &CC1Args) const override;
486  void AddHIPIncludeArgs(const llvm::opt::ArgList &DriverArgs,
487                         llvm::opt::ArgStringList &CC1Args) const override;
488
489  bool UseObjCMixedDispatch() const override {
490    // This is only used with the non-fragile ABI and non-legacy dispatch.
491
492    // Mixed dispatch is used everywhere except OS X before 10.6.
493    return !(isTargetMacOS() && isMacosxVersionLT(10, 6));
494  }
495
496  LangOptions::StackProtectorMode
497  GetDefaultStackProtectorLevel(bool KernelOrKext) const override {
498    // Stack protectors default to on for user code on 10.5,
499    // and for everything in 10.6 and beyond
500    if (isTargetIOSBased() || isTargetWatchOSBased())
501      return LangOptions::SSPOn;
502    else if (isTargetMacOS() && !isMacosxVersionLT(10, 6))
503      return LangOptions::SSPOn;
504    else if (isTargetMacOS() && !isMacosxVersionLT(10, 5) && !KernelOrKext)
505      return LangOptions::SSPOn;
506
507    return LangOptions::SSPOff;
508  }
509
510  void CheckObjCARC() const override;
511
512  llvm::ExceptionHandling GetExceptionModel(
513      const llvm::opt::ArgList &Args) const override;
514
515  bool SupportsEmbeddedBitcode() const override;
516
517  SanitizerMask getSupportedSanitizers() const override;
518
519  void printVerboseInfo(raw_ostream &OS) const override;
520};
521
522/// DarwinClang - The Darwin toolchain used by Clang.
523class LLVM_LIBRARY_VISIBILITY DarwinClang : public Darwin {
524public:
525  DarwinClang(const Driver &D, const llvm::Triple &Triple,
526              const llvm::opt::ArgList &Args);
527
528  /// @name Apple ToolChain Implementation
529  /// {
530
531  RuntimeLibType GetRuntimeLibType(const llvm::opt::ArgList &Args) const override;
532
533  void AddLinkRuntimeLibArgs(const llvm::opt::ArgList &Args,
534                             llvm::opt::ArgStringList &CmdArgs,
535                             bool ForceLinkBuiltinRT = false) const override;
536
537  void AddClangCXXStdlibIncludeArgs(
538      const llvm::opt::ArgList &DriverArgs,
539      llvm::opt::ArgStringList &CC1Args) const override;
540
541  void AddClangSystemIncludeArgs(const llvm::opt::ArgList &DriverArgs,
542                                 llvm::opt::ArgStringList &CC1Args) const override;
543
544  void AddCXXStdlibLibArgs(const llvm::opt::ArgList &Args,
545                           llvm::opt::ArgStringList &CmdArgs) const override;
546
547  void AddCCKextLibArgs(const llvm::opt::ArgList &Args,
548                        llvm::opt::ArgStringList &CmdArgs) const override;
549
550  void addClangWarningOptions(llvm::opt::ArgStringList &CC1Args) const override;
551
552  void AddLinkARCArgs(const llvm::opt::ArgList &Args,
553                      llvm::opt::ArgStringList &CmdArgs) const override;
554
555  unsigned GetDefaultDwarfVersion() const override;
556  // Until dtrace (via CTF) and LLDB can deal with distributed debug info,
557  // Darwin defaults to standalone/full debug info.
558  bool GetDefaultStandaloneDebug() const override { return true; }
559  llvm::DebuggerKind getDefaultDebuggerTuning() const override {
560    return llvm::DebuggerKind::LLDB;
561  }
562
563  /// }
564
565private:
566  void AddLinkSanitizerLibArgs(const llvm::opt::ArgList &Args,
567                               llvm::opt::ArgStringList &CmdArgs,
568                               StringRef Sanitizer,
569                               bool shared = true) const;
570
571  bool AddGnuCPlusPlusIncludePaths(const llvm::opt::ArgList &DriverArgs,
572                                   llvm::opt::ArgStringList &CC1Args,
573                                   llvm::SmallString<128> Base,
574                                   llvm::StringRef Version,
575                                   llvm::StringRef ArchDir,
576                                   llvm::StringRef BitDir) const;
577
578  llvm::StringRef GetHeaderSysroot(const llvm::opt::ArgList &DriverArgs) const;
579};
580
581} // end namespace toolchains
582} // end namespace driver
583} // end namespace clang
584
585#endif // LLVM_CLANG_LIB_DRIVER_TOOLCHAINS_DARWIN_H
586