xref: /llvm-project/clang/lib/Driver/ToolChain.cpp (revision 2a551ab3002897ba52a27961b766f3741695c816)
1 //===- ToolChain.cpp - Collections of tools for one platform --------------===//
2 //
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6 //
7 //===----------------------------------------------------------------------===//
8 
9 #include "clang/Driver/ToolChain.h"
10 #include "ToolChains/Arch/AArch64.h"
11 #include "ToolChains/Arch/ARM.h"
12 #include "ToolChains/Arch/RISCV.h"
13 #include "ToolChains/Clang.h"
14 #include "ToolChains/CommonArgs.h"
15 #include "ToolChains/Flang.h"
16 #include "ToolChains/InterfaceStubs.h"
17 #include "clang/Basic/ObjCRuntime.h"
18 #include "clang/Basic/Sanitizers.h"
19 #include "clang/Config/config.h"
20 #include "clang/Driver/Action.h"
21 #include "clang/Driver/Driver.h"
22 #include "clang/Driver/InputInfo.h"
23 #include "clang/Driver/Job.h"
24 #include "clang/Driver/Options.h"
25 #include "clang/Driver/SanitizerArgs.h"
26 #include "clang/Driver/XRayArgs.h"
27 #include "llvm/ADT/SmallString.h"
28 #include "llvm/ADT/StringExtras.h"
29 #include "llvm/ADT/StringRef.h"
30 #include "llvm/ADT/Twine.h"
31 #include "llvm/Config/llvm-config.h"
32 #include "llvm/MC/MCTargetOptions.h"
33 #include "llvm/MC/TargetRegistry.h"
34 #include "llvm/Option/Arg.h"
35 #include "llvm/Option/ArgList.h"
36 #include "llvm/Option/OptTable.h"
37 #include "llvm/Option/Option.h"
38 #include "llvm/Support/ErrorHandling.h"
39 #include "llvm/Support/FileSystem.h"
40 #include "llvm/Support/FileUtilities.h"
41 #include "llvm/Support/Path.h"
42 #include "llvm/Support/Process.h"
43 #include "llvm/Support/VersionTuple.h"
44 #include "llvm/Support/VirtualFileSystem.h"
45 #include "llvm/TargetParser/AArch64TargetParser.h"
46 #include "llvm/TargetParser/RISCVISAInfo.h"
47 #include "llvm/TargetParser/TargetParser.h"
48 #include "llvm/TargetParser/Triple.h"
49 #include <cassert>
50 #include <cstddef>
51 #include <cstring>
52 #include <string>
53 
54 using namespace clang;
55 using namespace driver;
56 using namespace tools;
57 using namespace llvm;
58 using namespace llvm::opt;
59 
60 static llvm::opt::Arg *GetRTTIArgument(const ArgList &Args) {
61   return Args.getLastArg(options::OPT_mkernel, options::OPT_fapple_kext,
62                          options::OPT_fno_rtti, options::OPT_frtti);
63 }
64 
65 static ToolChain::RTTIMode CalculateRTTIMode(const ArgList &Args,
66                                              const llvm::Triple &Triple,
67                                              const Arg *CachedRTTIArg) {
68   // Explicit rtti/no-rtti args
69   if (CachedRTTIArg) {
70     if (CachedRTTIArg->getOption().matches(options::OPT_frtti))
71       return ToolChain::RM_Enabled;
72     else
73       return ToolChain::RM_Disabled;
74   }
75 
76   // -frtti is default, except for the PS4/PS5 and DriverKit.
77   bool NoRTTI = Triple.isPS() || Triple.isDriverKit();
78   return NoRTTI ? ToolChain::RM_Disabled : ToolChain::RM_Enabled;
79 }
80 
81 static ToolChain::ExceptionsMode CalculateExceptionsMode(const ArgList &Args) {
82   if (Args.hasFlag(options::OPT_fexceptions, options::OPT_fno_exceptions,
83                    true)) {
84     return ToolChain::EM_Enabled;
85   }
86   return ToolChain::EM_Disabled;
87 }
88 
89 ToolChain::ToolChain(const Driver &D, const llvm::Triple &T,
90                      const ArgList &Args)
91     : D(D), Triple(T), Args(Args), CachedRTTIArg(GetRTTIArgument(Args)),
92       CachedRTTIMode(CalculateRTTIMode(Args, Triple, CachedRTTIArg)),
93       CachedExceptionsMode(CalculateExceptionsMode(Args)) {
94   auto addIfExists = [this](path_list &List, const std::string &Path) {
95     if (getVFS().exists(Path))
96       List.push_back(Path);
97   };
98 
99   if (std::optional<std::string> Path = getRuntimePath())
100     getLibraryPaths().push_back(*Path);
101   if (std::optional<std::string> Path = getStdlibPath())
102     getFilePaths().push_back(*Path);
103   for (const auto &Path : getArchSpecificLibPaths())
104     addIfExists(getFilePaths(), Path);
105 }
106 
107 llvm::Expected<std::unique_ptr<llvm::MemoryBuffer>>
108 ToolChain::executeToolChainProgram(StringRef Executable) const {
109   llvm::SmallString<64> OutputFile;
110   llvm::sys::fs::createTemporaryFile("toolchain-program", "txt", OutputFile,
111                                      llvm::sys::fs::OF_Text);
112   llvm::FileRemover OutputRemover(OutputFile.c_str());
113   std::optional<llvm::StringRef> Redirects[] = {
114       {""},
115       OutputFile.str(),
116       {""},
117   };
118 
119   std::string ErrorMessage;
120   int SecondsToWait = 60;
121   if (std::optional<std::string> Str =
122           llvm::sys::Process::GetEnv("CLANG_TOOLCHAIN_PROGRAM_TIMEOUT")) {
123     if (!llvm::to_integer(*Str, SecondsToWait))
124       return llvm::createStringError(std::error_code(),
125                                      "CLANG_TOOLCHAIN_PROGRAM_TIMEOUT expected "
126                                      "an integer, got '" +
127                                          *Str + "'");
128     SecondsToWait = std::max(SecondsToWait, 0); // infinite
129   }
130   if (llvm::sys::ExecuteAndWait(Executable, {Executable}, {}, Redirects,
131                                 SecondsToWait,
132                                 /*MemoryLimit=*/0, &ErrorMessage))
133     return llvm::createStringError(std::error_code(),
134                                    Executable + ": " + ErrorMessage);
135 
136   llvm::ErrorOr<std::unique_ptr<llvm::MemoryBuffer>> OutputBuf =
137       llvm::MemoryBuffer::getFile(OutputFile.c_str());
138   if (!OutputBuf)
139     return llvm::createStringError(OutputBuf.getError(),
140                                    "Failed to read stdout of " + Executable +
141                                        ": " + OutputBuf.getError().message());
142   return std::move(*OutputBuf);
143 }
144 
145 void ToolChain::setTripleEnvironment(llvm::Triple::EnvironmentType Env) {
146   Triple.setEnvironment(Env);
147   if (EffectiveTriple != llvm::Triple())
148     EffectiveTriple.setEnvironment(Env);
149 }
150 
151 ToolChain::~ToolChain() = default;
152 
153 llvm::vfs::FileSystem &ToolChain::getVFS() const {
154   return getDriver().getVFS();
155 }
156 
157 bool ToolChain::useIntegratedAs() const {
158   return Args.hasFlag(options::OPT_fintegrated_as,
159                       options::OPT_fno_integrated_as,
160                       IsIntegratedAssemblerDefault());
161 }
162 
163 bool ToolChain::useIntegratedBackend() const {
164   assert(
165       ((IsIntegratedBackendDefault() && IsIntegratedBackendSupported()) ||
166        (!IsIntegratedBackendDefault() || IsNonIntegratedBackendSupported())) &&
167       "(Non-)integrated backend set incorrectly!");
168 
169   bool IBackend = Args.hasFlag(options::OPT_fintegrated_objemitter,
170                                options::OPT_fno_integrated_objemitter,
171                                IsIntegratedBackendDefault());
172 
173   // Diagnose when integrated-objemitter options are not supported by this
174   // toolchain.
175   unsigned DiagID;
176   if ((IBackend && !IsIntegratedBackendSupported()) ||
177       (!IBackend && !IsNonIntegratedBackendSupported()))
178     DiagID = clang::diag::err_drv_unsupported_opt_for_target;
179   else
180     DiagID = clang::diag::warn_drv_unsupported_opt_for_target;
181   Arg *A = Args.getLastArg(options::OPT_fno_integrated_objemitter);
182   if (A && !IsNonIntegratedBackendSupported())
183     D.Diag(DiagID) << A->getAsString(Args) << Triple.getTriple();
184   A = Args.getLastArg(options::OPT_fintegrated_objemitter);
185   if (A && !IsIntegratedBackendSupported())
186     D.Diag(DiagID) << A->getAsString(Args) << Triple.getTriple();
187 
188   return IBackend;
189 }
190 
191 bool ToolChain::useRelaxRelocations() const {
192   return ENABLE_X86_RELAX_RELOCATIONS;
193 }
194 
195 bool ToolChain::defaultToIEEELongDouble() const {
196   return PPC_LINUX_DEFAULT_IEEELONGDOUBLE && getTriple().isOSLinux();
197 }
198 
199 static void processMultilibCustomFlags(Multilib::flags_list &List,
200                                        const llvm::opt::ArgList &Args) {
201   for (const Arg *MultilibFlagArg :
202        Args.filtered(options::OPT_fmultilib_flag)) {
203     List.push_back(MultilibFlagArg->getAsString(Args));
204     MultilibFlagArg->claim();
205   }
206 }
207 
208 static void getAArch64MultilibFlags(const Driver &D,
209                                           const llvm::Triple &Triple,
210                                           const llvm::opt::ArgList &Args,
211                                           Multilib::flags_list &Result) {
212   std::vector<StringRef> Features;
213   tools::aarch64::getAArch64TargetFeatures(D, Triple, Args, Features, false);
214   const auto UnifiedFeatures = tools::unifyTargetFeatures(Features);
215   llvm::DenseSet<StringRef> FeatureSet(UnifiedFeatures.begin(),
216                                        UnifiedFeatures.end());
217   std::vector<std::string> MArch;
218   for (const auto &Ext : AArch64::Extensions)
219     if (!Ext.UserVisibleName.empty())
220       if (FeatureSet.contains(Ext.PosTargetFeature))
221         MArch.push_back(Ext.UserVisibleName.str());
222   for (const auto &Ext : AArch64::Extensions)
223     if (!Ext.UserVisibleName.empty())
224       if (FeatureSet.contains(Ext.NegTargetFeature))
225         MArch.push_back(("no" + Ext.UserVisibleName).str());
226   StringRef ArchName;
227   for (const auto &ArchInfo : AArch64::ArchInfos)
228     if (FeatureSet.contains(ArchInfo->ArchFeature))
229       ArchName = ArchInfo->Name;
230   assert(!ArchName.empty() && "at least one architecture should be found");
231   MArch.insert(MArch.begin(), ("-march=" + ArchName).str());
232   Result.push_back(llvm::join(MArch, "+"));
233 
234   const Arg *BranchProtectionArg =
235       Args.getLastArgNoClaim(options::OPT_mbranch_protection_EQ);
236   if (BranchProtectionArg) {
237     Result.push_back(BranchProtectionArg->getAsString(Args));
238   }
239 
240   if (Arg *AlignArg = Args.getLastArg(
241           options::OPT_mstrict_align, options::OPT_mno_strict_align,
242           options::OPT_mno_unaligned_access, options::OPT_munaligned_access)) {
243     if (AlignArg->getOption().matches(options::OPT_mstrict_align) ||
244         AlignArg->getOption().matches(options::OPT_mno_unaligned_access))
245       Result.push_back(AlignArg->getAsString(Args));
246   }
247 
248   if (Arg *Endian = Args.getLastArg(options::OPT_mbig_endian,
249                                     options::OPT_mlittle_endian)) {
250     if (Endian->getOption().matches(options::OPT_mbig_endian))
251       Result.push_back(Endian->getAsString(Args));
252   }
253 
254   const Arg *ABIArg = Args.getLastArgNoClaim(options::OPT_mabi_EQ);
255   if (ABIArg) {
256     Result.push_back(ABIArg->getAsString(Args));
257   }
258 
259   processMultilibCustomFlags(Result, Args);
260 }
261 
262 static void getARMMultilibFlags(const Driver &D,
263                                       const llvm::Triple &Triple,
264                                       const llvm::opt::ArgList &Args,
265                                       Multilib::flags_list &Result) {
266   std::vector<StringRef> Features;
267   llvm::ARM::FPUKind FPUKind = tools::arm::getARMTargetFeatures(
268       D, Triple, Args, Features, false /*ForAs*/, true /*ForMultilib*/);
269   const auto UnifiedFeatures = tools::unifyTargetFeatures(Features);
270   llvm::DenseSet<StringRef> FeatureSet(UnifiedFeatures.begin(),
271                                        UnifiedFeatures.end());
272   std::vector<std::string> MArch;
273   for (const auto &Ext : ARM::ARCHExtNames)
274     if (!Ext.Name.empty())
275       if (FeatureSet.contains(Ext.Feature))
276         MArch.push_back(Ext.Name.str());
277   for (const auto &Ext : ARM::ARCHExtNames)
278     if (!Ext.Name.empty())
279       if (FeatureSet.contains(Ext.NegFeature))
280         MArch.push_back(("no" + Ext.Name).str());
281   MArch.insert(MArch.begin(), ("-march=" + Triple.getArchName()).str());
282   Result.push_back(llvm::join(MArch, "+"));
283 
284   switch (FPUKind) {
285 #define ARM_FPU(NAME, KIND, VERSION, NEON_SUPPORT, RESTRICTION)                \
286   case llvm::ARM::KIND:                                                        \
287     Result.push_back("-mfpu=" NAME);                                           \
288     break;
289 #include "llvm/TargetParser/ARMTargetParser.def"
290   default:
291     llvm_unreachable("Invalid FPUKind");
292   }
293 
294   switch (arm::getARMFloatABI(D, Triple, Args)) {
295   case arm::FloatABI::Soft:
296     Result.push_back("-mfloat-abi=soft");
297     break;
298   case arm::FloatABI::SoftFP:
299     Result.push_back("-mfloat-abi=softfp");
300     break;
301   case arm::FloatABI::Hard:
302     Result.push_back("-mfloat-abi=hard");
303     break;
304   case arm::FloatABI::Invalid:
305     llvm_unreachable("Invalid float ABI");
306   }
307 
308   const Arg *BranchProtectionArg =
309       Args.getLastArgNoClaim(options::OPT_mbranch_protection_EQ);
310   if (BranchProtectionArg) {
311     Result.push_back(BranchProtectionArg->getAsString(Args));
312   }
313 
314   if (Arg *AlignArg = Args.getLastArg(
315           options::OPT_mstrict_align, options::OPT_mno_strict_align,
316           options::OPT_mno_unaligned_access, options::OPT_munaligned_access)) {
317     if (AlignArg->getOption().matches(options::OPT_mstrict_align) ||
318         AlignArg->getOption().matches(options::OPT_mno_unaligned_access))
319       Result.push_back(AlignArg->getAsString(Args));
320   }
321 
322   if (Arg *Endian = Args.getLastArg(options::OPT_mbig_endian,
323                                     options::OPT_mlittle_endian)) {
324     if (Endian->getOption().matches(options::OPT_mbig_endian))
325       Result.push_back(Endian->getAsString(Args));
326   }
327   processMultilibCustomFlags(Result, Args);
328 }
329 
330 static void getRISCVMultilibFlags(const Driver &D, const llvm::Triple &Triple,
331                                   const llvm::opt::ArgList &Args,
332                                   Multilib::flags_list &Result) {
333   std::string Arch = riscv::getRISCVArch(Args, Triple);
334   // Canonicalize arch for easier matching
335   auto ISAInfo = llvm::RISCVISAInfo::parseArchString(
336       Arch, /*EnableExperimentalExtensions*/ true);
337   if (!llvm::errorToBool(ISAInfo.takeError()))
338     Result.push_back("-march=" + (*ISAInfo)->toString());
339 
340   Result.push_back(("-mabi=" + riscv::getRISCVABI(Args, Triple)).str());
341 }
342 
343 Multilib::flags_list
344 ToolChain::getMultilibFlags(const llvm::opt::ArgList &Args) const {
345   using namespace clang::driver::options;
346 
347   std::vector<std::string> Result;
348   const llvm::Triple Triple(ComputeEffectiveClangTriple(Args));
349   Result.push_back("--target=" + Triple.str());
350 
351   switch (Triple.getArch()) {
352   case llvm::Triple::aarch64:
353   case llvm::Triple::aarch64_32:
354   case llvm::Triple::aarch64_be:
355     getAArch64MultilibFlags(D, Triple, Args, Result);
356     break;
357   case llvm::Triple::arm:
358   case llvm::Triple::armeb:
359   case llvm::Triple::thumb:
360   case llvm::Triple::thumbeb:
361     getARMMultilibFlags(D, Triple, Args, Result);
362     break;
363   case llvm::Triple::riscv32:
364   case llvm::Triple::riscv64:
365     getRISCVMultilibFlags(D, Triple, Args, Result);
366     break;
367   default:
368     break;
369   }
370 
371   // Include fno-exceptions and fno-rtti
372   // to improve multilib selection
373   if (getRTTIMode() == ToolChain::RTTIMode::RM_Disabled)
374     Result.push_back("-fno-rtti");
375   else
376     Result.push_back("-frtti");
377 
378   if (getExceptionsMode() == ToolChain::ExceptionsMode::EM_Disabled)
379     Result.push_back("-fno-exceptions");
380   else
381     Result.push_back("-fexceptions");
382 
383   // Sort and remove duplicates.
384   std::sort(Result.begin(), Result.end());
385   Result.erase(std::unique(Result.begin(), Result.end()), Result.end());
386   return Result;
387 }
388 
389 SanitizerArgs
390 ToolChain::getSanitizerArgs(const llvm::opt::ArgList &JobArgs) const {
391   SanitizerArgs SanArgs(*this, JobArgs, !SanitizerArgsChecked);
392   SanitizerArgsChecked = true;
393   return SanArgs;
394 }
395 
396 const XRayArgs& ToolChain::getXRayArgs() const {
397   if (!XRayArguments)
398     XRayArguments.reset(new XRayArgs(*this, Args));
399   return *XRayArguments;
400 }
401 
402 namespace {
403 
404 struct DriverSuffix {
405   const char *Suffix;
406   const char *ModeFlag;
407 };
408 
409 } // namespace
410 
411 static const DriverSuffix *FindDriverSuffix(StringRef ProgName, size_t &Pos) {
412   // A list of known driver suffixes. Suffixes are compared against the
413   // program name in order. If there is a match, the frontend type is updated as
414   // necessary by applying the ModeFlag.
415   static const DriverSuffix DriverSuffixes[] = {
416       {"clang", nullptr},
417       {"clang++", "--driver-mode=g++"},
418       {"clang-c++", "--driver-mode=g++"},
419       {"clang-cc", nullptr},
420       {"clang-cpp", "--driver-mode=cpp"},
421       {"clang-g++", "--driver-mode=g++"},
422       {"clang-gcc", nullptr},
423       {"clang-cl", "--driver-mode=cl"},
424       {"cc", nullptr},
425       {"cpp", "--driver-mode=cpp"},
426       {"cl", "--driver-mode=cl"},
427       {"++", "--driver-mode=g++"},
428       {"flang", "--driver-mode=flang"},
429       // For backwards compatibility, we create a symlink for `flang` called
430       // `flang-new`. This will be removed in the future.
431       {"flang-new", "--driver-mode=flang"},
432       {"clang-dxc", "--driver-mode=dxc"},
433   };
434 
435   for (const auto &DS : DriverSuffixes) {
436     StringRef Suffix(DS.Suffix);
437     if (ProgName.ends_with(Suffix)) {
438       Pos = ProgName.size() - Suffix.size();
439       return &DS;
440     }
441   }
442   return nullptr;
443 }
444 
445 /// Normalize the program name from argv[0] by stripping the file extension if
446 /// present and lower-casing the string on Windows.
447 static std::string normalizeProgramName(llvm::StringRef Argv0) {
448   std::string ProgName = std::string(llvm::sys::path::filename(Argv0));
449   if (is_style_windows(llvm::sys::path::Style::native)) {
450     // Transform to lowercase for case insensitive file systems.
451     std::transform(ProgName.begin(), ProgName.end(), ProgName.begin(),
452                    ::tolower);
453   }
454   return ProgName;
455 }
456 
457 static const DriverSuffix *parseDriverSuffix(StringRef ProgName, size_t &Pos) {
458   // Try to infer frontend type and default target from the program name by
459   // comparing it against DriverSuffixes in order.
460 
461   // If there is a match, the function tries to identify a target as prefix.
462   // E.g. "x86_64-linux-clang" as interpreted as suffix "clang" with target
463   // prefix "x86_64-linux". If such a target prefix is found, it may be
464   // added via -target as implicit first argument.
465   const DriverSuffix *DS = FindDriverSuffix(ProgName, Pos);
466 
467   if (!DS && ProgName.ends_with(".exe")) {
468     // Try again after stripping the executable suffix:
469     // clang++.exe -> clang++
470     ProgName = ProgName.drop_back(StringRef(".exe").size());
471     DS = FindDriverSuffix(ProgName, Pos);
472   }
473 
474   if (!DS) {
475     // Try again after stripping any trailing version number:
476     // clang++3.5 -> clang++
477     ProgName = ProgName.rtrim("0123456789.");
478     DS = FindDriverSuffix(ProgName, Pos);
479   }
480 
481   if (!DS) {
482     // Try again after stripping trailing -component.
483     // clang++-tot -> clang++
484     ProgName = ProgName.slice(0, ProgName.rfind('-'));
485     DS = FindDriverSuffix(ProgName, Pos);
486   }
487   return DS;
488 }
489 
490 ParsedClangName
491 ToolChain::getTargetAndModeFromProgramName(StringRef PN) {
492   std::string ProgName = normalizeProgramName(PN);
493   size_t SuffixPos;
494   const DriverSuffix *DS = parseDriverSuffix(ProgName, SuffixPos);
495   if (!DS)
496     return {};
497   size_t SuffixEnd = SuffixPos + strlen(DS->Suffix);
498 
499   size_t LastComponent = ProgName.rfind('-', SuffixPos);
500   if (LastComponent == std::string::npos)
501     return ParsedClangName(ProgName.substr(0, SuffixEnd), DS->ModeFlag);
502   std::string ModeSuffix = ProgName.substr(LastComponent + 1,
503                                            SuffixEnd - LastComponent - 1);
504 
505   // Infer target from the prefix.
506   StringRef Prefix(ProgName);
507   Prefix = Prefix.slice(0, LastComponent);
508   std::string IgnoredError;
509   bool IsRegistered =
510       llvm::TargetRegistry::lookupTarget(std::string(Prefix), IgnoredError);
511   return ParsedClangName{std::string(Prefix), ModeSuffix, DS->ModeFlag,
512                          IsRegistered};
513 }
514 
515 StringRef ToolChain::getDefaultUniversalArchName() const {
516   // In universal driver terms, the arch name accepted by -arch isn't exactly
517   // the same as the ones that appear in the triple. Roughly speaking, this is
518   // an inverse of the darwin::getArchTypeForDarwinArchName() function.
519   switch (Triple.getArch()) {
520   case llvm::Triple::aarch64: {
521     if (getTriple().isArm64e())
522       return "arm64e";
523     return "arm64";
524   }
525   case llvm::Triple::aarch64_32:
526     return "arm64_32";
527   case llvm::Triple::ppc:
528     return "ppc";
529   case llvm::Triple::ppcle:
530     return "ppcle";
531   case llvm::Triple::ppc64:
532     return "ppc64";
533   case llvm::Triple::ppc64le:
534     return "ppc64le";
535   default:
536     return Triple.getArchName();
537   }
538 }
539 
540 std::string ToolChain::getInputFilename(const InputInfo &Input) const {
541   return Input.getFilename();
542 }
543 
544 ToolChain::UnwindTableLevel
545 ToolChain::getDefaultUnwindTableLevel(const ArgList &Args) const {
546   return UnwindTableLevel::None;
547 }
548 
549 Tool *ToolChain::getClang() const {
550   if (!Clang)
551     Clang.reset(new tools::Clang(*this, useIntegratedBackend()));
552   return Clang.get();
553 }
554 
555 Tool *ToolChain::getFlang() const {
556   if (!Flang)
557     Flang.reset(new tools::Flang(*this));
558   return Flang.get();
559 }
560 
561 Tool *ToolChain::buildAssembler() const {
562   return new tools::ClangAs(*this);
563 }
564 
565 Tool *ToolChain::buildLinker() const {
566   llvm_unreachable("Linking is not supported by this toolchain");
567 }
568 
569 Tool *ToolChain::buildStaticLibTool() const {
570   llvm_unreachable("Creating static lib is not supported by this toolchain");
571 }
572 
573 Tool *ToolChain::getAssemble() const {
574   if (!Assemble)
575     Assemble.reset(buildAssembler());
576   return Assemble.get();
577 }
578 
579 Tool *ToolChain::getClangAs() const {
580   if (!Assemble)
581     Assemble.reset(new tools::ClangAs(*this));
582   return Assemble.get();
583 }
584 
585 Tool *ToolChain::getLink() const {
586   if (!Link)
587     Link.reset(buildLinker());
588   return Link.get();
589 }
590 
591 Tool *ToolChain::getStaticLibTool() const {
592   if (!StaticLibTool)
593     StaticLibTool.reset(buildStaticLibTool());
594   return StaticLibTool.get();
595 }
596 
597 Tool *ToolChain::getIfsMerge() const {
598   if (!IfsMerge)
599     IfsMerge.reset(new tools::ifstool::Merger(*this));
600   return IfsMerge.get();
601 }
602 
603 Tool *ToolChain::getOffloadBundler() const {
604   if (!OffloadBundler)
605     OffloadBundler.reset(new tools::OffloadBundler(*this));
606   return OffloadBundler.get();
607 }
608 
609 Tool *ToolChain::getOffloadPackager() const {
610   if (!OffloadPackager)
611     OffloadPackager.reset(new tools::OffloadPackager(*this));
612   return OffloadPackager.get();
613 }
614 
615 Tool *ToolChain::getLinkerWrapper() const {
616   if (!LinkerWrapper)
617     LinkerWrapper.reset(new tools::LinkerWrapper(*this, getLink()));
618   return LinkerWrapper.get();
619 }
620 
621 Tool *ToolChain::getTool(Action::ActionClass AC) const {
622   switch (AC) {
623   case Action::AssembleJobClass:
624     return getAssemble();
625 
626   case Action::IfsMergeJobClass:
627     return getIfsMerge();
628 
629   case Action::LinkJobClass:
630     return getLink();
631 
632   case Action::StaticLibJobClass:
633     return getStaticLibTool();
634 
635   case Action::InputClass:
636   case Action::BindArchClass:
637   case Action::OffloadClass:
638   case Action::LipoJobClass:
639   case Action::DsymutilJobClass:
640   case Action::VerifyDebugInfoJobClass:
641   case Action::BinaryAnalyzeJobClass:
642     llvm_unreachable("Invalid tool kind.");
643 
644   case Action::CompileJobClass:
645   case Action::PrecompileJobClass:
646   case Action::PreprocessJobClass:
647   case Action::ExtractAPIJobClass:
648   case Action::AnalyzeJobClass:
649   case Action::MigrateJobClass:
650   case Action::VerifyPCHJobClass:
651   case Action::BackendJobClass:
652     return getClang();
653 
654   case Action::OffloadBundlingJobClass:
655   case Action::OffloadUnbundlingJobClass:
656     return getOffloadBundler();
657 
658   case Action::OffloadPackagerJobClass:
659     return getOffloadPackager();
660   case Action::LinkerWrapperJobClass:
661     return getLinkerWrapper();
662   }
663 
664   llvm_unreachable("Invalid tool kind.");
665 }
666 
667 static StringRef getArchNameForCompilerRTLib(const ToolChain &TC,
668                                              const ArgList &Args) {
669   const llvm::Triple &Triple = TC.getTriple();
670   bool IsWindows = Triple.isOSWindows();
671 
672   if (TC.isBareMetal())
673     return Triple.getArchName();
674 
675   if (TC.getArch() == llvm::Triple::arm || TC.getArch() == llvm::Triple::armeb)
676     return (arm::getARMFloatABI(TC, Args) == arm::FloatABI::Hard && !IsWindows)
677                ? "armhf"
678                : "arm";
679 
680   // For historic reasons, Android library is using i686 instead of i386.
681   if (TC.getArch() == llvm::Triple::x86 && Triple.isAndroid())
682     return "i686";
683 
684   if (TC.getArch() == llvm::Triple::x86_64 && Triple.isX32())
685     return "x32";
686 
687   return llvm::Triple::getArchTypeName(TC.getArch());
688 }
689 
690 StringRef ToolChain::getOSLibName() const {
691   if (Triple.isOSDarwin())
692     return "darwin";
693 
694   switch (Triple.getOS()) {
695   case llvm::Triple::FreeBSD:
696     return "freebsd";
697   case llvm::Triple::NetBSD:
698     return "netbsd";
699   case llvm::Triple::OpenBSD:
700     return "openbsd";
701   case llvm::Triple::Solaris:
702     return "sunos";
703   case llvm::Triple::AIX:
704     return "aix";
705   default:
706     return getOS();
707   }
708 }
709 
710 std::string ToolChain::getCompilerRTPath() const {
711   SmallString<128> Path(getDriver().ResourceDir);
712   if (isBareMetal()) {
713     llvm::sys::path::append(Path, "lib", getOSLibName());
714     if (!SelectedMultilibs.empty()) {
715       Path += SelectedMultilibs.back().gccSuffix();
716     }
717   } else if (Triple.isOSUnknown()) {
718     llvm::sys::path::append(Path, "lib");
719   } else {
720     llvm::sys::path::append(Path, "lib", getOSLibName());
721   }
722   return std::string(Path);
723 }
724 
725 std::string ToolChain::getCompilerRTBasename(const ArgList &Args,
726                                              StringRef Component,
727                                              FileType Type) const {
728   std::string CRTAbsolutePath = getCompilerRT(Args, Component, Type);
729   return llvm::sys::path::filename(CRTAbsolutePath).str();
730 }
731 
732 std::string ToolChain::buildCompilerRTBasename(const llvm::opt::ArgList &Args,
733                                                StringRef Component,
734                                                FileType Type,
735                                                bool AddArch) const {
736   const llvm::Triple &TT = getTriple();
737   bool IsITANMSVCWindows =
738       TT.isWindowsMSVCEnvironment() || TT.isWindowsItaniumEnvironment();
739 
740   const char *Prefix =
741       IsITANMSVCWindows || Type == ToolChain::FT_Object ? "" : "lib";
742   const char *Suffix;
743   switch (Type) {
744   case ToolChain::FT_Object:
745     Suffix = IsITANMSVCWindows ? ".obj" : ".o";
746     break;
747   case ToolChain::FT_Static:
748     Suffix = IsITANMSVCWindows ? ".lib" : ".a";
749     break;
750   case ToolChain::FT_Shared:
751     Suffix = TT.isOSWindows()
752                  ? (TT.isWindowsGNUEnvironment() ? ".dll.a" : ".lib")
753                  : ".so";
754     break;
755   }
756 
757   std::string ArchAndEnv;
758   if (AddArch) {
759     StringRef Arch = getArchNameForCompilerRTLib(*this, Args);
760     const char *Env = TT.isAndroid() ? "-android" : "";
761     ArchAndEnv = ("-" + Arch + Env).str();
762   }
763   return (Prefix + Twine("clang_rt.") + Component + ArchAndEnv + Suffix).str();
764 }
765 
766 std::string ToolChain::getCompilerRT(const ArgList &Args, StringRef Component,
767                                      FileType Type) const {
768   // Check for runtime files in the new layout without the architecture first.
769   std::string CRTBasename =
770       buildCompilerRTBasename(Args, Component, Type, /*AddArch=*/false);
771   SmallString<128> Path;
772   for (const auto &LibPath : getLibraryPaths()) {
773     SmallString<128> P(LibPath);
774     llvm::sys::path::append(P, CRTBasename);
775     if (getVFS().exists(P))
776       return std::string(P);
777     if (Path.empty())
778       Path = P;
779   }
780   if (getTriple().isOSAIX())
781     Path.clear();
782 
783   // Check the filename for the old layout if the new one does not exist.
784   CRTBasename =
785       buildCompilerRTBasename(Args, Component, Type, /*AddArch=*/true);
786   SmallString<128> OldPath(getCompilerRTPath());
787   llvm::sys::path::append(OldPath, CRTBasename);
788   if (Path.empty() || getVFS().exists(OldPath))
789     return std::string(OldPath);
790 
791   // If none is found, use a file name from the new layout, which may get
792   // printed in an error message, aiding users in knowing what Clang is
793   // looking for.
794   return std::string(Path);
795 }
796 
797 const char *ToolChain::getCompilerRTArgString(const llvm::opt::ArgList &Args,
798                                               StringRef Component,
799                                               FileType Type) const {
800   return Args.MakeArgString(getCompilerRT(Args, Component, Type));
801 }
802 
803 // Android target triples contain a target version. If we don't have libraries
804 // for the exact target version, we should fall back to the next newest version
805 // or a versionless path, if any.
806 std::optional<std::string>
807 ToolChain::getFallbackAndroidTargetPath(StringRef BaseDir) const {
808   llvm::Triple TripleWithoutLevel(getTriple());
809   TripleWithoutLevel.setEnvironmentName("android"); // remove any version number
810   const std::string &TripleWithoutLevelStr = TripleWithoutLevel.str();
811   unsigned TripleVersion = getTriple().getEnvironmentVersion().getMajor();
812   unsigned BestVersion = 0;
813 
814   SmallString<32> TripleDir;
815   bool UsingUnversionedDir = false;
816   std::error_code EC;
817   for (llvm::vfs::directory_iterator LI = getVFS().dir_begin(BaseDir, EC), LE;
818        !EC && LI != LE; LI = LI.increment(EC)) {
819     StringRef DirName = llvm::sys::path::filename(LI->path());
820     StringRef DirNameSuffix = DirName;
821     if (DirNameSuffix.consume_front(TripleWithoutLevelStr)) {
822       if (DirNameSuffix.empty() && TripleDir.empty()) {
823         TripleDir = DirName;
824         UsingUnversionedDir = true;
825       } else {
826         unsigned Version;
827         if (!DirNameSuffix.getAsInteger(10, Version) && Version > BestVersion &&
828             Version < TripleVersion) {
829           BestVersion = Version;
830           TripleDir = DirName;
831           UsingUnversionedDir = false;
832         }
833       }
834     }
835   }
836 
837   if (TripleDir.empty())
838     return {};
839 
840   SmallString<128> P(BaseDir);
841   llvm::sys::path::append(P, TripleDir);
842   if (UsingUnversionedDir)
843     D.Diag(diag::warn_android_unversioned_fallback) << P << getTripleString();
844   return std::string(P);
845 }
846 
847 std::optional<std::string>
848 ToolChain::getTargetSubDirPath(StringRef BaseDir) const {
849   auto getPathForTriple =
850       [&](const llvm::Triple &Triple) -> std::optional<std::string> {
851     SmallString<128> P(BaseDir);
852     llvm::sys::path::append(P, Triple.str());
853     if (getVFS().exists(P))
854       return std::string(P);
855     return {};
856   };
857 
858   if (auto Path = getPathForTriple(getTriple()))
859     return *Path;
860 
861   // When building with per target runtime directories, various ways of naming
862   // the Arm architecture may have been normalised to simply "arm".
863   // For example "armv8l" (Armv8 AArch32 little endian) is replaced with "arm".
864   // Since an armv8l system can use libraries built for earlier architecture
865   // versions assuming endian and float ABI match.
866   //
867   // Original triple: armv8l-unknown-linux-gnueabihf
868   //  Runtime triple: arm-unknown-linux-gnueabihf
869   //
870   // We do not do this for armeb (big endian) because doing so could make us
871   // select little endian libraries. In addition, all known armeb triples only
872   // use the "armeb" architecture name.
873   //
874   // M profile Arm is bare metal and we know they will not be using the per
875   // target runtime directory layout.
876   if (getTriple().getArch() == Triple::arm && !getTriple().isArmMClass()) {
877     llvm::Triple ArmTriple = getTriple();
878     ArmTriple.setArch(Triple::arm);
879     if (auto Path = getPathForTriple(ArmTriple))
880       return *Path;
881   }
882 
883   if (getTriple().isAndroid())
884     return getFallbackAndroidTargetPath(BaseDir);
885 
886   return {};
887 }
888 
889 std::optional<std::string> ToolChain::getRuntimePath() const {
890   SmallString<128> P(D.ResourceDir);
891   llvm::sys::path::append(P, "lib");
892   if (auto Ret = getTargetSubDirPath(P))
893     return Ret;
894   // Darwin and AIX does not use per-target runtime directory.
895   if (Triple.isOSDarwin() || Triple.isOSAIX())
896     return {};
897   llvm::sys::path::append(P, Triple.str());
898   return std::string(P);
899 }
900 
901 std::optional<std::string> ToolChain::getStdlibPath() const {
902   SmallString<128> P(D.Dir);
903   llvm::sys::path::append(P, "..", "lib");
904   return getTargetSubDirPath(P);
905 }
906 
907 std::optional<std::string> ToolChain::getStdlibIncludePath() const {
908   SmallString<128> P(D.Dir);
909   llvm::sys::path::append(P, "..", "include");
910   return getTargetSubDirPath(P);
911 }
912 
913 ToolChain::path_list ToolChain::getArchSpecificLibPaths() const {
914   path_list Paths;
915 
916   auto AddPath = [&](const ArrayRef<StringRef> &SS) {
917     SmallString<128> Path(getDriver().ResourceDir);
918     llvm::sys::path::append(Path, "lib");
919     for (auto &S : SS)
920       llvm::sys::path::append(Path, S);
921     Paths.push_back(std::string(Path));
922   };
923 
924   AddPath({getTriple().str()});
925   AddPath({getOSLibName(), llvm::Triple::getArchTypeName(getArch())});
926   return Paths;
927 }
928 
929 bool ToolChain::needsProfileRT(const ArgList &Args) {
930   if (Args.hasArg(options::OPT_noprofilelib))
931     return false;
932 
933   return Args.hasArg(options::OPT_fprofile_generate) ||
934          Args.hasArg(options::OPT_fprofile_generate_EQ) ||
935          Args.hasArg(options::OPT_fcs_profile_generate) ||
936          Args.hasArg(options::OPT_fcs_profile_generate_EQ) ||
937          Args.hasArg(options::OPT_fprofile_instr_generate) ||
938          Args.hasArg(options::OPT_fprofile_instr_generate_EQ) ||
939          Args.hasArg(options::OPT_fcreate_profile) ||
940          Args.hasArg(options::OPT_forder_file_instrumentation) ||
941          Args.hasArg(options::OPT_fprofile_generate_cold_function_coverage) ||
942          Args.hasArg(options::OPT_fprofile_generate_cold_function_coverage_EQ);
943 }
944 
945 bool ToolChain::needsGCovInstrumentation(const llvm::opt::ArgList &Args) {
946   return Args.hasArg(options::OPT_coverage) ||
947          Args.hasFlag(options::OPT_fprofile_arcs, options::OPT_fno_profile_arcs,
948                       false);
949 }
950 
951 Tool *ToolChain::SelectTool(const JobAction &JA) const {
952   if (D.IsFlangMode() && getDriver().ShouldUseFlangCompiler(JA)) return getFlang();
953   if (getDriver().ShouldUseClangCompiler(JA)) return getClang();
954   Action::ActionClass AC = JA.getKind();
955   if (AC == Action::AssembleJobClass && useIntegratedAs() &&
956       !getTriple().isOSAIX())
957     return getClangAs();
958   return getTool(AC);
959 }
960 
961 std::string ToolChain::GetFilePath(const char *Name) const {
962   return D.GetFilePath(Name, *this);
963 }
964 
965 std::string ToolChain::GetProgramPath(const char *Name) const {
966   return D.GetProgramPath(Name, *this);
967 }
968 
969 std::string ToolChain::GetLinkerPath(bool *LinkerIsLLD) const {
970   if (LinkerIsLLD)
971     *LinkerIsLLD = false;
972 
973   // Get -fuse-ld= first to prevent -Wunused-command-line-argument. -fuse-ld= is
974   // considered as the linker flavor, e.g. "bfd", "gold", or "lld".
975   const Arg* A = Args.getLastArg(options::OPT_fuse_ld_EQ);
976   StringRef UseLinker = A ? A->getValue() : CLANG_DEFAULT_LINKER;
977 
978   // --ld-path= takes precedence over -fuse-ld= and specifies the executable
979   // name. -B, COMPILER_PATH and PATH and consulted if the value does not
980   // contain a path component separator.
981   // -fuse-ld=lld can be used with --ld-path= to inform clang that the binary
982   // that --ld-path= points to is lld.
983   if (const Arg *A = Args.getLastArg(options::OPT_ld_path_EQ)) {
984     std::string Path(A->getValue());
985     if (!Path.empty()) {
986       if (llvm::sys::path::parent_path(Path).empty())
987         Path = GetProgramPath(A->getValue());
988       if (llvm::sys::fs::can_execute(Path)) {
989         if (LinkerIsLLD)
990           *LinkerIsLLD = UseLinker == "lld";
991         return std::string(Path);
992       }
993     }
994     getDriver().Diag(diag::err_drv_invalid_linker_name) << A->getAsString(Args);
995     return GetProgramPath(getDefaultLinker());
996   }
997   // If we're passed -fuse-ld= with no argument, or with the argument ld,
998   // then use whatever the default system linker is.
999   if (UseLinker.empty() || UseLinker == "ld") {
1000     const char *DefaultLinker = getDefaultLinker();
1001     if (llvm::sys::path::is_absolute(DefaultLinker))
1002       return std::string(DefaultLinker);
1003     else
1004       return GetProgramPath(DefaultLinker);
1005   }
1006 
1007   // Extending -fuse-ld= to an absolute or relative path is unexpected. Checking
1008   // for the linker flavor is brittle. In addition, prepending "ld." or "ld64."
1009   // to a relative path is surprising. This is more complex due to priorities
1010   // among -B, COMPILER_PATH and PATH. --ld-path= should be used instead.
1011   if (UseLinker.contains('/'))
1012     getDriver().Diag(diag::warn_drv_fuse_ld_path);
1013 
1014   if (llvm::sys::path::is_absolute(UseLinker)) {
1015     // If we're passed what looks like an absolute path, don't attempt to
1016     // second-guess that.
1017     if (llvm::sys::fs::can_execute(UseLinker))
1018       return std::string(UseLinker);
1019   } else {
1020     llvm::SmallString<8> LinkerName;
1021     if (Triple.isOSDarwin())
1022       LinkerName.append("ld64.");
1023     else
1024       LinkerName.append("ld.");
1025     LinkerName.append(UseLinker);
1026 
1027     std::string LinkerPath(GetProgramPath(LinkerName.c_str()));
1028     if (llvm::sys::fs::can_execute(LinkerPath)) {
1029       if (LinkerIsLLD)
1030         *LinkerIsLLD = UseLinker == "lld";
1031       return LinkerPath;
1032     }
1033   }
1034 
1035   if (A)
1036     getDriver().Diag(diag::err_drv_invalid_linker_name) << A->getAsString(Args);
1037 
1038   return GetProgramPath(getDefaultLinker());
1039 }
1040 
1041 std::string ToolChain::GetStaticLibToolPath() const {
1042   // TODO: Add support for static lib archiving on Windows
1043   if (Triple.isOSDarwin())
1044     return GetProgramPath("libtool");
1045   return GetProgramPath("llvm-ar");
1046 }
1047 
1048 types::ID ToolChain::LookupTypeForExtension(StringRef Ext) const {
1049   types::ID id = types::lookupTypeForExtension(Ext);
1050 
1051   // Flang always runs the preprocessor and has no notion of "preprocessed
1052   // fortran". Here, TY_PP_Fortran is coerced to TY_Fortran to avoid treating
1053   // them differently.
1054   if (D.IsFlangMode() && id == types::TY_PP_Fortran)
1055     id = types::TY_Fortran;
1056 
1057   return id;
1058 }
1059 
1060 bool ToolChain::HasNativeLLVMSupport() const {
1061   return false;
1062 }
1063 
1064 bool ToolChain::isCrossCompiling() const {
1065   llvm::Triple HostTriple(LLVM_HOST_TRIPLE);
1066   switch (HostTriple.getArch()) {
1067   // The A32/T32/T16 instruction sets are not separate architectures in this
1068   // context.
1069   case llvm::Triple::arm:
1070   case llvm::Triple::armeb:
1071   case llvm::Triple::thumb:
1072   case llvm::Triple::thumbeb:
1073     return getArch() != llvm::Triple::arm && getArch() != llvm::Triple::thumb &&
1074            getArch() != llvm::Triple::armeb && getArch() != llvm::Triple::thumbeb;
1075   default:
1076     return HostTriple.getArch() != getArch();
1077   }
1078 }
1079 
1080 ObjCRuntime ToolChain::getDefaultObjCRuntime(bool isNonFragile) const {
1081   return ObjCRuntime(isNonFragile ? ObjCRuntime::GNUstep : ObjCRuntime::GCC,
1082                      VersionTuple());
1083 }
1084 
1085 llvm::ExceptionHandling
1086 ToolChain::GetExceptionModel(const llvm::opt::ArgList &Args) const {
1087   return llvm::ExceptionHandling::None;
1088 }
1089 
1090 bool ToolChain::isThreadModelSupported(const StringRef Model) const {
1091   if (Model == "single") {
1092     // FIXME: 'single' is only supported on ARM and WebAssembly so far.
1093     return Triple.getArch() == llvm::Triple::arm ||
1094            Triple.getArch() == llvm::Triple::armeb ||
1095            Triple.getArch() == llvm::Triple::thumb ||
1096            Triple.getArch() == llvm::Triple::thumbeb || Triple.isWasm();
1097   } else if (Model == "posix")
1098     return true;
1099 
1100   return false;
1101 }
1102 
1103 std::string ToolChain::ComputeLLVMTriple(const ArgList &Args,
1104                                          types::ID InputType) const {
1105   switch (getTriple().getArch()) {
1106   default:
1107     return getTripleString();
1108 
1109   case llvm::Triple::x86_64: {
1110     llvm::Triple Triple = getTriple();
1111     if (!Triple.isOSBinFormatMachO())
1112       return getTripleString();
1113 
1114     if (Arg *A = Args.getLastArg(options::OPT_march_EQ)) {
1115       // x86_64h goes in the triple. Other -march options just use the
1116       // vanilla triple we already have.
1117       StringRef MArch = A->getValue();
1118       if (MArch == "x86_64h")
1119         Triple.setArchName(MArch);
1120     }
1121     return Triple.getTriple();
1122   }
1123   case llvm::Triple::aarch64: {
1124     llvm::Triple Triple = getTriple();
1125     tools::aarch64::setPAuthABIInTriple(getDriver(), Args, Triple);
1126     if (!Triple.isOSBinFormatMachO())
1127       return Triple.getTriple();
1128 
1129     if (Triple.isArm64e())
1130       return Triple.getTriple();
1131 
1132     // FIXME: older versions of ld64 expect the "arm64" component in the actual
1133     // triple string and query it to determine whether an LTO file can be
1134     // handled. Remove this when we don't care any more.
1135     Triple.setArchName("arm64");
1136     return Triple.getTriple();
1137   }
1138   case llvm::Triple::aarch64_32:
1139     return getTripleString();
1140   case llvm::Triple::amdgcn: {
1141     llvm::Triple Triple = getTriple();
1142     if (Args.getLastArgValue(options::OPT_mcpu_EQ) == "amdgcnspirv")
1143       Triple.setArch(llvm::Triple::ArchType::spirv64);
1144     return Triple.getTriple();
1145   }
1146   case llvm::Triple::arm:
1147   case llvm::Triple::armeb:
1148   case llvm::Triple::thumb:
1149   case llvm::Triple::thumbeb: {
1150     llvm::Triple Triple = getTriple();
1151     tools::arm::setArchNameInTriple(getDriver(), Args, InputType, Triple);
1152     tools::arm::setFloatABIInTriple(getDriver(), Args, Triple);
1153     return Triple.getTriple();
1154   }
1155   }
1156 }
1157 
1158 std::string ToolChain::ComputeEffectiveClangTriple(const ArgList &Args,
1159                                                    types::ID InputType) const {
1160   return ComputeLLVMTriple(Args, InputType);
1161 }
1162 
1163 std::string ToolChain::computeSysRoot() const {
1164   return D.SysRoot;
1165 }
1166 
1167 void ToolChain::AddClangSystemIncludeArgs(const ArgList &DriverArgs,
1168                                           ArgStringList &CC1Args) const {
1169   // Each toolchain should provide the appropriate include flags.
1170 }
1171 
1172 void ToolChain::addClangTargetOptions(
1173     const ArgList &DriverArgs, ArgStringList &CC1Args,
1174     Action::OffloadKind DeviceOffloadKind) const {}
1175 
1176 void ToolChain::addClangCC1ASTargetOptions(const ArgList &Args,
1177                                            ArgStringList &CC1ASArgs) const {}
1178 
1179 void ToolChain::addClangWarningOptions(ArgStringList &CC1Args) const {}
1180 
1181 void ToolChain::addProfileRTLibs(const llvm::opt::ArgList &Args,
1182                                  llvm::opt::ArgStringList &CmdArgs) const {
1183   if (!needsProfileRT(Args) && !needsGCovInstrumentation(Args))
1184     return;
1185 
1186   CmdArgs.push_back(getCompilerRTArgString(Args, "profile"));
1187 }
1188 
1189 ToolChain::RuntimeLibType ToolChain::GetRuntimeLibType(
1190     const ArgList &Args) const {
1191   if (runtimeLibType)
1192     return *runtimeLibType;
1193 
1194   const Arg* A = Args.getLastArg(options::OPT_rtlib_EQ);
1195   StringRef LibName = A ? A->getValue() : CLANG_DEFAULT_RTLIB;
1196 
1197   // Only use "platform" in tests to override CLANG_DEFAULT_RTLIB!
1198   if (LibName == "compiler-rt")
1199     runtimeLibType = ToolChain::RLT_CompilerRT;
1200   else if (LibName == "libgcc")
1201     runtimeLibType = ToolChain::RLT_Libgcc;
1202   else if (LibName == "platform")
1203     runtimeLibType = GetDefaultRuntimeLibType();
1204   else {
1205     if (A)
1206       getDriver().Diag(diag::err_drv_invalid_rtlib_name)
1207           << A->getAsString(Args);
1208 
1209     runtimeLibType = GetDefaultRuntimeLibType();
1210   }
1211 
1212   return *runtimeLibType;
1213 }
1214 
1215 ToolChain::UnwindLibType ToolChain::GetUnwindLibType(
1216     const ArgList &Args) const {
1217   if (unwindLibType)
1218     return *unwindLibType;
1219 
1220   const Arg *A = Args.getLastArg(options::OPT_unwindlib_EQ);
1221   StringRef LibName = A ? A->getValue() : CLANG_DEFAULT_UNWINDLIB;
1222 
1223   if (LibName == "none")
1224     unwindLibType = ToolChain::UNW_None;
1225   else if (LibName == "platform" || LibName == "") {
1226     ToolChain::RuntimeLibType RtLibType = GetRuntimeLibType(Args);
1227     if (RtLibType == ToolChain::RLT_CompilerRT) {
1228       if (getTriple().isAndroid() || getTriple().isOSAIX())
1229         unwindLibType = ToolChain::UNW_CompilerRT;
1230       else
1231         unwindLibType = ToolChain::UNW_None;
1232     } else if (RtLibType == ToolChain::RLT_Libgcc)
1233       unwindLibType = ToolChain::UNW_Libgcc;
1234   } else if (LibName == "libunwind") {
1235     if (GetRuntimeLibType(Args) == RLT_Libgcc)
1236       getDriver().Diag(diag::err_drv_incompatible_unwindlib);
1237     unwindLibType = ToolChain::UNW_CompilerRT;
1238   } else if (LibName == "libgcc")
1239     unwindLibType = ToolChain::UNW_Libgcc;
1240   else {
1241     if (A)
1242       getDriver().Diag(diag::err_drv_invalid_unwindlib_name)
1243           << A->getAsString(Args);
1244 
1245     unwindLibType = GetDefaultUnwindLibType();
1246   }
1247 
1248   return *unwindLibType;
1249 }
1250 
1251 ToolChain::CXXStdlibType ToolChain::GetCXXStdlibType(const ArgList &Args) const{
1252   if (cxxStdlibType)
1253     return *cxxStdlibType;
1254 
1255   const Arg *A = Args.getLastArg(options::OPT_stdlib_EQ);
1256   StringRef LibName = A ? A->getValue() : CLANG_DEFAULT_CXX_STDLIB;
1257 
1258   // Only use "platform" in tests to override CLANG_DEFAULT_CXX_STDLIB!
1259   if (LibName == "libc++")
1260     cxxStdlibType = ToolChain::CST_Libcxx;
1261   else if (LibName == "libstdc++")
1262     cxxStdlibType = ToolChain::CST_Libstdcxx;
1263   else if (LibName == "platform")
1264     cxxStdlibType = GetDefaultCXXStdlibType();
1265   else {
1266     if (A)
1267       getDriver().Diag(diag::err_drv_invalid_stdlib_name)
1268           << A->getAsString(Args);
1269 
1270     cxxStdlibType = GetDefaultCXXStdlibType();
1271   }
1272 
1273   return *cxxStdlibType;
1274 }
1275 
1276 /// Utility function to add a system include directory to CC1 arguments.
1277 /*static*/ void ToolChain::addSystemInclude(const ArgList &DriverArgs,
1278                                             ArgStringList &CC1Args,
1279                                             const Twine &Path) {
1280   CC1Args.push_back("-internal-isystem");
1281   CC1Args.push_back(DriverArgs.MakeArgString(Path));
1282 }
1283 
1284 /// Utility function to add a system include directory with extern "C"
1285 /// semantics to CC1 arguments.
1286 ///
1287 /// Note that this should be used rarely, and only for directories that
1288 /// historically and for legacy reasons are treated as having implicit extern
1289 /// "C" semantics. These semantics are *ignored* by and large today, but its
1290 /// important to preserve the preprocessor changes resulting from the
1291 /// classification.
1292 /*static*/ void ToolChain::addExternCSystemInclude(const ArgList &DriverArgs,
1293                                                    ArgStringList &CC1Args,
1294                                                    const Twine &Path) {
1295   CC1Args.push_back("-internal-externc-isystem");
1296   CC1Args.push_back(DriverArgs.MakeArgString(Path));
1297 }
1298 
1299 void ToolChain::addExternCSystemIncludeIfExists(const ArgList &DriverArgs,
1300                                                 ArgStringList &CC1Args,
1301                                                 const Twine &Path) {
1302   if (llvm::sys::fs::exists(Path))
1303     addExternCSystemInclude(DriverArgs, CC1Args, Path);
1304 }
1305 
1306 /// Utility function to add a list of system include directories to CC1.
1307 /*static*/ void ToolChain::addSystemIncludes(const ArgList &DriverArgs,
1308                                              ArgStringList &CC1Args,
1309                                              ArrayRef<StringRef> Paths) {
1310   for (const auto &Path : Paths) {
1311     CC1Args.push_back("-internal-isystem");
1312     CC1Args.push_back(DriverArgs.MakeArgString(Path));
1313   }
1314 }
1315 
1316 /*static*/ std::string ToolChain::concat(StringRef Path, const Twine &A,
1317                                          const Twine &B, const Twine &C,
1318                                          const Twine &D) {
1319   SmallString<128> Result(Path);
1320   llvm::sys::path::append(Result, llvm::sys::path::Style::posix, A, B, C, D);
1321   return std::string(Result);
1322 }
1323 
1324 std::string ToolChain::detectLibcxxVersion(StringRef IncludePath) const {
1325   std::error_code EC;
1326   int MaxVersion = 0;
1327   std::string MaxVersionString;
1328   SmallString<128> Path(IncludePath);
1329   llvm::sys::path::append(Path, "c++");
1330   for (llvm::vfs::directory_iterator LI = getVFS().dir_begin(Path, EC), LE;
1331        !EC && LI != LE; LI = LI.increment(EC)) {
1332     StringRef VersionText = llvm::sys::path::filename(LI->path());
1333     int Version;
1334     if (VersionText[0] == 'v' &&
1335         !VersionText.slice(1, StringRef::npos).getAsInteger(10, Version)) {
1336       if (Version > MaxVersion) {
1337         MaxVersion = Version;
1338         MaxVersionString = std::string(VersionText);
1339       }
1340     }
1341   }
1342   if (!MaxVersion)
1343     return "";
1344   return MaxVersionString;
1345 }
1346 
1347 void ToolChain::AddClangCXXStdlibIncludeArgs(const ArgList &DriverArgs,
1348                                              ArgStringList &CC1Args) const {
1349   // Header search paths should be handled by each of the subclasses.
1350   // Historically, they have not been, and instead have been handled inside of
1351   // the CC1-layer frontend. As the logic is hoisted out, this generic function
1352   // will slowly stop being called.
1353   //
1354   // While it is being called, replicate a bit of a hack to propagate the
1355   // '-stdlib=' flag down to CC1 so that it can in turn customize the C++
1356   // header search paths with it. Once all systems are overriding this
1357   // function, the CC1 flag and this line can be removed.
1358   DriverArgs.AddAllArgs(CC1Args, options::OPT_stdlib_EQ);
1359 }
1360 
1361 void ToolChain::AddClangCXXStdlibIsystemArgs(
1362     const llvm::opt::ArgList &DriverArgs,
1363     llvm::opt::ArgStringList &CC1Args) const {
1364   DriverArgs.ClaimAllArgs(options::OPT_stdlibxx_isystem);
1365   // This intentionally only looks at -nostdinc++, and not -nostdinc or
1366   // -nostdlibinc. The purpose of -stdlib++-isystem is to support toolchain
1367   // setups with non-standard search logic for the C++ headers, while still
1368   // allowing users of the toolchain to bring their own C++ headers. Such a
1369   // toolchain likely also has non-standard search logic for the C headers and
1370   // uses -nostdinc to suppress the default logic, but -stdlib++-isystem should
1371   // still work in that case and only be suppressed by an explicit -nostdinc++
1372   // in a project using the toolchain.
1373   if (!DriverArgs.hasArg(options::OPT_nostdincxx))
1374     for (const auto &P :
1375          DriverArgs.getAllArgValues(options::OPT_stdlibxx_isystem))
1376       addSystemInclude(DriverArgs, CC1Args, P);
1377 }
1378 
1379 bool ToolChain::ShouldLinkCXXStdlib(const llvm::opt::ArgList &Args) const {
1380   return getDriver().CCCIsCXX() &&
1381          !Args.hasArg(options::OPT_nostdlib, options::OPT_nodefaultlibs,
1382                       options::OPT_nostdlibxx);
1383 }
1384 
1385 void ToolChain::AddCXXStdlibLibArgs(const ArgList &Args,
1386                                     ArgStringList &CmdArgs) const {
1387   assert(!Args.hasArg(options::OPT_nostdlibxx) &&
1388          "should not have called this");
1389   CXXStdlibType Type = GetCXXStdlibType(Args);
1390 
1391   switch (Type) {
1392   case ToolChain::CST_Libcxx:
1393     CmdArgs.push_back("-lc++");
1394     if (Args.hasArg(options::OPT_fexperimental_library))
1395       CmdArgs.push_back("-lc++experimental");
1396     break;
1397 
1398   case ToolChain::CST_Libstdcxx:
1399     CmdArgs.push_back("-lstdc++");
1400     break;
1401   }
1402 }
1403 
1404 void ToolChain::AddFilePathLibArgs(const ArgList &Args,
1405                                    ArgStringList &CmdArgs) const {
1406   for (const auto &LibPath : getFilePaths())
1407     if(LibPath.length() > 0)
1408       CmdArgs.push_back(Args.MakeArgString(StringRef("-L") + LibPath));
1409 }
1410 
1411 void ToolChain::AddCCKextLibArgs(const ArgList &Args,
1412                                  ArgStringList &CmdArgs) const {
1413   CmdArgs.push_back("-lcc_kext");
1414 }
1415 
1416 bool ToolChain::isFastMathRuntimeAvailable(const ArgList &Args,
1417                                            std::string &Path) const {
1418   // Don't implicitly link in mode-changing libraries in a shared library, since
1419   // this can have very deleterious effects. See the various links from
1420   // https://github.com/llvm/llvm-project/issues/57589 for more information.
1421   bool Default = !Args.hasArgNoClaim(options::OPT_shared);
1422 
1423   // Do not check for -fno-fast-math or -fno-unsafe-math when -Ofast passed
1424   // (to keep the linker options consistent with gcc and clang itself).
1425   if (Default && !isOptimizationLevelFast(Args)) {
1426     // Check if -ffast-math or -funsafe-math.
1427     Arg *A = Args.getLastArg(
1428         options::OPT_ffast_math, options::OPT_fno_fast_math,
1429         options::OPT_funsafe_math_optimizations,
1430         options::OPT_fno_unsafe_math_optimizations, options::OPT_ffp_model_EQ);
1431 
1432     if (!A || A->getOption().getID() == options::OPT_fno_fast_math ||
1433         A->getOption().getID() == options::OPT_fno_unsafe_math_optimizations)
1434       Default = false;
1435     if (A && A->getOption().getID() == options::OPT_ffp_model_EQ) {
1436       StringRef Model = A->getValue();
1437       if (Model != "fast" && Model != "aggressive")
1438         Default = false;
1439     }
1440   }
1441 
1442   // Whatever decision came as a result of the above implicit settings, either
1443   // -mdaz-ftz or -mno-daz-ftz is capable of overriding it.
1444   if (!Args.hasFlag(options::OPT_mdaz_ftz, options::OPT_mno_daz_ftz, Default))
1445     return false;
1446 
1447   // If crtfastmath.o exists add it to the arguments.
1448   Path = GetFilePath("crtfastmath.o");
1449   return (Path != "crtfastmath.o"); // Not found.
1450 }
1451 
1452 bool ToolChain::addFastMathRuntimeIfAvailable(const ArgList &Args,
1453                                               ArgStringList &CmdArgs) const {
1454   std::string Path;
1455   if (isFastMathRuntimeAvailable(Args, Path)) {
1456     CmdArgs.push_back(Args.MakeArgString(Path));
1457     return true;
1458   }
1459 
1460   return false;
1461 }
1462 
1463 Expected<SmallVector<std::string>>
1464 ToolChain::getSystemGPUArchs(const llvm::opt::ArgList &Args) const {
1465   return SmallVector<std::string>();
1466 }
1467 
1468 SanitizerMask ToolChain::getSupportedSanitizers() const {
1469   // Return sanitizers which don't require runtime support and are not
1470   // platform dependent.
1471 
1472   SanitizerMask Res =
1473       (SanitizerKind::Undefined & ~SanitizerKind::Vptr) |
1474       (SanitizerKind::CFI & ~SanitizerKind::CFIICall) |
1475       SanitizerKind::CFICastStrict | SanitizerKind::FloatDivideByZero |
1476       SanitizerKind::KCFI | SanitizerKind::UnsignedIntegerOverflow |
1477       SanitizerKind::UnsignedShiftBase | SanitizerKind::ImplicitConversion |
1478       SanitizerKind::Nullability | SanitizerKind::LocalBounds;
1479   if (getTriple().getArch() == llvm::Triple::x86 ||
1480       getTriple().getArch() == llvm::Triple::x86_64 ||
1481       getTriple().getArch() == llvm::Triple::arm ||
1482       getTriple().getArch() == llvm::Triple::thumb || getTriple().isWasm() ||
1483       getTriple().isAArch64() || getTriple().isRISCV() ||
1484       getTriple().isLoongArch64())
1485     Res |= SanitizerKind::CFIICall;
1486   if (getTriple().getArch() == llvm::Triple::x86_64 ||
1487       getTriple().isAArch64(64) || getTriple().isRISCV())
1488     Res |= SanitizerKind::ShadowCallStack;
1489   if (getTriple().isAArch64(64))
1490     Res |= SanitizerKind::MemTag;
1491   return Res;
1492 }
1493 
1494 void ToolChain::AddCudaIncludeArgs(const ArgList &DriverArgs,
1495                                    ArgStringList &CC1Args) const {}
1496 
1497 void ToolChain::AddHIPIncludeArgs(const ArgList &DriverArgs,
1498                                   ArgStringList &CC1Args) const {}
1499 
1500 void ToolChain::addSYCLIncludeArgs(const ArgList &DriverArgs,
1501                                    ArgStringList &CC1Args) const {}
1502 
1503 llvm::SmallVector<ToolChain::BitCodeLibraryInfo, 12>
1504 ToolChain::getDeviceLibs(const ArgList &DriverArgs) const {
1505   return {};
1506 }
1507 
1508 void ToolChain::AddIAMCUIncludeArgs(const ArgList &DriverArgs,
1509                                     ArgStringList &CC1Args) const {}
1510 
1511 static VersionTuple separateMSVCFullVersion(unsigned Version) {
1512   if (Version < 100)
1513     return VersionTuple(Version);
1514 
1515   if (Version < 10000)
1516     return VersionTuple(Version / 100, Version % 100);
1517 
1518   unsigned Build = 0, Factor = 1;
1519   for (; Version > 10000; Version = Version / 10, Factor = Factor * 10)
1520     Build = Build + (Version % 10) * Factor;
1521   return VersionTuple(Version / 100, Version % 100, Build);
1522 }
1523 
1524 VersionTuple
1525 ToolChain::computeMSVCVersion(const Driver *D,
1526                               const llvm::opt::ArgList &Args) const {
1527   const Arg *MSCVersion = Args.getLastArg(options::OPT_fmsc_version);
1528   const Arg *MSCompatibilityVersion =
1529       Args.getLastArg(options::OPT_fms_compatibility_version);
1530 
1531   if (MSCVersion && MSCompatibilityVersion) {
1532     if (D)
1533       D->Diag(diag::err_drv_argument_not_allowed_with)
1534           << MSCVersion->getAsString(Args)
1535           << MSCompatibilityVersion->getAsString(Args);
1536     return VersionTuple();
1537   }
1538 
1539   if (MSCompatibilityVersion) {
1540     VersionTuple MSVT;
1541     if (MSVT.tryParse(MSCompatibilityVersion->getValue())) {
1542       if (D)
1543         D->Diag(diag::err_drv_invalid_value)
1544             << MSCompatibilityVersion->getAsString(Args)
1545             << MSCompatibilityVersion->getValue();
1546     } else {
1547       return MSVT;
1548     }
1549   }
1550 
1551   if (MSCVersion) {
1552     unsigned Version = 0;
1553     if (StringRef(MSCVersion->getValue()).getAsInteger(10, Version)) {
1554       if (D)
1555         D->Diag(diag::err_drv_invalid_value)
1556             << MSCVersion->getAsString(Args) << MSCVersion->getValue();
1557     } else {
1558       return separateMSVCFullVersion(Version);
1559     }
1560   }
1561 
1562   return VersionTuple();
1563 }
1564 
1565 llvm::opt::DerivedArgList *ToolChain::TranslateOpenMPTargetArgs(
1566     const llvm::opt::DerivedArgList &Args, bool SameTripleAsHost,
1567     SmallVectorImpl<llvm::opt::Arg *> &AllocatedArgs) const {
1568   DerivedArgList *DAL = new DerivedArgList(Args.getBaseArgs());
1569   const OptTable &Opts = getDriver().getOpts();
1570   bool Modified = false;
1571 
1572   // Handle -Xopenmp-target flags
1573   for (auto *A : Args) {
1574     // Exclude flags which may only apply to the host toolchain.
1575     // Do not exclude flags when the host triple (AuxTriple)
1576     // matches the current toolchain triple. If it is not present
1577     // at all, target and host share a toolchain.
1578     if (A->getOption().matches(options::OPT_m_Group)) {
1579       // Pass code object version to device toolchain
1580       // to correctly set metadata in intermediate files.
1581       if (SameTripleAsHost ||
1582           A->getOption().matches(options::OPT_mcode_object_version_EQ))
1583         DAL->append(A);
1584       else
1585         Modified = true;
1586       continue;
1587     }
1588 
1589     unsigned Index;
1590     unsigned Prev;
1591     bool XOpenMPTargetNoTriple =
1592         A->getOption().matches(options::OPT_Xopenmp_target);
1593 
1594     if (A->getOption().matches(options::OPT_Xopenmp_target_EQ)) {
1595       llvm::Triple TT(getOpenMPTriple(A->getValue(0)));
1596 
1597       // Passing device args: -Xopenmp-target=<triple> -opt=val.
1598       if (TT.getTriple() == getTripleString())
1599         Index = Args.getBaseArgs().MakeIndex(A->getValue(1));
1600       else
1601         continue;
1602     } else if (XOpenMPTargetNoTriple) {
1603       // Passing device args: -Xopenmp-target -opt=val.
1604       Index = Args.getBaseArgs().MakeIndex(A->getValue(0));
1605     } else {
1606       DAL->append(A);
1607       continue;
1608     }
1609 
1610     // Parse the argument to -Xopenmp-target.
1611     Prev = Index;
1612     std::unique_ptr<Arg> XOpenMPTargetArg(Opts.ParseOneArg(Args, Index));
1613     if (!XOpenMPTargetArg || Index > Prev + 1) {
1614       if (!A->isClaimed()) {
1615         getDriver().Diag(diag::err_drv_invalid_Xopenmp_target_with_args)
1616             << A->getAsString(Args);
1617       }
1618       continue;
1619     }
1620     if (XOpenMPTargetNoTriple && XOpenMPTargetArg &&
1621         Args.getAllArgValues(options::OPT_fopenmp_targets_EQ).size() != 1) {
1622       getDriver().Diag(diag::err_drv_Xopenmp_target_missing_triple);
1623       continue;
1624     }
1625     XOpenMPTargetArg->setBaseArg(A);
1626     A = XOpenMPTargetArg.release();
1627     AllocatedArgs.push_back(A);
1628     DAL->append(A);
1629     Modified = true;
1630   }
1631 
1632   if (Modified)
1633     return DAL;
1634 
1635   delete DAL;
1636   return nullptr;
1637 }
1638 
1639 // TODO: Currently argument values separated by space e.g.
1640 // -Xclang -mframe-pointer=no cannot be passed by -Xarch_. This should be
1641 // fixed.
1642 void ToolChain::TranslateXarchArgs(
1643     const llvm::opt::DerivedArgList &Args, llvm::opt::Arg *&A,
1644     llvm::opt::DerivedArgList *DAL,
1645     SmallVectorImpl<llvm::opt::Arg *> *AllocatedArgs) const {
1646   const OptTable &Opts = getDriver().getOpts();
1647   unsigned ValuePos = 1;
1648   if (A->getOption().matches(options::OPT_Xarch_device) ||
1649       A->getOption().matches(options::OPT_Xarch_host))
1650     ValuePos = 0;
1651 
1652   unsigned Index = Args.getBaseArgs().MakeIndex(A->getValue(ValuePos));
1653   unsigned Prev = Index;
1654   std::unique_ptr<llvm::opt::Arg> XarchArg(Opts.ParseOneArg(Args, Index));
1655 
1656   // If the argument parsing failed or more than one argument was
1657   // consumed, the -Xarch_ argument's parameter tried to consume
1658   // extra arguments. Emit an error and ignore.
1659   //
1660   // We also want to disallow any options which would alter the
1661   // driver behavior; that isn't going to work in our model. We
1662   // use options::NoXarchOption to control this.
1663   if (!XarchArg || Index > Prev + 1) {
1664     getDriver().Diag(diag::err_drv_invalid_Xarch_argument_with_args)
1665         << A->getAsString(Args);
1666     return;
1667   } else if (XarchArg->getOption().hasFlag(options::NoXarchOption)) {
1668     auto &Diags = getDriver().getDiags();
1669     unsigned DiagID =
1670         Diags.getCustomDiagID(DiagnosticsEngine::Error,
1671                               "invalid Xarch argument: '%0', not all driver "
1672                               "options can be forwared via Xarch argument");
1673     Diags.Report(DiagID) << A->getAsString(Args);
1674     return;
1675   }
1676   XarchArg->setBaseArg(A);
1677   A = XarchArg.release();
1678   if (!AllocatedArgs)
1679     DAL->AddSynthesizedArg(A);
1680   else
1681     AllocatedArgs->push_back(A);
1682 }
1683 
1684 llvm::opt::DerivedArgList *ToolChain::TranslateXarchArgs(
1685     const llvm::opt::DerivedArgList &Args, StringRef BoundArch,
1686     Action::OffloadKind OFK,
1687     SmallVectorImpl<llvm::opt::Arg *> *AllocatedArgs) const {
1688   DerivedArgList *DAL = new DerivedArgList(Args.getBaseArgs());
1689   bool Modified = false;
1690 
1691   bool IsDevice = OFK != Action::OFK_None && OFK != Action::OFK_Host;
1692   for (Arg *A : Args) {
1693     bool NeedTrans = false;
1694     bool Skip = false;
1695     if (A->getOption().matches(options::OPT_Xarch_device)) {
1696       NeedTrans = IsDevice;
1697       Skip = !IsDevice;
1698     } else if (A->getOption().matches(options::OPT_Xarch_host)) {
1699       NeedTrans = !IsDevice;
1700       Skip = IsDevice;
1701     } else if (A->getOption().matches(options::OPT_Xarch__) && IsDevice) {
1702       // Do not translate -Xarch_ options for non CUDA/HIP toolchain since
1703       // they may need special translation.
1704       // Skip this argument unless the architecture matches BoundArch
1705       if (BoundArch.empty() || A->getValue(0) != BoundArch)
1706         Skip = true;
1707       else
1708         NeedTrans = true;
1709     }
1710     if (NeedTrans || Skip)
1711       Modified = true;
1712     if (NeedTrans)
1713       TranslateXarchArgs(Args, A, DAL, AllocatedArgs);
1714     if (!Skip)
1715       DAL->append(A);
1716   }
1717 
1718   if (Modified)
1719     return DAL;
1720 
1721   delete DAL;
1722   return nullptr;
1723 }
1724