Path: blob/main/contrib/llvm-project/clang/lib/Driver/ToolChains/Darwin.h
35269 views
//===--- Darwin.h - Darwin ToolChain Implementations ------------*- C++ -*-===//1//2// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.3// See https://llvm.org/LICENSE.txt for license information.4// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception5//6//===----------------------------------------------------------------------===//78#ifndef LLVM_CLANG_LIB_DRIVER_TOOLCHAINS_DARWIN_H9#define LLVM_CLANG_LIB_DRIVER_TOOLCHAINS_DARWIN_H1011#include "Cuda.h"12#include "LazyDetector.h"13#include "ROCm.h"14#include "clang/Basic/DarwinSDKInfo.h"15#include "clang/Basic/LangOptions.h"16#include "clang/Driver/Tool.h"17#include "clang/Driver/ToolChain.h"18#include "clang/Driver/XRayArgs.h"1920namespace clang {21namespace driver {2223namespace toolchains {24class MachO;25} // end namespace toolchains2627namespace tools {2829namespace darwin {30llvm::Triple::ArchType getArchTypeForMachOArchName(StringRef Str);31void setTripleTypeForMachOArchName(llvm::Triple &T, StringRef Str,32const llvm::opt::ArgList &Args);3334class LLVM_LIBRARY_VISIBILITY MachOTool : public Tool {35virtual void anchor();3637protected:38void AddMachOArch(const llvm::opt::ArgList &Args,39llvm::opt::ArgStringList &CmdArgs) const;4041const toolchains::MachO &getMachOToolChain() const {42return reinterpret_cast<const toolchains::MachO &>(getToolChain());43}4445public:46MachOTool(const char *Name, const char *ShortName, const ToolChain &TC)47: Tool(Name, ShortName, TC) {}48};4950class LLVM_LIBRARY_VISIBILITY Assembler : public MachOTool {51public:52Assembler(const ToolChain &TC)53: MachOTool("darwin::Assembler", "assembler", TC) {}5455bool hasIntegratedCPP() const override { return false; }5657void ConstructJob(Compilation &C, const JobAction &JA,58const InputInfo &Output, const InputInfoList &Inputs,59const llvm::opt::ArgList &TCArgs,60const char *LinkingOutput) const override;61};6263class LLVM_LIBRARY_VISIBILITY Linker : public MachOTool {64bool NeedsTempPath(const InputInfoList &Inputs) const;65void AddLinkArgs(Compilation &C, const llvm::opt::ArgList &Args,66llvm::opt::ArgStringList &CmdArgs,67const InputInfoList &Inputs, VersionTuple Version,68bool LinkerIsLLD, bool UsePlatformVersion) const;6970public:71Linker(const ToolChain &TC) : MachOTool("darwin::Linker", "linker", TC) {}7273bool hasIntegratedCPP() const override { return false; }74bool isLinkJob() const override { return true; }7576void ConstructJob(Compilation &C, const JobAction &JA,77const InputInfo &Output, const InputInfoList &Inputs,78const llvm::opt::ArgList &TCArgs,79const char *LinkingOutput) const override;80};8182class LLVM_LIBRARY_VISIBILITY StaticLibTool : public MachOTool {83public:84StaticLibTool(const ToolChain &TC)85: MachOTool("darwin::StaticLibTool", "static-lib-linker", TC) {}8687bool hasIntegratedCPP() const override { return false; }88bool isLinkJob() const override { return true; }8990void ConstructJob(Compilation &C, const JobAction &JA,91const InputInfo &Output, const InputInfoList &Inputs,92const llvm::opt::ArgList &TCArgs,93const char *LinkingOutput) const override;94};9596class LLVM_LIBRARY_VISIBILITY Lipo : public MachOTool {97public:98Lipo(const ToolChain &TC) : MachOTool("darwin::Lipo", "lipo", TC) {}99100bool hasIntegratedCPP() const override { return false; }101102void ConstructJob(Compilation &C, const JobAction &JA,103const InputInfo &Output, const InputInfoList &Inputs,104const llvm::opt::ArgList &TCArgs,105const char *LinkingOutput) const override;106};107108class LLVM_LIBRARY_VISIBILITY Dsymutil : public MachOTool {109public:110Dsymutil(const ToolChain &TC)111: MachOTool("darwin::Dsymutil", "dsymutil", TC) {}112113bool hasIntegratedCPP() const override { return false; }114bool isDsymutilJob() const override { return true; }115116void ConstructJob(Compilation &C, const JobAction &JA,117const InputInfo &Output, const InputInfoList &Inputs,118const llvm::opt::ArgList &TCArgs,119const char *LinkingOutput) const override;120};121122class LLVM_LIBRARY_VISIBILITY VerifyDebug : public MachOTool {123public:124VerifyDebug(const ToolChain &TC)125: MachOTool("darwin::VerifyDebug", "dwarfdump", TC) {}126127bool hasIntegratedCPP() const override { return false; }128129void ConstructJob(Compilation &C, const JobAction &JA,130const InputInfo &Output, const InputInfoList &Inputs,131const llvm::opt::ArgList &TCArgs,132const char *LinkingOutput) const override;133};134} // end namespace darwin135} // end namespace tools136137namespace toolchains {138139class LLVM_LIBRARY_VISIBILITY MachO : public ToolChain {140protected:141Tool *buildAssembler() const override;142Tool *buildLinker() const override;143Tool *buildStaticLibTool() const override;144Tool *getTool(Action::ActionClass AC) const override;145146private:147mutable std::unique_ptr<tools::darwin::Lipo> Lipo;148mutable std::unique_ptr<tools::darwin::Dsymutil> Dsymutil;149mutable std::unique_ptr<tools::darwin::VerifyDebug> VerifyDebug;150151/// The version of the linker known to be available in the tool chain.152mutable std::optional<VersionTuple> LinkerVersion;153154public:155MachO(const Driver &D, const llvm::Triple &Triple,156const llvm::opt::ArgList &Args);157~MachO() override;158159/// @name MachO specific toolchain API160/// {161162/// Get the "MachO" arch name for a particular compiler invocation. For163/// example, Apple treats different ARM variations as distinct architectures.164StringRef getMachOArchName(const llvm::opt::ArgList &Args) const;165166/// Get the version of the linker known to be available for a particular167/// compiler invocation (via the `-mlinker-version=` arg).168VersionTuple getLinkerVersion(const llvm::opt::ArgList &Args) const;169170/// Add the linker arguments to link the ARC runtime library.171virtual void AddLinkARCArgs(const llvm::opt::ArgList &Args,172llvm::opt::ArgStringList &CmdArgs) const {}173174/// Add the linker arguments to link the compiler runtime library.175///176/// FIXME: This API is intended for use with embedded libraries only, and is177/// misleadingly named.178virtual void AddLinkRuntimeLibArgs(const llvm::opt::ArgList &Args,179llvm::opt::ArgStringList &CmdArgs,180bool ForceLinkBuiltinRT = false) const;181182virtual void addStartObjectFileArgs(const llvm::opt::ArgList &Args,183llvm::opt::ArgStringList &CmdArgs) const {184}185186virtual void addMinVersionArgs(const llvm::opt::ArgList &Args,187llvm::opt::ArgStringList &CmdArgs) const {}188189virtual void addPlatformVersionArgs(const llvm::opt::ArgList &Args,190llvm::opt::ArgStringList &CmdArgs) const {191}192193/// On some iOS platforms, kernel and kernel modules were built statically. Is194/// this such a target?195virtual bool isKernelStatic() const { return false; }196197/// Is the target either iOS or an iOS simulator?198bool isTargetIOSBased() const { return false; }199200/// Options to control how a runtime library is linked.201enum RuntimeLinkOptions : unsigned {202/// Link the library in even if it can't be found in the VFS.203RLO_AlwaysLink = 1 << 0,204205/// Use the embedded runtime from the macho_embedded directory.206RLO_IsEmbedded = 1 << 1,207208/// Emit rpaths for @executable_path as well as the resource directory.209RLO_AddRPath = 1 << 2,210};211212/// Add a runtime library to the list of items to link.213void AddLinkRuntimeLib(const llvm::opt::ArgList &Args,214llvm::opt::ArgStringList &CmdArgs, StringRef Component,215RuntimeLinkOptions Opts = RuntimeLinkOptions(),216bool IsShared = false) const;217218/// Add any profiling runtime libraries that are needed. This is essentially a219/// MachO specific version of addProfileRT in Tools.cpp.220void addProfileRTLibs(const llvm::opt::ArgList &Args,221llvm::opt::ArgStringList &CmdArgs) const override {222// There aren't any profiling libs for embedded targets currently.223}224225// Return the full path of the compiler-rt library on a non-Darwin MachO226// system. Those are under227// <resourcedir>/lib/darwin/macho_embedded/<...>(.dylib|.a).228std::string229getCompilerRT(const llvm::opt::ArgList &Args, StringRef Component,230FileType Type = ToolChain::FT_Static) const override;231232/// }233/// @name ToolChain Implementation234/// {235236types::ID LookupTypeForExtension(StringRef Ext) const override;237238bool HasNativeLLVMSupport() const override;239240llvm::opt::DerivedArgList *241TranslateArgs(const llvm::opt::DerivedArgList &Args, StringRef BoundArch,242Action::OffloadKind DeviceOffloadKind) const override;243244bool IsBlocksDefault() const override {245// Always allow blocks on Apple; users interested in versioning are246// expected to use /usr/include/Block.h.247return true;248}249250bool IsMathErrnoDefault() const override { return false; }251252bool IsEncodeExtendedBlockSignatureDefault() const override { return true; }253254bool IsObjCNonFragileABIDefault() const override {255// Non-fragile ABI is default for everything but i386.256return getTriple().getArch() != llvm::Triple::x86;257}258259bool UseObjCMixedDispatch() const override { return true; }260261UnwindTableLevel262getDefaultUnwindTableLevel(const llvm::opt::ArgList &Args) const override;263264RuntimeLibType GetDefaultRuntimeLibType() const override {265return ToolChain::RLT_CompilerRT;266}267268bool isPICDefault() const override;269bool isPIEDefault(const llvm::opt::ArgList &Args) const override;270bool isPICDefaultForced() const override;271272bool SupportsProfiling() const override;273274bool UseDwarfDebugFlags() const override;275std::string GetGlobalDebugPathRemapping() const override;276277llvm::ExceptionHandling278GetExceptionModel(const llvm::opt::ArgList &Args) const override {279return llvm::ExceptionHandling::None;280}281282virtual StringRef getOSLibraryNameSuffix(bool IgnoreSim = false) const {283return "";284}285286// Darwin toolchain uses legacy thin LTO API, which is not287// capable of unit splitting.288bool canSplitThinLTOUnit() const override { return false; }289/// }290};291292/// Darwin - The base Darwin tool chain.293class LLVM_LIBRARY_VISIBILITY Darwin : public MachO {294public:295/// Whether the information on the target has been initialized.296//297// FIXME: This should be eliminated. What we want to do is make this part of298// the "default target for arguments" selection process, once we get out of299// the argument translation business.300mutable bool TargetInitialized;301302enum DarwinPlatformKind {303MacOS,304IPhoneOS,305TvOS,306WatchOS,307DriverKit,308XROS,309LastDarwinPlatform = XROS310};311enum DarwinEnvironmentKind {312NativeEnvironment,313Simulator,314MacCatalyst,315};316317mutable DarwinPlatformKind TargetPlatform;318mutable DarwinEnvironmentKind TargetEnvironment;319320/// The native OS version we are targeting.321mutable VersionTuple TargetVersion;322/// The OS version we are targeting as specified in the triple.323mutable VersionTuple OSTargetVersion;324325/// The information about the darwin SDK that was used.326mutable std::optional<DarwinSDKInfo> SDKInfo;327328/// The target variant triple that was specified (if any).329mutable std::optional<llvm::Triple> TargetVariantTriple;330331LazyDetector<CudaInstallationDetector> CudaInstallation;332LazyDetector<RocmInstallationDetector> RocmInstallation;333334private:335void AddDeploymentTarget(llvm::opt::DerivedArgList &Args) const;336337public:338Darwin(const Driver &D, const llvm::Triple &Triple,339const llvm::opt::ArgList &Args);340~Darwin() override;341342std::string ComputeEffectiveClangTriple(const llvm::opt::ArgList &Args,343types::ID InputType) const override;344345/// @name Apple Specific Toolchain Implementation346/// {347348void addMinVersionArgs(const llvm::opt::ArgList &Args,349llvm::opt::ArgStringList &CmdArgs) const override;350351void addPlatformVersionArgs(const llvm::opt::ArgList &Args,352llvm::opt::ArgStringList &CmdArgs) const override;353354void addStartObjectFileArgs(const llvm::opt::ArgList &Args,355llvm::opt::ArgStringList &CmdArgs) const override;356357bool isKernelStatic() const override {358return (!(isTargetIPhoneOS() && !isIPhoneOSVersionLT(6, 0)) &&359!isTargetWatchOS() && !isTargetDriverKit());360}361362void addProfileRTLibs(const llvm::opt::ArgList &Args,363llvm::opt::ArgStringList &CmdArgs) const override;364365// Return the full path of the compiler-rt library on a Darwin MachO system.366// Those are under <resourcedir>/lib/darwin/<...>(.dylib|.a).367std::string368getCompilerRT(const llvm::opt::ArgList &Args, StringRef Component,369FileType Type = ToolChain::FT_Static) const override;370371protected:372/// }373/// @name Darwin specific Toolchain functions374/// {375376// FIXME: Eliminate these ...Target functions and derive separate tool chains377// for these targets and put version in constructor.378void setTarget(DarwinPlatformKind Platform, DarwinEnvironmentKind Environment,379unsigned Major, unsigned Minor, unsigned Micro,380VersionTuple NativeTargetVersion) const {381// FIXME: For now, allow reinitialization as long as values don't382// change. This will go away when we move away from argument translation.383if (TargetInitialized && TargetPlatform == Platform &&384TargetEnvironment == Environment &&385(Environment == MacCatalyst ? OSTargetVersion : TargetVersion) ==386VersionTuple(Major, Minor, Micro))387return;388389assert(!TargetInitialized && "Target already initialized!");390TargetInitialized = true;391TargetPlatform = Platform;392TargetEnvironment = Environment;393TargetVersion = VersionTuple(Major, Minor, Micro);394if (Environment == Simulator)395const_cast<Darwin *>(this)->setTripleEnvironment(llvm::Triple::Simulator);396else if (Environment == MacCatalyst) {397const_cast<Darwin *>(this)->setTripleEnvironment(llvm::Triple::MacABI);398TargetVersion = NativeTargetVersion;399OSTargetVersion = VersionTuple(Major, Minor, Micro);400}401}402403public:404bool isTargetIPhoneOS() const {405assert(TargetInitialized && "Target not initialized!");406return (TargetPlatform == IPhoneOS || TargetPlatform == TvOS) &&407TargetEnvironment == NativeEnvironment;408}409410bool isTargetIOSSimulator() const {411assert(TargetInitialized && "Target not initialized!");412return (TargetPlatform == IPhoneOS || TargetPlatform == TvOS) &&413TargetEnvironment == Simulator;414}415416bool isTargetIOSBased() const {417assert(TargetInitialized && "Target not initialized!");418return isTargetIPhoneOS() || isTargetIOSSimulator();419}420421bool isTargetXROSDevice() const {422return TargetPlatform == XROS && TargetEnvironment == NativeEnvironment;423}424425bool isTargetXROSSimulator() const {426return TargetPlatform == XROS && TargetEnvironment == Simulator;427}428429bool isTargetXROS() const { return TargetPlatform == XROS; }430431bool isTargetTvOS() const {432assert(TargetInitialized && "Target not initialized!");433return TargetPlatform == TvOS && TargetEnvironment == NativeEnvironment;434}435436bool isTargetTvOSSimulator() const {437assert(TargetInitialized && "Target not initialized!");438return TargetPlatform == TvOS && TargetEnvironment == Simulator;439}440441bool isTargetTvOSBased() const {442assert(TargetInitialized && "Target not initialized!");443return TargetPlatform == TvOS;444}445446bool isTargetWatchOS() const {447assert(TargetInitialized && "Target not initialized!");448return TargetPlatform == WatchOS && TargetEnvironment == NativeEnvironment;449}450451bool isTargetWatchOSSimulator() const {452assert(TargetInitialized && "Target not initialized!");453return TargetPlatform == WatchOS && TargetEnvironment == Simulator;454}455456bool isTargetWatchOSBased() const {457assert(TargetInitialized && "Target not initialized!");458return TargetPlatform == WatchOS;459}460461bool isTargetDriverKit() const {462assert(TargetInitialized && "Target not initialized!");463return TargetPlatform == DriverKit;464}465466bool isTargetMacCatalyst() const {467return TargetPlatform == IPhoneOS && TargetEnvironment == MacCatalyst;468}469470bool isTargetMacOS() const {471assert(TargetInitialized && "Target not initialized!");472return TargetPlatform == MacOS;473}474475bool isTargetMacOSBased() const {476assert(TargetInitialized && "Target not initialized!");477return TargetPlatform == MacOS || isTargetMacCatalyst();478}479480bool isTargetAppleSiliconMac() const {481assert(TargetInitialized && "Target not initialized!");482return isTargetMacOSBased() && getArch() == llvm::Triple::aarch64;483}484485bool isTargetInitialized() const { return TargetInitialized; }486487/// The version of the OS that's used by the OS specified in the target488/// triple. It might be different from the actual target OS on which the489/// program will run, e.g. MacCatalyst code runs on a macOS target, but its490/// target triple is iOS.491VersionTuple getTripleTargetVersion() const {492assert(TargetInitialized && "Target not initialized!");493return isTargetMacCatalyst() ? OSTargetVersion : TargetVersion;494}495496bool isIPhoneOSVersionLT(unsigned V0, unsigned V1 = 0,497unsigned V2 = 0) const {498assert(isTargetIOSBased() && "Unexpected call for non iOS target!");499return TargetVersion < VersionTuple(V0, V1, V2);500}501502/// Returns true if the minimum supported macOS version for the slice that's503/// being built is less than the specified version. If there's no minimum504/// supported macOS version, the deployment target version is compared to the505/// specifed version instead.506bool isMacosxVersionLT(unsigned V0, unsigned V1 = 0, unsigned V2 = 0) const {507assert(isTargetMacOSBased() &&508(getTriple().isMacOSX() || getTriple().isMacCatalystEnvironment()) &&509"Unexpected call for non OS X target!");510// The effective triple might not be initialized yet, so construct a511// pseudo-effective triple to get the minimum supported OS version.512VersionTuple MinVers =513llvm::Triple(getTriple().getArchName(), "apple", "macos")514.getMinimumSupportedOSVersion();515return (!MinVers.empty() && MinVers > TargetVersion516? MinVers517: TargetVersion) < VersionTuple(V0, V1, V2);518}519520protected:521/// Return true if c++17 aligned allocation/deallocation functions are not522/// implemented in the c++ standard library of the deployment target we are523/// targeting.524bool isAlignedAllocationUnavailable() const;525526/// Return true if c++14 sized deallocation functions are not implemented in527/// the c++ standard library of the deployment target we are targeting.528bool isSizedDeallocationUnavailable() const;529530void addClangTargetOptions(const llvm::opt::ArgList &DriverArgs,531llvm::opt::ArgStringList &CC1Args,532Action::OffloadKind DeviceOffloadKind) const override;533534void addClangCC1ASTargetOptions(535const llvm::opt::ArgList &Args,536llvm::opt::ArgStringList &CC1ASArgs) const override;537538StringRef getPlatformFamily() const;539StringRef getOSLibraryNameSuffix(bool IgnoreSim = false) const override;540541public:542static StringRef getSDKName(StringRef isysroot);543544/// }545/// @name ToolChain Implementation546/// {547548// Darwin tools support multiple architecture (e.g., i386 and x86_64) and549// most development is done against SDKs, so compiling for a different550// architecture should not get any special treatment.551bool isCrossCompiling() const override { return false; }552553llvm::opt::DerivedArgList *554TranslateArgs(const llvm::opt::DerivedArgList &Args, StringRef BoundArch,555Action::OffloadKind DeviceOffloadKind) const override;556557CXXStdlibType GetDefaultCXXStdlibType() const override;558ObjCRuntime getDefaultObjCRuntime(bool isNonFragile) const override;559bool hasBlocksRuntime() const override;560561void AddCudaIncludeArgs(const llvm::opt::ArgList &DriverArgs,562llvm::opt::ArgStringList &CC1Args) const override;563void AddHIPIncludeArgs(const llvm::opt::ArgList &DriverArgs,564llvm::opt::ArgStringList &CC1Args) const override;565566bool UseObjCMixedDispatch() const override {567// This is only used with the non-fragile ABI and non-legacy dispatch.568569// Mixed dispatch is used everywhere except OS X before 10.6.570return !(isTargetMacOSBased() && isMacosxVersionLT(10, 6));571}572573LangOptions::StackProtectorMode574GetDefaultStackProtectorLevel(bool KernelOrKext) const override {575// Stack protectors default to on for user code on 10.5,576// and for everything in 10.6 and beyond577if (isTargetIOSBased() || isTargetWatchOSBased() || isTargetDriverKit() ||578isTargetXROS())579return LangOptions::SSPOn;580else if (isTargetMacOSBased() && !isMacosxVersionLT(10, 6))581return LangOptions::SSPOn;582else if (isTargetMacOSBased() && !isMacosxVersionLT(10, 5) && !KernelOrKext)583return LangOptions::SSPOn;584585return LangOptions::SSPOff;586}587588void CheckObjCARC() const override;589590llvm::ExceptionHandling GetExceptionModel(591const llvm::opt::ArgList &Args) const override;592593bool SupportsEmbeddedBitcode() const override;594595SanitizerMask getSupportedSanitizers() const override;596597void printVerboseInfo(raw_ostream &OS) const override;598};599600/// DarwinClang - The Darwin toolchain used by Clang.601class LLVM_LIBRARY_VISIBILITY DarwinClang : public Darwin {602public:603DarwinClang(const Driver &D, const llvm::Triple &Triple,604const llvm::opt::ArgList &Args);605606/// @name Apple ToolChain Implementation607/// {608609RuntimeLibType GetRuntimeLibType(const llvm::opt::ArgList &Args) const override;610611void AddLinkRuntimeLibArgs(const llvm::opt::ArgList &Args,612llvm::opt::ArgStringList &CmdArgs,613bool ForceLinkBuiltinRT = false) const override;614615void AddClangCXXStdlibIncludeArgs(616const llvm::opt::ArgList &DriverArgs,617llvm::opt::ArgStringList &CC1Args) const override;618619void AddClangSystemIncludeArgs(const llvm::opt::ArgList &DriverArgs,620llvm::opt::ArgStringList &CC1Args) const override;621622void AddCXXStdlibLibArgs(const llvm::opt::ArgList &Args,623llvm::opt::ArgStringList &CmdArgs) const override;624625void AddCCKextLibArgs(const llvm::opt::ArgList &Args,626llvm::opt::ArgStringList &CmdArgs) const override;627628void addClangWarningOptions(llvm::opt::ArgStringList &CC1Args) const override;629630void AddLinkARCArgs(const llvm::opt::ArgList &Args,631llvm::opt::ArgStringList &CmdArgs) const override;632633unsigned GetDefaultDwarfVersion() const override;634// Until dtrace (via CTF) and LLDB can deal with distributed debug info,635// Darwin defaults to standalone/full debug info.636bool GetDefaultStandaloneDebug() const override { return true; }637llvm::DebuggerKind getDefaultDebuggerTuning() const override {638return llvm::DebuggerKind::LLDB;639}640641/// }642643private:644void AddLinkSanitizerLibArgs(const llvm::opt::ArgList &Args,645llvm::opt::ArgStringList &CmdArgs,646StringRef Sanitizer,647bool shared = true) const;648649bool AddGnuCPlusPlusIncludePaths(const llvm::opt::ArgList &DriverArgs,650llvm::opt::ArgStringList &CC1Args,651llvm::SmallString<128> Base,652llvm::StringRef Version,653llvm::StringRef ArchDir,654llvm::StringRef BitDir) const;655656llvm::SmallString<128>657GetEffectiveSysroot(const llvm::opt::ArgList &DriverArgs) const;658};659660} // end namespace toolchains661} // end namespace driver662} // end namespace clang663664#endif // LLVM_CLANG_LIB_DRIVER_TOOLCHAINS_DARWIN_H665666667