xref: /freebsd/contrib/llvm-project/clang/lib/Driver/ToolChains/Darwin.h (revision 7a6dacaca14b62ca4b74406814becb87a3fefac0)
10b57cec5SDimitry Andric //===--- Darwin.h - Darwin ToolChain Implementations ------------*- C++ -*-===//
20b57cec5SDimitry Andric //
30b57cec5SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
40b57cec5SDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
50b57cec5SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
60b57cec5SDimitry Andric //
70b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
80b57cec5SDimitry Andric 
90b57cec5SDimitry Andric #ifndef LLVM_CLANG_LIB_DRIVER_TOOLCHAINS_DARWIN_H
100b57cec5SDimitry Andric #define LLVM_CLANG_LIB_DRIVER_TOOLCHAINS_DARWIN_H
110b57cec5SDimitry Andric 
120b57cec5SDimitry Andric #include "Cuda.h"
13*7a6dacacSDimitry Andric #include "LazyDetector.h"
145ffd83dbSDimitry Andric #include "ROCm.h"
15fe6060f1SDimitry Andric #include "clang/Basic/DarwinSDKInfo.h"
16e8d8bef9SDimitry Andric #include "clang/Basic/LangOptions.h"
170b57cec5SDimitry Andric #include "clang/Driver/Tool.h"
180b57cec5SDimitry Andric #include "clang/Driver/ToolChain.h"
190b57cec5SDimitry Andric #include "clang/Driver/XRayArgs.h"
200b57cec5SDimitry Andric 
210b57cec5SDimitry Andric namespace clang {
220b57cec5SDimitry Andric namespace driver {
230b57cec5SDimitry Andric 
240b57cec5SDimitry Andric namespace toolchains {
250b57cec5SDimitry Andric class MachO;
260b57cec5SDimitry Andric } // end namespace toolchains
270b57cec5SDimitry Andric 
280b57cec5SDimitry Andric namespace tools {
290b57cec5SDimitry Andric 
300b57cec5SDimitry Andric namespace darwin {
310b57cec5SDimitry Andric llvm::Triple::ArchType getArchTypeForMachOArchName(StringRef Str);
3206c3fb27SDimitry Andric void setTripleTypeForMachOArchName(llvm::Triple &T, StringRef Str,
3306c3fb27SDimitry Andric                                    const llvm::opt::ArgList &Args);
340b57cec5SDimitry Andric 
350b57cec5SDimitry Andric class LLVM_LIBRARY_VISIBILITY MachOTool : public Tool {
360b57cec5SDimitry Andric   virtual void anchor();
370b57cec5SDimitry Andric 
380b57cec5SDimitry Andric protected:
390b57cec5SDimitry Andric   void AddMachOArch(const llvm::opt::ArgList &Args,
400b57cec5SDimitry Andric                     llvm::opt::ArgStringList &CmdArgs) const;
410b57cec5SDimitry Andric 
420b57cec5SDimitry Andric   const toolchains::MachO &getMachOToolChain() const {
430b57cec5SDimitry Andric     return reinterpret_cast<const toolchains::MachO &>(getToolChain());
440b57cec5SDimitry Andric   }
450b57cec5SDimitry Andric 
460b57cec5SDimitry Andric public:
475ffd83dbSDimitry Andric   MachOTool(const char *Name, const char *ShortName, const ToolChain &TC)
485ffd83dbSDimitry Andric       : Tool(Name, ShortName, TC) {}
490b57cec5SDimitry Andric };
500b57cec5SDimitry Andric 
510b57cec5SDimitry Andric class LLVM_LIBRARY_VISIBILITY Assembler : public MachOTool {
520b57cec5SDimitry Andric public:
530b57cec5SDimitry Andric   Assembler(const ToolChain &TC)
540b57cec5SDimitry Andric       : MachOTool("darwin::Assembler", "assembler", TC) {}
550b57cec5SDimitry Andric 
560b57cec5SDimitry Andric   bool hasIntegratedCPP() const override { return false; }
570b57cec5SDimitry Andric 
580b57cec5SDimitry Andric   void ConstructJob(Compilation &C, const JobAction &JA,
590b57cec5SDimitry Andric                     const InputInfo &Output, const InputInfoList &Inputs,
600b57cec5SDimitry Andric                     const llvm::opt::ArgList &TCArgs,
610b57cec5SDimitry Andric                     const char *LinkingOutput) const override;
620b57cec5SDimitry Andric };
630b57cec5SDimitry Andric 
640b57cec5SDimitry Andric class LLVM_LIBRARY_VISIBILITY Linker : public MachOTool {
650b57cec5SDimitry Andric   bool NeedsTempPath(const InputInfoList &Inputs) const;
660b57cec5SDimitry Andric   void AddLinkArgs(Compilation &C, const llvm::opt::ArgList &Args,
670b57cec5SDimitry Andric                    llvm::opt::ArgStringList &CmdArgs,
6881ad6265SDimitry Andric                    const InputInfoList &Inputs, VersionTuple Version,
69*7a6dacacSDimitry Andric                    bool LinkerIsLLD, bool UsePlatformVersion) const;
700b57cec5SDimitry Andric 
710b57cec5SDimitry Andric public:
725ffd83dbSDimitry Andric   Linker(const ToolChain &TC) : MachOTool("darwin::Linker", "linker", TC) {}
730b57cec5SDimitry Andric 
740b57cec5SDimitry Andric   bool hasIntegratedCPP() const override { return false; }
750b57cec5SDimitry Andric   bool isLinkJob() const override { return true; }
760b57cec5SDimitry Andric 
770b57cec5SDimitry Andric   void ConstructJob(Compilation &C, const JobAction &JA,
780b57cec5SDimitry Andric                     const InputInfo &Output, const InputInfoList &Inputs,
790b57cec5SDimitry Andric                     const llvm::opt::ArgList &TCArgs,
800b57cec5SDimitry Andric                     const char *LinkingOutput) const override;
810b57cec5SDimitry Andric };
820b57cec5SDimitry Andric 
83349cc55cSDimitry Andric class LLVM_LIBRARY_VISIBILITY StaticLibTool : public MachOTool {
84349cc55cSDimitry Andric public:
85349cc55cSDimitry Andric   StaticLibTool(const ToolChain &TC)
86349cc55cSDimitry Andric       : MachOTool("darwin::StaticLibTool", "static-lib-linker", TC) {}
87349cc55cSDimitry Andric 
88349cc55cSDimitry Andric   bool hasIntegratedCPP() const override { return false; }
89349cc55cSDimitry Andric   bool isLinkJob() const override { return true; }
90349cc55cSDimitry Andric 
91349cc55cSDimitry Andric   void ConstructJob(Compilation &C, const JobAction &JA,
92349cc55cSDimitry Andric                     const InputInfo &Output, const InputInfoList &Inputs,
93349cc55cSDimitry Andric                     const llvm::opt::ArgList &TCArgs,
94349cc55cSDimitry Andric                     const char *LinkingOutput) const override;
95349cc55cSDimitry Andric };
96349cc55cSDimitry Andric 
970b57cec5SDimitry Andric class LLVM_LIBRARY_VISIBILITY Lipo : public MachOTool {
980b57cec5SDimitry Andric public:
990b57cec5SDimitry Andric   Lipo(const ToolChain &TC) : MachOTool("darwin::Lipo", "lipo", TC) {}
1000b57cec5SDimitry Andric 
1010b57cec5SDimitry Andric   bool hasIntegratedCPP() const override { return false; }
1020b57cec5SDimitry Andric 
1030b57cec5SDimitry Andric   void ConstructJob(Compilation &C, const JobAction &JA,
1040b57cec5SDimitry Andric                     const InputInfo &Output, const InputInfoList &Inputs,
1050b57cec5SDimitry Andric                     const llvm::opt::ArgList &TCArgs,
1060b57cec5SDimitry Andric                     const char *LinkingOutput) const override;
1070b57cec5SDimitry Andric };
1080b57cec5SDimitry Andric 
1090b57cec5SDimitry Andric class LLVM_LIBRARY_VISIBILITY Dsymutil : public MachOTool {
1100b57cec5SDimitry Andric public:
1110b57cec5SDimitry Andric   Dsymutil(const ToolChain &TC)
1120b57cec5SDimitry Andric       : MachOTool("darwin::Dsymutil", "dsymutil", TC) {}
1130b57cec5SDimitry Andric 
1140b57cec5SDimitry Andric   bool hasIntegratedCPP() const override { return false; }
1150b57cec5SDimitry Andric   bool isDsymutilJob() const override { return true; }
1160b57cec5SDimitry Andric 
1170b57cec5SDimitry Andric   void ConstructJob(Compilation &C, const JobAction &JA,
1180b57cec5SDimitry Andric                     const InputInfo &Output, const InputInfoList &Inputs,
1190b57cec5SDimitry Andric                     const llvm::opt::ArgList &TCArgs,
1200b57cec5SDimitry Andric                     const char *LinkingOutput) const override;
1210b57cec5SDimitry Andric };
1220b57cec5SDimitry Andric 
1230b57cec5SDimitry Andric class LLVM_LIBRARY_VISIBILITY VerifyDebug : public MachOTool {
1240b57cec5SDimitry Andric public:
1250b57cec5SDimitry Andric   VerifyDebug(const ToolChain &TC)
1260b57cec5SDimitry Andric       : MachOTool("darwin::VerifyDebug", "dwarfdump", TC) {}
1270b57cec5SDimitry Andric 
1280b57cec5SDimitry Andric   bool hasIntegratedCPP() const override { return false; }
1290b57cec5SDimitry Andric 
1300b57cec5SDimitry Andric   void ConstructJob(Compilation &C, const JobAction &JA,
1310b57cec5SDimitry Andric                     const InputInfo &Output, const InputInfoList &Inputs,
1320b57cec5SDimitry Andric                     const llvm::opt::ArgList &TCArgs,
1330b57cec5SDimitry Andric                     const char *LinkingOutput) const override;
1340b57cec5SDimitry Andric };
1350b57cec5SDimitry Andric } // end namespace darwin
1360b57cec5SDimitry Andric } // end namespace tools
1370b57cec5SDimitry Andric 
1380b57cec5SDimitry Andric namespace toolchains {
1390b57cec5SDimitry Andric 
1400b57cec5SDimitry Andric class LLVM_LIBRARY_VISIBILITY MachO : public ToolChain {
1410b57cec5SDimitry Andric protected:
1420b57cec5SDimitry Andric   Tool *buildAssembler() const override;
1430b57cec5SDimitry Andric   Tool *buildLinker() const override;
144349cc55cSDimitry Andric   Tool *buildStaticLibTool() const override;
1450b57cec5SDimitry Andric   Tool *getTool(Action::ActionClass AC) const override;
1460b57cec5SDimitry Andric 
1470b57cec5SDimitry Andric private:
1480b57cec5SDimitry Andric   mutable std::unique_ptr<tools::darwin::Lipo> Lipo;
1490b57cec5SDimitry Andric   mutable std::unique_ptr<tools::darwin::Dsymutil> Dsymutil;
1500b57cec5SDimitry Andric   mutable std::unique_ptr<tools::darwin::VerifyDebug> VerifyDebug;
1510b57cec5SDimitry Andric 
15281ad6265SDimitry Andric   /// The version of the linker known to be available in the tool chain.
153bdd1243dSDimitry Andric   mutable std::optional<VersionTuple> LinkerVersion;
15481ad6265SDimitry Andric 
1550b57cec5SDimitry Andric public:
1560b57cec5SDimitry Andric   MachO(const Driver &D, const llvm::Triple &Triple,
1570b57cec5SDimitry Andric         const llvm::opt::ArgList &Args);
1580b57cec5SDimitry Andric   ~MachO() override;
1590b57cec5SDimitry Andric 
1600b57cec5SDimitry Andric   /// @name MachO specific toolchain API
1610b57cec5SDimitry Andric   /// {
1620b57cec5SDimitry Andric 
1630b57cec5SDimitry Andric   /// Get the "MachO" arch name for a particular compiler invocation. For
1640b57cec5SDimitry Andric   /// example, Apple treats different ARM variations as distinct architectures.
1650b57cec5SDimitry Andric   StringRef getMachOArchName(const llvm::opt::ArgList &Args) const;
1660b57cec5SDimitry Andric 
16781ad6265SDimitry Andric   /// Get the version of the linker known to be available for a particular
16881ad6265SDimitry Andric   /// compiler invocation (via the `-mlinker-version=` arg).
16981ad6265SDimitry Andric   VersionTuple getLinkerVersion(const llvm::opt::ArgList &Args) const;
17081ad6265SDimitry Andric 
1710b57cec5SDimitry Andric   /// Add the linker arguments to link the ARC runtime library.
1720b57cec5SDimitry Andric   virtual void AddLinkARCArgs(const llvm::opt::ArgList &Args,
1730b57cec5SDimitry Andric                               llvm::opt::ArgStringList &CmdArgs) const {}
1740b57cec5SDimitry Andric 
1750b57cec5SDimitry Andric   /// Add the linker arguments to link the compiler runtime library.
1760b57cec5SDimitry Andric   ///
1770b57cec5SDimitry Andric   /// FIXME: This API is intended for use with embedded libraries only, and is
1780b57cec5SDimitry Andric   /// misleadingly named.
1790b57cec5SDimitry Andric   virtual void AddLinkRuntimeLibArgs(const llvm::opt::ArgList &Args,
1800b57cec5SDimitry Andric                                      llvm::opt::ArgStringList &CmdArgs,
1810b57cec5SDimitry Andric                                      bool ForceLinkBuiltinRT = false) const;
1820b57cec5SDimitry Andric 
1830b57cec5SDimitry Andric   virtual void addStartObjectFileArgs(const llvm::opt::ArgList &Args,
1840b57cec5SDimitry Andric                                       llvm::opt::ArgStringList &CmdArgs) const {
1850b57cec5SDimitry Andric   }
1860b57cec5SDimitry Andric 
1870b57cec5SDimitry Andric   virtual void addMinVersionArgs(const llvm::opt::ArgList &Args,
1880b57cec5SDimitry Andric                                  llvm::opt::ArgStringList &CmdArgs) const {}
1890b57cec5SDimitry Andric 
190480093f4SDimitry Andric   virtual void addPlatformVersionArgs(const llvm::opt::ArgList &Args,
191480093f4SDimitry Andric                                       llvm::opt::ArgStringList &CmdArgs) const {
192480093f4SDimitry Andric   }
193480093f4SDimitry Andric 
1940b57cec5SDimitry Andric   /// On some iOS platforms, kernel and kernel modules were built statically. Is
1950b57cec5SDimitry Andric   /// this such a target?
1960b57cec5SDimitry Andric   virtual bool isKernelStatic() const { return false; }
1970b57cec5SDimitry Andric 
1980b57cec5SDimitry Andric   /// Is the target either iOS or an iOS simulator?
1990b57cec5SDimitry Andric   bool isTargetIOSBased() const { return false; }
2000b57cec5SDimitry Andric 
2010b57cec5SDimitry Andric   /// Options to control how a runtime library is linked.
2020b57cec5SDimitry Andric   enum RuntimeLinkOptions : unsigned {
2030b57cec5SDimitry Andric     /// Link the library in even if it can't be found in the VFS.
2040b57cec5SDimitry Andric     RLO_AlwaysLink = 1 << 0,
2050b57cec5SDimitry Andric 
2060b57cec5SDimitry Andric     /// Use the embedded runtime from the macho_embedded directory.
2070b57cec5SDimitry Andric     RLO_IsEmbedded = 1 << 1,
2080b57cec5SDimitry Andric 
2090b57cec5SDimitry Andric     /// Emit rpaths for @executable_path as well as the resource directory.
2100b57cec5SDimitry Andric     RLO_AddRPath = 1 << 2,
2110b57cec5SDimitry Andric   };
2120b57cec5SDimitry Andric 
2130b57cec5SDimitry Andric   /// Add a runtime library to the list of items to link.
2140b57cec5SDimitry Andric   void AddLinkRuntimeLib(const llvm::opt::ArgList &Args,
2150b57cec5SDimitry Andric                          llvm::opt::ArgStringList &CmdArgs, StringRef Component,
2160b57cec5SDimitry Andric                          RuntimeLinkOptions Opts = RuntimeLinkOptions(),
2170b57cec5SDimitry Andric                          bool IsShared = false) const;
2180b57cec5SDimitry Andric 
2190b57cec5SDimitry Andric   /// Add any profiling runtime libraries that are needed. This is essentially a
2200b57cec5SDimitry Andric   /// MachO specific version of addProfileRT in Tools.cpp.
2210b57cec5SDimitry Andric   void addProfileRTLibs(const llvm::opt::ArgList &Args,
2220b57cec5SDimitry Andric                         llvm::opt::ArgStringList &CmdArgs) const override {
2230b57cec5SDimitry Andric     // There aren't any profiling libs for embedded targets currently.
2240b57cec5SDimitry Andric   }
2250b57cec5SDimitry Andric 
2260b57cec5SDimitry Andric   /// }
2270b57cec5SDimitry Andric   /// @name ToolChain Implementation
2280b57cec5SDimitry Andric   /// {
2290b57cec5SDimitry Andric 
2300b57cec5SDimitry Andric   types::ID LookupTypeForExtension(StringRef Ext) const override;
2310b57cec5SDimitry Andric 
2320b57cec5SDimitry Andric   bool HasNativeLLVMSupport() const override;
2330b57cec5SDimitry Andric 
2340b57cec5SDimitry Andric   llvm::opt::DerivedArgList *
2350b57cec5SDimitry Andric   TranslateArgs(const llvm::opt::DerivedArgList &Args, StringRef BoundArch,
2360b57cec5SDimitry Andric                 Action::OffloadKind DeviceOffloadKind) const override;
2370b57cec5SDimitry Andric 
2380b57cec5SDimitry Andric   bool IsBlocksDefault() const override {
2390b57cec5SDimitry Andric     // Always allow blocks on Apple; users interested in versioning are
2400b57cec5SDimitry Andric     // expected to use /usr/include/Block.h.
2410b57cec5SDimitry Andric     return true;
2420b57cec5SDimitry Andric   }
2430b57cec5SDimitry Andric 
2440b57cec5SDimitry Andric   bool IsMathErrnoDefault() const override { return false; }
2450b57cec5SDimitry Andric 
2460b57cec5SDimitry Andric   bool IsEncodeExtendedBlockSignatureDefault() const override { return true; }
2470b57cec5SDimitry Andric 
2480b57cec5SDimitry Andric   bool IsObjCNonFragileABIDefault() const override {
2490b57cec5SDimitry Andric     // Non-fragile ABI is default for everything but i386.
2500b57cec5SDimitry Andric     return getTriple().getArch() != llvm::Triple::x86;
2510b57cec5SDimitry Andric   }
2520b57cec5SDimitry Andric 
2530b57cec5SDimitry Andric   bool UseObjCMixedDispatch() const override { return true; }
2540b57cec5SDimitry Andric 
255bdd1243dSDimitry Andric   UnwindTableLevel
256bdd1243dSDimitry Andric   getDefaultUnwindTableLevel(const llvm::opt::ArgList &Args) const override;
2570b57cec5SDimitry Andric 
2580b57cec5SDimitry Andric   RuntimeLibType GetDefaultRuntimeLibType() const override {
2590b57cec5SDimitry Andric     return ToolChain::RLT_CompilerRT;
2600b57cec5SDimitry Andric   }
2610b57cec5SDimitry Andric 
2620b57cec5SDimitry Andric   bool isPICDefault() const override;
263349cc55cSDimitry Andric   bool isPIEDefault(const llvm::opt::ArgList &Args) const override;
2640b57cec5SDimitry Andric   bool isPICDefaultForced() const override;
2650b57cec5SDimitry Andric 
2660b57cec5SDimitry Andric   bool SupportsProfiling() const override;
2670b57cec5SDimitry Andric 
2680b57cec5SDimitry Andric   bool UseDwarfDebugFlags() const override;
26981ad6265SDimitry Andric   std::string GetGlobalDebugPathRemapping() const override;
2700b57cec5SDimitry Andric 
2710b57cec5SDimitry Andric   llvm::ExceptionHandling
2720b57cec5SDimitry Andric   GetExceptionModel(const llvm::opt::ArgList &Args) const override {
2730b57cec5SDimitry Andric     return llvm::ExceptionHandling::None;
2740b57cec5SDimitry Andric   }
2750b57cec5SDimitry Andric 
2760b57cec5SDimitry Andric   virtual StringRef getOSLibraryNameSuffix(bool IgnoreSim = false) const {
2770b57cec5SDimitry Andric     return "";
2780b57cec5SDimitry Andric   }
2790b57cec5SDimitry Andric 
280480093f4SDimitry Andric   // Darwin toolchain uses legacy thin LTO API, which is not
281480093f4SDimitry Andric   // capable of unit splitting.
282480093f4SDimitry Andric   bool canSplitThinLTOUnit() const override { return false; }
2830b57cec5SDimitry Andric   /// }
2840b57cec5SDimitry Andric };
2850b57cec5SDimitry Andric 
2860b57cec5SDimitry Andric /// Darwin - The base Darwin tool chain.
2870b57cec5SDimitry Andric class LLVM_LIBRARY_VISIBILITY Darwin : public MachO {
2880b57cec5SDimitry Andric public:
2890b57cec5SDimitry Andric   /// Whether the information on the target has been initialized.
2900b57cec5SDimitry Andric   //
2910b57cec5SDimitry Andric   // FIXME: This should be eliminated. What we want to do is make this part of
2920b57cec5SDimitry Andric   // the "default target for arguments" selection process, once we get out of
2930b57cec5SDimitry Andric   // the argument translation business.
2940b57cec5SDimitry Andric   mutable bool TargetInitialized;
2950b57cec5SDimitry Andric 
2960b57cec5SDimitry Andric   enum DarwinPlatformKind {
2970b57cec5SDimitry Andric     MacOS,
2980b57cec5SDimitry Andric     IPhoneOS,
2990b57cec5SDimitry Andric     TvOS,
3000b57cec5SDimitry Andric     WatchOS,
30181ad6265SDimitry Andric     DriverKit,
302*7a6dacacSDimitry Andric     XROS,
30381ad6265SDimitry Andric     LastDarwinPlatform = DriverKit
3040b57cec5SDimitry Andric   };
3050b57cec5SDimitry Andric   enum DarwinEnvironmentKind {
3060b57cec5SDimitry Andric     NativeEnvironment,
3070b57cec5SDimitry Andric     Simulator,
308fe6060f1SDimitry Andric     MacCatalyst,
3090b57cec5SDimitry Andric   };
3100b57cec5SDimitry Andric 
3110b57cec5SDimitry Andric   mutable DarwinPlatformKind TargetPlatform;
3120b57cec5SDimitry Andric   mutable DarwinEnvironmentKind TargetEnvironment;
3130b57cec5SDimitry Andric 
314fe6060f1SDimitry Andric   /// The native OS version we are targeting.
3150b57cec5SDimitry Andric   mutable VersionTuple TargetVersion;
316fe6060f1SDimitry Andric   /// The OS version we are targeting as specified in the triple.
317fe6060f1SDimitry Andric   mutable VersionTuple OSTargetVersion;
3180b57cec5SDimitry Andric 
3190b57cec5SDimitry Andric   /// The information about the darwin SDK that was used.
320bdd1243dSDimitry Andric   mutable std::optional<DarwinSDKInfo> SDKInfo;
3210b57cec5SDimitry Andric 
32281ad6265SDimitry Andric   /// The target variant triple that was specified (if any).
323bdd1243dSDimitry Andric   mutable std::optional<llvm::Triple> TargetVariantTriple;
32481ad6265SDimitry Andric 
325*7a6dacacSDimitry Andric   LazyDetector<CudaInstallationDetector> CudaInstallation;
326*7a6dacacSDimitry Andric   LazyDetector<RocmInstallationDetector> RocmInstallation;
3270b57cec5SDimitry Andric 
3280b57cec5SDimitry Andric private:
3290b57cec5SDimitry Andric   void AddDeploymentTarget(llvm::opt::DerivedArgList &Args) const;
3300b57cec5SDimitry Andric 
3310b57cec5SDimitry Andric public:
3320b57cec5SDimitry Andric   Darwin(const Driver &D, const llvm::Triple &Triple,
3330b57cec5SDimitry Andric          const llvm::opt::ArgList &Args);
3340b57cec5SDimitry Andric   ~Darwin() override;
3350b57cec5SDimitry Andric 
3360b57cec5SDimitry Andric   std::string ComputeEffectiveClangTriple(const llvm::opt::ArgList &Args,
3370b57cec5SDimitry Andric                                           types::ID InputType) const override;
3380b57cec5SDimitry Andric 
3390b57cec5SDimitry Andric   /// @name Apple Specific Toolchain Implementation
3400b57cec5SDimitry Andric   /// {
3410b57cec5SDimitry Andric 
3420b57cec5SDimitry Andric   void addMinVersionArgs(const llvm::opt::ArgList &Args,
3430b57cec5SDimitry Andric                          llvm::opt::ArgStringList &CmdArgs) const override;
3440b57cec5SDimitry Andric 
345480093f4SDimitry Andric   void addPlatformVersionArgs(const llvm::opt::ArgList &Args,
346480093f4SDimitry Andric                               llvm::opt::ArgStringList &CmdArgs) const override;
347480093f4SDimitry Andric 
3480b57cec5SDimitry Andric   void addStartObjectFileArgs(const llvm::opt::ArgList &Args,
3490b57cec5SDimitry Andric                               llvm::opt::ArgStringList &CmdArgs) const override;
3500b57cec5SDimitry Andric 
3510b57cec5SDimitry Andric   bool isKernelStatic() const override {
3520b57cec5SDimitry Andric     return (!(isTargetIPhoneOS() && !isIPhoneOSVersionLT(6, 0)) &&
35381ad6265SDimitry Andric             !isTargetWatchOS() && !isTargetDriverKit());
3540b57cec5SDimitry Andric   }
3550b57cec5SDimitry Andric 
3560b57cec5SDimitry Andric   void addProfileRTLibs(const llvm::opt::ArgList &Args,
3570b57cec5SDimitry Andric                         llvm::opt::ArgStringList &CmdArgs) const override;
3580b57cec5SDimitry Andric 
3590b57cec5SDimitry Andric protected:
3600b57cec5SDimitry Andric   /// }
3610b57cec5SDimitry Andric   /// @name Darwin specific Toolchain functions
3620b57cec5SDimitry Andric   /// {
3630b57cec5SDimitry Andric 
3640b57cec5SDimitry Andric   // FIXME: Eliminate these ...Target functions and derive separate tool chains
3650b57cec5SDimitry Andric   // for these targets and put version in constructor.
3660b57cec5SDimitry Andric   void setTarget(DarwinPlatformKind Platform, DarwinEnvironmentKind Environment,
367fe6060f1SDimitry Andric                  unsigned Major, unsigned Minor, unsigned Micro,
368fe6060f1SDimitry Andric                  VersionTuple NativeTargetVersion) const {
3690b57cec5SDimitry Andric     // FIXME: For now, allow reinitialization as long as values don't
3700b57cec5SDimitry Andric     // change. This will go away when we move away from argument translation.
3710b57cec5SDimitry Andric     if (TargetInitialized && TargetPlatform == Platform &&
3720b57cec5SDimitry Andric         TargetEnvironment == Environment &&
373fe6060f1SDimitry Andric         (Environment == MacCatalyst ? OSTargetVersion : TargetVersion) ==
374fe6060f1SDimitry Andric             VersionTuple(Major, Minor, Micro))
3750b57cec5SDimitry Andric       return;
3760b57cec5SDimitry Andric 
3770b57cec5SDimitry Andric     assert(!TargetInitialized && "Target already initialized!");
3780b57cec5SDimitry Andric     TargetInitialized = true;
3790b57cec5SDimitry Andric     TargetPlatform = Platform;
3800b57cec5SDimitry Andric     TargetEnvironment = Environment;
3810b57cec5SDimitry Andric     TargetVersion = VersionTuple(Major, Minor, Micro);
3820b57cec5SDimitry Andric     if (Environment == Simulator)
3830b57cec5SDimitry Andric       const_cast<Darwin *>(this)->setTripleEnvironment(llvm::Triple::Simulator);
384fe6060f1SDimitry Andric     else if (Environment == MacCatalyst) {
385fe6060f1SDimitry Andric       const_cast<Darwin *>(this)->setTripleEnvironment(llvm::Triple::MacABI);
386fe6060f1SDimitry Andric       TargetVersion = NativeTargetVersion;
387fe6060f1SDimitry Andric       OSTargetVersion = VersionTuple(Major, Minor, Micro);
388fe6060f1SDimitry Andric     }
3890b57cec5SDimitry Andric   }
3900b57cec5SDimitry Andric 
3915ffd83dbSDimitry Andric public:
3920b57cec5SDimitry Andric   bool isTargetIPhoneOS() const {
3930b57cec5SDimitry Andric     assert(TargetInitialized && "Target not initialized!");
3940b57cec5SDimitry Andric     return (TargetPlatform == IPhoneOS || TargetPlatform == TvOS) &&
3950b57cec5SDimitry Andric            TargetEnvironment == NativeEnvironment;
3960b57cec5SDimitry Andric   }
3970b57cec5SDimitry Andric 
3980b57cec5SDimitry Andric   bool isTargetIOSSimulator() const {
3990b57cec5SDimitry Andric     assert(TargetInitialized && "Target not initialized!");
4000b57cec5SDimitry Andric     return (TargetPlatform == IPhoneOS || TargetPlatform == TvOS) &&
4010b57cec5SDimitry Andric            TargetEnvironment == Simulator;
4020b57cec5SDimitry Andric   }
4030b57cec5SDimitry Andric 
4040b57cec5SDimitry Andric   bool isTargetIOSBased() const {
4050b57cec5SDimitry Andric     assert(TargetInitialized && "Target not initialized!");
4060b57cec5SDimitry Andric     return isTargetIPhoneOS() || isTargetIOSSimulator();
4070b57cec5SDimitry Andric   }
4080b57cec5SDimitry Andric 
409*7a6dacacSDimitry Andric   bool isTargetXROSDevice() const {
410*7a6dacacSDimitry Andric     return TargetPlatform == XROS && TargetEnvironment == NativeEnvironment;
411*7a6dacacSDimitry Andric   }
412*7a6dacacSDimitry Andric 
413*7a6dacacSDimitry Andric   bool isTargetXROSSimulator() const {
414*7a6dacacSDimitry Andric     return TargetPlatform == XROS && TargetEnvironment == Simulator;
415*7a6dacacSDimitry Andric   }
416*7a6dacacSDimitry Andric 
417*7a6dacacSDimitry Andric   bool isTargetXROS() const { return TargetPlatform == XROS; }
418*7a6dacacSDimitry Andric 
4190b57cec5SDimitry Andric   bool isTargetTvOS() const {
4200b57cec5SDimitry Andric     assert(TargetInitialized && "Target not initialized!");
4210b57cec5SDimitry Andric     return TargetPlatform == TvOS && TargetEnvironment == NativeEnvironment;
4220b57cec5SDimitry Andric   }
4230b57cec5SDimitry Andric 
4240b57cec5SDimitry Andric   bool isTargetTvOSSimulator() const {
4250b57cec5SDimitry Andric     assert(TargetInitialized && "Target not initialized!");
4260b57cec5SDimitry Andric     return TargetPlatform == TvOS && TargetEnvironment == Simulator;
4270b57cec5SDimitry Andric   }
4280b57cec5SDimitry Andric 
4290b57cec5SDimitry Andric   bool isTargetTvOSBased() const {
4300b57cec5SDimitry Andric     assert(TargetInitialized && "Target not initialized!");
4310b57cec5SDimitry Andric     return TargetPlatform == TvOS;
4320b57cec5SDimitry Andric   }
4330b57cec5SDimitry Andric 
4340b57cec5SDimitry Andric   bool isTargetWatchOS() const {
4350b57cec5SDimitry Andric     assert(TargetInitialized && "Target not initialized!");
4360b57cec5SDimitry Andric     return TargetPlatform == WatchOS && TargetEnvironment == NativeEnvironment;
4370b57cec5SDimitry Andric   }
4380b57cec5SDimitry Andric 
4390b57cec5SDimitry Andric   bool isTargetWatchOSSimulator() const {
4400b57cec5SDimitry Andric     assert(TargetInitialized && "Target not initialized!");
4410b57cec5SDimitry Andric     return TargetPlatform == WatchOS && TargetEnvironment == Simulator;
4420b57cec5SDimitry Andric   }
4430b57cec5SDimitry Andric 
4440b57cec5SDimitry Andric   bool isTargetWatchOSBased() const {
4450b57cec5SDimitry Andric     assert(TargetInitialized && "Target not initialized!");
4460b57cec5SDimitry Andric     return TargetPlatform == WatchOS;
4470b57cec5SDimitry Andric   }
4480b57cec5SDimitry Andric 
44981ad6265SDimitry Andric   bool isTargetDriverKit() const {
45081ad6265SDimitry Andric     assert(TargetInitialized && "Target not initialized!");
45181ad6265SDimitry Andric     return TargetPlatform == DriverKit;
45281ad6265SDimitry Andric   }
45381ad6265SDimitry Andric 
454fe6060f1SDimitry Andric   bool isTargetMacCatalyst() const {
455fe6060f1SDimitry Andric     return TargetPlatform == IPhoneOS && TargetEnvironment == MacCatalyst;
456fe6060f1SDimitry Andric   }
457fe6060f1SDimitry Andric 
4580b57cec5SDimitry Andric   bool isTargetMacOS() const {
4590b57cec5SDimitry Andric     assert(TargetInitialized && "Target not initialized!");
4600b57cec5SDimitry Andric     return TargetPlatform == MacOS;
4610b57cec5SDimitry Andric   }
4620b57cec5SDimitry Andric 
4635ffd83dbSDimitry Andric   bool isTargetMacOSBased() const {
4645ffd83dbSDimitry Andric     assert(TargetInitialized && "Target not initialized!");
465fe6060f1SDimitry Andric     return TargetPlatform == MacOS || isTargetMacCatalyst();
4665ffd83dbSDimitry Andric   }
4675ffd83dbSDimitry Andric 
4685ffd83dbSDimitry Andric   bool isTargetAppleSiliconMac() const {
4695ffd83dbSDimitry Andric     assert(TargetInitialized && "Target not initialized!");
4705ffd83dbSDimitry Andric     return isTargetMacOSBased() && getArch() == llvm::Triple::aarch64;
4715ffd83dbSDimitry Andric   }
4725ffd83dbSDimitry Andric 
4730b57cec5SDimitry Andric   bool isTargetInitialized() const { return TargetInitialized; }
4740b57cec5SDimitry Andric 
475fe6060f1SDimitry Andric   /// The version of the OS that's used by the OS specified in the target
476fe6060f1SDimitry Andric   /// triple. It might be different from the actual target OS on which the
477fe6060f1SDimitry Andric   /// program will run, e.g. MacCatalyst code runs on a macOS target, but its
478fe6060f1SDimitry Andric   /// target triple is iOS.
479fe6060f1SDimitry Andric   VersionTuple getTripleTargetVersion() const {
4800b57cec5SDimitry Andric     assert(TargetInitialized && "Target not initialized!");
481fe6060f1SDimitry Andric     return isTargetMacCatalyst() ? OSTargetVersion : TargetVersion;
4820b57cec5SDimitry Andric   }
4830b57cec5SDimitry Andric 
4840b57cec5SDimitry Andric   bool isIPhoneOSVersionLT(unsigned V0, unsigned V1 = 0,
4850b57cec5SDimitry Andric                            unsigned V2 = 0) const {
4860b57cec5SDimitry Andric     assert(isTargetIOSBased() && "Unexpected call for non iOS target!");
4870b57cec5SDimitry Andric     return TargetVersion < VersionTuple(V0, V1, V2);
4880b57cec5SDimitry Andric   }
4890b57cec5SDimitry Andric 
4905ffd83dbSDimitry Andric   /// Returns true if the minimum supported macOS version for the slice that's
4915ffd83dbSDimitry Andric   /// being built is less than the specified version. If there's no minimum
4925ffd83dbSDimitry Andric   /// supported macOS version, the deployment target version is compared to the
4935ffd83dbSDimitry Andric   /// specifed version instead.
4940b57cec5SDimitry Andric   bool isMacosxVersionLT(unsigned V0, unsigned V1 = 0, unsigned V2 = 0) const {
495fe6060f1SDimitry Andric     assert(isTargetMacOSBased() &&
496fe6060f1SDimitry Andric            (getTriple().isMacOSX() || getTriple().isMacCatalystEnvironment()) &&
4975ffd83dbSDimitry Andric            "Unexpected call for non OS X target!");
498e8d8bef9SDimitry Andric     // The effective triple might not be initialized yet, so construct a
499e8d8bef9SDimitry Andric     // pseudo-effective triple to get the minimum supported OS version.
500e8d8bef9SDimitry Andric     VersionTuple MinVers =
501e8d8bef9SDimitry Andric         llvm::Triple(getTriple().getArchName(), "apple", "macos")
502e8d8bef9SDimitry Andric             .getMinimumSupportedOSVersion();
5035ffd83dbSDimitry Andric     return (!MinVers.empty() && MinVers > TargetVersion
5045ffd83dbSDimitry Andric                 ? MinVers
5055ffd83dbSDimitry Andric                 : TargetVersion) < VersionTuple(V0, V1, V2);
5060b57cec5SDimitry Andric   }
5070b57cec5SDimitry Andric 
5085ffd83dbSDimitry Andric protected:
5090b57cec5SDimitry Andric   /// Return true if c++17 aligned allocation/deallocation functions are not
5100b57cec5SDimitry Andric   /// implemented in the c++ standard library of the deployment target we are
5110b57cec5SDimitry Andric   /// targeting.
5120b57cec5SDimitry Andric   bool isAlignedAllocationUnavailable() const;
5130b57cec5SDimitry Andric 
5140b57cec5SDimitry Andric   void addClangTargetOptions(const llvm::opt::ArgList &DriverArgs,
5150b57cec5SDimitry Andric                              llvm::opt::ArgStringList &CC1Args,
5160b57cec5SDimitry Andric                              Action::OffloadKind DeviceOffloadKind) const override;
5170b57cec5SDimitry Andric 
518bdd1243dSDimitry Andric   void addClangCC1ASTargetOptions(
519bdd1243dSDimitry Andric       const llvm::opt::ArgList &Args,
520bdd1243dSDimitry Andric       llvm::opt::ArgStringList &CC1ASArgs) const override;
521bdd1243dSDimitry Andric 
5220b57cec5SDimitry Andric   StringRef getPlatformFamily() const;
5230b57cec5SDimitry Andric   StringRef getOSLibraryNameSuffix(bool IgnoreSim = false) const override;
5240b57cec5SDimitry Andric 
5250b57cec5SDimitry Andric public:
5260b57cec5SDimitry Andric   static StringRef getSDKName(StringRef isysroot);
5270b57cec5SDimitry Andric 
5280b57cec5SDimitry Andric   /// }
5290b57cec5SDimitry Andric   /// @name ToolChain Implementation
5300b57cec5SDimitry Andric   /// {
5310b57cec5SDimitry Andric 
5320b57cec5SDimitry Andric   // Darwin tools support multiple architecture (e.g., i386 and x86_64) and
5330b57cec5SDimitry Andric   // most development is done against SDKs, so compiling for a different
5340b57cec5SDimitry Andric   // architecture should not get any special treatment.
5350b57cec5SDimitry Andric   bool isCrossCompiling() const override { return false; }
5360b57cec5SDimitry Andric 
5370b57cec5SDimitry Andric   llvm::opt::DerivedArgList *
5380b57cec5SDimitry Andric   TranslateArgs(const llvm::opt::DerivedArgList &Args, StringRef BoundArch,
5390b57cec5SDimitry Andric                 Action::OffloadKind DeviceOffloadKind) const override;
5400b57cec5SDimitry Andric 
5410b57cec5SDimitry Andric   CXXStdlibType GetDefaultCXXStdlibType() const override;
5420b57cec5SDimitry Andric   ObjCRuntime getDefaultObjCRuntime(bool isNonFragile) const override;
5430b57cec5SDimitry Andric   bool hasBlocksRuntime() const override;
5440b57cec5SDimitry Andric 
5450b57cec5SDimitry Andric   void AddCudaIncludeArgs(const llvm::opt::ArgList &DriverArgs,
5460b57cec5SDimitry Andric                           llvm::opt::ArgStringList &CC1Args) const override;
5475ffd83dbSDimitry Andric   void AddHIPIncludeArgs(const llvm::opt::ArgList &DriverArgs,
5485ffd83dbSDimitry Andric                          llvm::opt::ArgStringList &CC1Args) const override;
5490b57cec5SDimitry Andric 
5500b57cec5SDimitry Andric   bool UseObjCMixedDispatch() const override {
5510b57cec5SDimitry Andric     // This is only used with the non-fragile ABI and non-legacy dispatch.
5520b57cec5SDimitry Andric 
5530b57cec5SDimitry Andric     // Mixed dispatch is used everywhere except OS X before 10.6.
554fe6060f1SDimitry Andric     return !(isTargetMacOSBased() && isMacosxVersionLT(10, 6));
5550b57cec5SDimitry Andric   }
5560b57cec5SDimitry Andric 
557e8d8bef9SDimitry Andric   LangOptions::StackProtectorMode
558e8d8bef9SDimitry Andric   GetDefaultStackProtectorLevel(bool KernelOrKext) const override {
5590b57cec5SDimitry Andric     // Stack protectors default to on for user code on 10.5,
5600b57cec5SDimitry Andric     // and for everything in 10.6 and beyond
561*7a6dacacSDimitry Andric     if (isTargetIOSBased() || isTargetWatchOSBased() || isTargetDriverKit() ||
562*7a6dacacSDimitry Andric         isTargetXROS())
563e8d8bef9SDimitry Andric       return LangOptions::SSPOn;
564fe6060f1SDimitry Andric     else if (isTargetMacOSBased() && !isMacosxVersionLT(10, 6))
565e8d8bef9SDimitry Andric       return LangOptions::SSPOn;
566fe6060f1SDimitry Andric     else if (isTargetMacOSBased() && !isMacosxVersionLT(10, 5) && !KernelOrKext)
567e8d8bef9SDimitry Andric       return LangOptions::SSPOn;
5680b57cec5SDimitry Andric 
569e8d8bef9SDimitry Andric     return LangOptions::SSPOff;
5700b57cec5SDimitry Andric   }
5710b57cec5SDimitry Andric 
5720b57cec5SDimitry Andric   void CheckObjCARC() const override;
5730b57cec5SDimitry Andric 
5740b57cec5SDimitry Andric   llvm::ExceptionHandling GetExceptionModel(
5750b57cec5SDimitry Andric       const llvm::opt::ArgList &Args) const override;
5760b57cec5SDimitry Andric 
5770b57cec5SDimitry Andric   bool SupportsEmbeddedBitcode() const override;
5780b57cec5SDimitry Andric 
5790b57cec5SDimitry Andric   SanitizerMask getSupportedSanitizers() const override;
5800b57cec5SDimitry Andric 
5810b57cec5SDimitry Andric   void printVerboseInfo(raw_ostream &OS) const override;
5820b57cec5SDimitry Andric };
5830b57cec5SDimitry Andric 
5840b57cec5SDimitry Andric /// DarwinClang - The Darwin toolchain used by Clang.
5850b57cec5SDimitry Andric class LLVM_LIBRARY_VISIBILITY DarwinClang : public Darwin {
5860b57cec5SDimitry Andric public:
5870b57cec5SDimitry Andric   DarwinClang(const Driver &D, const llvm::Triple &Triple,
5880b57cec5SDimitry Andric               const llvm::opt::ArgList &Args);
5890b57cec5SDimitry Andric 
5900b57cec5SDimitry Andric   /// @name Apple ToolChain Implementation
5910b57cec5SDimitry Andric   /// {
5920b57cec5SDimitry Andric 
5930b57cec5SDimitry Andric   RuntimeLibType GetRuntimeLibType(const llvm::opt::ArgList &Args) const override;
5940b57cec5SDimitry Andric 
5950b57cec5SDimitry Andric   void AddLinkRuntimeLibArgs(const llvm::opt::ArgList &Args,
5960b57cec5SDimitry Andric                              llvm::opt::ArgStringList &CmdArgs,
5970b57cec5SDimitry Andric                              bool ForceLinkBuiltinRT = false) const override;
5980b57cec5SDimitry Andric 
5990b57cec5SDimitry Andric   void AddClangCXXStdlibIncludeArgs(
6000b57cec5SDimitry Andric       const llvm::opt::ArgList &DriverArgs,
6010b57cec5SDimitry Andric       llvm::opt::ArgStringList &CC1Args) const override;
6020b57cec5SDimitry Andric 
6030b57cec5SDimitry Andric   void AddClangSystemIncludeArgs(const llvm::opt::ArgList &DriverArgs,
6040b57cec5SDimitry Andric                                  llvm::opt::ArgStringList &CC1Args) const override;
6050b57cec5SDimitry Andric 
6060b57cec5SDimitry Andric   void AddCXXStdlibLibArgs(const llvm::opt::ArgList &Args,
6070b57cec5SDimitry Andric                            llvm::opt::ArgStringList &CmdArgs) const override;
6080b57cec5SDimitry Andric 
6090b57cec5SDimitry Andric   void AddCCKextLibArgs(const llvm::opt::ArgList &Args,
6100b57cec5SDimitry Andric                         llvm::opt::ArgStringList &CmdArgs) const override;
6110b57cec5SDimitry Andric 
6120b57cec5SDimitry Andric   void addClangWarningOptions(llvm::opt::ArgStringList &CC1Args) const override;
6130b57cec5SDimitry Andric 
6140b57cec5SDimitry Andric   void AddLinkARCArgs(const llvm::opt::ArgList &Args,
6150b57cec5SDimitry Andric                       llvm::opt::ArgStringList &CmdArgs) const override;
6160b57cec5SDimitry Andric 
6170b57cec5SDimitry Andric   unsigned GetDefaultDwarfVersion() const override;
6180b57cec5SDimitry Andric   // Until dtrace (via CTF) and LLDB can deal with distributed debug info,
6190b57cec5SDimitry Andric   // Darwin defaults to standalone/full debug info.
6200b57cec5SDimitry Andric   bool GetDefaultStandaloneDebug() const override { return true; }
6210b57cec5SDimitry Andric   llvm::DebuggerKind getDefaultDebuggerTuning() const override {
6220b57cec5SDimitry Andric     return llvm::DebuggerKind::LLDB;
6230b57cec5SDimitry Andric   }
6240b57cec5SDimitry Andric 
6250b57cec5SDimitry Andric   /// }
6260b57cec5SDimitry Andric 
6270b57cec5SDimitry Andric private:
6280b57cec5SDimitry Andric   void AddLinkSanitizerLibArgs(const llvm::opt::ArgList &Args,
6290b57cec5SDimitry Andric                                llvm::opt::ArgStringList &CmdArgs,
6300b57cec5SDimitry Andric                                StringRef Sanitizer,
6310b57cec5SDimitry Andric                                bool shared = true) const;
6320b57cec5SDimitry Andric 
6330b57cec5SDimitry Andric   bool AddGnuCPlusPlusIncludePaths(const llvm::opt::ArgList &DriverArgs,
6340b57cec5SDimitry Andric                                    llvm::opt::ArgStringList &CC1Args,
6350b57cec5SDimitry Andric                                    llvm::SmallString<128> Base,
6360b57cec5SDimitry Andric                                    llvm::StringRef Version,
6370b57cec5SDimitry Andric                                    llvm::StringRef ArchDir,
6380b57cec5SDimitry Andric                                    llvm::StringRef BitDir) const;
6390b57cec5SDimitry Andric 
640bdd1243dSDimitry Andric   llvm::SmallString<128>
641bdd1243dSDimitry Andric   GetEffectiveSysroot(const llvm::opt::ArgList &DriverArgs) const;
6420b57cec5SDimitry Andric };
6430b57cec5SDimitry Andric 
6440b57cec5SDimitry Andric } // end namespace toolchains
6450b57cec5SDimitry Andric } // end namespace driver
6460b57cec5SDimitry Andric } // end namespace clang
6470b57cec5SDimitry Andric 
6480b57cec5SDimitry Andric #endif // LLVM_CLANG_LIB_DRIVER_TOOLCHAINS_DARWIN_H
649