1 //===--- Darwin.h - Darwin ToolChain Implementations ------------*- C++ -*-===//
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
7 //===----------------------------------------------------------------------===//
9 #ifndef LLVM_CLANG_LIB_DRIVER_TOOLCHAINS_DARWIN_H
10 #define LLVM_CLANG_LIB_DRIVER_TOOLCHAINS_DARWIN_H
13 #include "clang/Driver/DarwinSDKInfo.h"
14 #include "clang/Driver/Tool.h"
15 #include "clang/Driver/ToolChain.h"
16 #include "clang/Driver/XRayArgs.h"
21 namespace toolchains {
23 } // end namespace toolchains
28 llvm::Triple::ArchType getArchTypeForMachOArchName(StringRef Str);
29 void setTripleTypeForMachOArchName(llvm::Triple &T, StringRef Str);
31 class LLVM_LIBRARY_VISIBILITY MachOTool : public Tool {
32 virtual void anchor();
35 void AddMachOArch(const llvm::opt::ArgList &Args,
36 llvm::opt::ArgStringList &CmdArgs) const;
38 const toolchains::MachO &getMachOToolChain() const {
39 return reinterpret_cast<const toolchains::MachO &>(getToolChain());
44 const char *Name, const char *ShortName, const ToolChain &TC,
45 ResponseFileSupport ResponseSupport = RF_None,
46 llvm::sys::WindowsEncodingMethod ResponseEncoding = llvm::sys::WEM_UTF8,
47 const char *ResponseFlag = "@")
48 : Tool(Name, ShortName, TC, ResponseSupport, ResponseEncoding,
52 class LLVM_LIBRARY_VISIBILITY Assembler : public MachOTool {
54 Assembler(const ToolChain &TC)
55 : MachOTool("darwin::Assembler", "assembler", TC) {}
57 bool hasIntegratedCPP() const override { return false; }
59 void ConstructJob(Compilation &C, const JobAction &JA,
60 const InputInfo &Output, const InputInfoList &Inputs,
61 const llvm::opt::ArgList &TCArgs,
62 const char *LinkingOutput) const override;
65 class LLVM_LIBRARY_VISIBILITY Linker : public MachOTool {
66 bool NeedsTempPath(const InputInfoList &Inputs) const;
67 void AddLinkArgs(Compilation &C, const llvm::opt::ArgList &Args,
68 llvm::opt::ArgStringList &CmdArgs,
69 const InputInfoList &Inputs) const;
72 Linker(const ToolChain &TC)
73 : MachOTool("darwin::Linker", "linker", TC, RF_FileList,
74 llvm::sys::WEM_UTF8, "-filelist") {}
76 bool hasIntegratedCPP() const override { return false; }
77 bool isLinkJob() const override { return true; }
79 void ConstructJob(Compilation &C, const JobAction &JA,
80 const InputInfo &Output, const InputInfoList &Inputs,
81 const llvm::opt::ArgList &TCArgs,
82 const char *LinkingOutput) const override;
85 class LLVM_LIBRARY_VISIBILITY Lipo : public MachOTool {
87 Lipo(const ToolChain &TC) : MachOTool("darwin::Lipo", "lipo", TC) {}
89 bool hasIntegratedCPP() const override { return false; }
91 void ConstructJob(Compilation &C, const JobAction &JA,
92 const InputInfo &Output, const InputInfoList &Inputs,
93 const llvm::opt::ArgList &TCArgs,
94 const char *LinkingOutput) const override;
97 class LLVM_LIBRARY_VISIBILITY Dsymutil : public MachOTool {
99 Dsymutil(const ToolChain &TC)
100 : MachOTool("darwin::Dsymutil", "dsymutil", TC) {}
102 bool hasIntegratedCPP() const override { return false; }
103 bool isDsymutilJob() const override { return true; }
105 void ConstructJob(Compilation &C, const JobAction &JA,
106 const InputInfo &Output, const InputInfoList &Inputs,
107 const llvm::opt::ArgList &TCArgs,
108 const char *LinkingOutput) const override;
111 class LLVM_LIBRARY_VISIBILITY VerifyDebug : public MachOTool {
113 VerifyDebug(const ToolChain &TC)
114 : MachOTool("darwin::VerifyDebug", "dwarfdump", TC) {}
116 bool hasIntegratedCPP() const override { return false; }
118 void ConstructJob(Compilation &C, const JobAction &JA,
119 const InputInfo &Output, const InputInfoList &Inputs,
120 const llvm::opt::ArgList &TCArgs,
121 const char *LinkingOutput) const override;
123 } // end namespace darwin
124 } // end namespace tools
126 namespace toolchains {
128 class LLVM_LIBRARY_VISIBILITY MachO : public ToolChain {
130 Tool *buildAssembler() const override;
131 Tool *buildLinker() const override;
132 Tool *getTool(Action::ActionClass AC) const override;
135 mutable std::unique_ptr<tools::darwin::Lipo> Lipo;
136 mutable std::unique_ptr<tools::darwin::Dsymutil> Dsymutil;
137 mutable std::unique_ptr<tools::darwin::VerifyDebug> VerifyDebug;
140 MachO(const Driver &D, const llvm::Triple &Triple,
141 const llvm::opt::ArgList &Args);
144 /// @name MachO specific toolchain API
147 /// Get the "MachO" arch name for a particular compiler invocation. For
148 /// example, Apple treats different ARM variations as distinct architectures.
149 StringRef getMachOArchName(const llvm::opt::ArgList &Args) const;
151 /// Add the linker arguments to link the ARC runtime library.
152 virtual void AddLinkARCArgs(const llvm::opt::ArgList &Args,
153 llvm::opt::ArgStringList &CmdArgs) const {}
155 /// Add the linker arguments to link the compiler runtime library.
157 /// FIXME: This API is intended for use with embedded libraries only, and is
158 /// misleadingly named.
159 virtual void AddLinkRuntimeLibArgs(const llvm::opt::ArgList &Args,
160 llvm::opt::ArgStringList &CmdArgs,
161 bool ForceLinkBuiltinRT = false) const;
163 virtual void addStartObjectFileArgs(const llvm::opt::ArgList &Args,
164 llvm::opt::ArgStringList &CmdArgs) const {
167 virtual void addMinVersionArgs(const llvm::opt::ArgList &Args,
168 llvm::opt::ArgStringList &CmdArgs) const {}
170 virtual void addPlatformVersionArgs(const llvm::opt::ArgList &Args,
171 llvm::opt::ArgStringList &CmdArgs) const {
174 /// On some iOS platforms, kernel and kernel modules were built statically. Is
175 /// this such a target?
176 virtual bool isKernelStatic() const { return false; }
178 /// Is the target either iOS or an iOS simulator?
179 bool isTargetIOSBased() const { return false; }
181 /// Options to control how a runtime library is linked.
182 enum RuntimeLinkOptions : unsigned {
183 /// Link the library in even if it can't be found in the VFS.
184 RLO_AlwaysLink = 1 << 0,
186 /// Use the embedded runtime from the macho_embedded directory.
187 RLO_IsEmbedded = 1 << 1,
189 /// Emit rpaths for @executable_path as well as the resource directory.
190 RLO_AddRPath = 1 << 2,
192 /// Link the library in before any others.
193 RLO_FirstLink = 1 << 3,
196 /// Add a runtime library to the list of items to link.
197 void AddLinkRuntimeLib(const llvm::opt::ArgList &Args,
198 llvm::opt::ArgStringList &CmdArgs, StringRef Component,
199 RuntimeLinkOptions Opts = RuntimeLinkOptions(),
200 bool IsShared = false) const;
202 /// Add any profiling runtime libraries that are needed. This is essentially a
203 /// MachO specific version of addProfileRT in Tools.cpp.
204 void addProfileRTLibs(const llvm::opt::ArgList &Args,
205 llvm::opt::ArgStringList &CmdArgs) const override {
206 // There aren't any profiling libs for embedded targets currently.
210 /// @name ToolChain Implementation
213 types::ID LookupTypeForExtension(StringRef Ext) const override;
215 bool HasNativeLLVMSupport() const override;
217 llvm::opt::DerivedArgList *
218 TranslateArgs(const llvm::opt::DerivedArgList &Args, StringRef BoundArch,
219 Action::OffloadKind DeviceOffloadKind) const override;
221 bool IsBlocksDefault() const override {
222 // Always allow blocks on Apple; users interested in versioning are
223 // expected to use /usr/include/Block.h.
226 bool IsIntegratedAssemblerDefault() const override {
227 // Default integrated assembler to on for Apple's MachO targets.
231 bool IsMathErrnoDefault() const override { return false; }
233 bool IsEncodeExtendedBlockSignatureDefault() const override { return true; }
235 bool IsObjCNonFragileABIDefault() const override {
236 // Non-fragile ABI is default for everything but i386.
237 return getTriple().getArch() != llvm::Triple::x86;
240 bool UseObjCMixedDispatch() const override { return true; }
242 bool IsUnwindTablesDefault(const llvm::opt::ArgList &Args) const override;
244 RuntimeLibType GetDefaultRuntimeLibType() const override {
245 return ToolChain::RLT_CompilerRT;
248 bool isPICDefault() const override;
249 bool isPIEDefault() const override;
250 bool isPICDefaultForced() const override;
252 bool SupportsProfiling() const override;
254 bool UseDwarfDebugFlags() const override;
256 llvm::ExceptionHandling
257 GetExceptionModel(const llvm::opt::ArgList &Args) const override {
258 return llvm::ExceptionHandling::None;
261 virtual StringRef getOSLibraryNameSuffix(bool IgnoreSim = false) const {
265 // Darwin toolchain uses legacy thin LTO API, which is not
266 // capable of unit splitting.
267 bool canSplitThinLTOUnit() const override { return false; }
271 /// Darwin - The base Darwin tool chain.
272 class LLVM_LIBRARY_VISIBILITY Darwin : public MachO {
274 /// Whether the information on the target has been initialized.
276 // FIXME: This should be eliminated. What we want to do is make this part of
277 // the "default target for arguments" selection process, once we get out of
278 // the argument translation business.
279 mutable bool TargetInitialized;
281 enum DarwinPlatformKind {
286 LastDarwinPlatform = WatchOS
288 enum DarwinEnvironmentKind {
293 mutable DarwinPlatformKind TargetPlatform;
294 mutable DarwinEnvironmentKind TargetEnvironment;
296 /// The OS version we are targeting.
297 mutable VersionTuple TargetVersion;
299 /// The information about the darwin SDK that was used.
300 mutable Optional<DarwinSDKInfo> SDKInfo;
302 CudaInstallationDetector CudaInstallation;
305 void AddDeploymentTarget(llvm::opt::DerivedArgList &Args) const;
308 Darwin(const Driver &D, const llvm::Triple &Triple,
309 const llvm::opt::ArgList &Args);
312 std::string ComputeEffectiveClangTriple(const llvm::opt::ArgList &Args,
313 types::ID InputType) const override;
315 /// @name Apple Specific Toolchain Implementation
318 void addMinVersionArgs(const llvm::opt::ArgList &Args,
319 llvm::opt::ArgStringList &CmdArgs) const override;
321 void addPlatformVersionArgs(const llvm::opt::ArgList &Args,
322 llvm::opt::ArgStringList &CmdArgs) const override;
324 void addStartObjectFileArgs(const llvm::opt::ArgList &Args,
325 llvm::opt::ArgStringList &CmdArgs) const override;
327 bool isKernelStatic() const override {
328 return (!(isTargetIPhoneOS() && !isIPhoneOSVersionLT(6, 0)) &&
332 void addProfileRTLibs(const llvm::opt::ArgList &Args,
333 llvm::opt::ArgStringList &CmdArgs) const override;
337 /// @name Darwin specific Toolchain functions
340 // FIXME: Eliminate these ...Target functions and derive separate tool chains
341 // for these targets and put version in constructor.
342 void setTarget(DarwinPlatformKind Platform, DarwinEnvironmentKind Environment,
343 unsigned Major, unsigned Minor, unsigned Micro) const {
344 // FIXME: For now, allow reinitialization as long as values don't
345 // change. This will go away when we move away from argument translation.
346 if (TargetInitialized && TargetPlatform == Platform &&
347 TargetEnvironment == Environment &&
348 TargetVersion == VersionTuple(Major, Minor, Micro))
351 assert(!TargetInitialized && "Target already initialized!");
352 TargetInitialized = true;
353 TargetPlatform = Platform;
354 TargetEnvironment = Environment;
355 TargetVersion = VersionTuple(Major, Minor, Micro);
356 if (Environment == Simulator)
357 const_cast<Darwin *>(this)->setTripleEnvironment(llvm::Triple::Simulator);
360 bool isTargetIPhoneOS() const {
361 assert(TargetInitialized && "Target not initialized!");
362 return (TargetPlatform == IPhoneOS || TargetPlatform == TvOS) &&
363 TargetEnvironment == NativeEnvironment;
366 bool isTargetIOSSimulator() const {
367 assert(TargetInitialized && "Target not initialized!");
368 return (TargetPlatform == IPhoneOS || TargetPlatform == TvOS) &&
369 TargetEnvironment == Simulator;
372 bool isTargetIOSBased() const {
373 assert(TargetInitialized && "Target not initialized!");
374 return isTargetIPhoneOS() || isTargetIOSSimulator();
377 bool isTargetTvOS() const {
378 assert(TargetInitialized && "Target not initialized!");
379 return TargetPlatform == TvOS && TargetEnvironment == NativeEnvironment;
382 bool isTargetTvOSSimulator() const {
383 assert(TargetInitialized && "Target not initialized!");
384 return TargetPlatform == TvOS && TargetEnvironment == Simulator;
387 bool isTargetTvOSBased() const {
388 assert(TargetInitialized && "Target not initialized!");
389 return TargetPlatform == TvOS;
392 bool isTargetWatchOS() const {
393 assert(TargetInitialized && "Target not initialized!");
394 return TargetPlatform == WatchOS && TargetEnvironment == NativeEnvironment;
397 bool isTargetWatchOSSimulator() const {
398 assert(TargetInitialized && "Target not initialized!");
399 return TargetPlatform == WatchOS && TargetEnvironment == Simulator;
402 bool isTargetWatchOSBased() const {
403 assert(TargetInitialized && "Target not initialized!");
404 return TargetPlatform == WatchOS;
407 bool isTargetMacOS() const {
408 assert(TargetInitialized && "Target not initialized!");
409 return TargetPlatform == MacOS;
412 bool isTargetInitialized() const { return TargetInitialized; }
414 VersionTuple getTargetVersion() const {
415 assert(TargetInitialized && "Target not initialized!");
416 return TargetVersion;
419 bool isIPhoneOSVersionLT(unsigned V0, unsigned V1 = 0,
420 unsigned V2 = 0) const {
421 assert(isTargetIOSBased() && "Unexpected call for non iOS target!");
422 return TargetVersion < VersionTuple(V0, V1, V2);
425 bool isMacosxVersionLT(unsigned V0, unsigned V1 = 0, unsigned V2 = 0) const {
426 assert(isTargetMacOS() && "Unexpected call for non OS X target!");
427 return TargetVersion < VersionTuple(V0, V1, V2);
430 /// Return true if c++17 aligned allocation/deallocation functions are not
431 /// implemented in the c++ standard library of the deployment target we are
433 bool isAlignedAllocationUnavailable() const;
435 void addClangTargetOptions(const llvm::opt::ArgList &DriverArgs,
436 llvm::opt::ArgStringList &CC1Args,
437 Action::OffloadKind DeviceOffloadKind) const override;
439 StringRef getPlatformFamily() const;
440 StringRef getOSLibraryNameSuffix(bool IgnoreSim = false) const override;
443 static StringRef getSDKName(StringRef isysroot);
446 /// @name ToolChain Implementation
449 // Darwin tools support multiple architecture (e.g., i386 and x86_64) and
450 // most development is done against SDKs, so compiling for a different
451 // architecture should not get any special treatment.
452 bool isCrossCompiling() const override { return false; }
454 llvm::opt::DerivedArgList *
455 TranslateArgs(const llvm::opt::DerivedArgList &Args, StringRef BoundArch,
456 Action::OffloadKind DeviceOffloadKind) const override;
458 CXXStdlibType GetDefaultCXXStdlibType() const override;
459 ObjCRuntime getDefaultObjCRuntime(bool isNonFragile) const override;
460 bool hasBlocksRuntime() const override;
462 void AddCudaIncludeArgs(const llvm::opt::ArgList &DriverArgs,
463 llvm::opt::ArgStringList &CC1Args) const override;
465 bool UseObjCMixedDispatch() const override {
466 // This is only used with the non-fragile ABI and non-legacy dispatch.
468 // Mixed dispatch is used everywhere except OS X before 10.6.
469 return !(isTargetMacOS() && isMacosxVersionLT(10, 6));
472 unsigned GetDefaultStackProtectorLevel(bool KernelOrKext) const override {
473 // Stack protectors default to on for user code on 10.5,
474 // and for everything in 10.6 and beyond
475 if (isTargetIOSBased() || isTargetWatchOSBased())
477 else if (isTargetMacOS() && !isMacosxVersionLT(10, 6))
479 else if (isTargetMacOS() && !isMacosxVersionLT(10, 5) && !KernelOrKext)
485 void CheckObjCARC() const override;
487 llvm::ExceptionHandling GetExceptionModel(
488 const llvm::opt::ArgList &Args) const override;
490 bool SupportsEmbeddedBitcode() const override;
492 SanitizerMask getSupportedSanitizers() const override;
494 void printVerboseInfo(raw_ostream &OS) const override;
497 /// DarwinClang - The Darwin toolchain used by Clang.
498 class LLVM_LIBRARY_VISIBILITY DarwinClang : public Darwin {
500 DarwinClang(const Driver &D, const llvm::Triple &Triple,
501 const llvm::opt::ArgList &Args);
503 /// @name Apple ToolChain Implementation
506 RuntimeLibType GetRuntimeLibType(const llvm::opt::ArgList &Args) const override;
508 void AddLinkRuntimeLibArgs(const llvm::opt::ArgList &Args,
509 llvm::opt::ArgStringList &CmdArgs,
510 bool ForceLinkBuiltinRT = false) const override;
512 void AddClangCXXStdlibIncludeArgs(
513 const llvm::opt::ArgList &DriverArgs,
514 llvm::opt::ArgStringList &CC1Args) const override;
516 void AddClangSystemIncludeArgs(const llvm::opt::ArgList &DriverArgs,
517 llvm::opt::ArgStringList &CC1Args) const override;
519 void AddCXXStdlibLibArgs(const llvm::opt::ArgList &Args,
520 llvm::opt::ArgStringList &CmdArgs) const override;
522 void AddCCKextLibArgs(const llvm::opt::ArgList &Args,
523 llvm::opt::ArgStringList &CmdArgs) const override;
525 void addClangWarningOptions(llvm::opt::ArgStringList &CC1Args) const override;
527 void AddLinkARCArgs(const llvm::opt::ArgList &Args,
528 llvm::opt::ArgStringList &CmdArgs) const override;
530 unsigned GetDefaultDwarfVersion() const override;
531 // Until dtrace (via CTF) and LLDB can deal with distributed debug info,
532 // Darwin defaults to standalone/full debug info.
533 bool GetDefaultStandaloneDebug() const override { return true; }
534 llvm::DebuggerKind getDefaultDebuggerTuning() const override {
535 return llvm::DebuggerKind::LLDB;
541 void AddLinkSanitizerLibArgs(const llvm::opt::ArgList &Args,
542 llvm::opt::ArgStringList &CmdArgs,
544 bool shared = true) const;
546 bool AddGnuCPlusPlusIncludePaths(const llvm::opt::ArgList &DriverArgs,
547 llvm::opt::ArgStringList &CC1Args,
548 llvm::SmallString<128> Base,
549 llvm::StringRef Version,
550 llvm::StringRef ArchDir,
551 llvm::StringRef BitDir) const;
553 llvm::StringRef GetHeaderSysroot(const llvm::opt::ArgList &DriverArgs) const;
556 } // end namespace toolchains
557 } // end namespace driver
558 } // end namespace clang
560 #endif // LLVM_CLANG_LIB_DRIVER_TOOLCHAINS_DARWIN_H