forked from OSchip/llvm-project
525 lines
18 KiB
C++
525 lines
18 KiB
C++
//===--- Darwin.h - Darwin ToolChain Implementations ------------*- C++ -*-===//
|
|
//
|
|
// The LLVM Compiler Infrastructure
|
|
//
|
|
// This file is distributed under the University of Illinois Open Source
|
|
// License. See LICENSE.TXT for details.
|
|
//
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
#ifndef LLVM_CLANG_LIB_DRIVER_TOOLCHAINS_DARWIN_H
|
|
#define LLVM_CLANG_LIB_DRIVER_TOOLCHAINS_DARWIN_H
|
|
|
|
#include "Cuda.h"
|
|
#include "clang/Driver/Tool.h"
|
|
#include "clang/Driver/ToolChain.h"
|
|
|
|
namespace clang {
|
|
namespace driver {
|
|
|
|
namespace toolchains {
|
|
class MachO;
|
|
} // end namespace toolchains
|
|
|
|
namespace tools {
|
|
|
|
namespace darwin {
|
|
llvm::Triple::ArchType getArchTypeForMachOArchName(StringRef Str);
|
|
void setTripleTypeForMachOArchName(llvm::Triple &T, StringRef Str);
|
|
|
|
class LLVM_LIBRARY_VISIBILITY MachOTool : public Tool {
|
|
virtual void anchor();
|
|
|
|
protected:
|
|
void AddMachOArch(const llvm::opt::ArgList &Args,
|
|
llvm::opt::ArgStringList &CmdArgs) const;
|
|
|
|
const toolchains::MachO &getMachOToolChain() const {
|
|
return reinterpret_cast<const toolchains::MachO &>(getToolChain());
|
|
}
|
|
|
|
public:
|
|
MachOTool(
|
|
const char *Name, const char *ShortName, const ToolChain &TC,
|
|
ResponseFileSupport ResponseSupport = RF_None,
|
|
llvm::sys::WindowsEncodingMethod ResponseEncoding = llvm::sys::WEM_UTF8,
|
|
const char *ResponseFlag = "@")
|
|
: Tool(Name, ShortName, TC, ResponseSupport, ResponseEncoding,
|
|
ResponseFlag) {}
|
|
};
|
|
|
|
class LLVM_LIBRARY_VISIBILITY Assembler : public MachOTool {
|
|
public:
|
|
Assembler(const ToolChain &TC)
|
|
: MachOTool("darwin::Assembler", "assembler", TC) {}
|
|
|
|
bool hasIntegratedCPP() const override { return false; }
|
|
|
|
void ConstructJob(Compilation &C, const JobAction &JA,
|
|
const InputInfo &Output, const InputInfoList &Inputs,
|
|
const llvm::opt::ArgList &TCArgs,
|
|
const char *LinkingOutput) const override;
|
|
};
|
|
|
|
class LLVM_LIBRARY_VISIBILITY Linker : public MachOTool {
|
|
bool NeedsTempPath(const InputInfoList &Inputs) const;
|
|
void AddLinkArgs(Compilation &C, const llvm::opt::ArgList &Args,
|
|
llvm::opt::ArgStringList &CmdArgs,
|
|
const InputInfoList &Inputs) const;
|
|
|
|
public:
|
|
Linker(const ToolChain &TC)
|
|
: MachOTool("darwin::Linker", "linker", TC, RF_FileList,
|
|
llvm::sys::WEM_UTF8, "-filelist") {}
|
|
|
|
bool hasIntegratedCPP() const override { return false; }
|
|
bool isLinkJob() const override { return true; }
|
|
|
|
void ConstructJob(Compilation &C, const JobAction &JA,
|
|
const InputInfo &Output, const InputInfoList &Inputs,
|
|
const llvm::opt::ArgList &TCArgs,
|
|
const char *LinkingOutput) const override;
|
|
};
|
|
|
|
class LLVM_LIBRARY_VISIBILITY Lipo : public MachOTool {
|
|
public:
|
|
Lipo(const ToolChain &TC) : MachOTool("darwin::Lipo", "lipo", TC) {}
|
|
|
|
bool hasIntegratedCPP() const override { return false; }
|
|
|
|
void ConstructJob(Compilation &C, const JobAction &JA,
|
|
const InputInfo &Output, const InputInfoList &Inputs,
|
|
const llvm::opt::ArgList &TCArgs,
|
|
const char *LinkingOutput) const override;
|
|
};
|
|
|
|
class LLVM_LIBRARY_VISIBILITY Dsymutil : public MachOTool {
|
|
public:
|
|
Dsymutil(const ToolChain &TC)
|
|
: MachOTool("darwin::Dsymutil", "dsymutil", TC) {}
|
|
|
|
bool hasIntegratedCPP() const override { return false; }
|
|
bool isDsymutilJob() const override { return true; }
|
|
|
|
void ConstructJob(Compilation &C, const JobAction &JA,
|
|
const InputInfo &Output, const InputInfoList &Inputs,
|
|
const llvm::opt::ArgList &TCArgs,
|
|
const char *LinkingOutput) const override;
|
|
};
|
|
|
|
class LLVM_LIBRARY_VISIBILITY VerifyDebug : public MachOTool {
|
|
public:
|
|
VerifyDebug(const ToolChain &TC)
|
|
: MachOTool("darwin::VerifyDebug", "dwarfdump", TC) {}
|
|
|
|
bool hasIntegratedCPP() const override { return false; }
|
|
|
|
void ConstructJob(Compilation &C, const JobAction &JA,
|
|
const InputInfo &Output, const InputInfoList &Inputs,
|
|
const llvm::opt::ArgList &TCArgs,
|
|
const char *LinkingOutput) const override;
|
|
};
|
|
} // end namespace darwin
|
|
} // end namespace tools
|
|
|
|
namespace toolchains {
|
|
|
|
class LLVM_LIBRARY_VISIBILITY MachO : public ToolChain {
|
|
protected:
|
|
Tool *buildAssembler() const override;
|
|
Tool *buildLinker() const override;
|
|
Tool *getTool(Action::ActionClass AC) const override;
|
|
|
|
private:
|
|
mutable std::unique_ptr<tools::darwin::Lipo> Lipo;
|
|
mutable std::unique_ptr<tools::darwin::Dsymutil> Dsymutil;
|
|
mutable std::unique_ptr<tools::darwin::VerifyDebug> VerifyDebug;
|
|
|
|
public:
|
|
MachO(const Driver &D, const llvm::Triple &Triple,
|
|
const llvm::opt::ArgList &Args);
|
|
~MachO() override;
|
|
|
|
/// @name MachO specific toolchain API
|
|
/// {
|
|
|
|
/// Get the "MachO" arch name for a particular compiler invocation. For
|
|
/// example, Apple treats different ARM variations as distinct architectures.
|
|
StringRef getMachOArchName(const llvm::opt::ArgList &Args) const;
|
|
|
|
/// Add the linker arguments to link the ARC runtime library.
|
|
virtual void AddLinkARCArgs(const llvm::opt::ArgList &Args,
|
|
llvm::opt::ArgStringList &CmdArgs) const {}
|
|
|
|
/// Add the linker arguments to link the compiler runtime library.
|
|
///
|
|
/// FIXME: This API is intended for use with embedded libraries only, and is
|
|
/// misleadingly named.
|
|
virtual void AddLinkRuntimeLibArgs(const llvm::opt::ArgList &Args,
|
|
llvm::opt::ArgStringList &CmdArgs) const;
|
|
|
|
virtual void addStartObjectFileArgs(const llvm::opt::ArgList &Args,
|
|
llvm::opt::ArgStringList &CmdArgs) const {
|
|
}
|
|
|
|
virtual void addMinVersionArgs(const llvm::opt::ArgList &Args,
|
|
llvm::opt::ArgStringList &CmdArgs) const {}
|
|
|
|
/// On some iOS platforms, kernel and kernel modules were built statically. Is
|
|
/// this such a target?
|
|
virtual bool isKernelStatic() const { return false; }
|
|
|
|
/// Is the target either iOS or an iOS simulator?
|
|
bool isTargetIOSBased() const { return false; }
|
|
|
|
/// Options to control how a runtime library is linked.
|
|
enum RuntimeLinkOptions : unsigned {
|
|
/// Link the library in even if it can't be found in the VFS.
|
|
RLO_AlwaysLink = 1 << 0,
|
|
|
|
/// Use the embedded runtime from the macho_embedded directory.
|
|
RLO_IsEmbedded = 1 << 1,
|
|
|
|
/// Emit rpaths for @executable_path as well as the resource directory.
|
|
RLO_AddRPath = 1 << 2,
|
|
|
|
/// Link the library in before any others.
|
|
RLO_FirstLink = 1 << 3,
|
|
};
|
|
|
|
/// Add a runtime library to the list of items to link.
|
|
void AddLinkRuntimeLib(const llvm::opt::ArgList &Args,
|
|
llvm::opt::ArgStringList &CmdArgs,
|
|
StringRef DarwinLibName,
|
|
RuntimeLinkOptions Opts = RuntimeLinkOptions()) const;
|
|
|
|
/// Add any profiling runtime libraries that are needed. This is essentially a
|
|
/// MachO specific version of addProfileRT in Tools.cpp.
|
|
void addProfileRTLibs(const llvm::opt::ArgList &Args,
|
|
llvm::opt::ArgStringList &CmdArgs) const override {
|
|
// There aren't any profiling libs for embedded targets currently.
|
|
}
|
|
|
|
/// }
|
|
/// @name ToolChain Implementation
|
|
/// {
|
|
|
|
types::ID LookupTypeForExtension(StringRef Ext) const override;
|
|
|
|
bool HasNativeLLVMSupport() const override;
|
|
|
|
llvm::opt::DerivedArgList *
|
|
TranslateArgs(const llvm::opt::DerivedArgList &Args, StringRef BoundArch,
|
|
Action::OffloadKind DeviceOffloadKind) const override;
|
|
|
|
bool IsBlocksDefault() const override {
|
|
// Always allow blocks on Apple; users interested in versioning are
|
|
// expected to use /usr/include/Block.h.
|
|
return true;
|
|
}
|
|
bool IsIntegratedAssemblerDefault() const override {
|
|
// Default integrated assembler to on for Apple's MachO targets.
|
|
return true;
|
|
}
|
|
|
|
bool IsMathErrnoDefault() const override { return false; }
|
|
|
|
bool IsEncodeExtendedBlockSignatureDefault() const override { return true; }
|
|
|
|
bool IsObjCNonFragileABIDefault() const override {
|
|
// Non-fragile ABI is default for everything but i386.
|
|
return getTriple().getArch() != llvm::Triple::x86;
|
|
}
|
|
|
|
bool UseObjCMixedDispatch() const override { return true; }
|
|
|
|
bool IsUnwindTablesDefault(const llvm::opt::ArgList &Args) const override;
|
|
|
|
RuntimeLibType GetDefaultRuntimeLibType() const override {
|
|
return ToolChain::RLT_CompilerRT;
|
|
}
|
|
|
|
bool isPICDefault() const override;
|
|
bool isPIEDefault() const override;
|
|
bool isPICDefaultForced() const override;
|
|
|
|
bool SupportsProfiling() const override;
|
|
|
|
bool UseDwarfDebugFlags() const override;
|
|
|
|
llvm::ExceptionHandling
|
|
GetExceptionModel(const llvm::opt::ArgList &Args) const override {
|
|
return llvm::ExceptionHandling::None;
|
|
}
|
|
|
|
/// }
|
|
};
|
|
|
|
/// Darwin - The base Darwin tool chain.
|
|
class LLVM_LIBRARY_VISIBILITY Darwin : public MachO {
|
|
public:
|
|
/// Whether the information on the target has been initialized.
|
|
//
|
|
// FIXME: This should be eliminated. What we want to do is make this part of
|
|
// the "default target for arguments" selection process, once we get out of
|
|
// the argument translation business.
|
|
mutable bool TargetInitialized;
|
|
|
|
enum DarwinPlatformKind {
|
|
MacOS,
|
|
IPhoneOS,
|
|
TvOS,
|
|
WatchOS,
|
|
LastDarwinPlatform = WatchOS
|
|
};
|
|
enum DarwinEnvironmentKind {
|
|
NativeEnvironment,
|
|
Simulator,
|
|
};
|
|
|
|
mutable DarwinPlatformKind TargetPlatform;
|
|
mutable DarwinEnvironmentKind TargetEnvironment;
|
|
|
|
/// The OS version we are targeting.
|
|
mutable VersionTuple TargetVersion;
|
|
|
|
CudaInstallationDetector CudaInstallation;
|
|
|
|
private:
|
|
void AddDeploymentTarget(llvm::opt::DerivedArgList &Args) const;
|
|
|
|
public:
|
|
Darwin(const Driver &D, const llvm::Triple &Triple,
|
|
const llvm::opt::ArgList &Args);
|
|
~Darwin() override;
|
|
|
|
std::string ComputeEffectiveClangTriple(const llvm::opt::ArgList &Args,
|
|
types::ID InputType) const override;
|
|
|
|
/// @name Apple Specific Toolchain Implementation
|
|
/// {
|
|
|
|
void addMinVersionArgs(const llvm::opt::ArgList &Args,
|
|
llvm::opt::ArgStringList &CmdArgs) const override;
|
|
|
|
void addStartObjectFileArgs(const llvm::opt::ArgList &Args,
|
|
llvm::opt::ArgStringList &CmdArgs) const override;
|
|
|
|
bool isKernelStatic() const override {
|
|
return (!(isTargetIPhoneOS() && !isIPhoneOSVersionLT(6, 0)) &&
|
|
!isTargetWatchOS());
|
|
}
|
|
|
|
void addProfileRTLibs(const llvm::opt::ArgList &Args,
|
|
llvm::opt::ArgStringList &CmdArgs) const override;
|
|
|
|
protected:
|
|
/// }
|
|
/// @name Darwin specific Toolchain functions
|
|
/// {
|
|
|
|
// FIXME: Eliminate these ...Target functions and derive separate tool chains
|
|
// for these targets and put version in constructor.
|
|
void setTarget(DarwinPlatformKind Platform, DarwinEnvironmentKind Environment,
|
|
unsigned Major, unsigned Minor, unsigned Micro) const {
|
|
// FIXME: For now, allow reinitialization as long as values don't
|
|
// change. This will go away when we move away from argument translation.
|
|
if (TargetInitialized && TargetPlatform == Platform &&
|
|
TargetEnvironment == Environment &&
|
|
TargetVersion == VersionTuple(Major, Minor, Micro))
|
|
return;
|
|
|
|
assert(!TargetInitialized && "Target already initialized!");
|
|
TargetInitialized = true;
|
|
TargetPlatform = Platform;
|
|
TargetEnvironment = Environment;
|
|
TargetVersion = VersionTuple(Major, Minor, Micro);
|
|
if (Environment == Simulator)
|
|
const_cast<Darwin *>(this)->setTripleEnvironment(llvm::Triple::Simulator);
|
|
}
|
|
|
|
bool isTargetIPhoneOS() const {
|
|
assert(TargetInitialized && "Target not initialized!");
|
|
return (TargetPlatform == IPhoneOS || TargetPlatform == TvOS) &&
|
|
TargetEnvironment == NativeEnvironment;
|
|
}
|
|
|
|
bool isTargetIOSSimulator() const {
|
|
assert(TargetInitialized && "Target not initialized!");
|
|
return (TargetPlatform == IPhoneOS || TargetPlatform == TvOS) &&
|
|
TargetEnvironment == Simulator;
|
|
}
|
|
|
|
bool isTargetIOSBased() const {
|
|
assert(TargetInitialized && "Target not initialized!");
|
|
return isTargetIPhoneOS() || isTargetIOSSimulator();
|
|
}
|
|
|
|
bool isTargetTvOS() const {
|
|
assert(TargetInitialized && "Target not initialized!");
|
|
return TargetPlatform == TvOS && TargetEnvironment == NativeEnvironment;
|
|
}
|
|
|
|
bool isTargetTvOSSimulator() const {
|
|
assert(TargetInitialized && "Target not initialized!");
|
|
return TargetPlatform == TvOS && TargetEnvironment == Simulator;
|
|
}
|
|
|
|
bool isTargetTvOSBased() const {
|
|
assert(TargetInitialized && "Target not initialized!");
|
|
return TargetPlatform == TvOS;
|
|
}
|
|
|
|
bool isTargetWatchOS() const {
|
|
assert(TargetInitialized && "Target not initialized!");
|
|
return TargetPlatform == WatchOS && TargetEnvironment == NativeEnvironment;
|
|
}
|
|
|
|
bool isTargetWatchOSSimulator() const {
|
|
assert(TargetInitialized && "Target not initialized!");
|
|
return TargetPlatform == WatchOS && TargetEnvironment == Simulator;
|
|
}
|
|
|
|
bool isTargetWatchOSBased() const {
|
|
assert(TargetInitialized && "Target not initialized!");
|
|
return TargetPlatform == WatchOS;
|
|
}
|
|
|
|
bool isTargetMacOS() const {
|
|
assert(TargetInitialized && "Target not initialized!");
|
|
return TargetPlatform == MacOS;
|
|
}
|
|
|
|
bool isTargetInitialized() const { return TargetInitialized; }
|
|
|
|
VersionTuple getTargetVersion() const {
|
|
assert(TargetInitialized && "Target not initialized!");
|
|
return TargetVersion;
|
|
}
|
|
|
|
bool isIPhoneOSVersionLT(unsigned V0, unsigned V1 = 0,
|
|
unsigned V2 = 0) const {
|
|
assert(isTargetIOSBased() && "Unexpected call for non iOS target!");
|
|
return TargetVersion < VersionTuple(V0, V1, V2);
|
|
}
|
|
|
|
bool isMacosxVersionLT(unsigned V0, unsigned V1 = 0, unsigned V2 = 0) const {
|
|
assert(isTargetMacOS() && "Unexpected call for non OS X target!");
|
|
return TargetVersion < VersionTuple(V0, V1, V2);
|
|
}
|
|
|
|
/// Return true if c++17 aligned allocation/deallocation functions are not
|
|
/// implemented in the c++ standard library of the deployment target we are
|
|
/// targeting.
|
|
bool isAlignedAllocationUnavailable() const;
|
|
|
|
void addClangTargetOptions(const llvm::opt::ArgList &DriverArgs,
|
|
llvm::opt::ArgStringList &CC1Args,
|
|
Action::OffloadKind DeviceOffloadKind) const override;
|
|
|
|
StringRef getPlatformFamily() const;
|
|
StringRef getOSLibraryNameSuffix() const;
|
|
|
|
public:
|
|
static StringRef getSDKName(StringRef isysroot);
|
|
|
|
/// }
|
|
/// @name ToolChain Implementation
|
|
/// {
|
|
|
|
// Darwin tools support multiple architecture (e.g., i386 and x86_64) and
|
|
// most development is done against SDKs, so compiling for a different
|
|
// architecture should not get any special treatment.
|
|
bool isCrossCompiling() const override { return false; }
|
|
|
|
llvm::opt::DerivedArgList *
|
|
TranslateArgs(const llvm::opt::DerivedArgList &Args, StringRef BoundArch,
|
|
Action::OffloadKind DeviceOffloadKind) const override;
|
|
|
|
CXXStdlibType GetDefaultCXXStdlibType() const override;
|
|
ObjCRuntime getDefaultObjCRuntime(bool isNonFragile) const override;
|
|
bool hasBlocksRuntime() const override;
|
|
|
|
void AddCudaIncludeArgs(const llvm::opt::ArgList &DriverArgs,
|
|
llvm::opt::ArgStringList &CC1Args) const override;
|
|
|
|
bool UseObjCMixedDispatch() const override {
|
|
// This is only used with the non-fragile ABI and non-legacy dispatch.
|
|
|
|
// Mixed dispatch is used everywhere except OS X before 10.6.
|
|
return !(isTargetMacOS() && isMacosxVersionLT(10, 6));
|
|
}
|
|
|
|
unsigned GetDefaultStackProtectorLevel(bool KernelOrKext) const override {
|
|
// Stack protectors default to on for user code on 10.5,
|
|
// and for everything in 10.6 and beyond
|
|
if (isTargetIOSBased() || isTargetWatchOSBased())
|
|
return 1;
|
|
else if (isTargetMacOS() && !isMacosxVersionLT(10, 6))
|
|
return 1;
|
|
else if (isTargetMacOS() && !isMacosxVersionLT(10, 5) && !KernelOrKext)
|
|
return 1;
|
|
|
|
return 0;
|
|
}
|
|
|
|
void CheckObjCARC() const override;
|
|
|
|
llvm::ExceptionHandling GetExceptionModel(
|
|
const llvm::opt::ArgList &Args) const override;
|
|
|
|
bool SupportsEmbeddedBitcode() const override;
|
|
|
|
SanitizerMask getSupportedSanitizers() const override;
|
|
|
|
void printVerboseInfo(raw_ostream &OS) const override;
|
|
};
|
|
|
|
/// DarwinClang - The Darwin toolchain used by Clang.
|
|
class LLVM_LIBRARY_VISIBILITY DarwinClang : public Darwin {
|
|
public:
|
|
DarwinClang(const Driver &D, const llvm::Triple &Triple,
|
|
const llvm::opt::ArgList &Args);
|
|
|
|
/// @name Apple ToolChain Implementation
|
|
/// {
|
|
|
|
RuntimeLibType GetRuntimeLibType(const llvm::opt::ArgList &Args) const override;
|
|
|
|
void AddLinkRuntimeLibArgs(const llvm::opt::ArgList &Args,
|
|
llvm::opt::ArgStringList &CmdArgs) const override;
|
|
|
|
void AddCXXStdlibLibArgs(const llvm::opt::ArgList &Args,
|
|
llvm::opt::ArgStringList &CmdArgs) const override;
|
|
|
|
void AddCCKextLibArgs(const llvm::opt::ArgList &Args,
|
|
llvm::opt::ArgStringList &CmdArgs) const override;
|
|
|
|
void addClangWarningOptions(llvm::opt::ArgStringList &CC1Args) const override;
|
|
|
|
void AddLinkARCArgs(const llvm::opt::ArgList &Args,
|
|
llvm::opt::ArgStringList &CmdArgs) const override;
|
|
|
|
unsigned GetDefaultDwarfVersion() const override;
|
|
// Until dtrace (via CTF) and LLDB can deal with distributed debug info,
|
|
// Darwin defaults to standalone/full debug info.
|
|
bool GetDefaultStandaloneDebug() const override { return true; }
|
|
llvm::DebuggerKind getDefaultDebuggerTuning() const override {
|
|
return llvm::DebuggerKind::LLDB;
|
|
}
|
|
|
|
/// }
|
|
|
|
private:
|
|
void AddLinkSanitizerLibArgs(const llvm::opt::ArgList &Args,
|
|
llvm::opt::ArgStringList &CmdArgs,
|
|
StringRef Sanitizer,
|
|
bool shared = true) const;
|
|
};
|
|
|
|
} // end namespace toolchains
|
|
} // end namespace driver
|
|
} // end namespace clang
|
|
|
|
#endif // LLVM_CLANG_LIB_DRIVER_TOOLCHAINS_DARWIN_H
|