xref: /freebsd-src/contrib/llvm-project/clang/lib/Driver/Driver.cpp (revision 6c05f3a74f30934ee60919cc97e16ec69b542b06)
10b57cec5SDimitry Andric //===--- Driver.cpp - Clang GCC Compatible Driver -------------------------===//
20b57cec5SDimitry Andric //
30b57cec5SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
40b57cec5SDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
50b57cec5SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
60b57cec5SDimitry Andric //
70b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
80b57cec5SDimitry Andric 
90b57cec5SDimitry Andric #include "clang/Driver/Driver.h"
10480093f4SDimitry Andric #include "ToolChains/AIX.h"
110b57cec5SDimitry Andric #include "ToolChains/AMDGPU.h"
12fe6060f1SDimitry Andric #include "ToolChains/AMDGPUOpenMP.h"
130b57cec5SDimitry Andric #include "ToolChains/AVR.h"
1406c3fb27SDimitry Andric #include "ToolChains/Arch/RISCV.h"
150b57cec5SDimitry Andric #include "ToolChains/BareMetal.h"
1681ad6265SDimitry Andric #include "ToolChains/CSKYToolChain.h"
170b57cec5SDimitry Andric #include "ToolChains/Clang.h"
180b57cec5SDimitry Andric #include "ToolChains/CrossWindows.h"
190b57cec5SDimitry Andric #include "ToolChains/Cuda.h"
200b57cec5SDimitry Andric #include "ToolChains/Darwin.h"
210b57cec5SDimitry Andric #include "ToolChains/DragonFly.h"
220b57cec5SDimitry Andric #include "ToolChains/FreeBSD.h"
230b57cec5SDimitry Andric #include "ToolChains/Fuchsia.h"
240b57cec5SDimitry Andric #include "ToolChains/Gnu.h"
250eae32dcSDimitry Andric #include "ToolChains/HIPAMD.h"
260eae32dcSDimitry Andric #include "ToolChains/HIPSPV.h"
2781ad6265SDimitry Andric #include "ToolChains/HLSL.h"
280b57cec5SDimitry Andric #include "ToolChains/Haiku.h"
290b57cec5SDimitry Andric #include "ToolChains/Hexagon.h"
300b57cec5SDimitry Andric #include "ToolChains/Hurd.h"
310b57cec5SDimitry Andric #include "ToolChains/Lanai.h"
320b57cec5SDimitry Andric #include "ToolChains/Linux.h"
330b57cec5SDimitry Andric #include "ToolChains/MSP430.h"
340b57cec5SDimitry Andric #include "ToolChains/MSVC.h"
350b57cec5SDimitry Andric #include "ToolChains/MinGW.h"
360b57cec5SDimitry Andric #include "ToolChains/MipsLinux.h"
370b57cec5SDimitry Andric #include "ToolChains/NaCl.h"
380b57cec5SDimitry Andric #include "ToolChains/NetBSD.h"
3906c3fb27SDimitry Andric #include "ToolChains/OHOS.h"
400b57cec5SDimitry Andric #include "ToolChains/OpenBSD.h"
414824e7fdSDimitry Andric #include "ToolChains/PPCFreeBSD.h"
420b57cec5SDimitry Andric #include "ToolChains/PPCLinux.h"
435ffd83dbSDimitry Andric #include "ToolChains/PS4CPU.h"
440b57cec5SDimitry Andric #include "ToolChains/RISCVToolchain.h"
450eae32dcSDimitry Andric #include "ToolChains/SPIRV.h"
460b57cec5SDimitry Andric #include "ToolChains/Solaris.h"
470b57cec5SDimitry Andric #include "ToolChains/TCE.h"
485ffd83dbSDimitry Andric #include "ToolChains/VEToolchain.h"
490b57cec5SDimitry Andric #include "ToolChains/WebAssembly.h"
500b57cec5SDimitry Andric #include "ToolChains/XCore.h"
51e8d8bef9SDimitry Andric #include "ToolChains/ZOS.h"
520fca6ea1SDimitry Andric #include "clang/Basic/DiagnosticDriver.h"
53e8d8bef9SDimitry Andric #include "clang/Basic/TargetID.h"
540b57cec5SDimitry Andric #include "clang/Basic/Version.h"
550b57cec5SDimitry Andric #include "clang/Config/config.h"
560b57cec5SDimitry Andric #include "clang/Driver/Action.h"
570b57cec5SDimitry Andric #include "clang/Driver/Compilation.h"
580b57cec5SDimitry Andric #include "clang/Driver/DriverDiagnostic.h"
59fe6060f1SDimitry Andric #include "clang/Driver/InputInfo.h"
600b57cec5SDimitry Andric #include "clang/Driver/Job.h"
610b57cec5SDimitry Andric #include "clang/Driver/Options.h"
6281ad6265SDimitry Andric #include "clang/Driver/Phases.h"
630b57cec5SDimitry Andric #include "clang/Driver/SanitizerArgs.h"
640b57cec5SDimitry Andric #include "clang/Driver/Tool.h"
650b57cec5SDimitry Andric #include "clang/Driver/ToolChain.h"
6604eeddc0SDimitry Andric #include "clang/Driver/Types.h"
670b57cec5SDimitry Andric #include "llvm/ADT/ArrayRef.h"
680b57cec5SDimitry Andric #include "llvm/ADT/STLExtras.h"
690b57cec5SDimitry Andric #include "llvm/ADT/StringExtras.h"
70fe6060f1SDimitry Andric #include "llvm/ADT/StringRef.h"
710b57cec5SDimitry Andric #include "llvm/ADT/StringSet.h"
720b57cec5SDimitry Andric #include "llvm/ADT/StringSwitch.h"
730b57cec5SDimitry Andric #include "llvm/Config/llvm-config.h"
74349cc55cSDimitry Andric #include "llvm/MC/TargetRegistry.h"
750b57cec5SDimitry Andric #include "llvm/Option/Arg.h"
760b57cec5SDimitry Andric #include "llvm/Option/ArgList.h"
770b57cec5SDimitry Andric #include "llvm/Option/OptSpecifier.h"
780b57cec5SDimitry Andric #include "llvm/Option/OptTable.h"
790b57cec5SDimitry Andric #include "llvm/Option/Option.h"
800b57cec5SDimitry Andric #include "llvm/Support/CommandLine.h"
810b57cec5SDimitry Andric #include "llvm/Support/ErrorHandling.h"
82e8d8bef9SDimitry Andric #include "llvm/Support/ExitCodes.h"
830b57cec5SDimitry Andric #include "llvm/Support/FileSystem.h"
840b57cec5SDimitry Andric #include "llvm/Support/FormatVariadic.h"
85fe6060f1SDimitry Andric #include "llvm/Support/MD5.h"
860b57cec5SDimitry Andric #include "llvm/Support/Path.h"
870b57cec5SDimitry Andric #include "llvm/Support/PrettyStackTrace.h"
880b57cec5SDimitry Andric #include "llvm/Support/Process.h"
890b57cec5SDimitry Andric #include "llvm/Support/Program.h"
900fca6ea1SDimitry Andric #include "llvm/Support/Regex.h"
910b57cec5SDimitry Andric #include "llvm/Support/StringSaver.h"
920b57cec5SDimitry Andric #include "llvm/Support/VirtualFileSystem.h"
930b57cec5SDimitry Andric #include "llvm/Support/raw_ostream.h"
9406c3fb27SDimitry Andric #include "llvm/TargetParser/Host.h"
950fca6ea1SDimitry Andric #include "llvm/TargetParser/RISCVISAInfo.h"
96bdd1243dSDimitry Andric #include <cstdlib> // ::getenv
970b57cec5SDimitry Andric #include <map>
980b57cec5SDimitry Andric #include <memory>
99bdd1243dSDimitry Andric #include <optional>
10006c3fb27SDimitry Andric #include <set>
1010b57cec5SDimitry Andric #include <utility>
1020b57cec5SDimitry Andric #if LLVM_ON_UNIX
1030b57cec5SDimitry Andric #include <unistd.h> // getpid
1040b57cec5SDimitry Andric #endif
1050b57cec5SDimitry Andric 
1060b57cec5SDimitry Andric using namespace clang::driver;
1070b57cec5SDimitry Andric using namespace clang;
1080b57cec5SDimitry Andric using namespace llvm::opt;
1090b57cec5SDimitry Andric 
110bdd1243dSDimitry Andric static std::optional<llvm::Triple> getOffloadTargetTriple(const Driver &D,
111bdd1243dSDimitry Andric                                                           const ArgList &Args) {
1121fd87a68SDimitry Andric   auto OffloadTargets = Args.getAllArgValues(options::OPT_offload_EQ);
1131fd87a68SDimitry Andric   // Offload compilation flow does not support multiple targets for now. We
1141fd87a68SDimitry Andric   // need the HIPActionBuilder (and possibly the CudaActionBuilder{,Base}too)
1151fd87a68SDimitry Andric   // to support multiple tool chains first.
1161fd87a68SDimitry Andric   switch (OffloadTargets.size()) {
1170eae32dcSDimitry Andric   default:
1181fd87a68SDimitry Andric     D.Diag(diag::err_drv_only_one_offload_target_supported);
119bdd1243dSDimitry Andric     return std::nullopt;
1200eae32dcSDimitry Andric   case 0:
1210eae32dcSDimitry Andric     D.Diag(diag::err_drv_invalid_or_unsupported_offload_target) << "";
122bdd1243dSDimitry Andric     return std::nullopt;
1230eae32dcSDimitry Andric   case 1:
1240eae32dcSDimitry Andric     break;
1250eae32dcSDimitry Andric   }
1261fd87a68SDimitry Andric   return llvm::Triple(OffloadTargets[0]);
1270eae32dcSDimitry Andric }
1280eae32dcSDimitry Andric 
129bdd1243dSDimitry Andric static std::optional<llvm::Triple>
1301fd87a68SDimitry Andric getNVIDIAOffloadTargetTriple(const Driver &D, const ArgList &Args,
1311fd87a68SDimitry Andric                              const llvm::Triple &HostTriple) {
1321fd87a68SDimitry Andric   if (!Args.hasArg(options::OPT_offload_EQ)) {
1331fd87a68SDimitry Andric     return llvm::Triple(HostTriple.isArch64Bit() ? "nvptx64-nvidia-cuda"
1341fd87a68SDimitry Andric                                                  : "nvptx-nvidia-cuda");
1351fd87a68SDimitry Andric   }
1361fd87a68SDimitry Andric   auto TT = getOffloadTargetTriple(D, Args);
1371fd87a68SDimitry Andric   if (TT && (TT->getArch() == llvm::Triple::spirv32 ||
1381fd87a68SDimitry Andric              TT->getArch() == llvm::Triple::spirv64)) {
1391fd87a68SDimitry Andric     if (Args.hasArg(options::OPT_emit_llvm))
1401fd87a68SDimitry Andric       return TT;
1411fd87a68SDimitry Andric     D.Diag(diag::err_drv_cuda_offload_only_emit_bc);
142bdd1243dSDimitry Andric     return std::nullopt;
1431fd87a68SDimitry Andric   }
1441fd87a68SDimitry Andric   D.Diag(diag::err_drv_invalid_or_unsupported_offload_target) << TT->str();
145bdd1243dSDimitry Andric   return std::nullopt;
1461fd87a68SDimitry Andric }
147bdd1243dSDimitry Andric static std::optional<llvm::Triple>
1481fd87a68SDimitry Andric getHIPOffloadTargetTriple(const Driver &D, const ArgList &Args) {
1491fd87a68SDimitry Andric   if (!Args.hasArg(options::OPT_offload_EQ)) {
1500fca6ea1SDimitry Andric     auto OffloadArchs = Args.getAllArgValues(options::OPT_offload_arch_EQ);
1510fca6ea1SDimitry Andric     if (llvm::find(OffloadArchs, "amdgcnspirv") != OffloadArchs.cend()) {
1520fca6ea1SDimitry Andric       if (OffloadArchs.size() == 1)
1530fca6ea1SDimitry Andric         return llvm::Triple("spirv64-amd-amdhsa");
1540fca6ea1SDimitry Andric       // Mixing specific & SPIR-V compilation is not supported for now.
1550fca6ea1SDimitry Andric       D.Diag(diag::err_drv_only_one_offload_target_supported);
1560fca6ea1SDimitry Andric       return std::nullopt;
1570fca6ea1SDimitry Andric     }
1581fd87a68SDimitry Andric     return llvm::Triple("amdgcn-amd-amdhsa"); // Default HIP triple.
1591fd87a68SDimitry Andric   }
1601fd87a68SDimitry Andric   auto TT = getOffloadTargetTriple(D, Args);
1611fd87a68SDimitry Andric   if (!TT)
162bdd1243dSDimitry Andric     return std::nullopt;
1631fd87a68SDimitry Andric   if (TT->getArch() == llvm::Triple::amdgcn &&
1641fd87a68SDimitry Andric       TT->getVendor() == llvm::Triple::AMD &&
1651fd87a68SDimitry Andric       TT->getOS() == llvm::Triple::AMDHSA)
1661fd87a68SDimitry Andric     return TT;
1671fd87a68SDimitry Andric   if (TT->getArch() == llvm::Triple::spirv64)
1681fd87a68SDimitry Andric     return TT;
1691fd87a68SDimitry Andric   D.Diag(diag::err_drv_invalid_or_unsupported_offload_target) << TT->str();
170bdd1243dSDimitry Andric   return std::nullopt;
171e8d8bef9SDimitry Andric }
172e8d8bef9SDimitry Andric 
1730b57cec5SDimitry Andric // static
1740b57cec5SDimitry Andric std::string Driver::GetResourcesPath(StringRef BinaryPath,
1750b57cec5SDimitry Andric                                      StringRef CustomResourceDir) {
1760b57cec5SDimitry Andric   // Since the resource directory is embedded in the module hash, it's important
1770b57cec5SDimitry Andric   // that all places that need it call this function, so that they get the
1780b57cec5SDimitry Andric   // exact same string ("a/../b/" and "b/" get different hashes, for example).
1790b57cec5SDimitry Andric 
1800b57cec5SDimitry Andric   // Dir is bin/ or lib/, depending on where BinaryPath is.
1815ffd83dbSDimitry Andric   std::string Dir = std::string(llvm::sys::path::parent_path(BinaryPath));
1820b57cec5SDimitry Andric 
1830b57cec5SDimitry Andric   SmallString<128> P(Dir);
1840b57cec5SDimitry Andric   if (CustomResourceDir != "") {
1850b57cec5SDimitry Andric     llvm::sys::path::append(P, CustomResourceDir);
1860b57cec5SDimitry Andric   } else {
1870b57cec5SDimitry Andric     // On Windows, libclang.dll is in bin/.
1880b57cec5SDimitry Andric     // On non-Windows, libclang.so/.dylib is in lib/.
1890b57cec5SDimitry Andric     // With a static-library build of libclang, LibClangPath will contain the
1900b57cec5SDimitry Andric     // path of the embedding binary, which for LLVM binaries will be in bin/.
1910b57cec5SDimitry Andric     // ../lib gets us to lib/ in both cases.
1920b57cec5SDimitry Andric     P = llvm::sys::path::parent_path(Dir);
19306c3fb27SDimitry Andric     // This search path is also created in the COFF driver of lld, so any
19406c3fb27SDimitry Andric     // changes here also needs to happen in lld/COFF/Driver.cpp
195bdd1243dSDimitry Andric     llvm::sys::path::append(P, CLANG_INSTALL_LIBDIR_BASENAME, "clang",
196bdd1243dSDimitry Andric                             CLANG_VERSION_MAJOR_STRING);
1970b57cec5SDimitry Andric   }
1980b57cec5SDimitry Andric 
1997a6dacacSDimitry Andric   return std::string(P);
2000b57cec5SDimitry Andric }
2010b57cec5SDimitry Andric 
2020b57cec5SDimitry Andric Driver::Driver(StringRef ClangExecutable, StringRef TargetTriple,
203e8d8bef9SDimitry Andric                DiagnosticsEngine &Diags, std::string Title,
2040b57cec5SDimitry Andric                IntrusiveRefCntPtr<llvm::vfs::FileSystem> VFS)
205a7dea167SDimitry Andric     : Diags(Diags), VFS(std::move(VFS)), Mode(GCCMode),
20681ad6265SDimitry Andric       SaveTemps(SaveTempsNone), BitcodeEmbed(EmbedNone),
20781ad6265SDimitry Andric       Offload(OffloadHostDevice), CXX20HeaderType(HeaderMode_None),
20881ad6265SDimitry Andric       ModulesModeCXX20(false), LTOMode(LTOK_None),
209a7dea167SDimitry Andric       ClangExecutable(ClangExecutable), SysRoot(DEFAULT_SYSROOT),
21004eeddc0SDimitry Andric       DriverTitle(Title), CCCPrintBindings(false), CCPrintOptions(false),
211bdd1243dSDimitry Andric       CCLogDiagnostics(false), CCGenDiagnostics(false),
21206c3fb27SDimitry Andric       CCPrintProcessStats(false), CCPrintInternalStats(false),
21306c3fb27SDimitry Andric       TargetTriple(TargetTriple), Saver(Alloc), PrependArg(nullptr),
21481ad6265SDimitry Andric       CheckInputsExist(true), ProbePrecompiled(true),
21504eeddc0SDimitry Andric       SuppressMissingInputWarning(false) {
2160b57cec5SDimitry Andric   // Provide a sane fallback if no VFS is specified.
2170b57cec5SDimitry Andric   if (!this->VFS)
2180b57cec5SDimitry Andric     this->VFS = llvm::vfs::getRealFileSystem();
2190b57cec5SDimitry Andric 
2205ffd83dbSDimitry Andric   Name = std::string(llvm::sys::path::filename(ClangExecutable));
2215ffd83dbSDimitry Andric   Dir = std::string(llvm::sys::path::parent_path(ClangExecutable));
2220b57cec5SDimitry Andric 
2235ffd83dbSDimitry Andric   if ((!SysRoot.empty()) && llvm::sys::path::is_relative(SysRoot)) {
2245ffd83dbSDimitry Andric     // Prepend InstalledDir if SysRoot is relative
2250fca6ea1SDimitry Andric     SmallString<128> P(Dir);
2265ffd83dbSDimitry Andric     llvm::sys::path::append(P, SysRoot);
2275ffd83dbSDimitry Andric     SysRoot = std::string(P);
2285ffd83dbSDimitry Andric   }
2295ffd83dbSDimitry Andric 
2300b57cec5SDimitry Andric #if defined(CLANG_CONFIG_FILE_SYSTEM_DIR)
2310b57cec5SDimitry Andric   SystemConfigDir = CLANG_CONFIG_FILE_SYSTEM_DIR;
2320b57cec5SDimitry Andric #endif
2330b57cec5SDimitry Andric #if defined(CLANG_CONFIG_FILE_USER_DIR)
234bdd1243dSDimitry Andric   {
235bdd1243dSDimitry Andric     SmallString<128> P;
236bdd1243dSDimitry Andric     llvm::sys::fs::expand_tilde(CLANG_CONFIG_FILE_USER_DIR, P);
237bdd1243dSDimitry Andric     UserConfigDir = static_cast<std::string>(P);
238bdd1243dSDimitry Andric   }
2390b57cec5SDimitry Andric #endif
2400b57cec5SDimitry Andric 
2410b57cec5SDimitry Andric   // Compute the path to the resource directory.
2420b57cec5SDimitry Andric   ResourceDir = GetResourcesPath(ClangExecutable, CLANG_RESOURCE_DIR);
2430b57cec5SDimitry Andric }
2440b57cec5SDimitry Andric 
245fe6060f1SDimitry Andric void Driver::setDriverMode(StringRef Value) {
2465f757f3fSDimitry Andric   static StringRef OptName =
2470b57cec5SDimitry Andric       getOpts().getOption(options::OPT_driver_mode).getPrefixedName();
248bdd1243dSDimitry Andric   if (auto M = llvm::StringSwitch<std::optional<DriverMode>>(Value)
2490b57cec5SDimitry Andric                    .Case("gcc", GCCMode)
2500b57cec5SDimitry Andric                    .Case("g++", GXXMode)
2510b57cec5SDimitry Andric                    .Case("cpp", CPPMode)
2520b57cec5SDimitry Andric                    .Case("cl", CLMode)
253480093f4SDimitry Andric                    .Case("flang", FlangMode)
25481ad6265SDimitry Andric                    .Case("dxc", DXCMode)
255bdd1243dSDimitry Andric                    .Default(std::nullopt))
2560b57cec5SDimitry Andric     Mode = *M;
2570b57cec5SDimitry Andric   else
2580b57cec5SDimitry Andric     Diag(diag::err_drv_unsupported_option_argument) << OptName << Value;
2590b57cec5SDimitry Andric }
2600b57cec5SDimitry Andric 
2610b57cec5SDimitry Andric InputArgList Driver::ParseArgStrings(ArrayRef<const char *> ArgStrings,
2625f757f3fSDimitry Andric                                      bool UseDriverMode, bool &ContainsError) {
2630b57cec5SDimitry Andric   llvm::PrettyStackTraceString CrashInfo("Command line argument parsing");
2640b57cec5SDimitry Andric   ContainsError = false;
2650b57cec5SDimitry Andric 
2665f757f3fSDimitry Andric   llvm::opt::Visibility VisibilityMask = getOptionVisibilityMask(UseDriverMode);
2670b57cec5SDimitry Andric   unsigned MissingArgIndex, MissingArgCount;
2685f757f3fSDimitry Andric   InputArgList Args = getOpts().ParseArgs(ArgStrings, MissingArgIndex,
2695f757f3fSDimitry Andric                                           MissingArgCount, VisibilityMask);
2700b57cec5SDimitry Andric 
2710b57cec5SDimitry Andric   // Check for missing argument error.
2720b57cec5SDimitry Andric   if (MissingArgCount) {
2730b57cec5SDimitry Andric     Diag(diag::err_drv_missing_argument)
2740b57cec5SDimitry Andric         << Args.getArgString(MissingArgIndex) << MissingArgCount;
2750b57cec5SDimitry Andric     ContainsError |=
2760b57cec5SDimitry Andric         Diags.getDiagnosticLevel(diag::err_drv_missing_argument,
2770b57cec5SDimitry Andric                                  SourceLocation()) > DiagnosticsEngine::Warning;
2780b57cec5SDimitry Andric   }
2790b57cec5SDimitry Andric 
2800b57cec5SDimitry Andric   // Check for unsupported options.
2810b57cec5SDimitry Andric   for (const Arg *A : Args) {
2820b57cec5SDimitry Andric     if (A->getOption().hasFlag(options::Unsupported)) {
2835f757f3fSDimitry Andric       Diag(diag::err_drv_unsupported_opt) << A->getAsString(Args);
2845f757f3fSDimitry Andric       ContainsError |= Diags.getDiagnosticLevel(diag::err_drv_unsupported_opt,
2855f757f3fSDimitry Andric                                                 SourceLocation()) >
2860b57cec5SDimitry Andric                        DiagnosticsEngine::Warning;
2870b57cec5SDimitry Andric       continue;
2880b57cec5SDimitry Andric     }
2890b57cec5SDimitry Andric 
2900b57cec5SDimitry Andric     // Warn about -mcpu= without an argument.
2910b57cec5SDimitry Andric     if (A->getOption().matches(options::OPT_mcpu_EQ) && A->containsValue("")) {
2920b57cec5SDimitry Andric       Diag(diag::warn_drv_empty_joined_argument) << A->getAsString(Args);
2930b57cec5SDimitry Andric       ContainsError |= Diags.getDiagnosticLevel(
2940b57cec5SDimitry Andric                            diag::warn_drv_empty_joined_argument,
2950b57cec5SDimitry Andric                            SourceLocation()) > DiagnosticsEngine::Warning;
2960b57cec5SDimitry Andric     }
2970b57cec5SDimitry Andric   }
2980b57cec5SDimitry Andric 
2990b57cec5SDimitry Andric   for (const Arg *A : Args.filtered(options::OPT_UNKNOWN)) {
3000b57cec5SDimitry Andric     unsigned DiagID;
3010b57cec5SDimitry Andric     auto ArgString = A->getAsString(Args);
3020b57cec5SDimitry Andric     std::string Nearest;
3035f757f3fSDimitry Andric     if (getOpts().findNearest(ArgString, Nearest, VisibilityMask) > 1) {
304bdd1243dSDimitry Andric       if (!IsCLMode() &&
3055f757f3fSDimitry Andric           getOpts().findExact(ArgString, Nearest,
3065f757f3fSDimitry Andric                               llvm::opt::Visibility(options::CC1Option))) {
307bdd1243dSDimitry Andric         DiagID = diag::err_drv_unknown_argument_with_suggestion;
308bdd1243dSDimitry Andric         Diags.Report(DiagID) << ArgString << "-Xclang " + Nearest;
309bdd1243dSDimitry Andric       } else {
3100b57cec5SDimitry Andric         DiagID = IsCLMode() ? diag::warn_drv_unknown_argument_clang_cl
3110b57cec5SDimitry Andric                             : diag::err_drv_unknown_argument;
3120b57cec5SDimitry Andric         Diags.Report(DiagID) << ArgString;
313bdd1243dSDimitry Andric       }
3140b57cec5SDimitry Andric     } else {
3150b57cec5SDimitry Andric       DiagID = IsCLMode()
3160b57cec5SDimitry Andric                    ? diag::warn_drv_unknown_argument_clang_cl_with_suggestion
3170b57cec5SDimitry Andric                    : diag::err_drv_unknown_argument_with_suggestion;
3180b57cec5SDimitry Andric       Diags.Report(DiagID) << ArgString << Nearest;
3190b57cec5SDimitry Andric     }
3200b57cec5SDimitry Andric     ContainsError |= Diags.getDiagnosticLevel(DiagID, SourceLocation()) >
3210b57cec5SDimitry Andric                      DiagnosticsEngine::Warning;
3220b57cec5SDimitry Andric   }
3230b57cec5SDimitry Andric 
324bdd1243dSDimitry Andric   for (const Arg *A : Args.filtered(options::OPT_o)) {
325bdd1243dSDimitry Andric     if (ArgStrings[A->getIndex()] == A->getSpelling())
326bdd1243dSDimitry Andric       continue;
327bdd1243dSDimitry Andric 
328bdd1243dSDimitry Andric     // Warn on joined arguments that are similar to a long argument.
329bdd1243dSDimitry Andric     std::string ArgString = ArgStrings[A->getIndex()];
330bdd1243dSDimitry Andric     std::string Nearest;
3315f757f3fSDimitry Andric     if (getOpts().findExact("-" + ArgString, Nearest, VisibilityMask))
332bdd1243dSDimitry Andric       Diags.Report(diag::warn_drv_potentially_misspelled_joined_argument)
333bdd1243dSDimitry Andric           << A->getAsString(Args) << Nearest;
334bdd1243dSDimitry Andric   }
335bdd1243dSDimitry Andric 
3360b57cec5SDimitry Andric   return Args;
3370b57cec5SDimitry Andric }
3380b57cec5SDimitry Andric 
3390b57cec5SDimitry Andric // Determine which compilation mode we are in. We look for options which
3400b57cec5SDimitry Andric // affect the phase, starting with the earliest phases, and record which
3410b57cec5SDimitry Andric // option we used to determine the final phase.
3420b57cec5SDimitry Andric phases::ID Driver::getFinalPhase(const DerivedArgList &DAL,
3430b57cec5SDimitry Andric                                  Arg **FinalPhaseArg) const {
3440b57cec5SDimitry Andric   Arg *PhaseArg = nullptr;
3450b57cec5SDimitry Andric   phases::ID FinalPhase;
3460b57cec5SDimitry Andric 
3470b57cec5SDimitry Andric   // -{E,EP,P,M,MM} only run the preprocessor.
3480b57cec5SDimitry Andric   if (CCCIsCPP() || (PhaseArg = DAL.getLastArg(options::OPT_E)) ||
3490b57cec5SDimitry Andric       (PhaseArg = DAL.getLastArg(options::OPT__SLASH_EP)) ||
3500b57cec5SDimitry Andric       (PhaseArg = DAL.getLastArg(options::OPT_M, options::OPT_MM)) ||
351349cc55cSDimitry Andric       (PhaseArg = DAL.getLastArg(options::OPT__SLASH_P)) ||
352349cc55cSDimitry Andric       CCGenDiagnostics) {
3530b57cec5SDimitry Andric     FinalPhase = phases::Preprocess;
3540b57cec5SDimitry Andric 
3550b57cec5SDimitry Andric     // --precompile only runs up to precompilation.
35681ad6265SDimitry Andric     // Options that cause the output of C++20 compiled module interfaces or
35781ad6265SDimitry Andric     // header units have the same effect.
35881ad6265SDimitry Andric   } else if ((PhaseArg = DAL.getLastArg(options::OPT__precompile)) ||
35981ad6265SDimitry Andric              (PhaseArg = DAL.getLastArg(options::OPT_extract_api)) ||
36081ad6265SDimitry Andric              (PhaseArg = DAL.getLastArg(options::OPT_fmodule_header,
36181ad6265SDimitry Andric                                         options::OPT_fmodule_header_EQ))) {
3620b57cec5SDimitry Andric     FinalPhase = phases::Precompile;
3630b57cec5SDimitry Andric     // -{fsyntax-only,-analyze,emit-ast} only run up to the compiler.
3640b57cec5SDimitry Andric   } else if ((PhaseArg = DAL.getLastArg(options::OPT_fsyntax_only)) ||
3650b57cec5SDimitry Andric              (PhaseArg = DAL.getLastArg(options::OPT_print_supported_cpus)) ||
3660fca6ea1SDimitry Andric              (PhaseArg = DAL.getLastArg(options::OPT_print_enabled_extensions)) ||
3670b57cec5SDimitry Andric              (PhaseArg = DAL.getLastArg(options::OPT_module_file_info)) ||
3680b57cec5SDimitry Andric              (PhaseArg = DAL.getLastArg(options::OPT_verify_pch)) ||
3690b57cec5SDimitry Andric              (PhaseArg = DAL.getLastArg(options::OPT_rewrite_objc)) ||
3700b57cec5SDimitry Andric              (PhaseArg = DAL.getLastArg(options::OPT_rewrite_legacy_objc)) ||
3710b57cec5SDimitry Andric              (PhaseArg = DAL.getLastArg(options::OPT__migrate)) ||
372a7dea167SDimitry Andric              (PhaseArg = DAL.getLastArg(options::OPT__analyze)) ||
3730fca6ea1SDimitry Andric              (PhaseArg = DAL.getLastArg(options::OPT_emit_cir)) ||
37481ad6265SDimitry Andric              (PhaseArg = DAL.getLastArg(options::OPT_emit_ast))) {
3750b57cec5SDimitry Andric     FinalPhase = phases::Compile;
3760b57cec5SDimitry Andric 
3770b57cec5SDimitry Andric   // -S only runs up to the backend.
3780b57cec5SDimitry Andric   } else if ((PhaseArg = DAL.getLastArg(options::OPT_S))) {
3790b57cec5SDimitry Andric     FinalPhase = phases::Backend;
3800b57cec5SDimitry Andric 
3810b57cec5SDimitry Andric   // -c compilation only runs up to the assembler.
3820b57cec5SDimitry Andric   } else if ((PhaseArg = DAL.getLastArg(options::OPT_c))) {
3830b57cec5SDimitry Andric     FinalPhase = phases::Assemble;
3840b57cec5SDimitry Andric 
385349cc55cSDimitry Andric   } else if ((PhaseArg = DAL.getLastArg(options::OPT_emit_interface_stubs))) {
386349cc55cSDimitry Andric     FinalPhase = phases::IfsMerge;
387349cc55cSDimitry Andric 
3880b57cec5SDimitry Andric   // Otherwise do everything.
3890b57cec5SDimitry Andric   } else
3900b57cec5SDimitry Andric     FinalPhase = phases::Link;
3910b57cec5SDimitry Andric 
3920b57cec5SDimitry Andric   if (FinalPhaseArg)
3930b57cec5SDimitry Andric     *FinalPhaseArg = PhaseArg;
3940b57cec5SDimitry Andric 
3950b57cec5SDimitry Andric   return FinalPhase;
3960b57cec5SDimitry Andric }
3970b57cec5SDimitry Andric 
398a7dea167SDimitry Andric static Arg *MakeInputArg(DerivedArgList &Args, const OptTable &Opts,
3990b57cec5SDimitry Andric                          StringRef Value, bool Claim = true) {
4000b57cec5SDimitry Andric   Arg *A = new Arg(Opts.getOption(options::OPT_INPUT), Value,
4010b57cec5SDimitry Andric                    Args.getBaseArgs().MakeIndex(Value), Value.data());
4020b57cec5SDimitry Andric   Args.AddSynthesizedArg(A);
4030b57cec5SDimitry Andric   if (Claim)
4040b57cec5SDimitry Andric     A->claim();
4050b57cec5SDimitry Andric   return A;
4060b57cec5SDimitry Andric }
4070b57cec5SDimitry Andric 
4080b57cec5SDimitry Andric DerivedArgList *Driver::TranslateInputArgs(const InputArgList &Args) const {
409a7dea167SDimitry Andric   const llvm::opt::OptTable &Opts = getOpts();
4100b57cec5SDimitry Andric   DerivedArgList *DAL = new DerivedArgList(Args);
4110b57cec5SDimitry Andric 
4120b57cec5SDimitry Andric   bool HasNostdlib = Args.hasArg(options::OPT_nostdlib);
4130b57cec5SDimitry Andric   bool HasNostdlibxx = Args.hasArg(options::OPT_nostdlibxx);
4140b57cec5SDimitry Andric   bool HasNodefaultlib = Args.hasArg(options::OPT_nodefaultlibs);
41504eeddc0SDimitry Andric   bool IgnoreUnused = false;
4160b57cec5SDimitry Andric   for (Arg *A : Args) {
41704eeddc0SDimitry Andric     if (IgnoreUnused)
41804eeddc0SDimitry Andric       A->claim();
41904eeddc0SDimitry Andric 
42004eeddc0SDimitry Andric     if (A->getOption().matches(options::OPT_start_no_unused_arguments)) {
42104eeddc0SDimitry Andric       IgnoreUnused = true;
42204eeddc0SDimitry Andric       continue;
42304eeddc0SDimitry Andric     }
42404eeddc0SDimitry Andric     if (A->getOption().matches(options::OPT_end_no_unused_arguments)) {
42504eeddc0SDimitry Andric       IgnoreUnused = false;
42604eeddc0SDimitry Andric       continue;
42704eeddc0SDimitry Andric     }
42804eeddc0SDimitry Andric 
4290b57cec5SDimitry Andric     // Unfortunately, we have to parse some forwarding options (-Xassembler,
4300b57cec5SDimitry Andric     // -Xlinker, -Xpreprocessor) because we either integrate their functionality
4310b57cec5SDimitry Andric     // (assembler and preprocessor), or bypass a previous driver ('collect2').
4320b57cec5SDimitry Andric 
4330b57cec5SDimitry Andric     // Rewrite linker options, to replace --no-demangle with a custom internal
4340b57cec5SDimitry Andric     // option.
4350b57cec5SDimitry Andric     if ((A->getOption().matches(options::OPT_Wl_COMMA) ||
4360b57cec5SDimitry Andric          A->getOption().matches(options::OPT_Xlinker)) &&
4370b57cec5SDimitry Andric         A->containsValue("--no-demangle")) {
4380b57cec5SDimitry Andric       // Add the rewritten no-demangle argument.
439a7dea167SDimitry Andric       DAL->AddFlagArg(A, Opts.getOption(options::OPT_Z_Xlinker__no_demangle));
4400b57cec5SDimitry Andric 
4410b57cec5SDimitry Andric       // Add the remaining values as Xlinker arguments.
4420b57cec5SDimitry Andric       for (StringRef Val : A->getValues())
4430b57cec5SDimitry Andric         if (Val != "--no-demangle")
444a7dea167SDimitry Andric           DAL->AddSeparateArg(A, Opts.getOption(options::OPT_Xlinker), Val);
4450b57cec5SDimitry Andric 
4460b57cec5SDimitry Andric       continue;
4470b57cec5SDimitry Andric     }
4480b57cec5SDimitry Andric 
4490b57cec5SDimitry Andric     // Rewrite preprocessor options, to replace -Wp,-MD,FOO which is used by
4500b57cec5SDimitry Andric     // some build systems. We don't try to be complete here because we don't
4510b57cec5SDimitry Andric     // care to encourage this usage model.
4520b57cec5SDimitry Andric     if (A->getOption().matches(options::OPT_Wp_COMMA) &&
4530b57cec5SDimitry Andric         (A->getValue(0) == StringRef("-MD") ||
4540b57cec5SDimitry Andric          A->getValue(0) == StringRef("-MMD"))) {
4550b57cec5SDimitry Andric       // Rewrite to -MD/-MMD along with -MF.
4560b57cec5SDimitry Andric       if (A->getValue(0) == StringRef("-MD"))
457a7dea167SDimitry Andric         DAL->AddFlagArg(A, Opts.getOption(options::OPT_MD));
4580b57cec5SDimitry Andric       else
459a7dea167SDimitry Andric         DAL->AddFlagArg(A, Opts.getOption(options::OPT_MMD));
4600b57cec5SDimitry Andric       if (A->getNumValues() == 2)
461a7dea167SDimitry Andric         DAL->AddSeparateArg(A, Opts.getOption(options::OPT_MF), A->getValue(1));
4620b57cec5SDimitry Andric       continue;
4630b57cec5SDimitry Andric     }
4640b57cec5SDimitry Andric 
4650b57cec5SDimitry Andric     // Rewrite reserved library names.
4660b57cec5SDimitry Andric     if (A->getOption().matches(options::OPT_l)) {
4670b57cec5SDimitry Andric       StringRef Value = A->getValue();
4680b57cec5SDimitry Andric 
4690b57cec5SDimitry Andric       // Rewrite unless -nostdlib is present.
4700b57cec5SDimitry Andric       if (!HasNostdlib && !HasNodefaultlib && !HasNostdlibxx &&
4710b57cec5SDimitry Andric           Value == "stdc++") {
472a7dea167SDimitry Andric         DAL->AddFlagArg(A, Opts.getOption(options::OPT_Z_reserved_lib_stdcxx));
4730b57cec5SDimitry Andric         continue;
4740b57cec5SDimitry Andric       }
4750b57cec5SDimitry Andric 
4760b57cec5SDimitry Andric       // Rewrite unconditionally.
4770b57cec5SDimitry Andric       if (Value == "cc_kext") {
478a7dea167SDimitry Andric         DAL->AddFlagArg(A, Opts.getOption(options::OPT_Z_reserved_lib_cckext));
4790b57cec5SDimitry Andric         continue;
4800b57cec5SDimitry Andric       }
4810b57cec5SDimitry Andric     }
4820b57cec5SDimitry Andric 
4830b57cec5SDimitry Andric     // Pick up inputs via the -- option.
4840b57cec5SDimitry Andric     if (A->getOption().matches(options::OPT__DASH_DASH)) {
4850b57cec5SDimitry Andric       A->claim();
4860b57cec5SDimitry Andric       for (StringRef Val : A->getValues())
487a7dea167SDimitry Andric         DAL->append(MakeInputArg(*DAL, Opts, Val, false));
4880b57cec5SDimitry Andric       continue;
4890b57cec5SDimitry Andric     }
4900b57cec5SDimitry Andric 
4910b57cec5SDimitry Andric     DAL->append(A);
4920b57cec5SDimitry Andric   }
4930b57cec5SDimitry Andric 
4945f757f3fSDimitry Andric   // DXC mode quits before assembly if an output object file isn't specified.
4955f757f3fSDimitry Andric   if (IsDXCMode() && !Args.hasArg(options::OPT_dxc_Fo))
4965f757f3fSDimitry Andric     DAL->AddFlagArg(nullptr, Opts.getOption(options::OPT_S));
4975f757f3fSDimitry Andric 
4980b57cec5SDimitry Andric   // Enforce -static if -miamcu is present.
4990b57cec5SDimitry Andric   if (Args.hasFlag(options::OPT_miamcu, options::OPT_mno_iamcu, false))
50004eeddc0SDimitry Andric     DAL->AddFlagArg(nullptr, Opts.getOption(options::OPT_static));
5010b57cec5SDimitry Andric 
5020b57cec5SDimitry Andric // Add a default value of -mlinker-version=, if one was given and the user
5030b57cec5SDimitry Andric // didn't specify one.
5040b57cec5SDimitry Andric #if defined(HOST_LINK_VERSION)
5050b57cec5SDimitry Andric   if (!Args.hasArg(options::OPT_mlinker_version_EQ) &&
5060b57cec5SDimitry Andric       strlen(HOST_LINK_VERSION) > 0) {
507a7dea167SDimitry Andric     DAL->AddJoinedArg(0, Opts.getOption(options::OPT_mlinker_version_EQ),
5080b57cec5SDimitry Andric                       HOST_LINK_VERSION);
5090b57cec5SDimitry Andric     DAL->getLastArg(options::OPT_mlinker_version_EQ)->claim();
5100b57cec5SDimitry Andric   }
5110b57cec5SDimitry Andric #endif
5120b57cec5SDimitry Andric 
5130b57cec5SDimitry Andric   return DAL;
5140b57cec5SDimitry Andric }
5150b57cec5SDimitry Andric 
5160b57cec5SDimitry Andric /// Compute target triple from args.
5170b57cec5SDimitry Andric ///
5180b57cec5SDimitry Andric /// This routine provides the logic to compute a target triple from various
5190b57cec5SDimitry Andric /// args passed to the driver and the default triple string.
5200b57cec5SDimitry Andric static llvm::Triple computeTargetTriple(const Driver &D,
5210b57cec5SDimitry Andric                                         StringRef TargetTriple,
5220b57cec5SDimitry Andric                                         const ArgList &Args,
5230b57cec5SDimitry Andric                                         StringRef DarwinArchName = "") {
5240b57cec5SDimitry Andric   // FIXME: Already done in Compilation *Driver::BuildCompilation
5250b57cec5SDimitry Andric   if (const Arg *A = Args.getLastArg(options::OPT_target))
5260b57cec5SDimitry Andric     TargetTriple = A->getValue();
5270b57cec5SDimitry Andric 
5280b57cec5SDimitry Andric   llvm::Triple Target(llvm::Triple::normalize(TargetTriple));
5290b57cec5SDimitry Andric 
5300b57cec5SDimitry Andric   // GNU/Hurd's triples should have been -hurd-gnu*, but were historically made
5310b57cec5SDimitry Andric   // -gnu* only, and we can not change this, so we have to detect that case as
5320b57cec5SDimitry Andric   // being the Hurd OS.
533349cc55cSDimitry Andric   if (TargetTriple.contains("-unknown-gnu") || TargetTriple.contains("-pc-gnu"))
5340b57cec5SDimitry Andric     Target.setOSName("hurd");
5350b57cec5SDimitry Andric 
5360b57cec5SDimitry Andric   // Handle Apple-specific options available here.
5370b57cec5SDimitry Andric   if (Target.isOSBinFormatMachO()) {
5380b57cec5SDimitry Andric     // If an explicit Darwin arch name is given, that trumps all.
5390b57cec5SDimitry Andric     if (!DarwinArchName.empty()) {
54006c3fb27SDimitry Andric       tools::darwin::setTripleTypeForMachOArchName(Target, DarwinArchName,
54106c3fb27SDimitry Andric                                                    Args);
5420b57cec5SDimitry Andric       return Target;
5430b57cec5SDimitry Andric     }
5440b57cec5SDimitry Andric 
5450b57cec5SDimitry Andric     // Handle the Darwin '-arch' flag.
5460b57cec5SDimitry Andric     if (Arg *A = Args.getLastArg(options::OPT_arch)) {
5470b57cec5SDimitry Andric       StringRef ArchName = A->getValue();
54806c3fb27SDimitry Andric       tools::darwin::setTripleTypeForMachOArchName(Target, ArchName, Args);
5490b57cec5SDimitry Andric     }
5500b57cec5SDimitry Andric   }
5510b57cec5SDimitry Andric 
5520b57cec5SDimitry Andric   // Handle pseudo-target flags '-mlittle-endian'/'-EL' and
5530b57cec5SDimitry Andric   // '-mbig-endian'/'-EB'.
55406c3fb27SDimitry Andric   if (Arg *A = Args.getLastArgNoClaim(options::OPT_mlittle_endian,
5550b57cec5SDimitry Andric                                       options::OPT_mbig_endian)) {
55606c3fb27SDimitry Andric     llvm::Triple T = A->getOption().matches(options::OPT_mlittle_endian)
55706c3fb27SDimitry Andric                          ? Target.getLittleEndianArchVariant()
55806c3fb27SDimitry Andric                          : Target.getBigEndianArchVariant();
55906c3fb27SDimitry Andric     if (T.getArch() != llvm::Triple::UnknownArch) {
56006c3fb27SDimitry Andric       Target = std::move(T);
56106c3fb27SDimitry Andric       Args.claimAllArgs(options::OPT_mlittle_endian, options::OPT_mbig_endian);
5620b57cec5SDimitry Andric     }
5630b57cec5SDimitry Andric   }
5640b57cec5SDimitry Andric 
5650b57cec5SDimitry Andric   // Skip further flag support on OSes which don't support '-m32' or '-m64'.
5665f757f3fSDimitry Andric   if (Target.getArch() == llvm::Triple::tce)
5670b57cec5SDimitry Andric     return Target;
5680b57cec5SDimitry Andric 
5695ffd83dbSDimitry Andric   // On AIX, the env OBJECT_MODE may affect the resulting arch variant.
5705ffd83dbSDimitry Andric   if (Target.isOSAIX()) {
571bdd1243dSDimitry Andric     if (std::optional<std::string> ObjectModeValue =
5725ffd83dbSDimitry Andric             llvm::sys::Process::GetEnv("OBJECT_MODE")) {
5735ffd83dbSDimitry Andric       StringRef ObjectMode = *ObjectModeValue;
5745ffd83dbSDimitry Andric       llvm::Triple::ArchType AT = llvm::Triple::UnknownArch;
5755ffd83dbSDimitry Andric 
5760fca6ea1SDimitry Andric       if (ObjectMode == "64") {
5775ffd83dbSDimitry Andric         AT = Target.get64BitArchVariant().getArch();
5780fca6ea1SDimitry Andric       } else if (ObjectMode == "32") {
5795ffd83dbSDimitry Andric         AT = Target.get32BitArchVariant().getArch();
5805ffd83dbSDimitry Andric       } else {
5815ffd83dbSDimitry Andric         D.Diag(diag::err_drv_invalid_object_mode) << ObjectMode;
5825ffd83dbSDimitry Andric       }
5835ffd83dbSDimitry Andric 
5845ffd83dbSDimitry Andric       if (AT != llvm::Triple::UnknownArch && AT != Target.getArch())
5855ffd83dbSDimitry Andric         Target.setArch(AT);
5865ffd83dbSDimitry Andric     }
5875ffd83dbSDimitry Andric   }
5885ffd83dbSDimitry Andric 
58906c3fb27SDimitry Andric   // The `-maix[32|64]` flags are only valid for AIX targets.
59006c3fb27SDimitry Andric   if (Arg *A = Args.getLastArgNoClaim(options::OPT_maix32, options::OPT_maix64);
59106c3fb27SDimitry Andric       A && !Target.isOSAIX())
59206c3fb27SDimitry Andric     D.Diag(diag::err_drv_unsupported_opt_for_target)
59306c3fb27SDimitry Andric         << A->getAsString(Args) << Target.str();
59406c3fb27SDimitry Andric 
5950b57cec5SDimitry Andric   // Handle pseudo-target flags '-m64', '-mx32', '-m32' and '-m16'.
5960b57cec5SDimitry Andric   Arg *A = Args.getLastArg(options::OPT_m64, options::OPT_mx32,
59706c3fb27SDimitry Andric                            options::OPT_m32, options::OPT_m16,
59806c3fb27SDimitry Andric                            options::OPT_maix32, options::OPT_maix64);
5990b57cec5SDimitry Andric   if (A) {
6000b57cec5SDimitry Andric     llvm::Triple::ArchType AT = llvm::Triple::UnknownArch;
6010b57cec5SDimitry Andric 
60206c3fb27SDimitry Andric     if (A->getOption().matches(options::OPT_m64) ||
60306c3fb27SDimitry Andric         A->getOption().matches(options::OPT_maix64)) {
6040b57cec5SDimitry Andric       AT = Target.get64BitArchVariant().getArch();
605d686ce93SDimitry Andric       if (Target.getEnvironment() == llvm::Triple::GNUX32 ||
606d686ce93SDimitry Andric           Target.getEnvironment() == llvm::Triple::GNUT64)
6070b57cec5SDimitry Andric         Target.setEnvironment(llvm::Triple::GNU);
608fe6060f1SDimitry Andric       else if (Target.getEnvironment() == llvm::Triple::MuslX32)
609fe6060f1SDimitry Andric         Target.setEnvironment(llvm::Triple::Musl);
6100b57cec5SDimitry Andric     } else if (A->getOption().matches(options::OPT_mx32) &&
6110b57cec5SDimitry Andric                Target.get64BitArchVariant().getArch() == llvm::Triple::x86_64) {
6120b57cec5SDimitry Andric       AT = llvm::Triple::x86_64;
613fe6060f1SDimitry Andric       if (Target.getEnvironment() == llvm::Triple::Musl)
614fe6060f1SDimitry Andric         Target.setEnvironment(llvm::Triple::MuslX32);
615fe6060f1SDimitry Andric       else
6160b57cec5SDimitry Andric         Target.setEnvironment(llvm::Triple::GNUX32);
61706c3fb27SDimitry Andric     } else if (A->getOption().matches(options::OPT_m32) ||
61806c3fb27SDimitry Andric                A->getOption().matches(options::OPT_maix32)) {
6190b57cec5SDimitry Andric       AT = Target.get32BitArchVariant().getArch();
6200b57cec5SDimitry Andric       if (Target.getEnvironment() == llvm::Triple::GNUX32)
6210b57cec5SDimitry Andric         Target.setEnvironment(llvm::Triple::GNU);
622fe6060f1SDimitry Andric       else if (Target.getEnvironment() == llvm::Triple::MuslX32)
623fe6060f1SDimitry Andric         Target.setEnvironment(llvm::Triple::Musl);
6240b57cec5SDimitry Andric     } else if (A->getOption().matches(options::OPT_m16) &&
6250b57cec5SDimitry Andric                Target.get32BitArchVariant().getArch() == llvm::Triple::x86) {
6260b57cec5SDimitry Andric       AT = llvm::Triple::x86;
6270b57cec5SDimitry Andric       Target.setEnvironment(llvm::Triple::CODE16);
6280b57cec5SDimitry Andric     }
6290b57cec5SDimitry Andric 
630349cc55cSDimitry Andric     if (AT != llvm::Triple::UnknownArch && AT != Target.getArch()) {
6310b57cec5SDimitry Andric       Target.setArch(AT);
632349cc55cSDimitry Andric       if (Target.isWindowsGNUEnvironment())
633349cc55cSDimitry Andric         toolchains::MinGW::fixTripleArch(D, Target, Args);
634349cc55cSDimitry Andric     }
6350b57cec5SDimitry Andric   }
6360b57cec5SDimitry Andric 
6370b57cec5SDimitry Andric   // Handle -miamcu flag.
6380b57cec5SDimitry Andric   if (Args.hasFlag(options::OPT_miamcu, options::OPT_mno_iamcu, false)) {
6390b57cec5SDimitry Andric     if (Target.get32BitArchVariant().getArch() != llvm::Triple::x86)
6400b57cec5SDimitry Andric       D.Diag(diag::err_drv_unsupported_opt_for_target) << "-miamcu"
6410b57cec5SDimitry Andric                                                        << Target.str();
6420b57cec5SDimitry Andric 
6430b57cec5SDimitry Andric     if (A && !A->getOption().matches(options::OPT_m32))
6440b57cec5SDimitry Andric       D.Diag(diag::err_drv_argument_not_allowed_with)
6450b57cec5SDimitry Andric           << "-miamcu" << A->getBaseArg().getAsString(Args);
6460b57cec5SDimitry Andric 
6470b57cec5SDimitry Andric     Target.setArch(llvm::Triple::x86);
6480b57cec5SDimitry Andric     Target.setArchName("i586");
6490b57cec5SDimitry Andric     Target.setEnvironment(llvm::Triple::UnknownEnvironment);
6500b57cec5SDimitry Andric     Target.setEnvironmentName("");
6510b57cec5SDimitry Andric     Target.setOS(llvm::Triple::ELFIAMCU);
6520b57cec5SDimitry Andric     Target.setVendor(llvm::Triple::UnknownVendor);
6530b57cec5SDimitry Andric     Target.setVendorName("intel");
6540b57cec5SDimitry Andric   }
6550b57cec5SDimitry Andric 
6560b57cec5SDimitry Andric   // If target is MIPS adjust the target triple
6570b57cec5SDimitry Andric   // accordingly to provided ABI name.
658bdd1243dSDimitry Andric   if (Target.isMIPS()) {
659bdd1243dSDimitry Andric     if ((A = Args.getLastArg(options::OPT_mabi_EQ))) {
6600b57cec5SDimitry Andric       StringRef ABIName = A->getValue();
6610b57cec5SDimitry Andric       if (ABIName == "32") {
6620b57cec5SDimitry Andric         Target = Target.get32BitArchVariant();
6630b57cec5SDimitry Andric         if (Target.getEnvironment() == llvm::Triple::GNUABI64 ||
6640b57cec5SDimitry Andric             Target.getEnvironment() == llvm::Triple::GNUABIN32)
6650b57cec5SDimitry Andric           Target.setEnvironment(llvm::Triple::GNU);
6660b57cec5SDimitry Andric       } else if (ABIName == "n32") {
6670b57cec5SDimitry Andric         Target = Target.get64BitArchVariant();
6680b57cec5SDimitry Andric         if (Target.getEnvironment() == llvm::Triple::GNU ||
669d686ce93SDimitry Andric             Target.getEnvironment() == llvm::Triple::GNUT64 ||
6700b57cec5SDimitry Andric             Target.getEnvironment() == llvm::Triple::GNUABI64)
6710b57cec5SDimitry Andric           Target.setEnvironment(llvm::Triple::GNUABIN32);
6720b57cec5SDimitry Andric       } else if (ABIName == "64") {
6730b57cec5SDimitry Andric         Target = Target.get64BitArchVariant();
6740b57cec5SDimitry Andric         if (Target.getEnvironment() == llvm::Triple::GNU ||
675d686ce93SDimitry Andric             Target.getEnvironment() == llvm::Triple::GNUT64 ||
6760b57cec5SDimitry Andric             Target.getEnvironment() == llvm::Triple::GNUABIN32)
6770b57cec5SDimitry Andric           Target.setEnvironment(llvm::Triple::GNUABI64);
6780b57cec5SDimitry Andric       }
6790b57cec5SDimitry Andric     }
680bdd1243dSDimitry Andric   }
6810b57cec5SDimitry Andric 
682480093f4SDimitry Andric   // If target is RISC-V adjust the target triple according to
683480093f4SDimitry Andric   // provided architecture name
684bdd1243dSDimitry Andric   if (Target.isRISCV()) {
68506c3fb27SDimitry Andric     if (Args.hasArg(options::OPT_march_EQ) ||
68606c3fb27SDimitry Andric         Args.hasArg(options::OPT_mcpu_EQ)) {
6870fca6ea1SDimitry Andric       std::string ArchName = tools::riscv::getRISCVArch(Args, Target);
688647cbc5dSDimitry Andric       auto ISAInfo = llvm::RISCVISAInfo::parseArchString(
689647cbc5dSDimitry Andric           ArchName, /*EnableExperimentalExtensions=*/true);
690647cbc5dSDimitry Andric       if (!llvm::errorToBool(ISAInfo.takeError())) {
691647cbc5dSDimitry Andric         unsigned XLen = (*ISAInfo)->getXLen();
692647cbc5dSDimitry Andric         if (XLen == 32)
693480093f4SDimitry Andric           Target.setArch(llvm::Triple::riscv32);
694647cbc5dSDimitry Andric         else if (XLen == 64)
695480093f4SDimitry Andric           Target.setArch(llvm::Triple::riscv64);
696480093f4SDimitry Andric       }
697bdd1243dSDimitry Andric     }
698647cbc5dSDimitry Andric   }
699480093f4SDimitry Andric 
7000b57cec5SDimitry Andric   return Target;
7010b57cec5SDimitry Andric }
7020b57cec5SDimitry Andric 
7030b57cec5SDimitry Andric // Parse the LTO options and record the type of LTO compilation
704fe6060f1SDimitry Andric // based on which -f(no-)?lto(=.*)? or -f(no-)?offload-lto(=.*)?
705fe6060f1SDimitry Andric // option occurs last.
706349cc55cSDimitry Andric static driver::LTOKind parseLTOMode(Driver &D, const llvm::opt::ArgList &Args,
707349cc55cSDimitry Andric                                     OptSpecifier OptEq, OptSpecifier OptNeg) {
708349cc55cSDimitry Andric   if (!Args.hasFlag(OptEq, OptNeg, false))
709349cc55cSDimitry Andric     return LTOK_None;
7100b57cec5SDimitry Andric 
711fe6060f1SDimitry Andric   const Arg *A = Args.getLastArg(OptEq);
712349cc55cSDimitry Andric   StringRef LTOName = A->getValue();
7130b57cec5SDimitry Andric 
714349cc55cSDimitry Andric   driver::LTOKind LTOMode = llvm::StringSwitch<LTOKind>(LTOName)
7150b57cec5SDimitry Andric                                 .Case("full", LTOK_Full)
7160b57cec5SDimitry Andric                                 .Case("thin", LTOK_Thin)
7170b57cec5SDimitry Andric                                 .Default(LTOK_Unknown);
7180b57cec5SDimitry Andric 
7190b57cec5SDimitry Andric   if (LTOMode == LTOK_Unknown) {
720fe6060f1SDimitry Andric     D.Diag(diag::err_drv_unsupported_option_argument)
721bdd1243dSDimitry Andric         << A->getSpelling() << A->getValue();
722349cc55cSDimitry Andric     return LTOK_None;
7230b57cec5SDimitry Andric   }
724fe6060f1SDimitry Andric   return LTOMode;
725fe6060f1SDimitry Andric }
726fe6060f1SDimitry Andric 
727fe6060f1SDimitry Andric // Parse the LTO options.
728fe6060f1SDimitry Andric void Driver::setLTOMode(const llvm::opt::ArgList &Args) {
729349cc55cSDimitry Andric   LTOMode =
730349cc55cSDimitry Andric       parseLTOMode(*this, Args, options::OPT_flto_EQ, options::OPT_fno_lto);
731fe6060f1SDimitry Andric 
732349cc55cSDimitry Andric   OffloadLTOMode = parseLTOMode(*this, Args, options::OPT_foffload_lto_EQ,
733349cc55cSDimitry Andric                                 options::OPT_fno_offload_lto);
734bdd1243dSDimitry Andric 
735bdd1243dSDimitry Andric   // Try to enable `-foffload-lto=full` if `-fopenmp-target-jit` is on.
736bdd1243dSDimitry Andric   if (Args.hasFlag(options::OPT_fopenmp_target_jit,
737bdd1243dSDimitry Andric                    options::OPT_fno_openmp_target_jit, false)) {
738bdd1243dSDimitry Andric     if (Arg *A = Args.getLastArg(options::OPT_foffload_lto_EQ,
739bdd1243dSDimitry Andric                                  options::OPT_fno_offload_lto))
740bdd1243dSDimitry Andric       if (OffloadLTOMode != LTOK_Full)
741bdd1243dSDimitry Andric         Diag(diag::err_drv_incompatible_options)
742bdd1243dSDimitry Andric             << A->getSpelling() << "-fopenmp-target-jit";
743bdd1243dSDimitry Andric     OffloadLTOMode = LTOK_Full;
744bdd1243dSDimitry Andric   }
7450b57cec5SDimitry Andric }
7460b57cec5SDimitry Andric 
7470b57cec5SDimitry Andric /// Compute the desired OpenMP runtime from the flags provided.
7480b57cec5SDimitry Andric Driver::OpenMPRuntimeKind Driver::getOpenMPRuntime(const ArgList &Args) const {
7490b57cec5SDimitry Andric   StringRef RuntimeName(CLANG_DEFAULT_OPENMP_RUNTIME);
7500b57cec5SDimitry Andric 
7510b57cec5SDimitry Andric   const Arg *A = Args.getLastArg(options::OPT_fopenmp_EQ);
7520b57cec5SDimitry Andric   if (A)
7530b57cec5SDimitry Andric     RuntimeName = A->getValue();
7540b57cec5SDimitry Andric 
7550b57cec5SDimitry Andric   auto RT = llvm::StringSwitch<OpenMPRuntimeKind>(RuntimeName)
7560b57cec5SDimitry Andric                 .Case("libomp", OMPRT_OMP)
7570b57cec5SDimitry Andric                 .Case("libgomp", OMPRT_GOMP)
7580b57cec5SDimitry Andric                 .Case("libiomp5", OMPRT_IOMP5)
7590b57cec5SDimitry Andric                 .Default(OMPRT_Unknown);
7600b57cec5SDimitry Andric 
7610b57cec5SDimitry Andric   if (RT == OMPRT_Unknown) {
7620b57cec5SDimitry Andric     if (A)
7630b57cec5SDimitry Andric       Diag(diag::err_drv_unsupported_option_argument)
764bdd1243dSDimitry Andric           << A->getSpelling() << A->getValue();
7650b57cec5SDimitry Andric     else
7660b57cec5SDimitry Andric       // FIXME: We could use a nicer diagnostic here.
7670b57cec5SDimitry Andric       Diag(diag::err_drv_unsupported_opt) << "-fopenmp";
7680b57cec5SDimitry Andric   }
7690b57cec5SDimitry Andric 
7700b57cec5SDimitry Andric   return RT;
7710b57cec5SDimitry Andric }
7720b57cec5SDimitry Andric 
7730b57cec5SDimitry Andric void Driver::CreateOffloadingDeviceToolChains(Compilation &C,
7740b57cec5SDimitry Andric                                               InputList &Inputs) {
7750b57cec5SDimitry Andric 
7760b57cec5SDimitry Andric   //
7770b57cec5SDimitry Andric   // CUDA/HIP
7780b57cec5SDimitry Andric   //
7790b57cec5SDimitry Andric   // We need to generate a CUDA/HIP toolchain if any of the inputs has a CUDA
7800b57cec5SDimitry Andric   // or HIP type. However, mixed CUDA/HIP compilation is not supported.
7810b57cec5SDimitry Andric   bool IsCuda =
7820b57cec5SDimitry Andric       llvm::any_of(Inputs, [](std::pair<types::ID, const llvm::opt::Arg *> &I) {
7830b57cec5SDimitry Andric         return types::isCuda(I.first);
7840b57cec5SDimitry Andric       });
7850b57cec5SDimitry Andric   bool IsHIP =
7860b57cec5SDimitry Andric       llvm::any_of(Inputs,
7870b57cec5SDimitry Andric                    [](std::pair<types::ID, const llvm::opt::Arg *> &I) {
7880b57cec5SDimitry Andric                      return types::isHIP(I.first);
7890b57cec5SDimitry Andric                    }) ||
7905f757f3fSDimitry Andric       C.getInputArgs().hasArg(options::OPT_hip_link) ||
7915f757f3fSDimitry Andric       C.getInputArgs().hasArg(options::OPT_hipstdpar);
7920b57cec5SDimitry Andric   if (IsCuda && IsHIP) {
7930b57cec5SDimitry Andric     Diag(clang::diag::err_drv_mix_cuda_hip);
7940b57cec5SDimitry Andric     return;
7950b57cec5SDimitry Andric   }
7960b57cec5SDimitry Andric   if (IsCuda) {
7970b57cec5SDimitry Andric     const ToolChain *HostTC = C.getSingleOffloadToolChain<Action::OFK_Host>();
7980b57cec5SDimitry Andric     const llvm::Triple &HostTriple = HostTC->getTriple();
7990b57cec5SDimitry Andric     auto OFK = Action::OFK_Cuda;
8001fd87a68SDimitry Andric     auto CudaTriple =
8011fd87a68SDimitry Andric         getNVIDIAOffloadTargetTriple(*this, C.getInputArgs(), HostTriple);
8021fd87a68SDimitry Andric     if (!CudaTriple)
8031fd87a68SDimitry Andric       return;
8040b57cec5SDimitry Andric     // Use the CUDA and host triples as the key into the ToolChains map,
8050b57cec5SDimitry Andric     // because the device toolchain we create depends on both.
8061fd87a68SDimitry Andric     auto &CudaTC = ToolChains[CudaTriple->str() + "/" + HostTriple.str()];
8070b57cec5SDimitry Andric     if (!CudaTC) {
808a7dea167SDimitry Andric       CudaTC = std::make_unique<toolchains::CudaToolChain>(
809bdd1243dSDimitry Andric           *this, *CudaTriple, *HostTC, C.getInputArgs());
81006c3fb27SDimitry Andric 
81106c3fb27SDimitry Andric       // Emit a warning if the detected CUDA version is too new.
81206c3fb27SDimitry Andric       CudaInstallationDetector &CudaInstallation =
81306c3fb27SDimitry Andric           static_cast<toolchains::CudaToolChain &>(*CudaTC).CudaInstallation;
81406c3fb27SDimitry Andric       if (CudaInstallation.isValid())
81506c3fb27SDimitry Andric         CudaInstallation.WarnIfUnsupportedVersion();
8160b57cec5SDimitry Andric     }
8170b57cec5SDimitry Andric     C.addOffloadDeviceToolChain(CudaTC.get(), OFK);
8180b57cec5SDimitry Andric   } else if (IsHIP) {
819349cc55cSDimitry Andric     if (auto *OMPTargetArg =
820349cc55cSDimitry Andric             C.getInputArgs().getLastArg(options::OPT_fopenmp_targets_EQ)) {
821349cc55cSDimitry Andric       Diag(clang::diag::err_drv_unsupported_opt_for_language_mode)
822349cc55cSDimitry Andric           << OMPTargetArg->getSpelling() << "HIP";
823349cc55cSDimitry Andric       return;
824349cc55cSDimitry Andric     }
8250b57cec5SDimitry Andric     const ToolChain *HostTC = C.getSingleOffloadToolChain<Action::OFK_Host>();
8260b57cec5SDimitry Andric     auto OFK = Action::OFK_HIP;
8270eae32dcSDimitry Andric     auto HIPTriple = getHIPOffloadTargetTriple(*this, C.getInputArgs());
8280eae32dcSDimitry Andric     if (!HIPTriple)
8290eae32dcSDimitry Andric       return;
8300eae32dcSDimitry Andric     auto *HIPTC = &getOffloadingDeviceToolChain(C.getInputArgs(), *HIPTriple,
8310eae32dcSDimitry Andric                                                 *HostTC, OFK);
8320eae32dcSDimitry Andric     assert(HIPTC && "Could not create offloading device tool chain.");
8330eae32dcSDimitry Andric     C.addOffloadDeviceToolChain(HIPTC, OFK);
8340b57cec5SDimitry Andric   }
8350b57cec5SDimitry Andric 
8360b57cec5SDimitry Andric   //
8370b57cec5SDimitry Andric   // OpenMP
8380b57cec5SDimitry Andric   //
8390b57cec5SDimitry Andric   // We need to generate an OpenMP toolchain if the user specified targets with
84081ad6265SDimitry Andric   // the -fopenmp-targets option or used --offload-arch with OpenMP enabled.
84181ad6265SDimitry Andric   bool IsOpenMPOffloading =
84281ad6265SDimitry Andric       C.getInputArgs().hasFlag(options::OPT_fopenmp, options::OPT_fopenmp_EQ,
84381ad6265SDimitry Andric                                options::OPT_fno_openmp, false) &&
84481ad6265SDimitry Andric       (C.getInputArgs().hasArg(options::OPT_fopenmp_targets_EQ) ||
84581ad6265SDimitry Andric        C.getInputArgs().hasArg(options::OPT_offload_arch_EQ));
84681ad6265SDimitry Andric   if (IsOpenMPOffloading) {
8470b57cec5SDimitry Andric     // We expect that -fopenmp-targets is always used in conjunction with the
84881ad6265SDimitry Andric     // option -fopenmp specifying a valid runtime with offloading support, i.e.
84981ad6265SDimitry Andric     // libomp or libiomp.
85081ad6265SDimitry Andric     OpenMPRuntimeKind RuntimeKind = getOpenMPRuntime(C.getInputArgs());
85181ad6265SDimitry Andric     if (RuntimeKind != OMPRT_OMP && RuntimeKind != OMPRT_IOMP5) {
85281ad6265SDimitry Andric       Diag(clang::diag::err_drv_expecting_fopenmp_with_fopenmp_targets);
85381ad6265SDimitry Andric       return;
8540b57cec5SDimitry Andric     }
8550b57cec5SDimitry Andric 
85681ad6265SDimitry Andric     llvm::StringMap<llvm::DenseSet<StringRef>> DerivedArchs;
85781ad6265SDimitry Andric     llvm::StringMap<StringRef> FoundNormalizedTriples;
85806c3fb27SDimitry Andric     std::multiset<StringRef> OpenMPTriples;
85981ad6265SDimitry Andric 
86081ad6265SDimitry Andric     // If the user specified -fopenmp-targets= we create a toolchain for each
86181ad6265SDimitry Andric     // valid triple. Otherwise, if only --offload-arch= was specified we instead
86281ad6265SDimitry Andric     // attempt to derive the appropriate toolchains from the arguments.
86381ad6265SDimitry Andric     if (Arg *OpenMPTargets =
86481ad6265SDimitry Andric             C.getInputArgs().getLastArg(options::OPT_fopenmp_targets_EQ)) {
86581ad6265SDimitry Andric       if (OpenMPTargets && !OpenMPTargets->getNumValues()) {
86681ad6265SDimitry Andric         Diag(clang::diag::warn_drv_empty_joined_argument)
86781ad6265SDimitry Andric             << OpenMPTargets->getAsString(C.getInputArgs());
86881ad6265SDimitry Andric         return;
86981ad6265SDimitry Andric       }
87006c3fb27SDimitry Andric       for (StringRef T : OpenMPTargets->getValues())
87106c3fb27SDimitry Andric         OpenMPTriples.insert(T);
87281ad6265SDimitry Andric     } else if (C.getInputArgs().hasArg(options::OPT_offload_arch_EQ) &&
87381ad6265SDimitry Andric                !IsHIP && !IsCuda) {
87481ad6265SDimitry Andric       const ToolChain *HostTC = C.getSingleOffloadToolChain<Action::OFK_Host>();
87581ad6265SDimitry Andric       auto AMDTriple = getHIPOffloadTargetTriple(*this, C.getInputArgs());
87681ad6265SDimitry Andric       auto NVPTXTriple = getNVIDIAOffloadTargetTriple(*this, C.getInputArgs(),
87781ad6265SDimitry Andric                                                       HostTC->getTriple());
87881ad6265SDimitry Andric 
87981ad6265SDimitry Andric       // Attempt to deduce the offloading triple from the set of architectures.
880bdd1243dSDimitry Andric       // We can only correctly deduce NVPTX / AMDGPU triples currently. We need
881bdd1243dSDimitry Andric       // to temporarily create these toolchains so that we can access tools for
882bdd1243dSDimitry Andric       // inferring architectures.
883bdd1243dSDimitry Andric       llvm::DenseSet<StringRef> Archs;
884bdd1243dSDimitry Andric       if (NVPTXTriple) {
885bdd1243dSDimitry Andric         auto TempTC = std::make_unique<toolchains::CudaToolChain>(
886bdd1243dSDimitry Andric             *this, *NVPTXTriple, *HostTC, C.getInputArgs());
887bdd1243dSDimitry Andric         for (StringRef Arch : getOffloadArchs(
888bdd1243dSDimitry Andric                  C, C.getArgs(), Action::OFK_OpenMP, &*TempTC, true))
889bdd1243dSDimitry Andric           Archs.insert(Arch);
890bdd1243dSDimitry Andric       }
891bdd1243dSDimitry Andric       if (AMDTriple) {
892bdd1243dSDimitry Andric         auto TempTC = std::make_unique<toolchains::AMDGPUOpenMPToolChain>(
893bdd1243dSDimitry Andric             *this, *AMDTriple, *HostTC, C.getInputArgs());
894bdd1243dSDimitry Andric         for (StringRef Arch : getOffloadArchs(
895bdd1243dSDimitry Andric                  C, C.getArgs(), Action::OFK_OpenMP, &*TempTC, true))
896bdd1243dSDimitry Andric           Archs.insert(Arch);
897bdd1243dSDimitry Andric       }
898bdd1243dSDimitry Andric       if (!AMDTriple && !NVPTXTriple) {
899bdd1243dSDimitry Andric         for (StringRef Arch :
900bdd1243dSDimitry Andric              getOffloadArchs(C, C.getArgs(), Action::OFK_OpenMP, nullptr, true))
901bdd1243dSDimitry Andric           Archs.insert(Arch);
902bdd1243dSDimitry Andric       }
903bdd1243dSDimitry Andric 
90481ad6265SDimitry Andric       for (StringRef Arch : Archs) {
9050fca6ea1SDimitry Andric         if (NVPTXTriple && IsNVIDIAOffloadArch(StringToOffloadArch(
90681ad6265SDimitry Andric                                getProcessorFromTargetID(*NVPTXTriple, Arch)))) {
90781ad6265SDimitry Andric           DerivedArchs[NVPTXTriple->getTriple()].insert(Arch);
90881ad6265SDimitry Andric         } else if (AMDTriple &&
9090fca6ea1SDimitry Andric                    IsAMDOffloadArch(StringToOffloadArch(
91081ad6265SDimitry Andric                        getProcessorFromTargetID(*AMDTriple, Arch)))) {
91181ad6265SDimitry Andric           DerivedArchs[AMDTriple->getTriple()].insert(Arch);
91281ad6265SDimitry Andric         } else {
91381ad6265SDimitry Andric           Diag(clang::diag::err_drv_failed_to_deduce_target_from_arch) << Arch;
91481ad6265SDimitry Andric           return;
91581ad6265SDimitry Andric         }
91681ad6265SDimitry Andric       }
91781ad6265SDimitry Andric 
918bdd1243dSDimitry Andric       // If the set is empty then we failed to find a native architecture.
919bdd1243dSDimitry Andric       if (Archs.empty()) {
920bdd1243dSDimitry Andric         Diag(clang::diag::err_drv_failed_to_deduce_target_from_arch)
921bdd1243dSDimitry Andric             << "native";
922bdd1243dSDimitry Andric         return;
923bdd1243dSDimitry Andric       }
924bdd1243dSDimitry Andric 
92581ad6265SDimitry Andric       for (const auto &TripleAndArchs : DerivedArchs)
92606c3fb27SDimitry Andric         OpenMPTriples.insert(TripleAndArchs.first());
92781ad6265SDimitry Andric     }
92881ad6265SDimitry Andric 
92981ad6265SDimitry Andric     for (StringRef Val : OpenMPTriples) {
9301fd87a68SDimitry Andric       llvm::Triple TT(ToolChain::getOpenMPTriple(Val));
9310b57cec5SDimitry Andric       std::string NormalizedName = TT.normalize();
9320b57cec5SDimitry Andric 
9330b57cec5SDimitry Andric       // Make sure we don't have a duplicate triple.
9340b57cec5SDimitry Andric       auto Duplicate = FoundNormalizedTriples.find(NormalizedName);
9350b57cec5SDimitry Andric       if (Duplicate != FoundNormalizedTriples.end()) {
9360b57cec5SDimitry Andric         Diag(clang::diag::warn_drv_omp_offload_target_duplicate)
9370b57cec5SDimitry Andric             << Val << Duplicate->second;
9380b57cec5SDimitry Andric         continue;
9390b57cec5SDimitry Andric       }
9400b57cec5SDimitry Andric 
9410b57cec5SDimitry Andric       // Store the current triple so that we can check for duplicates in the
9420b57cec5SDimitry Andric       // following iterations.
9430b57cec5SDimitry Andric       FoundNormalizedTriples[NormalizedName] = Val;
9440b57cec5SDimitry Andric 
9450b57cec5SDimitry Andric       // If the specified target is invalid, emit a diagnostic.
9460b57cec5SDimitry Andric       if (TT.getArch() == llvm::Triple::UnknownArch)
9470b57cec5SDimitry Andric         Diag(clang::diag::err_drv_invalid_omp_target) << Val;
9480b57cec5SDimitry Andric       else {
9490b57cec5SDimitry Andric         const ToolChain *TC;
950fe6060f1SDimitry Andric         // Device toolchains have to be selected differently. They pair host
9510b57cec5SDimitry Andric         // and device in their implementation.
952fe6060f1SDimitry Andric         if (TT.isNVPTX() || TT.isAMDGCN()) {
9530b57cec5SDimitry Andric           const ToolChain *HostTC =
9540b57cec5SDimitry Andric               C.getSingleOffloadToolChain<Action::OFK_Host>();
9550b57cec5SDimitry Andric           assert(HostTC && "Host toolchain should be always defined.");
956fe6060f1SDimitry Andric           auto &DeviceTC =
9570b57cec5SDimitry Andric               ToolChains[TT.str() + "/" + HostTC->getTriple().normalize()];
958fe6060f1SDimitry Andric           if (!DeviceTC) {
959fe6060f1SDimitry Andric             if (TT.isNVPTX())
960fe6060f1SDimitry Andric               DeviceTC = std::make_unique<toolchains::CudaToolChain>(
961bdd1243dSDimitry Andric                   *this, TT, *HostTC, C.getInputArgs());
962fe6060f1SDimitry Andric             else if (TT.isAMDGCN())
96381ad6265SDimitry Andric               DeviceTC = std::make_unique<toolchains::AMDGPUOpenMPToolChain>(
964fe6060f1SDimitry Andric                   *this, TT, *HostTC, C.getInputArgs());
965fe6060f1SDimitry Andric             else
966fe6060f1SDimitry Andric               assert(DeviceTC && "Device toolchain not defined.");
967fe6060f1SDimitry Andric           }
968fe6060f1SDimitry Andric 
969fe6060f1SDimitry Andric           TC = DeviceTC.get();
9700b57cec5SDimitry Andric         } else
9710b57cec5SDimitry Andric           TC = &getToolChain(C.getInputArgs(), TT);
9720b57cec5SDimitry Andric         C.addOffloadDeviceToolChain(TC, Action::OFK_OpenMP);
97306c3fb27SDimitry Andric         if (DerivedArchs.contains(TT.getTriple()))
97481ad6265SDimitry Andric           KnownArchs[TC] = DerivedArchs[TT.getTriple()];
9750b57cec5SDimitry Andric       }
9760b57cec5SDimitry Andric     }
97781ad6265SDimitry Andric   } else if (C.getInputArgs().hasArg(options::OPT_fopenmp_targets_EQ)) {
9780b57cec5SDimitry Andric     Diag(clang::diag::err_drv_expecting_fopenmp_with_fopenmp_targets);
97981ad6265SDimitry Andric     return;
9800b57cec5SDimitry Andric   }
9810b57cec5SDimitry Andric 
9820b57cec5SDimitry Andric   //
9830b57cec5SDimitry Andric   // TODO: Add support for other offloading programming models here.
9840b57cec5SDimitry Andric   //
9850b57cec5SDimitry Andric }
9860b57cec5SDimitry Andric 
987bdd1243dSDimitry Andric static void appendOneArg(InputArgList &Args, const Arg *Opt,
988bdd1243dSDimitry Andric                          const Arg *BaseArg) {
989bdd1243dSDimitry Andric   // The args for config files or /clang: flags belong to different InputArgList
990bdd1243dSDimitry Andric   // objects than Args. This copies an Arg from one of those other InputArgLists
991bdd1243dSDimitry Andric   // to the ownership of Args.
992bdd1243dSDimitry Andric   unsigned Index = Args.MakeIndex(Opt->getSpelling());
993bdd1243dSDimitry Andric   Arg *Copy = new llvm::opt::Arg(Opt->getOption(), Args.getArgString(Index),
994bdd1243dSDimitry Andric                                  Index, BaseArg);
995bdd1243dSDimitry Andric   Copy->getValues() = Opt->getValues();
996bdd1243dSDimitry Andric   if (Opt->isClaimed())
997bdd1243dSDimitry Andric     Copy->claim();
998bdd1243dSDimitry Andric   Copy->setOwnsValues(Opt->getOwnsValues());
999bdd1243dSDimitry Andric   Opt->setOwnsValues(false);
1000bdd1243dSDimitry Andric   Args.append(Copy);
10010b57cec5SDimitry Andric }
10020b57cec5SDimitry Andric 
1003bdd1243dSDimitry Andric bool Driver::readConfigFile(StringRef FileName,
1004bdd1243dSDimitry Andric                             llvm::cl::ExpansionContext &ExpCtx) {
1005bdd1243dSDimitry Andric   // Try opening the given file.
1006bdd1243dSDimitry Andric   auto Status = getVFS().status(FileName);
1007bdd1243dSDimitry Andric   if (!Status) {
1008bdd1243dSDimitry Andric     Diag(diag::err_drv_cannot_open_config_file)
1009bdd1243dSDimitry Andric         << FileName << Status.getError().message();
1010bdd1243dSDimitry Andric     return true;
1011bdd1243dSDimitry Andric   }
1012bdd1243dSDimitry Andric   if (Status->getType() != llvm::sys::fs::file_type::regular_file) {
1013bdd1243dSDimitry Andric     Diag(diag::err_drv_cannot_open_config_file)
1014bdd1243dSDimitry Andric         << FileName << "not a regular file";
1015bdd1243dSDimitry Andric     return true;
1016bdd1243dSDimitry Andric   }
1017bdd1243dSDimitry Andric 
10180b57cec5SDimitry Andric   // Try reading the given file.
10190b57cec5SDimitry Andric   SmallVector<const char *, 32> NewCfgArgs;
1020bdd1243dSDimitry Andric   if (llvm::Error Err = ExpCtx.readConfigFile(FileName, NewCfgArgs)) {
1021bdd1243dSDimitry Andric     Diag(diag::err_drv_cannot_read_config_file)
1022bdd1243dSDimitry Andric         << FileName << toString(std::move(Err));
10230b57cec5SDimitry Andric     return true;
10240b57cec5SDimitry Andric   }
10250b57cec5SDimitry Andric 
10260b57cec5SDimitry Andric   // Read options from config file.
10270b57cec5SDimitry Andric   llvm::SmallString<128> CfgFileName(FileName);
10280b57cec5SDimitry Andric   llvm::sys::path::native(CfgFileName);
10290b57cec5SDimitry Andric   bool ContainErrors;
1030bdd1243dSDimitry Andric   std::unique_ptr<InputArgList> NewOptions = std::make_unique<InputArgList>(
10315f757f3fSDimitry Andric       ParseArgStrings(NewCfgArgs, /*UseDriverMode=*/true, ContainErrors));
1032bdd1243dSDimitry Andric   if (ContainErrors)
10330b57cec5SDimitry Andric     return true;
10340b57cec5SDimitry Andric 
10350b57cec5SDimitry Andric   // Claim all arguments that come from a configuration file so that the driver
10360b57cec5SDimitry Andric   // does not warn on any that is unused.
1037bdd1243dSDimitry Andric   for (Arg *A : *NewOptions)
10380b57cec5SDimitry Andric     A->claim();
1039bdd1243dSDimitry Andric 
1040bdd1243dSDimitry Andric   if (!CfgOptions)
1041bdd1243dSDimitry Andric     CfgOptions = std::move(NewOptions);
1042bdd1243dSDimitry Andric   else {
1043bdd1243dSDimitry Andric     // If this is a subsequent config file, append options to the previous one.
1044bdd1243dSDimitry Andric     for (auto *Opt : *NewOptions) {
1045bdd1243dSDimitry Andric       const Arg *BaseArg = &Opt->getBaseArg();
1046bdd1243dSDimitry Andric       if (BaseArg == Opt)
1047bdd1243dSDimitry Andric         BaseArg = nullptr;
1048bdd1243dSDimitry Andric       appendOneArg(*CfgOptions, Opt, BaseArg);
1049bdd1243dSDimitry Andric     }
1050bdd1243dSDimitry Andric   }
1051bdd1243dSDimitry Andric   ConfigFiles.push_back(std::string(CfgFileName));
10520b57cec5SDimitry Andric   return false;
10530b57cec5SDimitry Andric }
10540b57cec5SDimitry Andric 
1055bdd1243dSDimitry Andric bool Driver::loadConfigFiles() {
1056bdd1243dSDimitry Andric   llvm::cl::ExpansionContext ExpCtx(Saver.getAllocator(),
1057bdd1243dSDimitry Andric                                     llvm::cl::tokenizeConfigFile);
1058bdd1243dSDimitry Andric   ExpCtx.setVFS(&getVFS());
10590b57cec5SDimitry Andric 
10600b57cec5SDimitry Andric   // Process options that change search path for config files.
10610b57cec5SDimitry Andric   if (CLOptions) {
10620b57cec5SDimitry Andric     if (CLOptions->hasArg(options::OPT_config_system_dir_EQ)) {
10630b57cec5SDimitry Andric       SmallString<128> CfgDir;
10640b57cec5SDimitry Andric       CfgDir.append(
10650b57cec5SDimitry Andric           CLOptions->getLastArgValue(options::OPT_config_system_dir_EQ));
1066bdd1243dSDimitry Andric       if (CfgDir.empty() || getVFS().makeAbsolute(CfgDir))
10670b57cec5SDimitry Andric         SystemConfigDir.clear();
10680b57cec5SDimitry Andric       else
106981ad6265SDimitry Andric         SystemConfigDir = static_cast<std::string>(CfgDir);
10700b57cec5SDimitry Andric     }
10710b57cec5SDimitry Andric     if (CLOptions->hasArg(options::OPT_config_user_dir_EQ)) {
10720b57cec5SDimitry Andric       SmallString<128> CfgDir;
1073bdd1243dSDimitry Andric       llvm::sys::fs::expand_tilde(
1074bdd1243dSDimitry Andric           CLOptions->getLastArgValue(options::OPT_config_user_dir_EQ), CfgDir);
1075bdd1243dSDimitry Andric       if (CfgDir.empty() || getVFS().makeAbsolute(CfgDir))
10760b57cec5SDimitry Andric         UserConfigDir.clear();
10770b57cec5SDimitry Andric       else
107881ad6265SDimitry Andric         UserConfigDir = static_cast<std::string>(CfgDir);
10790b57cec5SDimitry Andric     }
10800b57cec5SDimitry Andric   }
10810b57cec5SDimitry Andric 
10820b57cec5SDimitry Andric   // Prepare list of directories where config file is searched for.
1083e8d8bef9SDimitry Andric   StringRef CfgFileSearchDirs[] = {UserConfigDir, SystemConfigDir, Dir};
1084bdd1243dSDimitry Andric   ExpCtx.setSearchDirs(CfgFileSearchDirs);
10850b57cec5SDimitry Andric 
1086bdd1243dSDimitry Andric   // First try to load configuration from the default files, return on error.
1087bdd1243dSDimitry Andric   if (loadDefaultConfigFiles(ExpCtx))
1088bdd1243dSDimitry Andric     return true;
1089bdd1243dSDimitry Andric 
1090bdd1243dSDimitry Andric   // Then load configuration files specified explicitly.
1091bdd1243dSDimitry Andric   SmallString<128> CfgFilePath;
1092bdd1243dSDimitry Andric   if (CLOptions) {
1093bdd1243dSDimitry Andric     for (auto CfgFileName : CLOptions->getAllArgValues(options::OPT_config)) {
1094bdd1243dSDimitry Andric       // If argument contains directory separator, treat it as a path to
1095bdd1243dSDimitry Andric       // configuration file.
1096bdd1243dSDimitry Andric       if (llvm::sys::path::has_parent_path(CfgFileName)) {
1097bdd1243dSDimitry Andric         CfgFilePath.assign(CfgFileName);
1098bdd1243dSDimitry Andric         if (llvm::sys::path::is_relative(CfgFilePath)) {
1099bdd1243dSDimitry Andric           if (getVFS().makeAbsolute(CfgFilePath)) {
1100bdd1243dSDimitry Andric             Diag(diag::err_drv_cannot_open_config_file)
1101bdd1243dSDimitry Andric                 << CfgFilePath << "cannot get absolute path";
1102bdd1243dSDimitry Andric             return true;
11030b57cec5SDimitry Andric           }
11040b57cec5SDimitry Andric         }
1105bdd1243dSDimitry Andric       } else if (!ExpCtx.findConfigFile(CfgFileName, CfgFilePath)) {
1106bdd1243dSDimitry Andric         // Report an error that the config file could not be found.
11070b57cec5SDimitry Andric         Diag(diag::err_drv_config_file_not_found) << CfgFileName;
1108e8d8bef9SDimitry Andric         for (const StringRef &SearchDir : CfgFileSearchDirs)
11090b57cec5SDimitry Andric           if (!SearchDir.empty())
11100b57cec5SDimitry Andric             Diag(diag::note_drv_config_file_searched_in) << SearchDir;
11110b57cec5SDimitry Andric         return true;
11120b57cec5SDimitry Andric       }
11130b57cec5SDimitry Andric 
1114bdd1243dSDimitry Andric       // Try to read the config file, return on error.
1115bdd1243dSDimitry Andric       if (readConfigFile(CfgFilePath, ExpCtx))
1116bdd1243dSDimitry Andric         return true;
1117bdd1243dSDimitry Andric     }
1118bdd1243dSDimitry Andric   }
1119bdd1243dSDimitry Andric 
1120bdd1243dSDimitry Andric   // No error occurred.
1121bdd1243dSDimitry Andric   return false;
1122bdd1243dSDimitry Andric }
1123bdd1243dSDimitry Andric 
1124bdd1243dSDimitry Andric bool Driver::loadDefaultConfigFiles(llvm::cl::ExpansionContext &ExpCtx) {
1125bdd1243dSDimitry Andric   // Disable default config if CLANG_NO_DEFAULT_CONFIG is set to a non-empty
1126bdd1243dSDimitry Andric   // value.
1127bdd1243dSDimitry Andric   if (const char *NoConfigEnv = ::getenv("CLANG_NO_DEFAULT_CONFIG")) {
1128bdd1243dSDimitry Andric     if (*NoConfigEnv)
1129bdd1243dSDimitry Andric       return false;
1130bdd1243dSDimitry Andric   }
1131bdd1243dSDimitry Andric   if (CLOptions && CLOptions->hasArg(options::OPT_no_default_config))
1132bdd1243dSDimitry Andric     return false;
1133bdd1243dSDimitry Andric 
1134bdd1243dSDimitry Andric   std::string RealMode = getExecutableForDriverMode(Mode);
1135bdd1243dSDimitry Andric   std::string Triple;
1136bdd1243dSDimitry Andric 
1137bdd1243dSDimitry Andric   // If name prefix is present, no --target= override was passed via CLOptions
1138bdd1243dSDimitry Andric   // and the name prefix is not a valid triple, force it for backwards
1139bdd1243dSDimitry Andric   // compatibility.
1140bdd1243dSDimitry Andric   if (!ClangNameParts.TargetPrefix.empty() &&
1141bdd1243dSDimitry Andric       computeTargetTriple(*this, "/invalid/", *CLOptions).str() ==
1142bdd1243dSDimitry Andric           "/invalid/") {
1143bdd1243dSDimitry Andric     llvm::Triple PrefixTriple{ClangNameParts.TargetPrefix};
1144bdd1243dSDimitry Andric     if (PrefixTriple.getArch() == llvm::Triple::UnknownArch ||
1145bdd1243dSDimitry Andric         PrefixTriple.isOSUnknown())
1146bdd1243dSDimitry Andric       Triple = PrefixTriple.str();
1147bdd1243dSDimitry Andric   }
1148bdd1243dSDimitry Andric 
1149bdd1243dSDimitry Andric   // Otherwise, use the real triple as used by the driver.
1150bdd1243dSDimitry Andric   if (Triple.empty()) {
1151bdd1243dSDimitry Andric     llvm::Triple RealTriple =
1152bdd1243dSDimitry Andric         computeTargetTriple(*this, TargetTriple, *CLOptions);
1153bdd1243dSDimitry Andric     Triple = RealTriple.str();
1154bdd1243dSDimitry Andric     assert(!Triple.empty());
1155bdd1243dSDimitry Andric   }
1156bdd1243dSDimitry Andric 
1157bdd1243dSDimitry Andric   // Search for config files in the following order:
1158bdd1243dSDimitry Andric   // 1. <triple>-<mode>.cfg using real driver mode
1159bdd1243dSDimitry Andric   //    (e.g. i386-pc-linux-gnu-clang++.cfg).
1160bdd1243dSDimitry Andric   // 2. <triple>-<mode>.cfg using executable suffix
1161bdd1243dSDimitry Andric   //    (e.g. i386-pc-linux-gnu-clang-g++.cfg for *clang-g++).
1162bdd1243dSDimitry Andric   // 3. <triple>.cfg + <mode>.cfg using real driver mode
1163bdd1243dSDimitry Andric   //    (e.g. i386-pc-linux-gnu.cfg + clang++.cfg).
1164bdd1243dSDimitry Andric   // 4. <triple>.cfg + <mode>.cfg using executable suffix
1165bdd1243dSDimitry Andric   //    (e.g. i386-pc-linux-gnu.cfg + clang-g++.cfg for *clang-g++).
1166bdd1243dSDimitry Andric 
1167bdd1243dSDimitry Andric   // Try loading <triple>-<mode>.cfg, and return if we find a match.
1168bdd1243dSDimitry Andric   SmallString<128> CfgFilePath;
1169bdd1243dSDimitry Andric   std::string CfgFileName = Triple + '-' + RealMode + ".cfg";
1170bdd1243dSDimitry Andric   if (ExpCtx.findConfigFile(CfgFileName, CfgFilePath))
1171bdd1243dSDimitry Andric     return readConfigFile(CfgFilePath, ExpCtx);
1172bdd1243dSDimitry Andric 
1173bdd1243dSDimitry Andric   bool TryModeSuffix = !ClangNameParts.ModeSuffix.empty() &&
1174bdd1243dSDimitry Andric                        ClangNameParts.ModeSuffix != RealMode;
1175bdd1243dSDimitry Andric   if (TryModeSuffix) {
1176bdd1243dSDimitry Andric     CfgFileName = Triple + '-' + ClangNameParts.ModeSuffix + ".cfg";
1177bdd1243dSDimitry Andric     if (ExpCtx.findConfigFile(CfgFileName, CfgFilePath))
1178bdd1243dSDimitry Andric       return readConfigFile(CfgFilePath, ExpCtx);
1179bdd1243dSDimitry Andric   }
1180bdd1243dSDimitry Andric 
1181bdd1243dSDimitry Andric   // Try loading <mode>.cfg, and return if loading failed.  If a matching file
1182bdd1243dSDimitry Andric   // was not found, still proceed on to try <triple>.cfg.
1183bdd1243dSDimitry Andric   CfgFileName = RealMode + ".cfg";
1184bdd1243dSDimitry Andric   if (ExpCtx.findConfigFile(CfgFileName, CfgFilePath)) {
1185bdd1243dSDimitry Andric     if (readConfigFile(CfgFilePath, ExpCtx))
1186bdd1243dSDimitry Andric       return true;
1187bdd1243dSDimitry Andric   } else if (TryModeSuffix) {
1188bdd1243dSDimitry Andric     CfgFileName = ClangNameParts.ModeSuffix + ".cfg";
1189bdd1243dSDimitry Andric     if (ExpCtx.findConfigFile(CfgFileName, CfgFilePath) &&
1190bdd1243dSDimitry Andric         readConfigFile(CfgFilePath, ExpCtx))
1191bdd1243dSDimitry Andric       return true;
1192bdd1243dSDimitry Andric   }
1193bdd1243dSDimitry Andric 
1194bdd1243dSDimitry Andric   // Try loading <triple>.cfg and return if we find a match.
1195bdd1243dSDimitry Andric   CfgFileName = Triple + ".cfg";
1196bdd1243dSDimitry Andric   if (ExpCtx.findConfigFile(CfgFileName, CfgFilePath))
1197bdd1243dSDimitry Andric     return readConfigFile(CfgFilePath, ExpCtx);
1198bdd1243dSDimitry Andric 
1199bdd1243dSDimitry Andric   // If we were unable to find a config file deduced from executable name,
1200bdd1243dSDimitry Andric   // that is not an error.
12010b57cec5SDimitry Andric   return false;
12020b57cec5SDimitry Andric }
12030b57cec5SDimitry Andric 
12040b57cec5SDimitry Andric Compilation *Driver::BuildCompilation(ArrayRef<const char *> ArgList) {
12050b57cec5SDimitry Andric   llvm::PrettyStackTraceString CrashInfo("Compilation construction");
12060b57cec5SDimitry Andric 
12070b57cec5SDimitry Andric   // FIXME: Handle environment options which affect driver behavior, somewhere
12080b57cec5SDimitry Andric   // (client?). GCC_EXEC_PREFIX, LPATH, CC_PRINT_OPTIONS.
12090b57cec5SDimitry Andric 
12100b57cec5SDimitry Andric   // We look for the driver mode option early, because the mode can affect
12110b57cec5SDimitry Andric   // how other options are parsed.
1212fe6060f1SDimitry Andric 
1213fe6060f1SDimitry Andric   auto DriverMode = getDriverMode(ClangExecutable, ArgList.slice(1));
1214fe6060f1SDimitry Andric   if (!DriverMode.empty())
1215fe6060f1SDimitry Andric     setDriverMode(DriverMode);
12160b57cec5SDimitry Andric 
12170b57cec5SDimitry Andric   // FIXME: What are we going to do with -V and -b?
12180b57cec5SDimitry Andric 
12190b57cec5SDimitry Andric   // Arguments specified in command line.
12200b57cec5SDimitry Andric   bool ContainsError;
1221a7dea167SDimitry Andric   CLOptions = std::make_unique<InputArgList>(
12225f757f3fSDimitry Andric       ParseArgStrings(ArgList.slice(1), /*UseDriverMode=*/true, ContainsError));
12230b57cec5SDimitry Andric 
12240b57cec5SDimitry Andric   // Try parsing configuration file.
12250b57cec5SDimitry Andric   if (!ContainsError)
1226bdd1243dSDimitry Andric     ContainsError = loadConfigFiles();
12270b57cec5SDimitry Andric   bool HasConfigFile = !ContainsError && (CfgOptions.get() != nullptr);
12280b57cec5SDimitry Andric 
12290b57cec5SDimitry Andric   // All arguments, from both config file and command line.
12300b57cec5SDimitry Andric   InputArgList Args = std::move(HasConfigFile ? std::move(*CfgOptions)
12310b57cec5SDimitry Andric                                               : std::move(*CLOptions));
12320b57cec5SDimitry Andric 
12330b57cec5SDimitry Andric   if (HasConfigFile)
12340b57cec5SDimitry Andric     for (auto *Opt : *CLOptions) {
12350b57cec5SDimitry Andric       if (Opt->getOption().matches(options::OPT_config))
12360b57cec5SDimitry Andric         continue;
12370b57cec5SDimitry Andric       const Arg *BaseArg = &Opt->getBaseArg();
12380b57cec5SDimitry Andric       if (BaseArg == Opt)
12390b57cec5SDimitry Andric         BaseArg = nullptr;
1240bdd1243dSDimitry Andric       appendOneArg(Args, Opt, BaseArg);
12410b57cec5SDimitry Andric     }
12420b57cec5SDimitry Andric 
12430b57cec5SDimitry Andric   // In CL mode, look for any pass-through arguments
12440b57cec5SDimitry Andric   if (IsCLMode() && !ContainsError) {
12450b57cec5SDimitry Andric     SmallVector<const char *, 16> CLModePassThroughArgList;
12460b57cec5SDimitry Andric     for (const auto *A : Args.filtered(options::OPT__SLASH_clang)) {
12470b57cec5SDimitry Andric       A->claim();
12480b57cec5SDimitry Andric       CLModePassThroughArgList.push_back(A->getValue());
12490b57cec5SDimitry Andric     }
12500b57cec5SDimitry Andric 
12510b57cec5SDimitry Andric     if (!CLModePassThroughArgList.empty()) {
12520b57cec5SDimitry Andric       // Parse any pass through args using default clang processing rather
12530b57cec5SDimitry Andric       // than clang-cl processing.
1254a7dea167SDimitry Andric       auto CLModePassThroughOptions = std::make_unique<InputArgList>(
12555f757f3fSDimitry Andric           ParseArgStrings(CLModePassThroughArgList, /*UseDriverMode=*/false,
12565f757f3fSDimitry Andric                           ContainsError));
12570b57cec5SDimitry Andric 
12580b57cec5SDimitry Andric       if (!ContainsError)
12590b57cec5SDimitry Andric         for (auto *Opt : *CLModePassThroughOptions) {
1260bdd1243dSDimitry Andric           appendOneArg(Args, Opt, nullptr);
12610b57cec5SDimitry Andric         }
12620b57cec5SDimitry Andric     }
12630b57cec5SDimitry Andric   }
12640b57cec5SDimitry Andric 
1265480093f4SDimitry Andric   // Check for working directory option before accessing any files
1266480093f4SDimitry Andric   if (Arg *WD = Args.getLastArg(options::OPT_working_directory))
1267480093f4SDimitry Andric     if (VFS->setCurrentWorkingDirectory(WD->getValue()))
1268480093f4SDimitry Andric       Diag(diag::err_drv_unable_to_set_working_directory) << WD->getValue();
1269480093f4SDimitry Andric 
12700fca6ea1SDimitry Andric   // Check for missing include directories.
12710fca6ea1SDimitry Andric   if (!Diags.isIgnored(diag::warn_missing_include_dirs, SourceLocation())) {
12720fca6ea1SDimitry Andric     for (auto IncludeDir : Args.getAllArgValues(options::OPT_I_Group)) {
12730fca6ea1SDimitry Andric       if (!VFS->exists(IncludeDir))
12740fca6ea1SDimitry Andric         Diag(diag::warn_missing_include_dirs) << IncludeDir;
12750fca6ea1SDimitry Andric     }
12760fca6ea1SDimitry Andric   }
12770fca6ea1SDimitry Andric 
12780b57cec5SDimitry Andric   // FIXME: This stuff needs to go into the Compilation, not the driver.
12790b57cec5SDimitry Andric   bool CCCPrintPhases;
12800b57cec5SDimitry Andric 
1281349cc55cSDimitry Andric   // -canonical-prefixes, -no-canonical-prefixes are used very early in main.
1282349cc55cSDimitry Andric   Args.ClaimAllArgs(options::OPT_canonical_prefixes);
12830b57cec5SDimitry Andric   Args.ClaimAllArgs(options::OPT_no_canonical_prefixes);
12840b57cec5SDimitry Andric 
128565286350SDimitry Andric   // f(no-)integated-cc1 is also used very early in main.
128665286350SDimitry Andric   Args.ClaimAllArgs(options::OPT_fintegrated_cc1);
128765286350SDimitry Andric   Args.ClaimAllArgs(options::OPT_fno_integrated_cc1);
128865286350SDimitry Andric 
12890b57cec5SDimitry Andric   // Ignore -pipe.
12900b57cec5SDimitry Andric   Args.ClaimAllArgs(options::OPT_pipe);
12910b57cec5SDimitry Andric 
12920b57cec5SDimitry Andric   // Extract -ccc args.
12930b57cec5SDimitry Andric   //
12940b57cec5SDimitry Andric   // FIXME: We need to figure out where this behavior should live. Most of it
12950b57cec5SDimitry Andric   // should be outside in the client; the parts that aren't should have proper
12960b57cec5SDimitry Andric   // options, either by introducing new ones or by overloading gcc ones like -V
12970b57cec5SDimitry Andric   // or -b.
12980b57cec5SDimitry Andric   CCCPrintPhases = Args.hasArg(options::OPT_ccc_print_phases);
12990b57cec5SDimitry Andric   CCCPrintBindings = Args.hasArg(options::OPT_ccc_print_bindings);
13000b57cec5SDimitry Andric   if (const Arg *A = Args.getLastArg(options::OPT_ccc_gcc_name))
13010b57cec5SDimitry Andric     CCCGenericGCCName = A->getValue();
1302fe6060f1SDimitry Andric 
1303fe6060f1SDimitry Andric   // Process -fproc-stat-report options.
1304fe6060f1SDimitry Andric   if (const Arg *A = Args.getLastArg(options::OPT_fproc_stat_report_EQ)) {
1305fe6060f1SDimitry Andric     CCPrintProcessStats = true;
1306fe6060f1SDimitry Andric     CCPrintStatReportFilename = A->getValue();
1307fe6060f1SDimitry Andric   }
1308fe6060f1SDimitry Andric   if (Args.hasArg(options::OPT_fproc_stat_report))
1309fe6060f1SDimitry Andric     CCPrintProcessStats = true;
1310fe6060f1SDimitry Andric 
13110b57cec5SDimitry Andric   // FIXME: TargetTriple is used by the target-prefixed calls to as/ld
13120b57cec5SDimitry Andric   // and getToolChain is const.
13130b57cec5SDimitry Andric   if (IsCLMode()) {
13140b57cec5SDimitry Andric     // clang-cl targets MSVC-style Win32.
13150b57cec5SDimitry Andric     llvm::Triple T(TargetTriple);
13160b57cec5SDimitry Andric     T.setOS(llvm::Triple::Win32);
13170b57cec5SDimitry Andric     T.setVendor(llvm::Triple::PC);
13180b57cec5SDimitry Andric     T.setEnvironment(llvm::Triple::MSVC);
13190b57cec5SDimitry Andric     T.setObjectFormat(llvm::Triple::COFF);
1320bdd1243dSDimitry Andric     if (Args.hasArg(options::OPT__SLASH_arm64EC))
1321bdd1243dSDimitry Andric       T.setArch(llvm::Triple::aarch64, llvm::Triple::AArch64SubArch_arm64ec);
13220b57cec5SDimitry Andric     TargetTriple = T.str();
132381ad6265SDimitry Andric   } else if (IsDXCMode()) {
132481ad6265SDimitry Andric     // Build TargetTriple from target_profile option for clang-dxc.
132581ad6265SDimitry Andric     if (const Arg *A = Args.getLastArg(options::OPT_target_profile)) {
132681ad6265SDimitry Andric       StringRef TargetProfile = A->getValue();
132781ad6265SDimitry Andric       if (auto Triple =
132881ad6265SDimitry Andric               toolchains::HLSLToolChain::parseTargetProfile(TargetProfile))
132981ad6265SDimitry Andric         TargetTriple = *Triple;
133081ad6265SDimitry Andric       else
133181ad6265SDimitry Andric         Diag(diag::err_drv_invalid_directx_shader_module) << TargetProfile;
133281ad6265SDimitry Andric 
133381ad6265SDimitry Andric       A->claim();
13345f757f3fSDimitry Andric 
13355f757f3fSDimitry Andric       if (Args.hasArg(options::OPT_spirv)) {
13365f757f3fSDimitry Andric         llvm::Triple T(TargetTriple);
13375f757f3fSDimitry Andric         T.setArch(llvm::Triple::spirv);
13387a6dacacSDimitry Andric         T.setOS(llvm::Triple::Vulkan);
13397a6dacacSDimitry Andric 
13407a6dacacSDimitry Andric         // Set specific Vulkan version if applicable.
13417a6dacacSDimitry Andric         if (const Arg *A = Args.getLastArg(options::OPT_fspv_target_env_EQ)) {
13427a6dacacSDimitry Andric           const llvm::StringSet<> ValidValues = {"vulkan1.2", "vulkan1.3"};
13437a6dacacSDimitry Andric           if (ValidValues.contains(A->getValue())) {
13447a6dacacSDimitry Andric             T.setOSName(A->getValue());
13457a6dacacSDimitry Andric           } else {
13467a6dacacSDimitry Andric             Diag(diag::err_drv_invalid_value)
13477a6dacacSDimitry Andric                 << A->getAsString(Args) << A->getValue();
13487a6dacacSDimitry Andric           }
13497a6dacacSDimitry Andric           A->claim();
13507a6dacacSDimitry Andric         }
13517a6dacacSDimitry Andric 
13525f757f3fSDimitry Andric         TargetTriple = T.str();
13535f757f3fSDimitry Andric       }
135481ad6265SDimitry Andric     } else {
135581ad6265SDimitry Andric       Diag(diag::err_drv_dxc_missing_target_profile);
13560b57cec5SDimitry Andric     }
135781ad6265SDimitry Andric   }
135881ad6265SDimitry Andric 
13590b57cec5SDimitry Andric   if (const Arg *A = Args.getLastArg(options::OPT_target))
13600b57cec5SDimitry Andric     TargetTriple = A->getValue();
13610b57cec5SDimitry Andric   if (const Arg *A = Args.getLastArg(options::OPT_ccc_install_dir))
13620fca6ea1SDimitry Andric     Dir = Dir = A->getValue();
13630b57cec5SDimitry Andric   for (const Arg *A : Args.filtered(options::OPT_B)) {
13640b57cec5SDimitry Andric     A->claim();
13650b57cec5SDimitry Andric     PrefixDirs.push_back(A->getValue(0));
13660b57cec5SDimitry Andric   }
1367bdd1243dSDimitry Andric   if (std::optional<std::string> CompilerPathValue =
1368e8d8bef9SDimitry Andric           llvm::sys::Process::GetEnv("COMPILER_PATH")) {
1369e8d8bef9SDimitry Andric     StringRef CompilerPath = *CompilerPathValue;
1370e8d8bef9SDimitry Andric     while (!CompilerPath.empty()) {
1371e8d8bef9SDimitry Andric       std::pair<StringRef, StringRef> Split =
1372e8d8bef9SDimitry Andric           CompilerPath.split(llvm::sys::EnvPathSeparator);
1373e8d8bef9SDimitry Andric       PrefixDirs.push_back(std::string(Split.first));
1374e8d8bef9SDimitry Andric       CompilerPath = Split.second;
1375e8d8bef9SDimitry Andric     }
1376e8d8bef9SDimitry Andric   }
13770b57cec5SDimitry Andric   if (const Arg *A = Args.getLastArg(options::OPT__sysroot_EQ))
13780b57cec5SDimitry Andric     SysRoot = A->getValue();
13790b57cec5SDimitry Andric   if (const Arg *A = Args.getLastArg(options::OPT__dyld_prefix_EQ))
13800b57cec5SDimitry Andric     DyldPrefix = A->getValue();
13810b57cec5SDimitry Andric 
13820b57cec5SDimitry Andric   if (const Arg *A = Args.getLastArg(options::OPT_resource_dir))
13830b57cec5SDimitry Andric     ResourceDir = A->getValue();
13840b57cec5SDimitry Andric 
13850b57cec5SDimitry Andric   if (const Arg *A = Args.getLastArg(options::OPT_save_temps_EQ)) {
13860b57cec5SDimitry Andric     SaveTemps = llvm::StringSwitch<SaveTempsMode>(A->getValue())
13870b57cec5SDimitry Andric                     .Case("cwd", SaveTempsCwd)
13880b57cec5SDimitry Andric                     .Case("obj", SaveTempsObj)
13890b57cec5SDimitry Andric                     .Default(SaveTempsCwd);
13900b57cec5SDimitry Andric   }
13910b57cec5SDimitry Andric 
139281ad6265SDimitry Andric   if (const Arg *A = Args.getLastArg(options::OPT_offload_host_only,
139381ad6265SDimitry Andric                                      options::OPT_offload_device_only,
139481ad6265SDimitry Andric                                      options::OPT_offload_host_device)) {
139581ad6265SDimitry Andric     if (A->getOption().matches(options::OPT_offload_host_only))
139681ad6265SDimitry Andric       Offload = OffloadHost;
139781ad6265SDimitry Andric     else if (A->getOption().matches(options::OPT_offload_device_only))
139881ad6265SDimitry Andric       Offload = OffloadDevice;
139981ad6265SDimitry Andric     else
140081ad6265SDimitry Andric       Offload = OffloadHostDevice;
140181ad6265SDimitry Andric   }
140281ad6265SDimitry Andric 
14030b57cec5SDimitry Andric   setLTOMode(Args);
14040b57cec5SDimitry Andric 
14050b57cec5SDimitry Andric   // Process -fembed-bitcode= flags.
14060b57cec5SDimitry Andric   if (Arg *A = Args.getLastArg(options::OPT_fembed_bitcode_EQ)) {
14070b57cec5SDimitry Andric     StringRef Name = A->getValue();
14080b57cec5SDimitry Andric     unsigned Model = llvm::StringSwitch<unsigned>(Name)
14090b57cec5SDimitry Andric         .Case("off", EmbedNone)
14100b57cec5SDimitry Andric         .Case("all", EmbedBitcode)
14110b57cec5SDimitry Andric         .Case("bitcode", EmbedBitcode)
14120b57cec5SDimitry Andric         .Case("marker", EmbedMarker)
14130b57cec5SDimitry Andric         .Default(~0U);
14140b57cec5SDimitry Andric     if (Model == ~0U) {
14150b57cec5SDimitry Andric       Diags.Report(diag::err_drv_invalid_value) << A->getAsString(Args)
14160b57cec5SDimitry Andric                                                 << Name;
14170b57cec5SDimitry Andric     } else
14180b57cec5SDimitry Andric       BitcodeEmbed = static_cast<BitcodeEmbedMode>(Model);
14190b57cec5SDimitry Andric   }
14200b57cec5SDimitry Andric 
142181ad6265SDimitry Andric   // Remove existing compilation database so that each job can append to it.
142281ad6265SDimitry Andric   if (Arg *A = Args.getLastArg(options::OPT_MJ))
142381ad6265SDimitry Andric     llvm::sys::fs::remove(A->getValue());
142481ad6265SDimitry Andric 
142581ad6265SDimitry Andric   // Setting up the jobs for some precompile cases depends on whether we are
142681ad6265SDimitry Andric   // treating them as PCH, implicit modules or C++20 ones.
142781ad6265SDimitry Andric   // TODO: inferring the mode like this seems fragile (it meets the objective
142881ad6265SDimitry Andric   // of not requiring anything new for operation, however).
142981ad6265SDimitry Andric   const Arg *Std = Args.getLastArg(options::OPT_std_EQ);
143081ad6265SDimitry Andric   ModulesModeCXX20 =
143181ad6265SDimitry Andric       !Args.hasArg(options::OPT_fmodules) && Std &&
143206c3fb27SDimitry Andric       (Std->containsValue("c++20") || Std->containsValue("c++2a") ||
143306c3fb27SDimitry Andric        Std->containsValue("c++23") || Std->containsValue("c++2b") ||
143406c3fb27SDimitry Andric        Std->containsValue("c++26") || Std->containsValue("c++2c") ||
143506c3fb27SDimitry Andric        Std->containsValue("c++latest"));
143681ad6265SDimitry Andric 
143781ad6265SDimitry Andric   // Process -fmodule-header{=} flags.
143881ad6265SDimitry Andric   if (Arg *A = Args.getLastArg(options::OPT_fmodule_header_EQ,
143981ad6265SDimitry Andric                                options::OPT_fmodule_header)) {
144081ad6265SDimitry Andric     // These flags force C++20 handling of headers.
144181ad6265SDimitry Andric     ModulesModeCXX20 = true;
144281ad6265SDimitry Andric     if (A->getOption().matches(options::OPT_fmodule_header))
144381ad6265SDimitry Andric       CXX20HeaderType = HeaderMode_Default;
144481ad6265SDimitry Andric     else {
144581ad6265SDimitry Andric       StringRef ArgName = A->getValue();
144681ad6265SDimitry Andric       unsigned Kind = llvm::StringSwitch<unsigned>(ArgName)
144781ad6265SDimitry Andric                           .Case("user", HeaderMode_User)
144881ad6265SDimitry Andric                           .Case("system", HeaderMode_System)
144981ad6265SDimitry Andric                           .Default(~0U);
145081ad6265SDimitry Andric       if (Kind == ~0U) {
145181ad6265SDimitry Andric         Diags.Report(diag::err_drv_invalid_value)
145281ad6265SDimitry Andric             << A->getAsString(Args) << ArgName;
145381ad6265SDimitry Andric       } else
145481ad6265SDimitry Andric         CXX20HeaderType = static_cast<ModuleHeaderMode>(Kind);
145581ad6265SDimitry Andric     }
145681ad6265SDimitry Andric   }
145781ad6265SDimitry Andric 
14580b57cec5SDimitry Andric   std::unique_ptr<llvm::opt::InputArgList> UArgs =
1459a7dea167SDimitry Andric       std::make_unique<InputArgList>(std::move(Args));
14600b57cec5SDimitry Andric 
14610b57cec5SDimitry Andric   // Perform the default argument translations.
14620b57cec5SDimitry Andric   DerivedArgList *TranslatedArgs = TranslateInputArgs(*UArgs);
14630b57cec5SDimitry Andric 
14640b57cec5SDimitry Andric   // Owned by the host.
14650b57cec5SDimitry Andric   const ToolChain &TC = getToolChain(
14660b57cec5SDimitry Andric       *UArgs, computeTargetTriple(*this, TargetTriple, *UArgs));
14670b57cec5SDimitry Andric 
14680fca6ea1SDimitry Andric   // Check if the environment version is valid except wasm case.
14691db9f3b2SDimitry Andric   llvm::Triple Triple = TC.getTriple();
14700fca6ea1SDimitry Andric   if (!Triple.isWasm()) {
14711db9f3b2SDimitry Andric     StringRef TripleVersionName = Triple.getEnvironmentVersionString();
14720fca6ea1SDimitry Andric     StringRef TripleObjectFormat =
14730fca6ea1SDimitry Andric         Triple.getObjectFormatTypeName(Triple.getObjectFormat());
14740fca6ea1SDimitry Andric     if (Triple.getEnvironmentVersion().empty() && TripleVersionName != "" &&
14750fca6ea1SDimitry Andric         TripleVersionName != TripleObjectFormat) {
14761db9f3b2SDimitry Andric       Diags.Report(diag::err_drv_triple_version_invalid)
14771db9f3b2SDimitry Andric           << TripleVersionName << TC.getTripleString();
14781db9f3b2SDimitry Andric       ContainsError = true;
14791db9f3b2SDimitry Andric     }
14801db9f3b2SDimitry Andric   }
14811db9f3b2SDimitry Andric 
1482bdd1243dSDimitry Andric   // Report warning when arm64EC option is overridden by specified target
1483bdd1243dSDimitry Andric   if ((TC.getTriple().getArch() != llvm::Triple::aarch64 ||
1484bdd1243dSDimitry Andric        TC.getTriple().getSubArch() != llvm::Triple::AArch64SubArch_arm64ec) &&
1485bdd1243dSDimitry Andric       UArgs->hasArg(options::OPT__SLASH_arm64EC)) {
1486bdd1243dSDimitry Andric     getDiags().Report(clang::diag::warn_target_override_arm64ec)
1487bdd1243dSDimitry Andric         << TC.getTriple().str();
1488bdd1243dSDimitry Andric   }
1489bdd1243dSDimitry Andric 
149006c3fb27SDimitry Andric   // A common user mistake is specifying a target of aarch64-none-eabi or
149106c3fb27SDimitry Andric   // arm-none-elf whereas the correct names are aarch64-none-elf &
149206c3fb27SDimitry Andric   // arm-none-eabi. Detect these cases and issue a warning.
149306c3fb27SDimitry Andric   if (TC.getTriple().getOS() == llvm::Triple::UnknownOS &&
149406c3fb27SDimitry Andric       TC.getTriple().getVendor() == llvm::Triple::UnknownVendor) {
149506c3fb27SDimitry Andric     switch (TC.getTriple().getArch()) {
149606c3fb27SDimitry Andric     case llvm::Triple::arm:
149706c3fb27SDimitry Andric     case llvm::Triple::armeb:
149806c3fb27SDimitry Andric     case llvm::Triple::thumb:
149906c3fb27SDimitry Andric     case llvm::Triple::thumbeb:
150006c3fb27SDimitry Andric       if (TC.getTriple().getEnvironmentName() == "elf") {
150106c3fb27SDimitry Andric         Diag(diag::warn_target_unrecognized_env)
150206c3fb27SDimitry Andric             << TargetTriple
150306c3fb27SDimitry Andric             << (TC.getTriple().getArchName().str() + "-none-eabi");
150406c3fb27SDimitry Andric       }
150506c3fb27SDimitry Andric       break;
150606c3fb27SDimitry Andric     case llvm::Triple::aarch64:
150706c3fb27SDimitry Andric     case llvm::Triple::aarch64_be:
150806c3fb27SDimitry Andric     case llvm::Triple::aarch64_32:
15095f757f3fSDimitry Andric       if (TC.getTriple().getEnvironmentName().starts_with("eabi")) {
151006c3fb27SDimitry Andric         Diag(diag::warn_target_unrecognized_env)
151106c3fb27SDimitry Andric             << TargetTriple
151206c3fb27SDimitry Andric             << (TC.getTriple().getArchName().str() + "-none-elf");
151306c3fb27SDimitry Andric       }
151406c3fb27SDimitry Andric       break;
151506c3fb27SDimitry Andric     default:
151606c3fb27SDimitry Andric       break;
151706c3fb27SDimitry Andric     }
151806c3fb27SDimitry Andric   }
151906c3fb27SDimitry Andric 
15200b57cec5SDimitry Andric   // The compilation takes ownership of Args.
15210b57cec5SDimitry Andric   Compilation *C = new Compilation(*this, TC, UArgs.release(), TranslatedArgs,
15220b57cec5SDimitry Andric                                    ContainsError);
15230b57cec5SDimitry Andric 
15240b57cec5SDimitry Andric   if (!HandleImmediateArgs(*C))
15250b57cec5SDimitry Andric     return C;
15260b57cec5SDimitry Andric 
15270b57cec5SDimitry Andric   // Construct the list of inputs.
15280b57cec5SDimitry Andric   InputList Inputs;
15290b57cec5SDimitry Andric   BuildInputs(C->getDefaultToolChain(), *TranslatedArgs, Inputs);
15300b57cec5SDimitry Andric 
15310b57cec5SDimitry Andric   // Populate the tool chains for the offloading devices, if any.
15320b57cec5SDimitry Andric   CreateOffloadingDeviceToolChains(*C, Inputs);
15330b57cec5SDimitry Andric 
15340b57cec5SDimitry Andric   // Construct the list of abstract actions to perform for this compilation. On
15350b57cec5SDimitry Andric   // MachO targets this uses the driver-driver and universal actions.
15360b57cec5SDimitry Andric   if (TC.getTriple().isOSBinFormatMachO())
15370b57cec5SDimitry Andric     BuildUniversalActions(*C, C->getDefaultToolChain(), Inputs);
15380b57cec5SDimitry Andric   else
15390b57cec5SDimitry Andric     BuildActions(*C, C->getArgs(), Inputs, C->getActions());
15400b57cec5SDimitry Andric 
15410b57cec5SDimitry Andric   if (CCCPrintPhases) {
15420b57cec5SDimitry Andric     PrintActions(*C);
15430b57cec5SDimitry Andric     return C;
15440b57cec5SDimitry Andric   }
15450b57cec5SDimitry Andric 
15460b57cec5SDimitry Andric   BuildJobs(*C);
15470b57cec5SDimitry Andric 
15480b57cec5SDimitry Andric   return C;
15490b57cec5SDimitry Andric }
15500b57cec5SDimitry Andric 
15510b57cec5SDimitry Andric static void printArgList(raw_ostream &OS, const llvm::opt::ArgList &Args) {
15520b57cec5SDimitry Andric   llvm::opt::ArgStringList ASL;
1553349cc55cSDimitry Andric   for (const auto *A : Args) {
1554349cc55cSDimitry Andric     // Use user's original spelling of flags. For example, use
1555349cc55cSDimitry Andric     // `/source-charset:utf-8` instead of `-finput-charset=utf-8` if the user
1556349cc55cSDimitry Andric     // wrote the former.
1557349cc55cSDimitry Andric     while (A->getAlias())
1558349cc55cSDimitry Andric       A = A->getAlias();
15590b57cec5SDimitry Andric     A->render(Args, ASL);
1560349cc55cSDimitry Andric   }
15610b57cec5SDimitry Andric 
15620b57cec5SDimitry Andric   for (auto I = ASL.begin(), E = ASL.end(); I != E; ++I) {
15630b57cec5SDimitry Andric     if (I != ASL.begin())
15640b57cec5SDimitry Andric       OS << ' ';
15655ffd83dbSDimitry Andric     llvm::sys::printArg(OS, *I, true);
15660b57cec5SDimitry Andric   }
15670b57cec5SDimitry Andric   OS << '\n';
15680b57cec5SDimitry Andric }
15690b57cec5SDimitry Andric 
15700b57cec5SDimitry Andric bool Driver::getCrashDiagnosticFile(StringRef ReproCrashFilename,
15710b57cec5SDimitry Andric                                     SmallString<128> &CrashDiagDir) {
15720b57cec5SDimitry Andric   using namespace llvm::sys;
15730b57cec5SDimitry Andric   assert(llvm::Triple(llvm::sys::getProcessTriple()).isOSDarwin() &&
15740b57cec5SDimitry Andric          "Only knows about .crash files on Darwin");
15750b57cec5SDimitry Andric 
15760b57cec5SDimitry Andric   // The .crash file can be found on at ~/Library/Logs/DiagnosticReports/
15770b57cec5SDimitry Andric   // (or /Library/Logs/DiagnosticReports for root) and has the filename pattern
15780b57cec5SDimitry Andric   // clang-<VERSION>_<YYYY-MM-DD-HHMMSS>_<hostname>.crash.
15790b57cec5SDimitry Andric   path::home_directory(CrashDiagDir);
15805f757f3fSDimitry Andric   if (CrashDiagDir.starts_with("/var/root"))
15810b57cec5SDimitry Andric     CrashDiagDir = "/";
15820b57cec5SDimitry Andric   path::append(CrashDiagDir, "Library/Logs/DiagnosticReports");
15830b57cec5SDimitry Andric   int PID =
15840b57cec5SDimitry Andric #if LLVM_ON_UNIX
15850b57cec5SDimitry Andric       getpid();
15860b57cec5SDimitry Andric #else
15870b57cec5SDimitry Andric       0;
15880b57cec5SDimitry Andric #endif
15890b57cec5SDimitry Andric   std::error_code EC;
15900b57cec5SDimitry Andric   fs::file_status FileStatus;
15910b57cec5SDimitry Andric   TimePoint<> LastAccessTime;
15920b57cec5SDimitry Andric   SmallString<128> CrashFilePath;
15930b57cec5SDimitry Andric   // Lookup the .crash files and get the one generated by a subprocess spawned
15940b57cec5SDimitry Andric   // by this driver invocation.
15950b57cec5SDimitry Andric   for (fs::directory_iterator File(CrashDiagDir, EC), FileEnd;
15960b57cec5SDimitry Andric        File != FileEnd && !EC; File.increment(EC)) {
15970b57cec5SDimitry Andric     StringRef FileName = path::filename(File->path());
15985f757f3fSDimitry Andric     if (!FileName.starts_with(Name))
15990b57cec5SDimitry Andric       continue;
16000b57cec5SDimitry Andric     if (fs::status(File->path(), FileStatus))
16010b57cec5SDimitry Andric       continue;
16020b57cec5SDimitry Andric     llvm::ErrorOr<std::unique_ptr<llvm::MemoryBuffer>> CrashFile =
16030b57cec5SDimitry Andric         llvm::MemoryBuffer::getFile(File->path());
16040b57cec5SDimitry Andric     if (!CrashFile)
16050b57cec5SDimitry Andric       continue;
16060b57cec5SDimitry Andric     // The first line should start with "Process:", otherwise this isn't a real
16070b57cec5SDimitry Andric     // .crash file.
16080b57cec5SDimitry Andric     StringRef Data = CrashFile.get()->getBuffer();
16095f757f3fSDimitry Andric     if (!Data.starts_with("Process:"))
16100b57cec5SDimitry Andric       continue;
16110b57cec5SDimitry Andric     // Parse parent process pid line, e.g: "Parent Process: clang-4.0 [79141]"
16120b57cec5SDimitry Andric     size_t ParentProcPos = Data.find("Parent Process:");
16130b57cec5SDimitry Andric     if (ParentProcPos == StringRef::npos)
16140b57cec5SDimitry Andric       continue;
16150b57cec5SDimitry Andric     size_t LineEnd = Data.find_first_of("\n", ParentProcPos);
16160b57cec5SDimitry Andric     if (LineEnd == StringRef::npos)
16170b57cec5SDimitry Andric       continue;
16180b57cec5SDimitry Andric     StringRef ParentProcess = Data.slice(ParentProcPos+15, LineEnd).trim();
16190b57cec5SDimitry Andric     int OpenBracket = -1, CloseBracket = -1;
16200b57cec5SDimitry Andric     for (size_t i = 0, e = ParentProcess.size(); i < e; ++i) {
16210b57cec5SDimitry Andric       if (ParentProcess[i] == '[')
16220b57cec5SDimitry Andric         OpenBracket = i;
16230b57cec5SDimitry Andric       if (ParentProcess[i] == ']')
16240b57cec5SDimitry Andric         CloseBracket = i;
16250b57cec5SDimitry Andric     }
16260b57cec5SDimitry Andric     // Extract the parent process PID from the .crash file and check whether
16270b57cec5SDimitry Andric     // it matches this driver invocation pid.
16280b57cec5SDimitry Andric     int CrashPID;
16290b57cec5SDimitry Andric     if (OpenBracket < 0 || CloseBracket < 0 ||
16300b57cec5SDimitry Andric         ParentProcess.slice(OpenBracket + 1, CloseBracket)
16310b57cec5SDimitry Andric             .getAsInteger(10, CrashPID) || CrashPID != PID) {
16320b57cec5SDimitry Andric       continue;
16330b57cec5SDimitry Andric     }
16340b57cec5SDimitry Andric 
16350b57cec5SDimitry Andric     // Found a .crash file matching the driver pid. To avoid getting an older
16360b57cec5SDimitry Andric     // and misleading crash file, continue looking for the most recent.
16370b57cec5SDimitry Andric     // FIXME: the driver can dispatch multiple cc1 invocations, leading to
16380b57cec5SDimitry Andric     // multiple crashes poiting to the same parent process. Since the driver
16390b57cec5SDimitry Andric     // does not collect pid information for the dispatched invocation there's
16400b57cec5SDimitry Andric     // currently no way to distinguish among them.
16410b57cec5SDimitry Andric     const auto FileAccessTime = FileStatus.getLastModificationTime();
16420b57cec5SDimitry Andric     if (FileAccessTime > LastAccessTime) {
16430b57cec5SDimitry Andric       CrashFilePath.assign(File->path());
16440b57cec5SDimitry Andric       LastAccessTime = FileAccessTime;
16450b57cec5SDimitry Andric     }
16460b57cec5SDimitry Andric   }
16470b57cec5SDimitry Andric 
16480b57cec5SDimitry Andric   // If found, copy it over to the location of other reproducer files.
16490b57cec5SDimitry Andric   if (!CrashFilePath.empty()) {
16500b57cec5SDimitry Andric     EC = fs::copy_file(CrashFilePath, ReproCrashFilename);
16510b57cec5SDimitry Andric     if (EC)
16520b57cec5SDimitry Andric       return false;
16530b57cec5SDimitry Andric     return true;
16540b57cec5SDimitry Andric   }
16550b57cec5SDimitry Andric 
16560b57cec5SDimitry Andric   return false;
16570b57cec5SDimitry Andric }
16580b57cec5SDimitry Andric 
1659bdd1243dSDimitry Andric static const char BugReporMsg[] =
1660bdd1243dSDimitry Andric     "\n********************\n\n"
1661bdd1243dSDimitry Andric     "PLEASE ATTACH THE FOLLOWING FILES TO THE BUG REPORT:\n"
1662bdd1243dSDimitry Andric     "Preprocessed source(s) and associated run script(s) are located at:";
1663bdd1243dSDimitry Andric 
16640b57cec5SDimitry Andric // When clang crashes, produce diagnostic information including the fully
16650b57cec5SDimitry Andric // preprocessed source file(s).  Request that the developer attach the
16660b57cec5SDimitry Andric // diagnostic information to a bug report.
16670b57cec5SDimitry Andric void Driver::generateCompilationDiagnostics(
16680b57cec5SDimitry Andric     Compilation &C, const Command &FailingCommand,
16690b57cec5SDimitry Andric     StringRef AdditionalInformation, CompilationDiagnosticReport *Report) {
16700b57cec5SDimitry Andric   if (C.getArgs().hasArg(options::OPT_fno_crash_diagnostics))
16710b57cec5SDimitry Andric     return;
16720b57cec5SDimitry Andric 
1673bdd1243dSDimitry Andric   unsigned Level = 1;
1674bdd1243dSDimitry Andric   if (Arg *A = C.getArgs().getLastArg(options::OPT_fcrash_diagnostics_EQ)) {
1675bdd1243dSDimitry Andric     Level = llvm::StringSwitch<unsigned>(A->getValue())
1676bdd1243dSDimitry Andric                 .Case("off", 0)
1677bdd1243dSDimitry Andric                 .Case("compiler", 1)
1678bdd1243dSDimitry Andric                 .Case("all", 2)
1679bdd1243dSDimitry Andric                 .Default(1);
1680bdd1243dSDimitry Andric   }
1681bdd1243dSDimitry Andric   if (!Level)
16820b57cec5SDimitry Andric     return;
16830b57cec5SDimitry Andric 
1684bdd1243dSDimitry Andric   // Don't try to generate diagnostics for dsymutil jobs.
1685bdd1243dSDimitry Andric   if (FailingCommand.getCreator().isDsymutilJob())
1686bdd1243dSDimitry Andric     return;
1687bdd1243dSDimitry Andric 
1688bdd1243dSDimitry Andric   bool IsLLD = false;
1689bdd1243dSDimitry Andric   ArgStringList SavedTemps;
1690bdd1243dSDimitry Andric   if (FailingCommand.getCreator().isLinkJob()) {
1691bdd1243dSDimitry Andric     C.getDefaultToolChain().GetLinkerPath(&IsLLD);
1692bdd1243dSDimitry Andric     if (!IsLLD || Level < 2)
1693bdd1243dSDimitry Andric       return;
1694bdd1243dSDimitry Andric 
1695bdd1243dSDimitry Andric     // If lld crashed, we will re-run the same command with the input it used
1696bdd1243dSDimitry Andric     // to have. In that case we should not remove temp files in
1697bdd1243dSDimitry Andric     // initCompilationForDiagnostics yet. They will be added back and removed
1698bdd1243dSDimitry Andric     // later.
1699bdd1243dSDimitry Andric     SavedTemps = std::move(C.getTempFiles());
1700bdd1243dSDimitry Andric     assert(!C.getTempFiles().size());
1701bdd1243dSDimitry Andric   }
1702bdd1243dSDimitry Andric 
17030b57cec5SDimitry Andric   // Print the version of the compiler.
17040b57cec5SDimitry Andric   PrintVersion(C, llvm::errs());
17050b57cec5SDimitry Andric 
17060b57cec5SDimitry Andric   // Suppress driver output and emit preprocessor output to temp file.
17070b57cec5SDimitry Andric   CCGenDiagnostics = true;
17080b57cec5SDimitry Andric 
17090b57cec5SDimitry Andric   // Save the original job command(s).
17100b57cec5SDimitry Andric   Command Cmd = FailingCommand;
17110b57cec5SDimitry Andric 
17120b57cec5SDimitry Andric   // Keep track of whether we produce any errors while trying to produce
17130b57cec5SDimitry Andric   // preprocessed sources.
17140b57cec5SDimitry Andric   DiagnosticErrorTrap Trap(Diags);
17150b57cec5SDimitry Andric 
17160b57cec5SDimitry Andric   // Suppress tool output.
17170b57cec5SDimitry Andric   C.initCompilationForDiagnostics();
17180b57cec5SDimitry Andric 
1719bdd1243dSDimitry Andric   // If lld failed, rerun it again with --reproduce.
1720bdd1243dSDimitry Andric   if (IsLLD) {
1721bdd1243dSDimitry Andric     const char *TmpName = CreateTempFile(C, "linker-crash", "tar");
1722bdd1243dSDimitry Andric     Command NewLLDInvocation = Cmd;
1723bdd1243dSDimitry Andric     llvm::opt::ArgStringList ArgList = NewLLDInvocation.getArguments();
1724bdd1243dSDimitry Andric     StringRef ReproduceOption =
1725bdd1243dSDimitry Andric         C.getDefaultToolChain().getTriple().isWindowsMSVCEnvironment()
1726bdd1243dSDimitry Andric             ? "/reproduce:"
1727bdd1243dSDimitry Andric             : "--reproduce=";
1728bdd1243dSDimitry Andric     ArgList.push_back(Saver.save(Twine(ReproduceOption) + TmpName).data());
1729bdd1243dSDimitry Andric     NewLLDInvocation.replaceArguments(std::move(ArgList));
1730bdd1243dSDimitry Andric 
1731bdd1243dSDimitry Andric     // Redirect stdout/stderr to /dev/null.
1732bdd1243dSDimitry Andric     NewLLDInvocation.Execute({std::nullopt, {""}, {""}}, nullptr, nullptr);
1733bdd1243dSDimitry Andric     Diag(clang::diag::note_drv_command_failed_diag_msg) << BugReporMsg;
1734bdd1243dSDimitry Andric     Diag(clang::diag::note_drv_command_failed_diag_msg) << TmpName;
1735bdd1243dSDimitry Andric     Diag(clang::diag::note_drv_command_failed_diag_msg)
1736bdd1243dSDimitry Andric         << "\n\n********************";
1737bdd1243dSDimitry Andric     if (Report)
1738bdd1243dSDimitry Andric       Report->TemporaryFiles.push_back(TmpName);
1739bdd1243dSDimitry Andric     return;
1740bdd1243dSDimitry Andric   }
1741bdd1243dSDimitry Andric 
17420b57cec5SDimitry Andric   // Construct the list of inputs.
17430b57cec5SDimitry Andric   InputList Inputs;
17440b57cec5SDimitry Andric   BuildInputs(C.getDefaultToolChain(), C.getArgs(), Inputs);
17450b57cec5SDimitry Andric 
17460b57cec5SDimitry Andric   for (InputList::iterator it = Inputs.begin(), ie = Inputs.end(); it != ie;) {
17470b57cec5SDimitry Andric     bool IgnoreInput = false;
17480b57cec5SDimitry Andric 
17490b57cec5SDimitry Andric     // Ignore input from stdin or any inputs that cannot be preprocessed.
17500b57cec5SDimitry Andric     // Check type first as not all linker inputs have a value.
17510b57cec5SDimitry Andric     if (types::getPreprocessedType(it->first) == types::TY_INVALID) {
17520b57cec5SDimitry Andric       IgnoreInput = true;
17530b57cec5SDimitry Andric     } else if (!strcmp(it->second->getValue(), "-")) {
17540b57cec5SDimitry Andric       Diag(clang::diag::note_drv_command_failed_diag_msg)
17550b57cec5SDimitry Andric           << "Error generating preprocessed source(s) - "
17560b57cec5SDimitry Andric              "ignoring input from stdin.";
17570b57cec5SDimitry Andric       IgnoreInput = true;
17580b57cec5SDimitry Andric     }
17590b57cec5SDimitry Andric 
17600b57cec5SDimitry Andric     if (IgnoreInput) {
17610b57cec5SDimitry Andric       it = Inputs.erase(it);
17620b57cec5SDimitry Andric       ie = Inputs.end();
17630b57cec5SDimitry Andric     } else {
17640b57cec5SDimitry Andric       ++it;
17650b57cec5SDimitry Andric     }
17660b57cec5SDimitry Andric   }
17670b57cec5SDimitry Andric 
17680b57cec5SDimitry Andric   if (Inputs.empty()) {
17690b57cec5SDimitry Andric     Diag(clang::diag::note_drv_command_failed_diag_msg)
17700b57cec5SDimitry Andric         << "Error generating preprocessed source(s) - "
17710b57cec5SDimitry Andric            "no preprocessable inputs.";
17720b57cec5SDimitry Andric     return;
17730b57cec5SDimitry Andric   }
17740b57cec5SDimitry Andric 
17750b57cec5SDimitry Andric   // Don't attempt to generate preprocessed files if multiple -arch options are
17760b57cec5SDimitry Andric   // used, unless they're all duplicates.
17770b57cec5SDimitry Andric   llvm::StringSet<> ArchNames;
17780b57cec5SDimitry Andric   for (const Arg *A : C.getArgs()) {
17790b57cec5SDimitry Andric     if (A->getOption().matches(options::OPT_arch)) {
17800b57cec5SDimitry Andric       StringRef ArchName = A->getValue();
17810b57cec5SDimitry Andric       ArchNames.insert(ArchName);
17820b57cec5SDimitry Andric     }
17830b57cec5SDimitry Andric   }
17840b57cec5SDimitry Andric   if (ArchNames.size() > 1) {
17850b57cec5SDimitry Andric     Diag(clang::diag::note_drv_command_failed_diag_msg)
17860b57cec5SDimitry Andric         << "Error generating preprocessed source(s) - cannot generate "
17870b57cec5SDimitry Andric            "preprocessed source with multiple -arch options.";
17880b57cec5SDimitry Andric     return;
17890b57cec5SDimitry Andric   }
17900b57cec5SDimitry Andric 
17910b57cec5SDimitry Andric   // Construct the list of abstract actions to perform for this compilation. On
17920b57cec5SDimitry Andric   // Darwin OSes this uses the driver-driver and builds universal actions.
17930b57cec5SDimitry Andric   const ToolChain &TC = C.getDefaultToolChain();
17940b57cec5SDimitry Andric   if (TC.getTriple().isOSBinFormatMachO())
17950b57cec5SDimitry Andric     BuildUniversalActions(C, TC, Inputs);
17960b57cec5SDimitry Andric   else
17970b57cec5SDimitry Andric     BuildActions(C, C.getArgs(), Inputs, C.getActions());
17980b57cec5SDimitry Andric 
17990b57cec5SDimitry Andric   BuildJobs(C);
18000b57cec5SDimitry Andric 
18010b57cec5SDimitry Andric   // If there were errors building the compilation, quit now.
18020b57cec5SDimitry Andric   if (Trap.hasErrorOccurred()) {
18030b57cec5SDimitry Andric     Diag(clang::diag::note_drv_command_failed_diag_msg)
18040b57cec5SDimitry Andric         << "Error generating preprocessed source(s).";
18050b57cec5SDimitry Andric     return;
18060b57cec5SDimitry Andric   }
18070b57cec5SDimitry Andric 
18080b57cec5SDimitry Andric   // Generate preprocessed output.
18090b57cec5SDimitry Andric   SmallVector<std::pair<int, const Command *>, 4> FailingCommands;
18100b57cec5SDimitry Andric   C.ExecuteJobs(C.getJobs(), FailingCommands);
18110b57cec5SDimitry Andric 
18120b57cec5SDimitry Andric   // If any of the preprocessing commands failed, clean up and exit.
18130b57cec5SDimitry Andric   if (!FailingCommands.empty()) {
18140b57cec5SDimitry Andric     Diag(clang::diag::note_drv_command_failed_diag_msg)
18150b57cec5SDimitry Andric         << "Error generating preprocessed source(s).";
18160b57cec5SDimitry Andric     return;
18170b57cec5SDimitry Andric   }
18180b57cec5SDimitry Andric 
18190b57cec5SDimitry Andric   const ArgStringList &TempFiles = C.getTempFiles();
18200b57cec5SDimitry Andric   if (TempFiles.empty()) {
18210b57cec5SDimitry Andric     Diag(clang::diag::note_drv_command_failed_diag_msg)
18220b57cec5SDimitry Andric         << "Error generating preprocessed source(s).";
18230b57cec5SDimitry Andric     return;
18240b57cec5SDimitry Andric   }
18250b57cec5SDimitry Andric 
1826bdd1243dSDimitry Andric   Diag(clang::diag::note_drv_command_failed_diag_msg) << BugReporMsg;
18270b57cec5SDimitry Andric 
18280b57cec5SDimitry Andric   SmallString<128> VFS;
18290b57cec5SDimitry Andric   SmallString<128> ReproCrashFilename;
18300b57cec5SDimitry Andric   for (const char *TempFile : TempFiles) {
18310b57cec5SDimitry Andric     Diag(clang::diag::note_drv_command_failed_diag_msg) << TempFile;
18320b57cec5SDimitry Andric     if (Report)
18330b57cec5SDimitry Andric       Report->TemporaryFiles.push_back(TempFile);
18340b57cec5SDimitry Andric     if (ReproCrashFilename.empty()) {
18350b57cec5SDimitry Andric       ReproCrashFilename = TempFile;
18360b57cec5SDimitry Andric       llvm::sys::path::replace_extension(ReproCrashFilename, ".crash");
18370b57cec5SDimitry Andric     }
18385f757f3fSDimitry Andric     if (StringRef(TempFile).ends_with(".cache")) {
18390b57cec5SDimitry Andric       // In some cases (modules) we'll dump extra data to help with reproducing
18400b57cec5SDimitry Andric       // the crash into a directory next to the output.
18410b57cec5SDimitry Andric       VFS = llvm::sys::path::filename(TempFile);
18420b57cec5SDimitry Andric       llvm::sys::path::append(VFS, "vfs", "vfs.yaml");
18430b57cec5SDimitry Andric     }
18440b57cec5SDimitry Andric   }
18450b57cec5SDimitry Andric 
1846bdd1243dSDimitry Andric   for (const char *TempFile : SavedTemps)
1847bdd1243dSDimitry Andric     C.addTempFile(TempFile);
1848bdd1243dSDimitry Andric 
18490b57cec5SDimitry Andric   // Assume associated files are based off of the first temporary file.
18500b57cec5SDimitry Andric   CrashReportInfo CrashInfo(TempFiles[0], VFS);
18510b57cec5SDimitry Andric 
18520b57cec5SDimitry Andric   llvm::SmallString<128> Script(CrashInfo.Filename);
18530b57cec5SDimitry Andric   llvm::sys::path::replace_extension(Script, "sh");
18540b57cec5SDimitry Andric   std::error_code EC;
1855fe6060f1SDimitry Andric   llvm::raw_fd_ostream ScriptOS(Script, EC, llvm::sys::fs::CD_CreateNew,
1856fe6060f1SDimitry Andric                                 llvm::sys::fs::FA_Write,
1857fe6060f1SDimitry Andric                                 llvm::sys::fs::OF_Text);
18580b57cec5SDimitry Andric   if (EC) {
18590b57cec5SDimitry Andric     Diag(clang::diag::note_drv_command_failed_diag_msg)
18600b57cec5SDimitry Andric         << "Error generating run script: " << Script << " " << EC.message();
18610b57cec5SDimitry Andric   } else {
18620b57cec5SDimitry Andric     ScriptOS << "# Crash reproducer for " << getClangFullVersion() << "\n"
18630b57cec5SDimitry Andric              << "# Driver args: ";
18640b57cec5SDimitry Andric     printArgList(ScriptOS, C.getInputArgs());
18650b57cec5SDimitry Andric     ScriptOS << "# Original command: ";
18660b57cec5SDimitry Andric     Cmd.Print(ScriptOS, "\n", /*Quote=*/true);
18670b57cec5SDimitry Andric     Cmd.Print(ScriptOS, "\n", /*Quote=*/true, &CrashInfo);
18680b57cec5SDimitry Andric     if (!AdditionalInformation.empty())
18690b57cec5SDimitry Andric       ScriptOS << "\n# Additional information: " << AdditionalInformation
18700b57cec5SDimitry Andric                << "\n";
18710b57cec5SDimitry Andric     if (Report)
18727a6dacacSDimitry Andric       Report->TemporaryFiles.push_back(std::string(Script));
18730b57cec5SDimitry Andric     Diag(clang::diag::note_drv_command_failed_diag_msg) << Script;
18740b57cec5SDimitry Andric   }
18750b57cec5SDimitry Andric 
18760b57cec5SDimitry Andric   // On darwin, provide information about the .crash diagnostic report.
18770b57cec5SDimitry Andric   if (llvm::Triple(llvm::sys::getProcessTriple()).isOSDarwin()) {
18780b57cec5SDimitry Andric     SmallString<128> CrashDiagDir;
18790b57cec5SDimitry Andric     if (getCrashDiagnosticFile(ReproCrashFilename, CrashDiagDir)) {
18800b57cec5SDimitry Andric       Diag(clang::diag::note_drv_command_failed_diag_msg)
18810b57cec5SDimitry Andric           << ReproCrashFilename.str();
18820b57cec5SDimitry Andric     } else { // Suggest a directory for the user to look for .crash files.
18830b57cec5SDimitry Andric       llvm::sys::path::append(CrashDiagDir, Name);
18840b57cec5SDimitry Andric       CrashDiagDir += "_<YYYY-MM-DD-HHMMSS>_<hostname>.crash";
18850b57cec5SDimitry Andric       Diag(clang::diag::note_drv_command_failed_diag_msg)
18860b57cec5SDimitry Andric           << "Crash backtrace is located in";
18870b57cec5SDimitry Andric       Diag(clang::diag::note_drv_command_failed_diag_msg)
18880b57cec5SDimitry Andric           << CrashDiagDir.str();
18890b57cec5SDimitry Andric       Diag(clang::diag::note_drv_command_failed_diag_msg)
18900b57cec5SDimitry Andric           << "(choose the .crash file that corresponds to your crash)";
18910b57cec5SDimitry Andric     }
18920b57cec5SDimitry Andric   }
18930b57cec5SDimitry Andric 
18940b57cec5SDimitry Andric   Diag(clang::diag::note_drv_command_failed_diag_msg)
18950b57cec5SDimitry Andric       << "\n\n********************";
18960b57cec5SDimitry Andric }
18970b57cec5SDimitry Andric 
18980b57cec5SDimitry Andric void Driver::setUpResponseFiles(Compilation &C, Command &Cmd) {
18990b57cec5SDimitry Andric   // Since commandLineFitsWithinSystemLimits() may underestimate system's
19000b57cec5SDimitry Andric   // capacity if the tool does not support response files, there is a chance/
19010b57cec5SDimitry Andric   // that things will just work without a response file, so we silently just
19020b57cec5SDimitry Andric   // skip it.
19035ffd83dbSDimitry Andric   if (Cmd.getResponseFileSupport().ResponseKind ==
19045ffd83dbSDimitry Andric           ResponseFileSupport::RF_None ||
19050b57cec5SDimitry Andric       llvm::sys::commandLineFitsWithinSystemLimits(Cmd.getExecutable(),
19060b57cec5SDimitry Andric                                                    Cmd.getArguments()))
19070b57cec5SDimitry Andric     return;
19080b57cec5SDimitry Andric 
19090b57cec5SDimitry Andric   std::string TmpName = GetTemporaryPath("response", "txt");
19100b57cec5SDimitry Andric   Cmd.setResponseFile(C.addTempFile(C.getArgs().MakeArgString(TmpName)));
19110b57cec5SDimitry Andric }
19120b57cec5SDimitry Andric 
19130b57cec5SDimitry Andric int Driver::ExecuteCompilation(
19140b57cec5SDimitry Andric     Compilation &C,
19150b57cec5SDimitry Andric     SmallVectorImpl<std::pair<int, const Command *>> &FailingCommands) {
191681ad6265SDimitry Andric   if (C.getArgs().hasArg(options::OPT_fdriver_only)) {
191781ad6265SDimitry Andric     if (C.getArgs().hasArg(options::OPT_v))
191881ad6265SDimitry Andric       C.getJobs().Print(llvm::errs(), "\n", true);
191981ad6265SDimitry Andric 
192081ad6265SDimitry Andric     C.ExecuteJobs(C.getJobs(), FailingCommands, /*LogOnly=*/true);
192181ad6265SDimitry Andric 
192281ad6265SDimitry Andric     // If there were errors building the compilation, quit now.
192381ad6265SDimitry Andric     if (!FailingCommands.empty() || Diags.hasErrorOccurred())
192481ad6265SDimitry Andric       return 1;
192581ad6265SDimitry Andric 
192681ad6265SDimitry Andric     return 0;
192781ad6265SDimitry Andric   }
192881ad6265SDimitry Andric 
19290b57cec5SDimitry Andric   // Just print if -### was present.
19300b57cec5SDimitry Andric   if (C.getArgs().hasArg(options::OPT__HASH_HASH_HASH)) {
19310b57cec5SDimitry Andric     C.getJobs().Print(llvm::errs(), "\n", true);
19325f757f3fSDimitry Andric     return Diags.hasErrorOccurred() ? 1 : 0;
19330b57cec5SDimitry Andric   }
19340b57cec5SDimitry Andric 
19350b57cec5SDimitry Andric   // If there were errors building the compilation, quit now.
19360b57cec5SDimitry Andric   if (Diags.hasErrorOccurred())
19370b57cec5SDimitry Andric     return 1;
19380b57cec5SDimitry Andric 
19390eae32dcSDimitry Andric   // Set up response file names for each command, if necessary.
19400b57cec5SDimitry Andric   for (auto &Job : C.getJobs())
19410b57cec5SDimitry Andric     setUpResponseFiles(C, Job);
19420b57cec5SDimitry Andric 
19430b57cec5SDimitry Andric   C.ExecuteJobs(C.getJobs(), FailingCommands);
19440b57cec5SDimitry Andric 
19450b57cec5SDimitry Andric   // If the command succeeded, we are done.
19460b57cec5SDimitry Andric   if (FailingCommands.empty())
19470b57cec5SDimitry Andric     return 0;
19480b57cec5SDimitry Andric 
19490b57cec5SDimitry Andric   // Otherwise, remove result files and print extra information about abnormal
19500b57cec5SDimitry Andric   // failures.
19510b57cec5SDimitry Andric   int Res = 0;
19520b57cec5SDimitry Andric   for (const auto &CmdPair : FailingCommands) {
19530b57cec5SDimitry Andric     int CommandRes = CmdPair.first;
19540b57cec5SDimitry Andric     const Command *FailingCommand = CmdPair.second;
19550b57cec5SDimitry Andric 
19560b57cec5SDimitry Andric     // Remove result files if we're not saving temps.
19570b57cec5SDimitry Andric     if (!isSaveTempsEnabled()) {
19580b57cec5SDimitry Andric       const JobAction *JA = cast<JobAction>(&FailingCommand->getSource());
19590b57cec5SDimitry Andric       C.CleanupFileMap(C.getResultFiles(), JA, true);
19600b57cec5SDimitry Andric 
19610b57cec5SDimitry Andric       // Failure result files are valid unless we crashed.
19620b57cec5SDimitry Andric       if (CommandRes < 0)
19630b57cec5SDimitry Andric         C.CleanupFileMap(C.getFailureResultFiles(), JA, true);
19640b57cec5SDimitry Andric     }
19650b57cec5SDimitry Andric 
19661ac55f4cSDimitry Andric     // llvm/lib/Support/*/Signals.inc will exit with a special return code
19670b57cec5SDimitry Andric     // for SIGPIPE. Do not print diagnostics for this case.
19680b57cec5SDimitry Andric     if (CommandRes == EX_IOERR) {
19690b57cec5SDimitry Andric       Res = CommandRes;
19700b57cec5SDimitry Andric       continue;
19710b57cec5SDimitry Andric     }
19720b57cec5SDimitry Andric 
19730b57cec5SDimitry Andric     // Print extra information about abnormal failures, if possible.
19740b57cec5SDimitry Andric     //
19750b57cec5SDimitry Andric     // This is ad-hoc, but we don't want to be excessively noisy. If the result
19760b57cec5SDimitry Andric     // status was 1, assume the command failed normally. In particular, if it
19770b57cec5SDimitry Andric     // was the compiler then assume it gave a reasonable error code. Failures
19780b57cec5SDimitry Andric     // in other tools are less common, and they generally have worse
19790b57cec5SDimitry Andric     // diagnostics, so always print the diagnostic there.
19800b57cec5SDimitry Andric     const Tool &FailingTool = FailingCommand->getCreator();
19810b57cec5SDimitry Andric 
19820b57cec5SDimitry Andric     if (!FailingCommand->getCreator().hasGoodDiagnostics() || CommandRes != 1) {
19830b57cec5SDimitry Andric       // FIXME: See FIXME above regarding result code interpretation.
19840b57cec5SDimitry Andric       if (CommandRes < 0)
19850b57cec5SDimitry Andric         Diag(clang::diag::err_drv_command_signalled)
19860b57cec5SDimitry Andric             << FailingTool.getShortName();
19870b57cec5SDimitry Andric       else
19880b57cec5SDimitry Andric         Diag(clang::diag::err_drv_command_failed)
19890b57cec5SDimitry Andric             << FailingTool.getShortName() << CommandRes;
19900b57cec5SDimitry Andric     }
19910b57cec5SDimitry Andric   }
19920b57cec5SDimitry Andric   return Res;
19930b57cec5SDimitry Andric }
19940b57cec5SDimitry Andric 
19950b57cec5SDimitry Andric void Driver::PrintHelp(bool ShowHidden) const {
19965f757f3fSDimitry Andric   llvm::opt::Visibility VisibilityMask = getOptionVisibilityMask();
1997e8d8bef9SDimitry Andric 
19980b57cec5SDimitry Andric   std::string Usage = llvm::formatv("{0} [options] file...", Name).str();
1999fe6060f1SDimitry Andric   getOpts().printHelp(llvm::outs(), Usage.c_str(), DriverTitle.c_str(),
20005f757f3fSDimitry Andric                       ShowHidden, /*ShowAllAliases=*/false,
20015f757f3fSDimitry Andric                       VisibilityMask);
20020b57cec5SDimitry Andric }
20030b57cec5SDimitry Andric 
20040b57cec5SDimitry Andric void Driver::PrintVersion(const Compilation &C, raw_ostream &OS) const {
2005e8d8bef9SDimitry Andric   if (IsFlangMode()) {
2006e8d8bef9SDimitry Andric     OS << getClangToolFullVersion("flang-new") << '\n';
2007e8d8bef9SDimitry Andric   } else {
20080b57cec5SDimitry Andric     // FIXME: The following handlers should use a callback mechanism, we don't
20090b57cec5SDimitry Andric     // know what the client would like to do.
20100b57cec5SDimitry Andric     OS << getClangFullVersion() << '\n';
2011e8d8bef9SDimitry Andric   }
20120b57cec5SDimitry Andric   const ToolChain &TC = C.getDefaultToolChain();
20130b57cec5SDimitry Andric   OS << "Target: " << TC.getTripleString() << '\n';
20140b57cec5SDimitry Andric 
20150b57cec5SDimitry Andric   // Print the threading model.
20160b57cec5SDimitry Andric   if (Arg *A = C.getArgs().getLastArg(options::OPT_mthread_model)) {
20170b57cec5SDimitry Andric     // Don't print if the ToolChain would have barfed on it already
20180b57cec5SDimitry Andric     if (TC.isThreadModelSupported(A->getValue()))
20190b57cec5SDimitry Andric       OS << "Thread model: " << A->getValue();
20200b57cec5SDimitry Andric   } else
20210b57cec5SDimitry Andric     OS << "Thread model: " << TC.getThreadModel();
20220b57cec5SDimitry Andric   OS << '\n';
20230b57cec5SDimitry Andric 
20240b57cec5SDimitry Andric   // Print out the install directory.
20250fca6ea1SDimitry Andric   OS << "InstalledDir: " << Dir << '\n';
20260fca6ea1SDimitry Andric 
20270fca6ea1SDimitry Andric   // Print the build config if it's non-default.
20280fca6ea1SDimitry Andric   // Intended to help LLVM developers understand the configs of compilers
20290fca6ea1SDimitry Andric   // they're investigating.
20300fca6ea1SDimitry Andric   if (!llvm::cl::getCompilerBuildConfig().empty())
20310fca6ea1SDimitry Andric     llvm::cl::printBuildConfig(OS);
20320b57cec5SDimitry Andric 
2033bdd1243dSDimitry Andric   // If configuration files were used, print their paths.
2034bdd1243dSDimitry Andric   for (auto ConfigFile : ConfigFiles)
20350b57cec5SDimitry Andric     OS << "Configuration file: " << ConfigFile << '\n';
20360b57cec5SDimitry Andric }
20370b57cec5SDimitry Andric 
20380b57cec5SDimitry Andric /// PrintDiagnosticCategories - Implement the --print-diagnostic-categories
20390b57cec5SDimitry Andric /// option.
20400b57cec5SDimitry Andric static void PrintDiagnosticCategories(raw_ostream &OS) {
20410b57cec5SDimitry Andric   // Skip the empty category.
20420b57cec5SDimitry Andric   for (unsigned i = 1, max = DiagnosticIDs::getNumberOfCategories(); i != max;
20430b57cec5SDimitry Andric        ++i)
20440b57cec5SDimitry Andric     OS << i << ',' << DiagnosticIDs::getCategoryNameFromID(i) << '\n';
20450b57cec5SDimitry Andric }
20460b57cec5SDimitry Andric 
20470b57cec5SDimitry Andric void Driver::HandleAutocompletions(StringRef PassedFlags) const {
20480b57cec5SDimitry Andric   if (PassedFlags == "")
20490b57cec5SDimitry Andric     return;
20500b57cec5SDimitry Andric   // Print out all options that start with a given argument. This is used for
20510b57cec5SDimitry Andric   // shell autocompletion.
20520b57cec5SDimitry Andric   std::vector<std::string> SuggestedCompletions;
20530b57cec5SDimitry Andric   std::vector<std::string> Flags;
20540b57cec5SDimitry Andric 
20555f757f3fSDimitry Andric   llvm::opt::Visibility VisibilityMask(options::ClangOption);
20560b57cec5SDimitry Andric 
2057e8d8bef9SDimitry Andric   // Make sure that Flang-only options don't pollute the Clang output
2058e8d8bef9SDimitry Andric   // TODO: Make sure that Clang-only options don't pollute Flang output
20595f757f3fSDimitry Andric   if (IsFlangMode())
20605f757f3fSDimitry Andric     VisibilityMask = llvm::opt::Visibility(options::FlangOption);
2061e8d8bef9SDimitry Andric 
20620b57cec5SDimitry Andric   // Distinguish "--autocomplete=-someflag" and "--autocomplete=-someflag,"
20630b57cec5SDimitry Andric   // because the latter indicates that the user put space before pushing tab
20640b57cec5SDimitry Andric   // which should end up in a file completion.
20655f757f3fSDimitry Andric   const bool HasSpace = PassedFlags.ends_with(",");
20660b57cec5SDimitry Andric 
20670b57cec5SDimitry Andric   // Parse PassedFlags by "," as all the command-line flags are passed to this
20680b57cec5SDimitry Andric   // function separated by ","
20690b57cec5SDimitry Andric   StringRef TargetFlags = PassedFlags;
20700b57cec5SDimitry Andric   while (TargetFlags != "") {
20710b57cec5SDimitry Andric     StringRef CurFlag;
20720b57cec5SDimitry Andric     std::tie(CurFlag, TargetFlags) = TargetFlags.split(",");
20730b57cec5SDimitry Andric     Flags.push_back(std::string(CurFlag));
20740b57cec5SDimitry Andric   }
20750b57cec5SDimitry Andric 
20760b57cec5SDimitry Andric   // We want to show cc1-only options only when clang is invoked with -cc1 or
20770b57cec5SDimitry Andric   // -Xclang.
20780b57cec5SDimitry Andric   if (llvm::is_contained(Flags, "-Xclang") || llvm::is_contained(Flags, "-cc1"))
20795f757f3fSDimitry Andric     VisibilityMask = llvm::opt::Visibility(options::CC1Option);
20800b57cec5SDimitry Andric 
2081a7dea167SDimitry Andric   const llvm::opt::OptTable &Opts = getOpts();
20820b57cec5SDimitry Andric   StringRef Cur;
20830b57cec5SDimitry Andric   Cur = Flags.at(Flags.size() - 1);
20840b57cec5SDimitry Andric   StringRef Prev;
20850b57cec5SDimitry Andric   if (Flags.size() >= 2) {
20860b57cec5SDimitry Andric     Prev = Flags.at(Flags.size() - 2);
2087a7dea167SDimitry Andric     SuggestedCompletions = Opts.suggestValueCompletions(Prev, Cur);
20880b57cec5SDimitry Andric   }
20890b57cec5SDimitry Andric 
20900b57cec5SDimitry Andric   if (SuggestedCompletions.empty())
2091a7dea167SDimitry Andric     SuggestedCompletions = Opts.suggestValueCompletions(Cur, "");
20920b57cec5SDimitry Andric 
20930b57cec5SDimitry Andric   // If Flags were empty, it means the user typed `clang [tab]` where we should
20940b57cec5SDimitry Andric   // list all possible flags. If there was no value completion and the user
20950b57cec5SDimitry Andric   // pressed tab after a space, we should fall back to a file completion.
20960b57cec5SDimitry Andric   // We're printing a newline to be consistent with what we print at the end of
20970b57cec5SDimitry Andric   // this function.
20980b57cec5SDimitry Andric   if (SuggestedCompletions.empty() && HasSpace && !Flags.empty()) {
20990b57cec5SDimitry Andric     llvm::outs() << '\n';
21000b57cec5SDimitry Andric     return;
21010b57cec5SDimitry Andric   }
21020b57cec5SDimitry Andric 
21030b57cec5SDimitry Andric   // When flag ends with '=' and there was no value completion, return empty
21040b57cec5SDimitry Andric   // string and fall back to the file autocompletion.
21055f757f3fSDimitry Andric   if (SuggestedCompletions.empty() && !Cur.ends_with("=")) {
21060b57cec5SDimitry Andric     // If the flag is in the form of "--autocomplete=-foo",
21070b57cec5SDimitry Andric     // we were requested to print out all option names that start with "-foo".
21080b57cec5SDimitry Andric     // For example, "--autocomplete=-fsyn" is expanded to "-fsyntax-only".
21095f757f3fSDimitry Andric     SuggestedCompletions = Opts.findByPrefix(
21105f757f3fSDimitry Andric         Cur, VisibilityMask,
21115f757f3fSDimitry Andric         /*DisableFlags=*/options::Unsupported | options::Ignored);
21120b57cec5SDimitry Andric 
21130b57cec5SDimitry Andric     // We have to query the -W flags manually as they're not in the OptTable.
21140b57cec5SDimitry Andric     // TODO: Find a good way to add them to OptTable instead and them remove
21150b57cec5SDimitry Andric     // this code.
21160b57cec5SDimitry Andric     for (StringRef S : DiagnosticIDs::getDiagnosticFlags())
21175f757f3fSDimitry Andric       if (S.starts_with(Cur))
21185ffd83dbSDimitry Andric         SuggestedCompletions.push_back(std::string(S));
21190b57cec5SDimitry Andric   }
21200b57cec5SDimitry Andric 
21210b57cec5SDimitry Andric   // Sort the autocomplete candidates so that shells print them out in a
21220b57cec5SDimitry Andric   // deterministic order. We could sort in any way, but we chose
21230b57cec5SDimitry Andric   // case-insensitive sorting for consistency with the -help option
21240b57cec5SDimitry Andric   // which prints out options in the case-insensitive alphabetical order.
21250b57cec5SDimitry Andric   llvm::sort(SuggestedCompletions, [](StringRef A, StringRef B) {
2126fe6060f1SDimitry Andric     if (int X = A.compare_insensitive(B))
21270b57cec5SDimitry Andric       return X < 0;
21280b57cec5SDimitry Andric     return A.compare(B) > 0;
21290b57cec5SDimitry Andric   });
21300b57cec5SDimitry Andric 
21310b57cec5SDimitry Andric   llvm::outs() << llvm::join(SuggestedCompletions, "\n") << '\n';
21320b57cec5SDimitry Andric }
21330b57cec5SDimitry Andric 
21340fca6ea1SDimitry Andric bool Driver::HandleImmediateArgs(Compilation &C) {
21350b57cec5SDimitry Andric   // The order these options are handled in gcc is all over the place, but we
21360b57cec5SDimitry Andric   // don't expect inconsistencies w.r.t. that to matter in practice.
21370b57cec5SDimitry Andric 
21380b57cec5SDimitry Andric   if (C.getArgs().hasArg(options::OPT_dumpmachine)) {
21390b57cec5SDimitry Andric     llvm::outs() << C.getDefaultToolChain().getTripleString() << '\n';
21400b57cec5SDimitry Andric     return false;
21410b57cec5SDimitry Andric   }
21420b57cec5SDimitry Andric 
21430b57cec5SDimitry Andric   if (C.getArgs().hasArg(options::OPT_dumpversion)) {
21440b57cec5SDimitry Andric     // Since -dumpversion is only implemented for pedantic GCC compatibility, we
21450b57cec5SDimitry Andric     // return an answer which matches our definition of __VERSION__.
21460b57cec5SDimitry Andric     llvm::outs() << CLANG_VERSION_STRING << "\n";
21470b57cec5SDimitry Andric     return false;
21480b57cec5SDimitry Andric   }
21490b57cec5SDimitry Andric 
21500b57cec5SDimitry Andric   if (C.getArgs().hasArg(options::OPT__print_diagnostic_categories)) {
21510b57cec5SDimitry Andric     PrintDiagnosticCategories(llvm::outs());
21520b57cec5SDimitry Andric     return false;
21530b57cec5SDimitry Andric   }
21540b57cec5SDimitry Andric 
21550b57cec5SDimitry Andric   if (C.getArgs().hasArg(options::OPT_help) ||
21560b57cec5SDimitry Andric       C.getArgs().hasArg(options::OPT__help_hidden)) {
21570b57cec5SDimitry Andric     PrintHelp(C.getArgs().hasArg(options::OPT__help_hidden));
21580b57cec5SDimitry Andric     return false;
21590b57cec5SDimitry Andric   }
21600b57cec5SDimitry Andric 
21610b57cec5SDimitry Andric   if (C.getArgs().hasArg(options::OPT__version)) {
21620b57cec5SDimitry Andric     // Follow gcc behavior and use stdout for --version and stderr for -v.
21630b57cec5SDimitry Andric     PrintVersion(C, llvm::outs());
21640b57cec5SDimitry Andric     return false;
21650b57cec5SDimitry Andric   }
21660b57cec5SDimitry Andric 
21670b57cec5SDimitry Andric   if (C.getArgs().hasArg(options::OPT_v) ||
21680b57cec5SDimitry Andric       C.getArgs().hasArg(options::OPT__HASH_HASH_HASH) ||
21695f757f3fSDimitry Andric       C.getArgs().hasArg(options::OPT_print_supported_cpus) ||
21700fca6ea1SDimitry Andric       C.getArgs().hasArg(options::OPT_print_supported_extensions) ||
21710fca6ea1SDimitry Andric       C.getArgs().hasArg(options::OPT_print_enabled_extensions)) {
21720b57cec5SDimitry Andric     PrintVersion(C, llvm::errs());
21730b57cec5SDimitry Andric     SuppressMissingInputWarning = true;
21740b57cec5SDimitry Andric   }
21750b57cec5SDimitry Andric 
21760b57cec5SDimitry Andric   if (C.getArgs().hasArg(options::OPT_v)) {
21770b57cec5SDimitry Andric     if (!SystemConfigDir.empty())
21780b57cec5SDimitry Andric       llvm::errs() << "System configuration file directory: "
21790b57cec5SDimitry Andric                    << SystemConfigDir << "\n";
21800b57cec5SDimitry Andric     if (!UserConfigDir.empty())
21810b57cec5SDimitry Andric       llvm::errs() << "User configuration file directory: "
21820b57cec5SDimitry Andric                    << UserConfigDir << "\n";
21830b57cec5SDimitry Andric   }
21840b57cec5SDimitry Andric 
21850b57cec5SDimitry Andric   const ToolChain &TC = C.getDefaultToolChain();
21860b57cec5SDimitry Andric 
21870b57cec5SDimitry Andric   if (C.getArgs().hasArg(options::OPT_v))
21880b57cec5SDimitry Andric     TC.printVerboseInfo(llvm::errs());
21890b57cec5SDimitry Andric 
21900b57cec5SDimitry Andric   if (C.getArgs().hasArg(options::OPT_print_resource_dir)) {
21910b57cec5SDimitry Andric     llvm::outs() << ResourceDir << '\n';
21920b57cec5SDimitry Andric     return false;
21930b57cec5SDimitry Andric   }
21940b57cec5SDimitry Andric 
21950b57cec5SDimitry Andric   if (C.getArgs().hasArg(options::OPT_print_search_dirs)) {
21960b57cec5SDimitry Andric     llvm::outs() << "programs: =";
21970b57cec5SDimitry Andric     bool separator = false;
2198e8d8bef9SDimitry Andric     // Print -B and COMPILER_PATH.
2199e8d8bef9SDimitry Andric     for (const std::string &Path : PrefixDirs) {
2200e8d8bef9SDimitry Andric       if (separator)
2201e8d8bef9SDimitry Andric         llvm::outs() << llvm::sys::EnvPathSeparator;
2202e8d8bef9SDimitry Andric       llvm::outs() << Path;
2203e8d8bef9SDimitry Andric       separator = true;
2204e8d8bef9SDimitry Andric     }
22050b57cec5SDimitry Andric     for (const std::string &Path : TC.getProgramPaths()) {
22060b57cec5SDimitry Andric       if (separator)
22070b57cec5SDimitry Andric         llvm::outs() << llvm::sys::EnvPathSeparator;
22080b57cec5SDimitry Andric       llvm::outs() << Path;
22090b57cec5SDimitry Andric       separator = true;
22100b57cec5SDimitry Andric     }
22110b57cec5SDimitry Andric     llvm::outs() << "\n";
22120b57cec5SDimitry Andric     llvm::outs() << "libraries: =" << ResourceDir;
22130b57cec5SDimitry Andric 
22140b57cec5SDimitry Andric     StringRef sysroot = C.getSysRoot();
22150b57cec5SDimitry Andric 
22160b57cec5SDimitry Andric     for (const std::string &Path : TC.getFilePaths()) {
22170b57cec5SDimitry Andric       // Always print a separator. ResourceDir was the first item shown.
22180b57cec5SDimitry Andric       llvm::outs() << llvm::sys::EnvPathSeparator;
22190b57cec5SDimitry Andric       // Interpretation of leading '=' is needed only for NetBSD.
22200b57cec5SDimitry Andric       if (Path[0] == '=')
22210b57cec5SDimitry Andric         llvm::outs() << sysroot << Path.substr(1);
22220b57cec5SDimitry Andric       else
22230b57cec5SDimitry Andric         llvm::outs() << Path;
22240b57cec5SDimitry Andric     }
22250b57cec5SDimitry Andric     llvm::outs() << "\n";
22260b57cec5SDimitry Andric     return false;
22270b57cec5SDimitry Andric   }
22280b57cec5SDimitry Andric 
22290fca6ea1SDimitry Andric   if (C.getArgs().hasArg(options::OPT_print_std_module_manifest_path)) {
22300fca6ea1SDimitry Andric     llvm::outs() << GetStdModuleManifestPath(C, C.getDefaultToolChain())
22310fca6ea1SDimitry Andric                  << '\n';
22320fca6ea1SDimitry Andric     return false;
22330fca6ea1SDimitry Andric   }
22340fca6ea1SDimitry Andric 
2235fe6060f1SDimitry Andric   if (C.getArgs().hasArg(options::OPT_print_runtime_dir)) {
22365f757f3fSDimitry Andric     if (std::optional<std::string> RuntimePath = TC.getRuntimePath())
22375f757f3fSDimitry Andric       llvm::outs() << *RuntimePath << '\n';
2238fe6060f1SDimitry Andric     else
2239fe6060f1SDimitry Andric       llvm::outs() << TC.getCompilerRTPath() << '\n';
2240fe6060f1SDimitry Andric     return false;
2241fe6060f1SDimitry Andric   }
2242fe6060f1SDimitry Andric 
224381ad6265SDimitry Andric   if (C.getArgs().hasArg(options::OPT_print_diagnostic_options)) {
224481ad6265SDimitry Andric     std::vector<std::string> Flags = DiagnosticIDs::getDiagnosticFlags();
224581ad6265SDimitry Andric     for (std::size_t I = 0; I != Flags.size(); I += 2)
224681ad6265SDimitry Andric       llvm::outs() << "  " << Flags[I] << "\n  " << Flags[I + 1] << "\n\n";
224781ad6265SDimitry Andric     return false;
224881ad6265SDimitry Andric   }
224981ad6265SDimitry Andric 
22500b57cec5SDimitry Andric   // FIXME: The following handlers should use a callback mechanism, we don't
22510b57cec5SDimitry Andric   // know what the client would like to do.
22520b57cec5SDimitry Andric   if (Arg *A = C.getArgs().getLastArg(options::OPT_print_file_name_EQ)) {
22530b57cec5SDimitry Andric     llvm::outs() << GetFilePath(A->getValue(), TC) << "\n";
22540b57cec5SDimitry Andric     return false;
22550b57cec5SDimitry Andric   }
22560b57cec5SDimitry Andric 
22570b57cec5SDimitry Andric   if (Arg *A = C.getArgs().getLastArg(options::OPT_print_prog_name_EQ)) {
22580b57cec5SDimitry Andric     StringRef ProgName = A->getValue();
22590b57cec5SDimitry Andric 
22600b57cec5SDimitry Andric     // Null program name cannot have a path.
22610b57cec5SDimitry Andric     if (! ProgName.empty())
22620b57cec5SDimitry Andric       llvm::outs() << GetProgramPath(ProgName, TC);
22630b57cec5SDimitry Andric 
22640b57cec5SDimitry Andric     llvm::outs() << "\n";
22650b57cec5SDimitry Andric     return false;
22660b57cec5SDimitry Andric   }
22670b57cec5SDimitry Andric 
22680b57cec5SDimitry Andric   if (Arg *A = C.getArgs().getLastArg(options::OPT_autocomplete)) {
22690b57cec5SDimitry Andric     StringRef PassedFlags = A->getValue();
22700b57cec5SDimitry Andric     HandleAutocompletions(PassedFlags);
22710b57cec5SDimitry Andric     return false;
22720b57cec5SDimitry Andric   }
22730b57cec5SDimitry Andric 
22740b57cec5SDimitry Andric   if (C.getArgs().hasArg(options::OPT_print_libgcc_file_name)) {
22750b57cec5SDimitry Andric     ToolChain::RuntimeLibType RLT = TC.GetRuntimeLibType(C.getArgs());
22760b57cec5SDimitry Andric     const llvm::Triple Triple(TC.ComputeEffectiveClangTriple(C.getArgs()));
22770fca6ea1SDimitry Andric     // The 'Darwin' toolchain is initialized only when its arguments are
22780fca6ea1SDimitry Andric     // computed. Get the default arguments for OFK_None to ensure that
22790fca6ea1SDimitry Andric     // initialization is performed before trying to access properties of
22800fca6ea1SDimitry Andric     // the toolchain in the functions below.
22810fca6ea1SDimitry Andric     // FIXME: Remove when darwin's toolchain is initialized during construction.
22820fca6ea1SDimitry Andric     // FIXME: For some more esoteric targets the default toolchain is not the
22830fca6ea1SDimitry Andric     //        correct one.
22840fca6ea1SDimitry Andric     C.getArgsForToolChain(&TC, Triple.getArchName(), Action::OFK_None);
22850b57cec5SDimitry Andric     RegisterEffectiveTriple TripleRAII(TC, Triple);
22860b57cec5SDimitry Andric     switch (RLT) {
22870b57cec5SDimitry Andric     case ToolChain::RLT_CompilerRT:
22880b57cec5SDimitry Andric       llvm::outs() << TC.getCompilerRT(C.getArgs(), "builtins") << "\n";
22890b57cec5SDimitry Andric       break;
22900b57cec5SDimitry Andric     case ToolChain::RLT_Libgcc:
22910b57cec5SDimitry Andric       llvm::outs() << GetFilePath("libgcc.a", TC) << "\n";
22920b57cec5SDimitry Andric       break;
22930b57cec5SDimitry Andric     }
22940b57cec5SDimitry Andric     return false;
22950b57cec5SDimitry Andric   }
22960b57cec5SDimitry Andric 
22970b57cec5SDimitry Andric   if (C.getArgs().hasArg(options::OPT_print_multi_lib)) {
22980b57cec5SDimitry Andric     for (const Multilib &Multilib : TC.getMultilibs())
22990b57cec5SDimitry Andric       llvm::outs() << Multilib << "\n";
23000b57cec5SDimitry Andric     return false;
23010b57cec5SDimitry Andric   }
23020b57cec5SDimitry Andric 
230306c3fb27SDimitry Andric   if (C.getArgs().hasArg(options::OPT_print_multi_flags)) {
230406c3fb27SDimitry Andric     Multilib::flags_list ArgFlags = TC.getMultilibFlags(C.getArgs());
230506c3fb27SDimitry Andric     llvm::StringSet<> ExpandedFlags = TC.getMultilibs().expandFlags(ArgFlags);
230606c3fb27SDimitry Andric     std::set<llvm::StringRef> SortedFlags;
230706c3fb27SDimitry Andric     for (const auto &FlagEntry : ExpandedFlags)
230806c3fb27SDimitry Andric       SortedFlags.insert(FlagEntry.getKey());
230906c3fb27SDimitry Andric     for (auto Flag : SortedFlags)
231006c3fb27SDimitry Andric       llvm::outs() << Flag << '\n';
231106c3fb27SDimitry Andric     return false;
231206c3fb27SDimitry Andric   }
231306c3fb27SDimitry Andric 
23140b57cec5SDimitry Andric   if (C.getArgs().hasArg(options::OPT_print_multi_directory)) {
231506c3fb27SDimitry Andric     for (const Multilib &Multilib : TC.getSelectedMultilibs()) {
23160b57cec5SDimitry Andric       if (Multilib.gccSuffix().empty())
23170b57cec5SDimitry Andric         llvm::outs() << ".\n";
23180b57cec5SDimitry Andric       else {
23190b57cec5SDimitry Andric         StringRef Suffix(Multilib.gccSuffix());
23200b57cec5SDimitry Andric         assert(Suffix.front() == '/');
23210b57cec5SDimitry Andric         llvm::outs() << Suffix.substr(1) << "\n";
23220b57cec5SDimitry Andric       }
232306c3fb27SDimitry Andric     }
23240b57cec5SDimitry Andric     return false;
23250b57cec5SDimitry Andric   }
23260b57cec5SDimitry Andric 
23270b57cec5SDimitry Andric   if (C.getArgs().hasArg(options::OPT_print_target_triple)) {
23280b57cec5SDimitry Andric     llvm::outs() << TC.getTripleString() << "\n";
23290b57cec5SDimitry Andric     return false;
23300b57cec5SDimitry Andric   }
23310b57cec5SDimitry Andric 
23320b57cec5SDimitry Andric   if (C.getArgs().hasArg(options::OPT_print_effective_triple)) {
23330b57cec5SDimitry Andric     const llvm::Triple Triple(TC.ComputeEffectiveClangTriple(C.getArgs()));
23340b57cec5SDimitry Andric     llvm::outs() << Triple.getTriple() << "\n";
23350b57cec5SDimitry Andric     return false;
23360b57cec5SDimitry Andric   }
23370b57cec5SDimitry Andric 
23385ffd83dbSDimitry Andric   if (C.getArgs().hasArg(options::OPT_print_targets)) {
23395ffd83dbSDimitry Andric     llvm::TargetRegistry::printRegisteredTargetsForVersion(llvm::outs());
23405ffd83dbSDimitry Andric     return false;
23415ffd83dbSDimitry Andric   }
23425ffd83dbSDimitry Andric 
23430b57cec5SDimitry Andric   return true;
23440b57cec5SDimitry Andric }
23450b57cec5SDimitry Andric 
2346a7dea167SDimitry Andric enum {
2347a7dea167SDimitry Andric   TopLevelAction = 0,
2348a7dea167SDimitry Andric   HeadSibAction = 1,
2349a7dea167SDimitry Andric   OtherSibAction = 2,
2350a7dea167SDimitry Andric };
2351a7dea167SDimitry Andric 
23520b57cec5SDimitry Andric // Display an action graph human-readably.  Action A is the "sink" node
23530b57cec5SDimitry Andric // and latest-occuring action. Traversal is in pre-order, visiting the
23540b57cec5SDimitry Andric // inputs to each action before printing the action itself.
23550b57cec5SDimitry Andric static unsigned PrintActions1(const Compilation &C, Action *A,
2356a7dea167SDimitry Andric                               std::map<Action *, unsigned> &Ids,
2357a7dea167SDimitry Andric                               Twine Indent = {}, int Kind = TopLevelAction) {
23580b57cec5SDimitry Andric   if (Ids.count(A)) // A was already visited.
23590b57cec5SDimitry Andric     return Ids[A];
23600b57cec5SDimitry Andric 
23610b57cec5SDimitry Andric   std::string str;
23620b57cec5SDimitry Andric   llvm::raw_string_ostream os(str);
23630b57cec5SDimitry Andric 
2364a7dea167SDimitry Andric   auto getSibIndent = [](int K) -> Twine {
2365a7dea167SDimitry Andric     return (K == HeadSibAction) ? "   " : (K == OtherSibAction) ? "|  " : "";
2366a7dea167SDimitry Andric   };
2367a7dea167SDimitry Andric 
2368a7dea167SDimitry Andric   Twine SibIndent = Indent + getSibIndent(Kind);
2369a7dea167SDimitry Andric   int SibKind = HeadSibAction;
23700b57cec5SDimitry Andric   os << Action::getClassName(A->getKind()) << ", ";
23710b57cec5SDimitry Andric   if (InputAction *IA = dyn_cast<InputAction>(A)) {
23720b57cec5SDimitry Andric     os << "\"" << IA->getInputArg().getValue() << "\"";
23730b57cec5SDimitry Andric   } else if (BindArchAction *BIA = dyn_cast<BindArchAction>(A)) {
23740b57cec5SDimitry Andric     os << '"' << BIA->getArchName() << '"' << ", {"
2375a7dea167SDimitry Andric        << PrintActions1(C, *BIA->input_begin(), Ids, SibIndent, SibKind) << "}";
23760b57cec5SDimitry Andric   } else if (OffloadAction *OA = dyn_cast<OffloadAction>(A)) {
23770b57cec5SDimitry Andric     bool IsFirst = true;
23780b57cec5SDimitry Andric     OA->doOnEachDependence(
23790b57cec5SDimitry Andric         [&](Action *A, const ToolChain *TC, const char *BoundArch) {
23805ffd83dbSDimitry Andric           assert(TC && "Unknown host toolchain");
23810b57cec5SDimitry Andric           // E.g. for two CUDA device dependences whose bound arch is sm_20 and
23820b57cec5SDimitry Andric           // sm_35 this will generate:
23830b57cec5SDimitry Andric           // "cuda-device" (nvptx64-nvidia-cuda:sm_20) {#ID}, "cuda-device"
23840b57cec5SDimitry Andric           // (nvptx64-nvidia-cuda:sm_35) {#ID}
23850b57cec5SDimitry Andric           if (!IsFirst)
23860b57cec5SDimitry Andric             os << ", ";
23870b57cec5SDimitry Andric           os << '"';
23880b57cec5SDimitry Andric           os << A->getOffloadingKindPrefix();
23890b57cec5SDimitry Andric           os << " (";
23900b57cec5SDimitry Andric           os << TC->getTriple().normalize();
23910b57cec5SDimitry Andric           if (BoundArch)
23920b57cec5SDimitry Andric             os << ":" << BoundArch;
23930b57cec5SDimitry Andric           os << ")";
23940b57cec5SDimitry Andric           os << '"';
2395a7dea167SDimitry Andric           os << " {" << PrintActions1(C, A, Ids, SibIndent, SibKind) << "}";
23960b57cec5SDimitry Andric           IsFirst = false;
2397a7dea167SDimitry Andric           SibKind = OtherSibAction;
23980b57cec5SDimitry Andric         });
23990b57cec5SDimitry Andric   } else {
24000b57cec5SDimitry Andric     const ActionList *AL = &A->getInputs();
24010b57cec5SDimitry Andric 
24020b57cec5SDimitry Andric     if (AL->size()) {
24030b57cec5SDimitry Andric       const char *Prefix = "{";
24040b57cec5SDimitry Andric       for (Action *PreRequisite : *AL) {
2405a7dea167SDimitry Andric         os << Prefix << PrintActions1(C, PreRequisite, Ids, SibIndent, SibKind);
24060b57cec5SDimitry Andric         Prefix = ", ";
2407a7dea167SDimitry Andric         SibKind = OtherSibAction;
24080b57cec5SDimitry Andric       }
24090b57cec5SDimitry Andric       os << "}";
24100b57cec5SDimitry Andric     } else
24110b57cec5SDimitry Andric       os << "{}";
24120b57cec5SDimitry Andric   }
24130b57cec5SDimitry Andric 
24140b57cec5SDimitry Andric   // Append offload info for all options other than the offloading action
24150b57cec5SDimitry Andric   // itself (e.g. (cuda-device, sm_20) or (cuda-host)).
24160b57cec5SDimitry Andric   std::string offload_str;
24170b57cec5SDimitry Andric   llvm::raw_string_ostream offload_os(offload_str);
24180b57cec5SDimitry Andric   if (!isa<OffloadAction>(A)) {
24190b57cec5SDimitry Andric     auto S = A->getOffloadingKindPrefix();
24200b57cec5SDimitry Andric     if (!S.empty()) {
24210b57cec5SDimitry Andric       offload_os << ", (" << S;
24220b57cec5SDimitry Andric       if (A->getOffloadingArch())
24230b57cec5SDimitry Andric         offload_os << ", " << A->getOffloadingArch();
24240b57cec5SDimitry Andric       offload_os << ")";
24250b57cec5SDimitry Andric     }
24260b57cec5SDimitry Andric   }
24270b57cec5SDimitry Andric 
2428a7dea167SDimitry Andric   auto getSelfIndent = [](int K) -> Twine {
2429a7dea167SDimitry Andric     return (K == HeadSibAction) ? "+- " : (K == OtherSibAction) ? "|- " : "";
2430a7dea167SDimitry Andric   };
2431a7dea167SDimitry Andric 
24320b57cec5SDimitry Andric   unsigned Id = Ids.size();
24330b57cec5SDimitry Andric   Ids[A] = Id;
2434a7dea167SDimitry Andric   llvm::errs() << Indent + getSelfIndent(Kind) << Id << ": " << os.str() << ", "
24350b57cec5SDimitry Andric                << types::getTypeName(A->getType()) << offload_os.str() << "\n";
24360b57cec5SDimitry Andric 
24370b57cec5SDimitry Andric   return Id;
24380b57cec5SDimitry Andric }
24390b57cec5SDimitry Andric 
24400b57cec5SDimitry Andric // Print the action graphs in a compilation C.
24410b57cec5SDimitry Andric // For example "clang -c file1.c file2.c" is composed of two subgraphs.
24420b57cec5SDimitry Andric void Driver::PrintActions(const Compilation &C) const {
24430b57cec5SDimitry Andric   std::map<Action *, unsigned> Ids;
24440b57cec5SDimitry Andric   for (Action *A : C.getActions())
24450b57cec5SDimitry Andric     PrintActions1(C, A, Ids);
24460b57cec5SDimitry Andric }
24470b57cec5SDimitry Andric 
24480b57cec5SDimitry Andric /// Check whether the given input tree contains any compilation or
24490b57cec5SDimitry Andric /// assembly actions.
24500b57cec5SDimitry Andric static bool ContainsCompileOrAssembleAction(const Action *A) {
24510b57cec5SDimitry Andric   if (isa<CompileJobAction>(A) || isa<BackendJobAction>(A) ||
24520b57cec5SDimitry Andric       isa<AssembleJobAction>(A))
24530b57cec5SDimitry Andric     return true;
24540b57cec5SDimitry Andric 
24550eae32dcSDimitry Andric   return llvm::any_of(A->inputs(), ContainsCompileOrAssembleAction);
24560b57cec5SDimitry Andric }
24570b57cec5SDimitry Andric 
24580b57cec5SDimitry Andric void Driver::BuildUniversalActions(Compilation &C, const ToolChain &TC,
24590b57cec5SDimitry Andric                                    const InputList &BAInputs) const {
24600b57cec5SDimitry Andric   DerivedArgList &Args = C.getArgs();
24610b57cec5SDimitry Andric   ActionList &Actions = C.getActions();
24620b57cec5SDimitry Andric   llvm::PrettyStackTraceString CrashInfo("Building universal build actions");
24630b57cec5SDimitry Andric   // Collect the list of architectures. Duplicates are allowed, but should only
24640b57cec5SDimitry Andric   // be handled once (in the order seen).
24650b57cec5SDimitry Andric   llvm::StringSet<> ArchNames;
24660b57cec5SDimitry Andric   SmallVector<const char *, 4> Archs;
24670b57cec5SDimitry Andric   for (Arg *A : Args) {
24680b57cec5SDimitry Andric     if (A->getOption().matches(options::OPT_arch)) {
24690b57cec5SDimitry Andric       // Validate the option here; we don't save the type here because its
24700b57cec5SDimitry Andric       // particular spelling may participate in other driver choices.
24710b57cec5SDimitry Andric       llvm::Triple::ArchType Arch =
24720b57cec5SDimitry Andric           tools::darwin::getArchTypeForMachOArchName(A->getValue());
24730b57cec5SDimitry Andric       if (Arch == llvm::Triple::UnknownArch) {
24740b57cec5SDimitry Andric         Diag(clang::diag::err_drv_invalid_arch_name) << A->getAsString(Args);
24750b57cec5SDimitry Andric         continue;
24760b57cec5SDimitry Andric       }
24770b57cec5SDimitry Andric 
24780b57cec5SDimitry Andric       A->claim();
24790b57cec5SDimitry Andric       if (ArchNames.insert(A->getValue()).second)
24800b57cec5SDimitry Andric         Archs.push_back(A->getValue());
24810b57cec5SDimitry Andric     }
24820b57cec5SDimitry Andric   }
24830b57cec5SDimitry Andric 
24840b57cec5SDimitry Andric   // When there is no explicit arch for this platform, make sure we still bind
24850b57cec5SDimitry Andric   // the architecture (to the default) so that -Xarch_ is handled correctly.
24860b57cec5SDimitry Andric   if (!Archs.size())
24870b57cec5SDimitry Andric     Archs.push_back(Args.MakeArgString(TC.getDefaultUniversalArchName()));
24880b57cec5SDimitry Andric 
24890b57cec5SDimitry Andric   ActionList SingleActions;
24900b57cec5SDimitry Andric   BuildActions(C, Args, BAInputs, SingleActions);
24910b57cec5SDimitry Andric 
24920b57cec5SDimitry Andric   // Add in arch bindings for every top level action, as well as lipo and
24930b57cec5SDimitry Andric   // dsymutil steps if needed.
24940b57cec5SDimitry Andric   for (Action* Act : SingleActions) {
24950b57cec5SDimitry Andric     // Make sure we can lipo this kind of output. If not (and it is an actual
24960b57cec5SDimitry Andric     // output) then we disallow, since we can't create an output file with the
24970b57cec5SDimitry Andric     // right name without overwriting it. We could remove this oddity by just
24980b57cec5SDimitry Andric     // changing the output names to include the arch, which would also fix
24990b57cec5SDimitry Andric     // -save-temps. Compatibility wins for now.
25000b57cec5SDimitry Andric 
25010b57cec5SDimitry Andric     if (Archs.size() > 1 && !types::canLipoType(Act->getType()))
25020b57cec5SDimitry Andric       Diag(clang::diag::err_drv_invalid_output_with_multiple_archs)
25030b57cec5SDimitry Andric           << types::getTypeName(Act->getType());
25040b57cec5SDimitry Andric 
25050b57cec5SDimitry Andric     ActionList Inputs;
25060b57cec5SDimitry Andric     for (unsigned i = 0, e = Archs.size(); i != e; ++i)
25070b57cec5SDimitry Andric       Inputs.push_back(C.MakeAction<BindArchAction>(Act, Archs[i]));
25080b57cec5SDimitry Andric 
25090b57cec5SDimitry Andric     // Lipo if necessary, we do it this way because we need to set the arch flag
25100b57cec5SDimitry Andric     // so that -Xarch_ gets overwritten.
25110b57cec5SDimitry Andric     if (Inputs.size() == 1 || Act->getType() == types::TY_Nothing)
25120b57cec5SDimitry Andric       Actions.append(Inputs.begin(), Inputs.end());
25130b57cec5SDimitry Andric     else
25140b57cec5SDimitry Andric       Actions.push_back(C.MakeAction<LipoJobAction>(Inputs, Act->getType()));
25150b57cec5SDimitry Andric 
25160b57cec5SDimitry Andric     // Handle debug info queries.
25170b57cec5SDimitry Andric     Arg *A = Args.getLastArg(options::OPT_g_Group);
2518480093f4SDimitry Andric     bool enablesDebugInfo = A && !A->getOption().matches(options::OPT_g0) &&
2519480093f4SDimitry Andric                             !A->getOption().matches(options::OPT_gstabs);
2520480093f4SDimitry Andric     if ((enablesDebugInfo || willEmitRemarks(Args)) &&
25210b57cec5SDimitry Andric         ContainsCompileOrAssembleAction(Actions.back())) {
25220b57cec5SDimitry Andric 
25230b57cec5SDimitry Andric       // Add a 'dsymutil' step if necessary, when debug info is enabled and we
25240b57cec5SDimitry Andric       // have a compile input. We need to run 'dsymutil' ourselves in such cases
25250b57cec5SDimitry Andric       // because the debug info will refer to a temporary object file which
25260b57cec5SDimitry Andric       // will be removed at the end of the compilation process.
25270b57cec5SDimitry Andric       if (Act->getType() == types::TY_Image) {
25280b57cec5SDimitry Andric         ActionList Inputs;
25290b57cec5SDimitry Andric         Inputs.push_back(Actions.back());
25300b57cec5SDimitry Andric         Actions.pop_back();
25310b57cec5SDimitry Andric         Actions.push_back(
25320b57cec5SDimitry Andric             C.MakeAction<DsymutilJobAction>(Inputs, types::TY_dSYM));
25330b57cec5SDimitry Andric       }
25340b57cec5SDimitry Andric 
25350b57cec5SDimitry Andric       // Verify the debug info output.
25360b57cec5SDimitry Andric       if (Args.hasArg(options::OPT_verify_debug_info)) {
25370b57cec5SDimitry Andric         Action* LastAction = Actions.back();
25380b57cec5SDimitry Andric         Actions.pop_back();
25390b57cec5SDimitry Andric         Actions.push_back(C.MakeAction<VerifyDebugInfoJobAction>(
25400b57cec5SDimitry Andric             LastAction, types::TY_Nothing));
25410b57cec5SDimitry Andric       }
25420b57cec5SDimitry Andric     }
25430b57cec5SDimitry Andric   }
25440b57cec5SDimitry Andric }
25450b57cec5SDimitry Andric 
25460b57cec5SDimitry Andric bool Driver::DiagnoseInputExistence(const DerivedArgList &Args, StringRef Value,
25470b57cec5SDimitry Andric                                     types::ID Ty, bool TypoCorrect) const {
25480b57cec5SDimitry Andric   if (!getCheckInputsExist())
25490b57cec5SDimitry Andric     return true;
25500b57cec5SDimitry Andric 
25510b57cec5SDimitry Andric   // stdin always exists.
25520b57cec5SDimitry Andric   if (Value == "-")
25530b57cec5SDimitry Andric     return true;
25540b57cec5SDimitry Andric 
255581ad6265SDimitry Andric   // If it's a header to be found in the system or user search path, then defer
255681ad6265SDimitry Andric   // complaints about its absence until those searches can be done.  When we
255781ad6265SDimitry Andric   // are definitely processing headers for C++20 header units, extend this to
255881ad6265SDimitry Andric   // allow the user to put "-fmodule-header -xc++-header vector" for example.
255981ad6265SDimitry Andric   if (Ty == types::TY_CXXSHeader || Ty == types::TY_CXXUHeader ||
256081ad6265SDimitry Andric       (ModulesModeCXX20 && Ty == types::TY_CXXHeader))
256181ad6265SDimitry Andric     return true;
256281ad6265SDimitry Andric 
2563480093f4SDimitry Andric   if (getVFS().exists(Value))
25640b57cec5SDimitry Andric     return true;
25650b57cec5SDimitry Andric 
25660b57cec5SDimitry Andric   if (TypoCorrect) {
25670b57cec5SDimitry Andric     // Check if the filename is a typo for an option flag. OptTable thinks
25680b57cec5SDimitry Andric     // that all args that are not known options and that start with / are
25690b57cec5SDimitry Andric     // filenames, but e.g. `/diagnostic:caret` is more likely a typo for
25700b57cec5SDimitry Andric     // the option `/diagnostics:caret` than a reference to a file in the root
25710b57cec5SDimitry Andric     // directory.
25720b57cec5SDimitry Andric     std::string Nearest;
25735f757f3fSDimitry Andric     if (getOpts().findNearest(Value, Nearest, getOptionVisibilityMask()) <= 1) {
25740b57cec5SDimitry Andric       Diag(clang::diag::err_drv_no_such_file_with_suggestion)
2575480093f4SDimitry Andric           << Value << Nearest;
25760b57cec5SDimitry Andric       return false;
25770b57cec5SDimitry Andric     }
25780b57cec5SDimitry Andric   }
25790b57cec5SDimitry Andric 
2580349cc55cSDimitry Andric   // In CL mode, don't error on apparently non-existent linker inputs, because
2581349cc55cSDimitry Andric   // they can be influenced by linker flags the clang driver might not
2582349cc55cSDimitry Andric   // understand.
2583349cc55cSDimitry Andric   // Examples:
2584bdd1243dSDimitry Andric   // - `clang-cl main.cc ole32.lib` in a non-MSVC shell will make the driver
2585349cc55cSDimitry Andric   //   module look for an MSVC installation in the registry. (We could ask
2586349cc55cSDimitry Andric   //   the MSVCToolChain object if it can find `ole32.lib`, but the logic to
2587349cc55cSDimitry Andric   //   look in the registry might move into lld-link in the future so that
2588349cc55cSDimitry Andric   //   lld-link invocations in non-MSVC shells just work too.)
2589349cc55cSDimitry Andric   // - `clang-cl ... /link ...` can pass arbitrary flags to the linker,
2590349cc55cSDimitry Andric   //   including /libpath:, which is used to find .lib and .obj files.
2591349cc55cSDimitry Andric   // So do not diagnose this on the driver level. Rely on the linker diagnosing
2592349cc55cSDimitry Andric   // it. (If we don't end up invoking the linker, this means we'll emit a
2593349cc55cSDimitry Andric   // "'linker' input unused [-Wunused-command-line-argument]" warning instead
2594349cc55cSDimitry Andric   // of an error.)
2595349cc55cSDimitry Andric   //
2596349cc55cSDimitry Andric   // Only do this skip after the typo correction step above. `/Brepo` is treated
2597349cc55cSDimitry Andric   // as TY_Object, but it's clearly a typo for `/Brepro`. It seems fine to emit
2598349cc55cSDimitry Andric   // an error if we have a flag that's within an edit distance of 1 from a
2599349cc55cSDimitry Andric   // flag. (Users can use `-Wl,` or `/linker` to launder the flag past the
2600349cc55cSDimitry Andric   // driver in the unlikely case they run into this.)
2601349cc55cSDimitry Andric   //
2602349cc55cSDimitry Andric   // Don't do this for inputs that start with a '/', else we'd pass options
2603349cc55cSDimitry Andric   // like /libpath: through to the linker silently.
2604349cc55cSDimitry Andric   //
2605349cc55cSDimitry Andric   // Emitting an error for linker inputs can also cause incorrect diagnostics
2606349cc55cSDimitry Andric   // with the gcc driver. The command
2607349cc55cSDimitry Andric   //     clang -fuse-ld=lld -Wl,--chroot,some/dir /file.o
2608349cc55cSDimitry Andric   // will make lld look for some/dir/file.o, while we will diagnose here that
2609349cc55cSDimitry Andric   // `/file.o` does not exist. However, configure scripts check if
2610349cc55cSDimitry Andric   // `clang /GR-` compiles without error to see if the compiler is cl.exe,
2611349cc55cSDimitry Andric   // so we can't downgrade diagnostics for `/GR-` from an error to a warning
2612349cc55cSDimitry Andric   // in cc mode. (We can in cl mode because cl.exe itself only warns on
2613349cc55cSDimitry Andric   // unknown flags.)
26145f757f3fSDimitry Andric   if (IsCLMode() && Ty == types::TY_Object && !Value.starts_with("/"))
2615349cc55cSDimitry Andric     return true;
2616349cc55cSDimitry Andric 
2617480093f4SDimitry Andric   Diag(clang::diag::err_drv_no_such_file) << Value;
26180b57cec5SDimitry Andric   return false;
26190b57cec5SDimitry Andric }
26200b57cec5SDimitry Andric 
262181ad6265SDimitry Andric // Get the C++20 Header Unit type corresponding to the input type.
262281ad6265SDimitry Andric static types::ID CXXHeaderUnitType(ModuleHeaderMode HM) {
262381ad6265SDimitry Andric   switch (HM) {
262481ad6265SDimitry Andric   case HeaderMode_User:
262581ad6265SDimitry Andric     return types::TY_CXXUHeader;
262681ad6265SDimitry Andric   case HeaderMode_System:
262781ad6265SDimitry Andric     return types::TY_CXXSHeader;
262881ad6265SDimitry Andric   case HeaderMode_Default:
262981ad6265SDimitry Andric     break;
263081ad6265SDimitry Andric   case HeaderMode_None:
263181ad6265SDimitry Andric     llvm_unreachable("should not be called in this case");
263281ad6265SDimitry Andric   }
263381ad6265SDimitry Andric   return types::TY_CXXHUHeader;
263481ad6265SDimitry Andric }
263581ad6265SDimitry Andric 
26360b57cec5SDimitry Andric // Construct a the list of inputs and their types.
26370b57cec5SDimitry Andric void Driver::BuildInputs(const ToolChain &TC, DerivedArgList &Args,
26380b57cec5SDimitry Andric                          InputList &Inputs) const {
2639a7dea167SDimitry Andric   const llvm::opt::OptTable &Opts = getOpts();
26400b57cec5SDimitry Andric   // Track the current user specified (-x) input. We also explicitly track the
26410b57cec5SDimitry Andric   // argument used to set the type; we only want to claim the type when we
26420b57cec5SDimitry Andric   // actually use it, so we warn about unused -x arguments.
26430b57cec5SDimitry Andric   types::ID InputType = types::TY_Nothing;
26440b57cec5SDimitry Andric   Arg *InputTypeArg = nullptr;
26450b57cec5SDimitry Andric 
26460b57cec5SDimitry Andric   // The last /TC or /TP option sets the input type to C or C++ globally.
26470b57cec5SDimitry Andric   if (Arg *TCTP = Args.getLastArgNoClaim(options::OPT__SLASH_TC,
26480b57cec5SDimitry Andric                                          options::OPT__SLASH_TP)) {
26490b57cec5SDimitry Andric     InputTypeArg = TCTP;
26500b57cec5SDimitry Andric     InputType = TCTP->getOption().matches(options::OPT__SLASH_TC)
26510b57cec5SDimitry Andric                     ? types::TY_C
26520b57cec5SDimitry Andric                     : types::TY_CXX;
26530b57cec5SDimitry Andric 
26540b57cec5SDimitry Andric     Arg *Previous = nullptr;
26550b57cec5SDimitry Andric     bool ShowNote = false;
26560b57cec5SDimitry Andric     for (Arg *A :
26570b57cec5SDimitry Andric          Args.filtered(options::OPT__SLASH_TC, options::OPT__SLASH_TP)) {
26580b57cec5SDimitry Andric       if (Previous) {
26595f757f3fSDimitry Andric         Diag(clang::diag::warn_drv_overriding_option)
26600b57cec5SDimitry Andric             << Previous->getSpelling() << A->getSpelling();
26610b57cec5SDimitry Andric         ShowNote = true;
26620b57cec5SDimitry Andric       }
26630b57cec5SDimitry Andric       Previous = A;
26640b57cec5SDimitry Andric     }
26650b57cec5SDimitry Andric     if (ShowNote)
26660b57cec5SDimitry Andric       Diag(clang::diag::note_drv_t_option_is_global);
26670b57cec5SDimitry Andric   }
26680b57cec5SDimitry Andric 
266981ad6265SDimitry Andric   // Warn -x after last input file has no effect
26700fca6ea1SDimitry Andric   {
267181ad6265SDimitry Andric     Arg *LastXArg = Args.getLastArgNoClaim(options::OPT_x);
267281ad6265SDimitry Andric     Arg *LastInputArg = Args.getLastArgNoClaim(options::OPT_INPUT);
267306c3fb27SDimitry Andric     if (LastXArg && LastInputArg &&
267406c3fb27SDimitry Andric         LastInputArg->getIndex() < LastXArg->getIndex())
267581ad6265SDimitry Andric       Diag(clang::diag::warn_drv_unused_x) << LastXArg->getValue();
267681ad6265SDimitry Andric   }
267781ad6265SDimitry Andric 
26780b57cec5SDimitry Andric   for (Arg *A : Args) {
26790b57cec5SDimitry Andric     if (A->getOption().getKind() == Option::InputClass) {
26800b57cec5SDimitry Andric       const char *Value = A->getValue();
26810b57cec5SDimitry Andric       types::ID Ty = types::TY_INVALID;
26820b57cec5SDimitry Andric 
26830b57cec5SDimitry Andric       // Infer the input type if necessary.
26840b57cec5SDimitry Andric       if (InputType == types::TY_Nothing) {
26850b57cec5SDimitry Andric         // If there was an explicit arg for this, claim it.
26860b57cec5SDimitry Andric         if (InputTypeArg)
26870b57cec5SDimitry Andric           InputTypeArg->claim();
26880b57cec5SDimitry Andric 
26890b57cec5SDimitry Andric         // stdin must be handled specially.
26900b57cec5SDimitry Andric         if (memcmp(Value, "-", 2) == 0) {
2691fe6060f1SDimitry Andric           if (IsFlangMode()) {
2692fe6060f1SDimitry Andric             Ty = types::TY_Fortran;
26935f757f3fSDimitry Andric           } else if (IsDXCMode()) {
26945f757f3fSDimitry Andric             Ty = types::TY_HLSL;
2695fe6060f1SDimitry Andric           } else {
2696fe6060f1SDimitry Andric             // If running with -E, treat as a C input (this changes the
2697fe6060f1SDimitry Andric             // builtin macros, for example). This may be overridden by -ObjC
2698fe6060f1SDimitry Andric             // below.
26990b57cec5SDimitry Andric             //
27000b57cec5SDimitry Andric             // Otherwise emit an error but still use a valid type to avoid
27010b57cec5SDimitry Andric             // spurious errors (e.g., no inputs).
2702349cc55cSDimitry Andric             assert(!CCGenDiagnostics && "stdin produces no crash reproducer");
27030b57cec5SDimitry Andric             if (!Args.hasArgNoClaim(options::OPT_E) && !CCCIsCPP())
27040b57cec5SDimitry Andric               Diag(IsCLMode() ? clang::diag::err_drv_unknown_stdin_type_clang_cl
27050b57cec5SDimitry Andric                               : clang::diag::err_drv_unknown_stdin_type);
27060b57cec5SDimitry Andric             Ty = types::TY_C;
2707fe6060f1SDimitry Andric           }
27080b57cec5SDimitry Andric         } else {
27090b57cec5SDimitry Andric           // Otherwise lookup by extension.
27100b57cec5SDimitry Andric           // Fallback is C if invoked as C preprocessor, C++ if invoked with
27110b57cec5SDimitry Andric           // clang-cl /E, or Object otherwise.
27120b57cec5SDimitry Andric           // We use a host hook here because Darwin at least has its own
27130b57cec5SDimitry Andric           // idea of what .s is.
27140b57cec5SDimitry Andric           if (const char *Ext = strrchr(Value, '.'))
27150b57cec5SDimitry Andric             Ty = TC.LookupTypeForExtension(Ext + 1);
27160b57cec5SDimitry Andric 
27170b57cec5SDimitry Andric           if (Ty == types::TY_INVALID) {
2718349cc55cSDimitry Andric             if (IsCLMode() && (Args.hasArgNoClaim(options::OPT_E) || CCGenDiagnostics))
27190b57cec5SDimitry Andric               Ty = types::TY_CXX;
2720349cc55cSDimitry Andric             else if (CCCIsCPP() || CCGenDiagnostics)
2721349cc55cSDimitry Andric               Ty = types::TY_C;
27220b57cec5SDimitry Andric             else
27230b57cec5SDimitry Andric               Ty = types::TY_Object;
27240b57cec5SDimitry Andric           }
27250b57cec5SDimitry Andric 
27260b57cec5SDimitry Andric           // If the driver is invoked as C++ compiler (like clang++ or c++) it
27270b57cec5SDimitry Andric           // should autodetect some input files as C++ for g++ compatibility.
27280b57cec5SDimitry Andric           if (CCCIsCXX()) {
27290b57cec5SDimitry Andric             types::ID OldTy = Ty;
27300b57cec5SDimitry Andric             Ty = types::lookupCXXTypeForCType(Ty);
27310b57cec5SDimitry Andric 
273281ad6265SDimitry Andric             // Do not complain about foo.h, when we are known to be processing
273381ad6265SDimitry Andric             // it as a C++20 header unit.
273481ad6265SDimitry Andric             if (Ty != OldTy && !(OldTy == types::TY_CHeader && hasHeaderMode()))
27350b57cec5SDimitry Andric               Diag(clang::diag::warn_drv_treating_input_as_cxx)
27360b57cec5SDimitry Andric                   << getTypeName(OldTy) << getTypeName(Ty);
27370b57cec5SDimitry Andric           }
27380b57cec5SDimitry Andric 
27390b57cec5SDimitry Andric           // If running with -fthinlto-index=, extensions that normally identify
27400b57cec5SDimitry Andric           // native object files actually identify LLVM bitcode files.
27410b57cec5SDimitry Andric           if (Args.hasArgNoClaim(options::OPT_fthinlto_index_EQ) &&
27420b57cec5SDimitry Andric               Ty == types::TY_Object)
27430b57cec5SDimitry Andric             Ty = types::TY_LLVM_BC;
27440b57cec5SDimitry Andric         }
27450b57cec5SDimitry Andric 
27460b57cec5SDimitry Andric         // -ObjC and -ObjC++ override the default language, but only for "source
27470b57cec5SDimitry Andric         // files". We just treat everything that isn't a linker input as a
27480b57cec5SDimitry Andric         // source file.
27490b57cec5SDimitry Andric         //
27500b57cec5SDimitry Andric         // FIXME: Clean this up if we move the phase sequence into the type.
27510b57cec5SDimitry Andric         if (Ty != types::TY_Object) {
27520b57cec5SDimitry Andric           if (Args.hasArg(options::OPT_ObjC))
27530b57cec5SDimitry Andric             Ty = types::TY_ObjC;
27540b57cec5SDimitry Andric           else if (Args.hasArg(options::OPT_ObjCXX))
27550b57cec5SDimitry Andric             Ty = types::TY_ObjCXX;
27560b57cec5SDimitry Andric         }
275781ad6265SDimitry Andric 
275881ad6265SDimitry Andric         // Disambiguate headers that are meant to be header units from those
275981ad6265SDimitry Andric         // intended to be PCH.  Avoid missing '.h' cases that are counted as
276081ad6265SDimitry Andric         // C headers by default - we know we are in C++ mode and we do not
276181ad6265SDimitry Andric         // want to issue a complaint about compiling things in the wrong mode.
276281ad6265SDimitry Andric         if ((Ty == types::TY_CXXHeader || Ty == types::TY_CHeader) &&
276381ad6265SDimitry Andric             hasHeaderMode())
276481ad6265SDimitry Andric           Ty = CXXHeaderUnitType(CXX20HeaderType);
27650b57cec5SDimitry Andric       } else {
27660b57cec5SDimitry Andric         assert(InputTypeArg && "InputType set w/o InputTypeArg");
27670b57cec5SDimitry Andric         if (!InputTypeArg->getOption().matches(options::OPT_x)) {
27680b57cec5SDimitry Andric           // If emulating cl.exe, make sure that /TC and /TP don't affect input
27690b57cec5SDimitry Andric           // object files.
27700b57cec5SDimitry Andric           const char *Ext = strrchr(Value, '.');
27710b57cec5SDimitry Andric           if (Ext && TC.LookupTypeForExtension(Ext + 1) == types::TY_Object)
27720b57cec5SDimitry Andric             Ty = types::TY_Object;
27730b57cec5SDimitry Andric         }
27740b57cec5SDimitry Andric         if (Ty == types::TY_INVALID) {
27750b57cec5SDimitry Andric           Ty = InputType;
27760b57cec5SDimitry Andric           InputTypeArg->claim();
27770b57cec5SDimitry Andric         }
27780b57cec5SDimitry Andric       }
27790b57cec5SDimitry Andric 
27805f757f3fSDimitry Andric       if ((Ty == types::TY_C || Ty == types::TY_CXX) &&
27815f757f3fSDimitry Andric           Args.hasArgNoClaim(options::OPT_hipstdpar))
27825f757f3fSDimitry Andric         Ty = types::TY_HIP;
27835f757f3fSDimitry Andric 
27840b57cec5SDimitry Andric       if (DiagnoseInputExistence(Args, Value, Ty, /*TypoCorrect=*/true))
27850b57cec5SDimitry Andric         Inputs.push_back(std::make_pair(Ty, A));
27860b57cec5SDimitry Andric 
27870b57cec5SDimitry Andric     } else if (A->getOption().matches(options::OPT__SLASH_Tc)) {
27880b57cec5SDimitry Andric       StringRef Value = A->getValue();
27890b57cec5SDimitry Andric       if (DiagnoseInputExistence(Args, Value, types::TY_C,
27900b57cec5SDimitry Andric                                  /*TypoCorrect=*/false)) {
2791a7dea167SDimitry Andric         Arg *InputArg = MakeInputArg(Args, Opts, A->getValue());
27920b57cec5SDimitry Andric         Inputs.push_back(std::make_pair(types::TY_C, InputArg));
27930b57cec5SDimitry Andric       }
27940b57cec5SDimitry Andric       A->claim();
27950b57cec5SDimitry Andric     } else if (A->getOption().matches(options::OPT__SLASH_Tp)) {
27960b57cec5SDimitry Andric       StringRef Value = A->getValue();
27970b57cec5SDimitry Andric       if (DiagnoseInputExistence(Args, Value, types::TY_CXX,
27980b57cec5SDimitry Andric                                  /*TypoCorrect=*/false)) {
2799a7dea167SDimitry Andric         Arg *InputArg = MakeInputArg(Args, Opts, A->getValue());
28000b57cec5SDimitry Andric         Inputs.push_back(std::make_pair(types::TY_CXX, InputArg));
28010b57cec5SDimitry Andric       }
28020b57cec5SDimitry Andric       A->claim();
28030b57cec5SDimitry Andric     } else if (A->getOption().hasFlag(options::LinkerInput)) {
28040b57cec5SDimitry Andric       // Just treat as object type, we could make a special type for this if
28050b57cec5SDimitry Andric       // necessary.
28060b57cec5SDimitry Andric       Inputs.push_back(std::make_pair(types::TY_Object, A));
28070b57cec5SDimitry Andric 
28080b57cec5SDimitry Andric     } else if (A->getOption().matches(options::OPT_x)) {
28090b57cec5SDimitry Andric       InputTypeArg = A;
28100b57cec5SDimitry Andric       InputType = types::lookupTypeForTypeSpecifier(A->getValue());
28110b57cec5SDimitry Andric       A->claim();
28120b57cec5SDimitry Andric 
28130b57cec5SDimitry Andric       // Follow gcc behavior and treat as linker input for invalid -x
28140b57cec5SDimitry Andric       // options. Its not clear why we shouldn't just revert to unknown; but
28150b57cec5SDimitry Andric       // this isn't very important, we might as well be bug compatible.
28160b57cec5SDimitry Andric       if (!InputType) {
28170b57cec5SDimitry Andric         Diag(clang::diag::err_drv_unknown_language) << A->getValue();
28180b57cec5SDimitry Andric         InputType = types::TY_Object;
28190b57cec5SDimitry Andric       }
282081ad6265SDimitry Andric 
282181ad6265SDimitry Andric       // If the user has put -fmodule-header{,=} then we treat C++ headers as
282281ad6265SDimitry Andric       // header unit inputs.  So we 'promote' -xc++-header appropriately.
282381ad6265SDimitry Andric       if (InputType == types::TY_CXXHeader && hasHeaderMode())
282481ad6265SDimitry Andric         InputType = CXXHeaderUnitType(CXX20HeaderType);
28250b57cec5SDimitry Andric     } else if (A->getOption().getID() == options::OPT_U) {
28260b57cec5SDimitry Andric       assert(A->getNumValues() == 1 && "The /U option has one value.");
28270b57cec5SDimitry Andric       StringRef Val = A->getValue(0);
28280b57cec5SDimitry Andric       if (Val.find_first_of("/\\") != StringRef::npos) {
28290b57cec5SDimitry Andric         // Warn about e.g. "/Users/me/myfile.c".
28300b57cec5SDimitry Andric         Diag(diag::warn_slash_u_filename) << Val;
28310b57cec5SDimitry Andric         Diag(diag::note_use_dashdash);
28320b57cec5SDimitry Andric       }
28330b57cec5SDimitry Andric     }
28340b57cec5SDimitry Andric   }
28350b57cec5SDimitry Andric   if (CCCIsCPP() && Inputs.empty()) {
28360b57cec5SDimitry Andric     // If called as standalone preprocessor, stdin is processed
28370b57cec5SDimitry Andric     // if no other input is present.
2838a7dea167SDimitry Andric     Arg *A = MakeInputArg(Args, Opts, "-");
28390b57cec5SDimitry Andric     Inputs.push_back(std::make_pair(types::TY_C, A));
28400b57cec5SDimitry Andric   }
28410b57cec5SDimitry Andric }
28420b57cec5SDimitry Andric 
28430b57cec5SDimitry Andric namespace {
28440b57cec5SDimitry Andric /// Provides a convenient interface for different programming models to generate
28450b57cec5SDimitry Andric /// the required device actions.
28460b57cec5SDimitry Andric class OffloadingActionBuilder final {
28470b57cec5SDimitry Andric   /// Flag used to trace errors in the builder.
28480b57cec5SDimitry Andric   bool IsValid = false;
28490b57cec5SDimitry Andric 
28500b57cec5SDimitry Andric   /// The compilation that is using this builder.
28510b57cec5SDimitry Andric   Compilation &C;
28520b57cec5SDimitry Andric 
28530b57cec5SDimitry Andric   /// Map between an input argument and the offload kinds used to process it.
28540b57cec5SDimitry Andric   std::map<const Arg *, unsigned> InputArgToOffloadKindMap;
28550b57cec5SDimitry Andric 
285681ad6265SDimitry Andric   /// Map between a host action and its originating input argument.
285781ad6265SDimitry Andric   std::map<Action *, const Arg *> HostActionToInputArgMap;
285881ad6265SDimitry Andric 
28590b57cec5SDimitry Andric   /// Builder interface. It doesn't build anything or keep any state.
28600b57cec5SDimitry Andric   class DeviceActionBuilder {
28610b57cec5SDimitry Andric   public:
2862a7dea167SDimitry Andric     typedef const llvm::SmallVectorImpl<phases::ID> PhasesTy;
28630b57cec5SDimitry Andric 
28640b57cec5SDimitry Andric     enum ActionBuilderReturnCode {
28650b57cec5SDimitry Andric       // The builder acted successfully on the current action.
28660b57cec5SDimitry Andric       ABRT_Success,
28670b57cec5SDimitry Andric       // The builder didn't have to act on the current action.
28680b57cec5SDimitry Andric       ABRT_Inactive,
28690b57cec5SDimitry Andric       // The builder was successful and requested the host action to not be
28700b57cec5SDimitry Andric       // generated.
28710b57cec5SDimitry Andric       ABRT_Ignore_Host,
28720b57cec5SDimitry Andric     };
28730b57cec5SDimitry Andric 
28740b57cec5SDimitry Andric   protected:
28750b57cec5SDimitry Andric     /// Compilation associated with this builder.
28760b57cec5SDimitry Andric     Compilation &C;
28770b57cec5SDimitry Andric 
28780b57cec5SDimitry Andric     /// Tool chains associated with this builder. The same programming
28790b57cec5SDimitry Andric     /// model may have associated one or more tool chains.
28800b57cec5SDimitry Andric     SmallVector<const ToolChain *, 2> ToolChains;
28810b57cec5SDimitry Andric 
28820b57cec5SDimitry Andric     /// The derived arguments associated with this builder.
28830b57cec5SDimitry Andric     DerivedArgList &Args;
28840b57cec5SDimitry Andric 
28850b57cec5SDimitry Andric     /// The inputs associated with this builder.
28860b57cec5SDimitry Andric     const Driver::InputList &Inputs;
28870b57cec5SDimitry Andric 
28880b57cec5SDimitry Andric     /// The associated offload kind.
28890b57cec5SDimitry Andric     Action::OffloadKind AssociatedOffloadKind = Action::OFK_None;
28900b57cec5SDimitry Andric 
28910b57cec5SDimitry Andric   public:
28920b57cec5SDimitry Andric     DeviceActionBuilder(Compilation &C, DerivedArgList &Args,
28930b57cec5SDimitry Andric                         const Driver::InputList &Inputs,
28940b57cec5SDimitry Andric                         Action::OffloadKind AssociatedOffloadKind)
28950b57cec5SDimitry Andric         : C(C), Args(Args), Inputs(Inputs),
28960b57cec5SDimitry Andric           AssociatedOffloadKind(AssociatedOffloadKind) {}
28970b57cec5SDimitry Andric     virtual ~DeviceActionBuilder() {}
28980b57cec5SDimitry Andric 
28990b57cec5SDimitry Andric     /// Fill up the array \a DA with all the device dependences that should be
29000b57cec5SDimitry Andric     /// added to the provided host action \a HostAction. By default it is
29010b57cec5SDimitry Andric     /// inactive.
29020b57cec5SDimitry Andric     virtual ActionBuilderReturnCode
29030b57cec5SDimitry Andric     getDeviceDependences(OffloadAction::DeviceDependences &DA,
29040b57cec5SDimitry Andric                          phases::ID CurPhase, phases::ID FinalPhase,
29050b57cec5SDimitry Andric                          PhasesTy &Phases) {
29060b57cec5SDimitry Andric       return ABRT_Inactive;
29070b57cec5SDimitry Andric     }
29080b57cec5SDimitry Andric 
29090b57cec5SDimitry Andric     /// Update the state to include the provided host action \a HostAction as a
29100b57cec5SDimitry Andric     /// dependency of the current device action. By default it is inactive.
2911bdd1243dSDimitry Andric     virtual ActionBuilderReturnCode addDeviceDependences(Action *HostAction) {
29120b57cec5SDimitry Andric       return ABRT_Inactive;
29130b57cec5SDimitry Andric     }
29140b57cec5SDimitry Andric 
2915a7dea167SDimitry Andric     /// Append top level actions generated by the builder.
29160b57cec5SDimitry Andric     virtual void appendTopLevelActions(ActionList &AL) {}
29170b57cec5SDimitry Andric 
29185ffd83dbSDimitry Andric     /// Append linker device actions generated by the builder.
29195ffd83dbSDimitry Andric     virtual void appendLinkDeviceActions(ActionList &AL) {}
29205ffd83dbSDimitry Andric 
29215ffd83dbSDimitry Andric     /// Append linker host action generated by the builder.
29225ffd83dbSDimitry Andric     virtual Action* appendLinkHostActions(ActionList &AL) { return nullptr; }
2923a7dea167SDimitry Andric 
2924a7dea167SDimitry Andric     /// Append linker actions generated by the builder.
29250b57cec5SDimitry Andric     virtual void appendLinkDependences(OffloadAction::DeviceDependences &DA) {}
29260b57cec5SDimitry Andric 
29270b57cec5SDimitry Andric     /// Initialize the builder. Return true if any initialization errors are
29280b57cec5SDimitry Andric     /// found.
29290b57cec5SDimitry Andric     virtual bool initialize() { return false; }
29300b57cec5SDimitry Andric 
29310b57cec5SDimitry Andric     /// Return true if the builder can use bundling/unbundling.
29320b57cec5SDimitry Andric     virtual bool canUseBundlerUnbundler() const { return false; }
29330b57cec5SDimitry Andric 
29340b57cec5SDimitry Andric     /// Return true if this builder is valid. We have a valid builder if we have
29350b57cec5SDimitry Andric     /// associated device tool chains.
29360b57cec5SDimitry Andric     bool isValid() { return !ToolChains.empty(); }
29370b57cec5SDimitry Andric 
29380b57cec5SDimitry Andric     /// Return the associated offload kind.
29390b57cec5SDimitry Andric     Action::OffloadKind getAssociatedOffloadKind() {
29400b57cec5SDimitry Andric       return AssociatedOffloadKind;
29410b57cec5SDimitry Andric     }
29420b57cec5SDimitry Andric   };
29430b57cec5SDimitry Andric 
29440b57cec5SDimitry Andric   /// Base class for CUDA/HIP action builder. It injects device code in
29450b57cec5SDimitry Andric   /// the host backend action.
29460b57cec5SDimitry Andric   class CudaActionBuilderBase : public DeviceActionBuilder {
29470b57cec5SDimitry Andric   protected:
29480b57cec5SDimitry Andric     /// Flags to signal if the user requested host-only or device-only
29490b57cec5SDimitry Andric     /// compilation.
29500b57cec5SDimitry Andric     bool CompileHostOnly = false;
29510b57cec5SDimitry Andric     bool CompileDeviceOnly = false;
2952a7dea167SDimitry Andric     bool EmitLLVM = false;
2953a7dea167SDimitry Andric     bool EmitAsm = false;
29540b57cec5SDimitry Andric 
2955e8d8bef9SDimitry Andric     /// ID to identify each device compilation. For CUDA it is simply the
2956e8d8bef9SDimitry Andric     /// GPU arch string. For HIP it is either the GPU arch string or GPU
2957e8d8bef9SDimitry Andric     /// arch string plus feature strings delimited by a plus sign, e.g.
2958e8d8bef9SDimitry Andric     /// gfx906+xnack.
2959e8d8bef9SDimitry Andric     struct TargetID {
2960e8d8bef9SDimitry Andric       /// Target ID string which is persistent throughout the compilation.
2961e8d8bef9SDimitry Andric       const char *ID;
29620fca6ea1SDimitry Andric       TargetID(OffloadArch Arch) { ID = OffloadArchToString(Arch); }
2963e8d8bef9SDimitry Andric       TargetID(const char *ID) : ID(ID) {}
2964e8d8bef9SDimitry Andric       operator const char *() { return ID; }
2965e8d8bef9SDimitry Andric       operator StringRef() { return StringRef(ID); }
2966e8d8bef9SDimitry Andric     };
29670b57cec5SDimitry Andric     /// List of GPU architectures to use in this compilation.
2968e8d8bef9SDimitry Andric     SmallVector<TargetID, 4> GpuArchList;
29690b57cec5SDimitry Andric 
29700b57cec5SDimitry Andric     /// The CUDA actions for the current input.
29710b57cec5SDimitry Andric     ActionList CudaDeviceActions;
29720b57cec5SDimitry Andric 
29730b57cec5SDimitry Andric     /// The CUDA fat binary if it was generated for the current input.
29740b57cec5SDimitry Andric     Action *CudaFatBinary = nullptr;
29750b57cec5SDimitry Andric 
29760b57cec5SDimitry Andric     /// Flag that is set to true if this builder acted on the current input.
29770b57cec5SDimitry Andric     bool IsActive = false;
29780b57cec5SDimitry Andric 
29790b57cec5SDimitry Andric     /// Flag for -fgpu-rdc.
29800b57cec5SDimitry Andric     bool Relocatable = false;
2981a7dea167SDimitry Andric 
2982a7dea167SDimitry Andric     /// Default GPU architecture if there's no one specified.
29830fca6ea1SDimitry Andric     OffloadArch DefaultOffloadArch = OffloadArch::UNKNOWN;
2984a7dea167SDimitry Andric 
2985fe6060f1SDimitry Andric     /// Method to generate compilation unit ID specified by option
2986fe6060f1SDimitry Andric     /// '-fuse-cuid='.
2987fe6060f1SDimitry Andric     enum UseCUIDKind { CUID_Hash, CUID_Random, CUID_None, CUID_Invalid };
2988fe6060f1SDimitry Andric     UseCUIDKind UseCUID = CUID_Hash;
2989fe6060f1SDimitry Andric 
2990fe6060f1SDimitry Andric     /// Compilation unit ID specified by option '-cuid='.
2991fe6060f1SDimitry Andric     StringRef FixedCUID;
2992fe6060f1SDimitry Andric 
29930b57cec5SDimitry Andric   public:
29940b57cec5SDimitry Andric     CudaActionBuilderBase(Compilation &C, DerivedArgList &Args,
29950b57cec5SDimitry Andric                           const Driver::InputList &Inputs,
29960b57cec5SDimitry Andric                           Action::OffloadKind OFKind)
299706c3fb27SDimitry Andric         : DeviceActionBuilder(C, Args, Inputs, OFKind) {
299806c3fb27SDimitry Andric 
299906c3fb27SDimitry Andric       CompileDeviceOnly = C.getDriver().offloadDeviceOnly();
300006c3fb27SDimitry Andric       Relocatable = Args.hasFlag(options::OPT_fgpu_rdc,
300106c3fb27SDimitry Andric                                  options::OPT_fno_gpu_rdc, /*Default=*/false);
300206c3fb27SDimitry Andric     }
30030b57cec5SDimitry Andric 
3004bdd1243dSDimitry Andric     ActionBuilderReturnCode addDeviceDependences(Action *HostAction) override {
30050b57cec5SDimitry Andric       // While generating code for CUDA, we only depend on the host input action
30060b57cec5SDimitry Andric       // to trigger the creation of all the CUDA device actions.
30070b57cec5SDimitry Andric 
30080b57cec5SDimitry Andric       // If we are dealing with an input action, replicate it for each GPU
30090b57cec5SDimitry Andric       // architecture. If we are in host-only mode we return 'success' so that
30100b57cec5SDimitry Andric       // the host uses the CUDA offload kind.
30110b57cec5SDimitry Andric       if (auto *IA = dyn_cast<InputAction>(HostAction)) {
30120b57cec5SDimitry Andric         assert(!GpuArchList.empty() &&
30130b57cec5SDimitry Andric                "We should have at least one GPU architecture.");
30140b57cec5SDimitry Andric 
30150b57cec5SDimitry Andric         // If the host input is not CUDA or HIP, we don't need to bother about
30160b57cec5SDimitry Andric         // this input.
3017e8d8bef9SDimitry Andric         if (!(IA->getType() == types::TY_CUDA ||
3018e8d8bef9SDimitry Andric               IA->getType() == types::TY_HIP ||
3019e8d8bef9SDimitry Andric               IA->getType() == types::TY_PP_HIP)) {
30200b57cec5SDimitry Andric           // The builder will ignore this input.
30210b57cec5SDimitry Andric           IsActive = false;
30220b57cec5SDimitry Andric           return ABRT_Inactive;
30230b57cec5SDimitry Andric         }
30240b57cec5SDimitry Andric 
30250b57cec5SDimitry Andric         // Set the flag to true, so that the builder acts on the current input.
30260b57cec5SDimitry Andric         IsActive = true;
30270b57cec5SDimitry Andric 
30280b57cec5SDimitry Andric         if (CompileHostOnly)
30290b57cec5SDimitry Andric           return ABRT_Success;
30300b57cec5SDimitry Andric 
30310b57cec5SDimitry Andric         // Replicate inputs for each GPU architecture.
30320b57cec5SDimitry Andric         auto Ty = IA->getType() == types::TY_HIP ? types::TY_HIP_DEVICE
30330b57cec5SDimitry Andric                                                  : types::TY_CUDA_DEVICE;
3034fe6060f1SDimitry Andric         std::string CUID = FixedCUID.str();
3035fe6060f1SDimitry Andric         if (CUID.empty()) {
3036fe6060f1SDimitry Andric           if (UseCUID == CUID_Random)
3037fe6060f1SDimitry Andric             CUID = llvm::utohexstr(llvm::sys::Process::GetRandomNumber(),
3038fe6060f1SDimitry Andric                                    /*LowerCase=*/true);
3039fe6060f1SDimitry Andric           else if (UseCUID == CUID_Hash) {
3040fe6060f1SDimitry Andric             llvm::MD5 Hasher;
3041fe6060f1SDimitry Andric             llvm::MD5::MD5Result Hash;
3042fe6060f1SDimitry Andric             SmallString<256> RealPath;
3043fe6060f1SDimitry Andric             llvm::sys::fs::real_path(IA->getInputArg().getValue(), RealPath,
3044fe6060f1SDimitry Andric                                      /*expand_tilde=*/true);
3045fe6060f1SDimitry Andric             Hasher.update(RealPath);
3046fe6060f1SDimitry Andric             for (auto *A : Args) {
3047fe6060f1SDimitry Andric               if (A->getOption().matches(options::OPT_INPUT))
3048fe6060f1SDimitry Andric                 continue;
3049fe6060f1SDimitry Andric               Hasher.update(A->getAsString(Args));
3050fe6060f1SDimitry Andric             }
3051fe6060f1SDimitry Andric             Hasher.final(Hash);
3052fe6060f1SDimitry Andric             CUID = llvm::utohexstr(Hash.low(), /*LowerCase=*/true);
3053fe6060f1SDimitry Andric           }
3054fe6060f1SDimitry Andric         }
3055fe6060f1SDimitry Andric         IA->setId(CUID);
3056fe6060f1SDimitry Andric 
30570b57cec5SDimitry Andric         for (unsigned I = 0, E = GpuArchList.size(); I != E; ++I) {
30580b57cec5SDimitry Andric           CudaDeviceActions.push_back(
3059fe6060f1SDimitry Andric               C.MakeAction<InputAction>(IA->getInputArg(), Ty, IA->getId()));
30600b57cec5SDimitry Andric         }
30610b57cec5SDimitry Andric 
30620b57cec5SDimitry Andric         return ABRT_Success;
30630b57cec5SDimitry Andric       }
30640b57cec5SDimitry Andric 
30650b57cec5SDimitry Andric       // If this is an unbundling action use it as is for each CUDA toolchain.
30660b57cec5SDimitry Andric       if (auto *UA = dyn_cast<OffloadUnbundlingJobAction>(HostAction)) {
30670b57cec5SDimitry Andric 
30680b57cec5SDimitry Andric         // If -fgpu-rdc is disabled, should not unbundle since there is no
30690b57cec5SDimitry Andric         // device code to link.
3070e8d8bef9SDimitry Andric         if (UA->getType() == types::TY_Object && !Relocatable)
30710b57cec5SDimitry Andric           return ABRT_Inactive;
30720b57cec5SDimitry Andric 
30730b57cec5SDimitry Andric         CudaDeviceActions.clear();
30740b57cec5SDimitry Andric         auto *IA = cast<InputAction>(UA->getInputs().back());
30750b57cec5SDimitry Andric         std::string FileName = IA->getInputArg().getAsString(Args);
30760b57cec5SDimitry Andric         // Check if the type of the file is the same as the action. Do not
30770b57cec5SDimitry Andric         // unbundle it if it is not. Do not unbundle .so files, for example,
3078bdd1243dSDimitry Andric         // which are not object files. Files with extension ".lib" is classified
3079bdd1243dSDimitry Andric         // as TY_Object but they are actually archives, therefore should not be
3080bdd1243dSDimitry Andric         // unbundled here as objects. They will be handled at other places.
3081bdd1243dSDimitry Andric         const StringRef LibFileExt = ".lib";
30820b57cec5SDimitry Andric         if (IA->getType() == types::TY_Object &&
30830b57cec5SDimitry Andric             (!llvm::sys::path::has_extension(FileName) ||
30840b57cec5SDimitry Andric              types::lookupTypeForExtension(
30850b57cec5SDimitry Andric                  llvm::sys::path::extension(FileName).drop_front()) !=
3086bdd1243dSDimitry Andric                  types::TY_Object ||
3087bdd1243dSDimitry Andric              llvm::sys::path::extension(FileName) == LibFileExt))
30880b57cec5SDimitry Andric           return ABRT_Inactive;
30890b57cec5SDimitry Andric 
30900b57cec5SDimitry Andric         for (auto Arch : GpuArchList) {
30910b57cec5SDimitry Andric           CudaDeviceActions.push_back(UA);
3092e8d8bef9SDimitry Andric           UA->registerDependentActionInfo(ToolChains[0], Arch,
30930b57cec5SDimitry Andric                                           AssociatedOffloadKind);
30940b57cec5SDimitry Andric         }
309581ad6265SDimitry Andric         IsActive = true;
30960b57cec5SDimitry Andric         return ABRT_Success;
30970b57cec5SDimitry Andric       }
30980b57cec5SDimitry Andric 
30990b57cec5SDimitry Andric       return IsActive ? ABRT_Success : ABRT_Inactive;
31000b57cec5SDimitry Andric     }
31010b57cec5SDimitry Andric 
31020b57cec5SDimitry Andric     void appendTopLevelActions(ActionList &AL) override {
31030b57cec5SDimitry Andric       // Utility to append actions to the top level list.
3104e8d8bef9SDimitry Andric       auto AddTopLevel = [&](Action *A, TargetID TargetID) {
31050b57cec5SDimitry Andric         OffloadAction::DeviceDependences Dep;
3106e8d8bef9SDimitry Andric         Dep.add(*A, *ToolChains.front(), TargetID, AssociatedOffloadKind);
31070b57cec5SDimitry Andric         AL.push_back(C.MakeAction<OffloadAction>(Dep, A->getType()));
31080b57cec5SDimitry Andric       };
31090b57cec5SDimitry Andric 
31100b57cec5SDimitry Andric       // If we have a fat binary, add it to the list.
31110b57cec5SDimitry Andric       if (CudaFatBinary) {
31120fca6ea1SDimitry Andric         AddTopLevel(CudaFatBinary, OffloadArch::UNUSED);
31130b57cec5SDimitry Andric         CudaDeviceActions.clear();
31140b57cec5SDimitry Andric         CudaFatBinary = nullptr;
31150b57cec5SDimitry Andric         return;
31160b57cec5SDimitry Andric       }
31170b57cec5SDimitry Andric 
31180b57cec5SDimitry Andric       if (CudaDeviceActions.empty())
31190b57cec5SDimitry Andric         return;
31200b57cec5SDimitry Andric 
31210b57cec5SDimitry Andric       // If we have CUDA actions at this point, that's because we have a have
31220b57cec5SDimitry Andric       // partial compilation, so we should have an action for each GPU
31230b57cec5SDimitry Andric       // architecture.
31240b57cec5SDimitry Andric       assert(CudaDeviceActions.size() == GpuArchList.size() &&
31250b57cec5SDimitry Andric              "Expecting one action per GPU architecture.");
31260b57cec5SDimitry Andric       assert(ToolChains.size() == 1 &&
3127349cc55cSDimitry Andric              "Expecting to have a single CUDA toolchain.");
31280b57cec5SDimitry Andric       for (unsigned I = 0, E = GpuArchList.size(); I != E; ++I)
31290b57cec5SDimitry Andric         AddTopLevel(CudaDeviceActions[I], GpuArchList[I]);
31300b57cec5SDimitry Andric 
31310b57cec5SDimitry Andric       CudaDeviceActions.clear();
31320b57cec5SDimitry Andric     }
31330b57cec5SDimitry Andric 
3134e8d8bef9SDimitry Andric     /// Get canonicalized offload arch option. \returns empty StringRef if the
3135e8d8bef9SDimitry Andric     /// option is invalid.
3136e8d8bef9SDimitry Andric     virtual StringRef getCanonicalOffloadArch(StringRef Arch) = 0;
3137e8d8bef9SDimitry Andric 
3138bdd1243dSDimitry Andric     virtual std::optional<std::pair<llvm::StringRef, llvm::StringRef>>
3139e8d8bef9SDimitry Andric     getConflictOffloadArchCombination(const std::set<StringRef> &GpuArchs) = 0;
3140e8d8bef9SDimitry Andric 
31410b57cec5SDimitry Andric     bool initialize() override {
31420b57cec5SDimitry Andric       assert(AssociatedOffloadKind == Action::OFK_Cuda ||
31430b57cec5SDimitry Andric              AssociatedOffloadKind == Action::OFK_HIP);
31440b57cec5SDimitry Andric 
31450b57cec5SDimitry Andric       // We don't need to support CUDA.
31460b57cec5SDimitry Andric       if (AssociatedOffloadKind == Action::OFK_Cuda &&
31470b57cec5SDimitry Andric           !C.hasOffloadToolChain<Action::OFK_Cuda>())
31480b57cec5SDimitry Andric         return false;
31490b57cec5SDimitry Andric 
31500b57cec5SDimitry Andric       // We don't need to support HIP.
31510b57cec5SDimitry Andric       if (AssociatedOffloadKind == Action::OFK_HIP &&
31520b57cec5SDimitry Andric           !C.hasOffloadToolChain<Action::OFK_HIP>())
31530b57cec5SDimitry Andric         return false;
31540b57cec5SDimitry Andric 
31550b57cec5SDimitry Andric       const ToolChain *HostTC = C.getSingleOffloadToolChain<Action::OFK_Host>();
31560b57cec5SDimitry Andric       assert(HostTC && "No toolchain for host compilation.");
31570b57cec5SDimitry Andric       if (HostTC->getTriple().isNVPTX() ||
31580b57cec5SDimitry Andric           HostTC->getTriple().getArch() == llvm::Triple::amdgcn) {
31590b57cec5SDimitry Andric         // We do not support targeting NVPTX/AMDGCN for host compilation. Throw
31600b57cec5SDimitry Andric         // an error and abort pipeline construction early so we don't trip
31610b57cec5SDimitry Andric         // asserts that assume device-side compilation.
31620b57cec5SDimitry Andric         C.getDriver().Diag(diag::err_drv_cuda_host_arch)
31630b57cec5SDimitry Andric             << HostTC->getTriple().getArchName();
31640b57cec5SDimitry Andric         return true;
31650b57cec5SDimitry Andric       }
31660b57cec5SDimitry Andric 
31670b57cec5SDimitry Andric       ToolChains.push_back(
31680b57cec5SDimitry Andric           AssociatedOffloadKind == Action::OFK_Cuda
31690b57cec5SDimitry Andric               ? C.getSingleOffloadToolChain<Action::OFK_Cuda>()
31700b57cec5SDimitry Andric               : C.getSingleOffloadToolChain<Action::OFK_HIP>());
31710b57cec5SDimitry Andric 
317281ad6265SDimitry Andric       CompileHostOnly = C.getDriver().offloadHostOnly();
3173a7dea167SDimitry Andric       EmitLLVM = Args.getLastArg(options::OPT_emit_llvm);
3174a7dea167SDimitry Andric       EmitAsm = Args.getLastArg(options::OPT_S);
3175fe6060f1SDimitry Andric       FixedCUID = Args.getLastArgValue(options::OPT_cuid_EQ);
3176fe6060f1SDimitry Andric       if (Arg *A = Args.getLastArg(options::OPT_fuse_cuid_EQ)) {
3177fe6060f1SDimitry Andric         StringRef UseCUIDStr = A->getValue();
3178fe6060f1SDimitry Andric         UseCUID = llvm::StringSwitch<UseCUIDKind>(UseCUIDStr)
3179fe6060f1SDimitry Andric                       .Case("hash", CUID_Hash)
3180fe6060f1SDimitry Andric                       .Case("random", CUID_Random)
3181fe6060f1SDimitry Andric                       .Case("none", CUID_None)
3182fe6060f1SDimitry Andric                       .Default(CUID_Invalid);
3183fe6060f1SDimitry Andric         if (UseCUID == CUID_Invalid) {
3184fe6060f1SDimitry Andric           C.getDriver().Diag(diag::err_drv_invalid_value)
3185fe6060f1SDimitry Andric               << A->getAsString(Args) << UseCUIDStr;
3186fe6060f1SDimitry Andric           C.setContainsError();
3187fe6060f1SDimitry Andric           return true;
3188fe6060f1SDimitry Andric         }
3189fe6060f1SDimitry Andric       }
31900b57cec5SDimitry Andric 
31910eae32dcSDimitry Andric       // --offload and --offload-arch options are mutually exclusive.
31920eae32dcSDimitry Andric       if (Args.hasArgNoClaim(options::OPT_offload_EQ) &&
31930eae32dcSDimitry Andric           Args.hasArgNoClaim(options::OPT_offload_arch_EQ,
31940eae32dcSDimitry Andric                              options::OPT_no_offload_arch_EQ)) {
31950eae32dcSDimitry Andric         C.getDriver().Diag(diag::err_opt_not_valid_with_opt) << "--offload-arch"
31960eae32dcSDimitry Andric                                                              << "--offload";
31970eae32dcSDimitry Andric       }
31980eae32dcSDimitry Andric 
319981ad6265SDimitry Andric       // Collect all offload arch parameters, removing duplicates.
3200e8d8bef9SDimitry Andric       std::set<StringRef> GpuArchs;
32010b57cec5SDimitry Andric       bool Error = false;
32020b57cec5SDimitry Andric       for (Arg *A : Args) {
32035ffd83dbSDimitry Andric         if (!(A->getOption().matches(options::OPT_offload_arch_EQ) ||
32045ffd83dbSDimitry Andric               A->getOption().matches(options::OPT_no_offload_arch_EQ)))
32050b57cec5SDimitry Andric           continue;
32060b57cec5SDimitry Andric         A->claim();
32070b57cec5SDimitry Andric 
320881ad6265SDimitry Andric         for (StringRef ArchStr : llvm::split(A->getValue(), ",")) {
32095ffd83dbSDimitry Andric           if (A->getOption().matches(options::OPT_no_offload_arch_EQ) &&
32100b57cec5SDimitry Andric               ArchStr == "all") {
32110b57cec5SDimitry Andric             GpuArchs.clear();
3212bdd1243dSDimitry Andric           } else if (ArchStr == "native") {
3213bdd1243dSDimitry Andric             const ToolChain &TC = *ToolChains.front();
3214bdd1243dSDimitry Andric             auto GPUsOrErr = ToolChains.front()->getSystemGPUArchs(Args);
3215bdd1243dSDimitry Andric             if (!GPUsOrErr) {
3216bdd1243dSDimitry Andric               TC.getDriver().Diag(diag::err_drv_undetermined_gpu_arch)
3217bdd1243dSDimitry Andric                   << llvm::Triple::getArchTypeName(TC.getArch())
3218bdd1243dSDimitry Andric                   << llvm::toString(GPUsOrErr.takeError()) << "--offload-arch";
3219bdd1243dSDimitry Andric               continue;
3220bdd1243dSDimitry Andric             }
3221bdd1243dSDimitry Andric 
3222bdd1243dSDimitry Andric             for (auto GPU : *GPUsOrErr) {
3223bdd1243dSDimitry Andric               GpuArchs.insert(Args.MakeArgString(GPU));
3224bdd1243dSDimitry Andric             }
322581ad6265SDimitry Andric           } else {
3226e8d8bef9SDimitry Andric             ArchStr = getCanonicalOffloadArch(ArchStr);
3227e8d8bef9SDimitry Andric             if (ArchStr.empty()) {
32280b57cec5SDimitry Andric               Error = true;
32295ffd83dbSDimitry Andric             } else if (A->getOption().matches(options::OPT_offload_arch_EQ))
3230e8d8bef9SDimitry Andric               GpuArchs.insert(ArchStr);
32315ffd83dbSDimitry Andric             else if (A->getOption().matches(options::OPT_no_offload_arch_EQ))
3232e8d8bef9SDimitry Andric               GpuArchs.erase(ArchStr);
32330b57cec5SDimitry Andric             else
32340b57cec5SDimitry Andric               llvm_unreachable("Unexpected option.");
32350b57cec5SDimitry Andric           }
323681ad6265SDimitry Andric         }
323781ad6265SDimitry Andric       }
32380b57cec5SDimitry Andric 
3239e8d8bef9SDimitry Andric       auto &&ConflictingArchs = getConflictOffloadArchCombination(GpuArchs);
3240e8d8bef9SDimitry Andric       if (ConflictingArchs) {
3241e8d8bef9SDimitry Andric         C.getDriver().Diag(clang::diag::err_drv_bad_offload_arch_combo)
324281ad6265SDimitry Andric             << ConflictingArchs->first << ConflictingArchs->second;
3243e8d8bef9SDimitry Andric         C.setContainsError();
3244e8d8bef9SDimitry Andric         return true;
3245e8d8bef9SDimitry Andric       }
3246e8d8bef9SDimitry Andric 
32470b57cec5SDimitry Andric       // Collect list of GPUs remaining in the set.
3248e8d8bef9SDimitry Andric       for (auto Arch : GpuArchs)
3249e8d8bef9SDimitry Andric         GpuArchList.push_back(Arch.data());
32500b57cec5SDimitry Andric 
32510b57cec5SDimitry Andric       // Default to sm_20 which is the lowest common denominator for
32520b57cec5SDimitry Andric       // supported GPUs.  sm_20 code should work correctly, if
32530b57cec5SDimitry Andric       // suboptimally, on all newer GPUs.
32540eae32dcSDimitry Andric       if (GpuArchList.empty()) {
32550fca6ea1SDimitry Andric         if (ToolChains.front()->getTriple().isSPIRV()) {
32560fca6ea1SDimitry Andric           if (ToolChains.front()->getTriple().getVendor() == llvm::Triple::AMD)
32570fca6ea1SDimitry Andric             GpuArchList.push_back(OffloadArch::AMDGCNSPIRV);
32580eae32dcSDimitry Andric           else
32590fca6ea1SDimitry Andric             GpuArchList.push_back(OffloadArch::Generic);
32600fca6ea1SDimitry Andric         } else {
32610fca6ea1SDimitry Andric           GpuArchList.push_back(DefaultOffloadArch);
32620fca6ea1SDimitry Andric         }
32630eae32dcSDimitry Andric       }
32640b57cec5SDimitry Andric 
32650b57cec5SDimitry Andric       return Error;
32660b57cec5SDimitry Andric     }
32670b57cec5SDimitry Andric   };
32680b57cec5SDimitry Andric 
32690b57cec5SDimitry Andric   /// \brief CUDA action builder. It injects device code in the host backend
32700b57cec5SDimitry Andric   /// action.
32710b57cec5SDimitry Andric   class CudaActionBuilder final : public CudaActionBuilderBase {
32720b57cec5SDimitry Andric   public:
32730b57cec5SDimitry Andric     CudaActionBuilder(Compilation &C, DerivedArgList &Args,
32740b57cec5SDimitry Andric                       const Driver::InputList &Inputs)
3275a7dea167SDimitry Andric         : CudaActionBuilderBase(C, Args, Inputs, Action::OFK_Cuda) {
32760fca6ea1SDimitry Andric       DefaultOffloadArch = OffloadArch::CudaDefault;
3277a7dea167SDimitry Andric     }
32780b57cec5SDimitry Andric 
3279e8d8bef9SDimitry Andric     StringRef getCanonicalOffloadArch(StringRef ArchStr) override {
32800fca6ea1SDimitry Andric       OffloadArch Arch = StringToOffloadArch(ArchStr);
32810fca6ea1SDimitry Andric       if (Arch == OffloadArch::UNKNOWN || !IsNVIDIAOffloadArch(Arch)) {
3282e8d8bef9SDimitry Andric         C.getDriver().Diag(clang::diag::err_drv_cuda_bad_gpu_arch) << ArchStr;
3283e8d8bef9SDimitry Andric         return StringRef();
3284e8d8bef9SDimitry Andric       }
32850fca6ea1SDimitry Andric       return OffloadArchToString(Arch);
3286e8d8bef9SDimitry Andric     }
3287e8d8bef9SDimitry Andric 
3288bdd1243dSDimitry Andric     std::optional<std::pair<llvm::StringRef, llvm::StringRef>>
3289e8d8bef9SDimitry Andric     getConflictOffloadArchCombination(
3290e8d8bef9SDimitry Andric         const std::set<StringRef> &GpuArchs) override {
3291bdd1243dSDimitry Andric       return std::nullopt;
3292e8d8bef9SDimitry Andric     }
3293e8d8bef9SDimitry Andric 
32940b57cec5SDimitry Andric     ActionBuilderReturnCode
32950b57cec5SDimitry Andric     getDeviceDependences(OffloadAction::DeviceDependences &DA,
32960b57cec5SDimitry Andric                          phases::ID CurPhase, phases::ID FinalPhase,
32970b57cec5SDimitry Andric                          PhasesTy &Phases) override {
32980b57cec5SDimitry Andric       if (!IsActive)
32990b57cec5SDimitry Andric         return ABRT_Inactive;
33000b57cec5SDimitry Andric 
33010b57cec5SDimitry Andric       // If we don't have more CUDA actions, we don't have any dependences to
33020b57cec5SDimitry Andric       // create for the host.
33030b57cec5SDimitry Andric       if (CudaDeviceActions.empty())
33040b57cec5SDimitry Andric         return ABRT_Success;
33050b57cec5SDimitry Andric 
33060b57cec5SDimitry Andric       assert(CudaDeviceActions.size() == GpuArchList.size() &&
33070b57cec5SDimitry Andric              "Expecting one action per GPU architecture.");
33080b57cec5SDimitry Andric       assert(!CompileHostOnly &&
33090b57cec5SDimitry Andric              "Not expecting CUDA actions in host-only compilation.");
33100b57cec5SDimitry Andric 
33110b57cec5SDimitry Andric       // If we are generating code for the device or we are in a backend phase,
33120b57cec5SDimitry Andric       // we attempt to generate the fat binary. We compile each arch to ptx and
33130b57cec5SDimitry Andric       // assemble to cubin, then feed the cubin *and* the ptx into a device
33140b57cec5SDimitry Andric       // "link" action, which uses fatbinary to combine these cubins into one
33150b57cec5SDimitry Andric       // fatbin.  The fatbin is then an input to the host action if not in
33160b57cec5SDimitry Andric       // device-only mode.
33170b57cec5SDimitry Andric       if (CompileDeviceOnly || CurPhase == phases::Backend) {
33180b57cec5SDimitry Andric         ActionList DeviceActions;
33190b57cec5SDimitry Andric         for (unsigned I = 0, E = GpuArchList.size(); I != E; ++I) {
33200b57cec5SDimitry Andric           // Produce the device action from the current phase up to the assemble
33210b57cec5SDimitry Andric           // phase.
33220b57cec5SDimitry Andric           for (auto Ph : Phases) {
33230b57cec5SDimitry Andric             // Skip the phases that were already dealt with.
33240b57cec5SDimitry Andric             if (Ph < CurPhase)
33250b57cec5SDimitry Andric               continue;
33260b57cec5SDimitry Andric             // We have to be consistent with the host final phase.
33270b57cec5SDimitry Andric             if (Ph > FinalPhase)
33280b57cec5SDimitry Andric               break;
33290b57cec5SDimitry Andric 
33300b57cec5SDimitry Andric             CudaDeviceActions[I] = C.getDriver().ConstructPhaseAction(
33310b57cec5SDimitry Andric                 C, Args, Ph, CudaDeviceActions[I], Action::OFK_Cuda);
33320b57cec5SDimitry Andric 
33330b57cec5SDimitry Andric             if (Ph == phases::Assemble)
33340b57cec5SDimitry Andric               break;
33350b57cec5SDimitry Andric           }
33360b57cec5SDimitry Andric 
33370b57cec5SDimitry Andric           // If we didn't reach the assemble phase, we can't generate the fat
33380b57cec5SDimitry Andric           // binary. We don't need to generate the fat binary if we are not in
33390b57cec5SDimitry Andric           // device-only mode.
33400b57cec5SDimitry Andric           if (!isa<AssembleJobAction>(CudaDeviceActions[I]) ||
33410b57cec5SDimitry Andric               CompileDeviceOnly)
33420b57cec5SDimitry Andric             continue;
33430b57cec5SDimitry Andric 
33440b57cec5SDimitry Andric           Action *AssembleAction = CudaDeviceActions[I];
33450b57cec5SDimitry Andric           assert(AssembleAction->getType() == types::TY_Object);
33460b57cec5SDimitry Andric           assert(AssembleAction->getInputs().size() == 1);
33470b57cec5SDimitry Andric 
33480b57cec5SDimitry Andric           Action *BackendAction = AssembleAction->getInputs()[0];
33490b57cec5SDimitry Andric           assert(BackendAction->getType() == types::TY_PP_Asm);
33500b57cec5SDimitry Andric 
33510b57cec5SDimitry Andric           for (auto &A : {AssembleAction, BackendAction}) {
33520b57cec5SDimitry Andric             OffloadAction::DeviceDependences DDep;
3353e8d8bef9SDimitry Andric             DDep.add(*A, *ToolChains.front(), GpuArchList[I], Action::OFK_Cuda);
33540b57cec5SDimitry Andric             DeviceActions.push_back(
33550b57cec5SDimitry Andric                 C.MakeAction<OffloadAction>(DDep, A->getType()));
33560b57cec5SDimitry Andric           }
33570b57cec5SDimitry Andric         }
33580b57cec5SDimitry Andric 
33590b57cec5SDimitry Andric         // We generate the fat binary if we have device input actions.
33600b57cec5SDimitry Andric         if (!DeviceActions.empty()) {
33610b57cec5SDimitry Andric           CudaFatBinary =
33620b57cec5SDimitry Andric               C.MakeAction<LinkJobAction>(DeviceActions, types::TY_CUDA_FATBIN);
33630b57cec5SDimitry Andric 
33640b57cec5SDimitry Andric           if (!CompileDeviceOnly) {
33650b57cec5SDimitry Andric             DA.add(*CudaFatBinary, *ToolChains.front(), /*BoundArch=*/nullptr,
33660b57cec5SDimitry Andric                    Action::OFK_Cuda);
33670b57cec5SDimitry Andric             // Clear the fat binary, it is already a dependence to an host
33680b57cec5SDimitry Andric             // action.
33690b57cec5SDimitry Andric             CudaFatBinary = nullptr;
33700b57cec5SDimitry Andric           }
33710b57cec5SDimitry Andric 
33720b57cec5SDimitry Andric           // Remove the CUDA actions as they are already connected to an host
33730b57cec5SDimitry Andric           // action or fat binary.
33740b57cec5SDimitry Andric           CudaDeviceActions.clear();
33750b57cec5SDimitry Andric         }
33760b57cec5SDimitry Andric 
33770b57cec5SDimitry Andric         // We avoid creating host action in device-only mode.
33780b57cec5SDimitry Andric         return CompileDeviceOnly ? ABRT_Ignore_Host : ABRT_Success;
33790b57cec5SDimitry Andric       } else if (CurPhase > phases::Backend) {
33800b57cec5SDimitry Andric         // If we are past the backend phase and still have a device action, we
33810b57cec5SDimitry Andric         // don't have to do anything as this action is already a device
33820b57cec5SDimitry Andric         // top-level action.
33830b57cec5SDimitry Andric         return ABRT_Success;
33840b57cec5SDimitry Andric       }
33850b57cec5SDimitry Andric 
33860b57cec5SDimitry Andric       assert(CurPhase < phases::Backend && "Generating single CUDA "
33870b57cec5SDimitry Andric                                            "instructions should only occur "
33880b57cec5SDimitry Andric                                            "before the backend phase!");
33890b57cec5SDimitry Andric 
33900b57cec5SDimitry Andric       // By default, we produce an action for each device arch.
33910b57cec5SDimitry Andric       for (Action *&A : CudaDeviceActions)
33920b57cec5SDimitry Andric         A = C.getDriver().ConstructPhaseAction(C, Args, CurPhase, A);
33930b57cec5SDimitry Andric 
33940b57cec5SDimitry Andric       return ABRT_Success;
33950b57cec5SDimitry Andric     }
33960b57cec5SDimitry Andric   };
33970b57cec5SDimitry Andric   /// \brief HIP action builder. It injects device code in the host backend
33980b57cec5SDimitry Andric   /// action.
33990b57cec5SDimitry Andric   class HIPActionBuilder final : public CudaActionBuilderBase {
34000b57cec5SDimitry Andric     /// The linker inputs obtained for each device arch.
34010b57cec5SDimitry Andric     SmallVector<ActionList, 8> DeviceLinkerInputs;
3402fe6060f1SDimitry Andric     // The default bundling behavior depends on the type of output, therefore
3403fe6060f1SDimitry Andric     // BundleOutput needs to be tri-value: None, true, or false.
3404fe6060f1SDimitry Andric     // Bundle code objects except --no-gpu-output is specified for device
3405fe6060f1SDimitry Andric     // only compilation. Bundle other type of output files only if
3406fe6060f1SDimitry Andric     // --gpu-bundle-output is specified for device only compilation.
3407bdd1243dSDimitry Andric     std::optional<bool> BundleOutput;
340806c3fb27SDimitry Andric     std::optional<bool> EmitReloc;
34090b57cec5SDimitry Andric 
34100b57cec5SDimitry Andric   public:
34110b57cec5SDimitry Andric     HIPActionBuilder(Compilation &C, DerivedArgList &Args,
34120b57cec5SDimitry Andric                      const Driver::InputList &Inputs)
3413a7dea167SDimitry Andric         : CudaActionBuilderBase(C, Args, Inputs, Action::OFK_HIP) {
341406c3fb27SDimitry Andric 
34150fca6ea1SDimitry Andric       DefaultOffloadArch = OffloadArch::HIPDefault;
341606c3fb27SDimitry Andric 
341706c3fb27SDimitry Andric       if (Args.hasArg(options::OPT_fhip_emit_relocatable,
341806c3fb27SDimitry Andric                       options::OPT_fno_hip_emit_relocatable)) {
341906c3fb27SDimitry Andric         EmitReloc = Args.hasFlag(options::OPT_fhip_emit_relocatable,
342006c3fb27SDimitry Andric                                  options::OPT_fno_hip_emit_relocatable, false);
342106c3fb27SDimitry Andric 
342206c3fb27SDimitry Andric         if (*EmitReloc) {
342306c3fb27SDimitry Andric           if (Relocatable) {
342406c3fb27SDimitry Andric             C.getDriver().Diag(diag::err_opt_not_valid_with_opt)
342506c3fb27SDimitry Andric                 << "-fhip-emit-relocatable"
342606c3fb27SDimitry Andric                 << "-fgpu-rdc";
342706c3fb27SDimitry Andric           }
342806c3fb27SDimitry Andric 
342906c3fb27SDimitry Andric           if (!CompileDeviceOnly) {
343006c3fb27SDimitry Andric             C.getDriver().Diag(diag::err_opt_not_valid_without_opt)
343106c3fb27SDimitry Andric                 << "-fhip-emit-relocatable"
343206c3fb27SDimitry Andric                 << "--cuda-device-only";
343306c3fb27SDimitry Andric           }
343406c3fb27SDimitry Andric         }
343506c3fb27SDimitry Andric       }
343606c3fb27SDimitry Andric 
3437fe6060f1SDimitry Andric       if (Args.hasArg(options::OPT_gpu_bundle_output,
3438fe6060f1SDimitry Andric                       options::OPT_no_gpu_bundle_output))
3439fe6060f1SDimitry Andric         BundleOutput = Args.hasFlag(options::OPT_gpu_bundle_output,
344006c3fb27SDimitry Andric                                     options::OPT_no_gpu_bundle_output, true) &&
344106c3fb27SDimitry Andric                        (!EmitReloc || !*EmitReloc);
3442a7dea167SDimitry Andric     }
34430b57cec5SDimitry Andric 
34440b57cec5SDimitry Andric     bool canUseBundlerUnbundler() const override { return true; }
34450b57cec5SDimitry Andric 
3446e8d8bef9SDimitry Andric     StringRef getCanonicalOffloadArch(StringRef IdStr) override {
3447e8d8bef9SDimitry Andric       llvm::StringMap<bool> Features;
34480eae32dcSDimitry Andric       // getHIPOffloadTargetTriple() is known to return valid value as it has
34490eae32dcSDimitry Andric       // been called successfully in the CreateOffloadingDeviceToolChains().
34500eae32dcSDimitry Andric       auto ArchStr = parseTargetID(
34510eae32dcSDimitry Andric           *getHIPOffloadTargetTriple(C.getDriver(), C.getInputArgs()), IdStr,
34520eae32dcSDimitry Andric           &Features);
3453e8d8bef9SDimitry Andric       if (!ArchStr) {
3454e8d8bef9SDimitry Andric         C.getDriver().Diag(clang::diag::err_drv_bad_target_id) << IdStr;
3455e8d8bef9SDimitry Andric         C.setContainsError();
3456e8d8bef9SDimitry Andric         return StringRef();
3457e8d8bef9SDimitry Andric       }
345881ad6265SDimitry Andric       auto CanId = getCanonicalTargetID(*ArchStr, Features);
3459e8d8bef9SDimitry Andric       return Args.MakeArgStringRef(CanId);
3460e8d8bef9SDimitry Andric     };
3461e8d8bef9SDimitry Andric 
3462bdd1243dSDimitry Andric     std::optional<std::pair<llvm::StringRef, llvm::StringRef>>
3463e8d8bef9SDimitry Andric     getConflictOffloadArchCombination(
3464e8d8bef9SDimitry Andric         const std::set<StringRef> &GpuArchs) override {
3465e8d8bef9SDimitry Andric       return getConflictTargetIDCombination(GpuArchs);
3466e8d8bef9SDimitry Andric     }
3467e8d8bef9SDimitry Andric 
34680b57cec5SDimitry Andric     ActionBuilderReturnCode
34690b57cec5SDimitry Andric     getDeviceDependences(OffloadAction::DeviceDependences &DA,
34700b57cec5SDimitry Andric                          phases::ID CurPhase, phases::ID FinalPhase,
34710b57cec5SDimitry Andric                          PhasesTy &Phases) override {
347281ad6265SDimitry Andric       if (!IsActive)
347381ad6265SDimitry Andric         return ABRT_Inactive;
347481ad6265SDimitry Andric 
34750b57cec5SDimitry Andric       // amdgcn does not support linking of object files, therefore we skip
34760b57cec5SDimitry Andric       // backend and assemble phases to output LLVM IR. Except for generating
347781ad6265SDimitry Andric       // non-relocatable device code, where we generate fat binary for device
34780b57cec5SDimitry Andric       // code and pass to host in Backend phase.
34795ffd83dbSDimitry Andric       if (CudaDeviceActions.empty())
34800b57cec5SDimitry Andric         return ABRT_Success;
34810b57cec5SDimitry Andric 
34820b57cec5SDimitry Andric       assert(((CurPhase == phases::Link && Relocatable) ||
34830b57cec5SDimitry Andric               CudaDeviceActions.size() == GpuArchList.size()) &&
34840b57cec5SDimitry Andric              "Expecting one action per GPU architecture.");
34850b57cec5SDimitry Andric       assert(!CompileHostOnly &&
348681ad6265SDimitry Andric              "Not expecting HIP actions in host-only compilation.");
34870b57cec5SDimitry Andric 
348806c3fb27SDimitry Andric       bool ShouldLink = !EmitReloc || !*EmitReloc;
348906c3fb27SDimitry Andric 
3490a7dea167SDimitry Andric       if (!Relocatable && CurPhase == phases::Backend && !EmitLLVM &&
349106c3fb27SDimitry Andric           !EmitAsm && ShouldLink) {
34920b57cec5SDimitry Andric         // If we are in backend phase, we attempt to generate the fat binary.
34930b57cec5SDimitry Andric         // We compile each arch to IR and use a link action to generate code
34940b57cec5SDimitry Andric         // object containing ISA. Then we use a special "link" action to create
34950b57cec5SDimitry Andric         // a fat binary containing all the code objects for different GPU's.
34960b57cec5SDimitry Andric         // The fat binary is then an input to the host action.
34970b57cec5SDimitry Andric         for (unsigned I = 0, E = GpuArchList.size(); I != E; ++I) {
3498fe6060f1SDimitry Andric           if (C.getDriver().isUsingLTO(/*IsOffload=*/true)) {
3499fe6060f1SDimitry Andric             // When LTO is enabled, skip the backend and assemble phases and
3500fe6060f1SDimitry Andric             // use lld to link the bitcode.
3501fe6060f1SDimitry Andric             ActionList AL;
3502fe6060f1SDimitry Andric             AL.push_back(CudaDeviceActions[I]);
3503fe6060f1SDimitry Andric             // Create a link action to link device IR with device library
3504fe6060f1SDimitry Andric             // and generate ISA.
3505fe6060f1SDimitry Andric             CudaDeviceActions[I] =
3506fe6060f1SDimitry Andric                 C.MakeAction<LinkJobAction>(AL, types::TY_Image);
3507fe6060f1SDimitry Andric           } else {
3508fe6060f1SDimitry Andric             // When LTO is not enabled, we follow the conventional
3509fe6060f1SDimitry Andric             // compiler phases, including backend and assemble phases.
3510fe6060f1SDimitry Andric             ActionList AL;
35110eae32dcSDimitry Andric             Action *BackendAction = nullptr;
35120eae32dcSDimitry Andric             if (ToolChains.front()->getTriple().isSPIRV()) {
35130eae32dcSDimitry Andric               // Emit LLVM bitcode for SPIR-V targets. SPIR-V device tool chain
35140eae32dcSDimitry Andric               // (HIPSPVToolChain) runs post-link LLVM IR passes.
35150eae32dcSDimitry Andric               types::ID Output = Args.hasArg(options::OPT_S)
35160eae32dcSDimitry Andric                                      ? types::TY_LLVM_IR
35170eae32dcSDimitry Andric                                      : types::TY_LLVM_BC;
35180eae32dcSDimitry Andric               BackendAction =
35190eae32dcSDimitry Andric                   C.MakeAction<BackendJobAction>(CudaDeviceActions[I], Output);
35200eae32dcSDimitry Andric             } else
35210eae32dcSDimitry Andric               BackendAction = C.getDriver().ConstructPhaseAction(
35225ffd83dbSDimitry Andric                   C, Args, phases::Backend, CudaDeviceActions[I],
35235ffd83dbSDimitry Andric                   AssociatedOffloadKind);
35245ffd83dbSDimitry Andric             auto AssembleAction = C.getDriver().ConstructPhaseAction(
3525fe6060f1SDimitry Andric                 C, Args, phases::Assemble, BackendAction,
3526fe6060f1SDimitry Andric                 AssociatedOffloadKind);
3527fe6060f1SDimitry Andric             AL.push_back(AssembleAction);
35280b57cec5SDimitry Andric             // Create a link action to link device IR with device library
35290b57cec5SDimitry Andric             // and generate ISA.
35300b57cec5SDimitry Andric             CudaDeviceActions[I] =
35310b57cec5SDimitry Andric                 C.MakeAction<LinkJobAction>(AL, types::TY_Image);
3532fe6060f1SDimitry Andric           }
35330b57cec5SDimitry Andric 
35340b57cec5SDimitry Andric           // OffloadingActionBuilder propagates device arch until an offload
35350b57cec5SDimitry Andric           // action. Since the next action for creating fatbin does
35360b57cec5SDimitry Andric           // not have device arch, whereas the above link action and its input
35370b57cec5SDimitry Andric           // have device arch, an offload action is needed to stop the null
35380b57cec5SDimitry Andric           // device arch of the next action being propagated to the above link
35390b57cec5SDimitry Andric           // action.
35400b57cec5SDimitry Andric           OffloadAction::DeviceDependences DDep;
3541e8d8bef9SDimitry Andric           DDep.add(*CudaDeviceActions[I], *ToolChains.front(), GpuArchList[I],
3542e8d8bef9SDimitry Andric                    AssociatedOffloadKind);
35430b57cec5SDimitry Andric           CudaDeviceActions[I] = C.MakeAction<OffloadAction>(
35440b57cec5SDimitry Andric               DDep, CudaDeviceActions[I]->getType());
35450b57cec5SDimitry Andric         }
3546fe6060f1SDimitry Andric 
354781ad6265SDimitry Andric         if (!CompileDeviceOnly || !BundleOutput || *BundleOutput) {
35480b57cec5SDimitry Andric           // Create HIP fat binary with a special "link" action.
3549fe6060f1SDimitry Andric           CudaFatBinary = C.MakeAction<LinkJobAction>(CudaDeviceActions,
35500b57cec5SDimitry Andric                                                       types::TY_HIP_FATBIN);
35510b57cec5SDimitry Andric 
35520b57cec5SDimitry Andric           if (!CompileDeviceOnly) {
35530b57cec5SDimitry Andric             DA.add(*CudaFatBinary, *ToolChains.front(), /*BoundArch=*/nullptr,
35540b57cec5SDimitry Andric                    AssociatedOffloadKind);
35550b57cec5SDimitry Andric             // Clear the fat binary, it is already a dependence to an host
35560b57cec5SDimitry Andric             // action.
35570b57cec5SDimitry Andric             CudaFatBinary = nullptr;
35580b57cec5SDimitry Andric           }
35590b57cec5SDimitry Andric 
35600b57cec5SDimitry Andric           // Remove the CUDA actions as they are already connected to an host
35610b57cec5SDimitry Andric           // action or fat binary.
35620b57cec5SDimitry Andric           CudaDeviceActions.clear();
3563fe6060f1SDimitry Andric         }
35640b57cec5SDimitry Andric 
35650b57cec5SDimitry Andric         return CompileDeviceOnly ? ABRT_Ignore_Host : ABRT_Success;
35660b57cec5SDimitry Andric       } else if (CurPhase == phases::Link) {
356706c3fb27SDimitry Andric         if (!ShouldLink)
356806c3fb27SDimitry Andric           return ABRT_Success;
35690b57cec5SDimitry Andric         // Save CudaDeviceActions to DeviceLinkerInputs for each GPU subarch.
35700b57cec5SDimitry Andric         // This happens to each device action originated from each input file.
35710b57cec5SDimitry Andric         // Later on, device actions in DeviceLinkerInputs are used to create
35720b57cec5SDimitry Andric         // device link actions in appendLinkDependences and the created device
35730b57cec5SDimitry Andric         // link actions are passed to the offload action as device dependence.
35740b57cec5SDimitry Andric         DeviceLinkerInputs.resize(CudaDeviceActions.size());
35750b57cec5SDimitry Andric         auto LI = DeviceLinkerInputs.begin();
35760b57cec5SDimitry Andric         for (auto *A : CudaDeviceActions) {
35770b57cec5SDimitry Andric           LI->push_back(A);
35780b57cec5SDimitry Andric           ++LI;
35790b57cec5SDimitry Andric         }
35800b57cec5SDimitry Andric 
35810b57cec5SDimitry Andric         // We will pass the device action as a host dependence, so we don't
35820b57cec5SDimitry Andric         // need to do anything else with them.
35830b57cec5SDimitry Andric         CudaDeviceActions.clear();
358404eeddc0SDimitry Andric         return CompileDeviceOnly ? ABRT_Ignore_Host : ABRT_Success;
35850b57cec5SDimitry Andric       }
35860b57cec5SDimitry Andric 
35870b57cec5SDimitry Andric       // By default, we produce an action for each device arch.
35880b57cec5SDimitry Andric       for (Action *&A : CudaDeviceActions)
35890b57cec5SDimitry Andric         A = C.getDriver().ConstructPhaseAction(C, Args, CurPhase, A,
35900b57cec5SDimitry Andric                                                AssociatedOffloadKind);
35910b57cec5SDimitry Andric 
359281ad6265SDimitry Andric       if (CompileDeviceOnly && CurPhase == FinalPhase && BundleOutput &&
3593bdd1243dSDimitry Andric           *BundleOutput) {
3594fe6060f1SDimitry Andric         for (unsigned I = 0, E = GpuArchList.size(); I != E; ++I) {
3595fe6060f1SDimitry Andric           OffloadAction::DeviceDependences DDep;
3596fe6060f1SDimitry Andric           DDep.add(*CudaDeviceActions[I], *ToolChains.front(), GpuArchList[I],
3597fe6060f1SDimitry Andric                    AssociatedOffloadKind);
3598fe6060f1SDimitry Andric           CudaDeviceActions[I] = C.MakeAction<OffloadAction>(
3599fe6060f1SDimitry Andric               DDep, CudaDeviceActions[I]->getType());
3600fe6060f1SDimitry Andric         }
3601fe6060f1SDimitry Andric         CudaFatBinary =
3602fe6060f1SDimitry Andric             C.MakeAction<OffloadBundlingJobAction>(CudaDeviceActions);
3603fe6060f1SDimitry Andric         CudaDeviceActions.clear();
3604fe6060f1SDimitry Andric       }
3605fe6060f1SDimitry Andric 
360606c3fb27SDimitry Andric       return (CompileDeviceOnly &&
360706c3fb27SDimitry Andric               (CurPhase == FinalPhase ||
360806c3fb27SDimitry Andric                (!ShouldLink && CurPhase == phases::Assemble)))
360906c3fb27SDimitry Andric                  ? ABRT_Ignore_Host
3610a7dea167SDimitry Andric                  : ABRT_Success;
36110b57cec5SDimitry Andric     }
36120b57cec5SDimitry Andric 
36135ffd83dbSDimitry Andric     void appendLinkDeviceActions(ActionList &AL) override {
36145ffd83dbSDimitry Andric       if (DeviceLinkerInputs.size() == 0)
36155ffd83dbSDimitry Andric         return;
36165ffd83dbSDimitry Andric 
36175ffd83dbSDimitry Andric       assert(DeviceLinkerInputs.size() == GpuArchList.size() &&
36185ffd83dbSDimitry Andric              "Linker inputs and GPU arch list sizes do not match.");
36195ffd83dbSDimitry Andric 
362004eeddc0SDimitry Andric       ActionList Actions;
36210b57cec5SDimitry Andric       unsigned I = 0;
362281ad6265SDimitry Andric       // Append a new link action for each device.
36235ffd83dbSDimitry Andric       // Each entry in DeviceLinkerInputs corresponds to a GPU arch.
362481ad6265SDimitry Andric       for (auto &LI : DeviceLinkerInputs) {
362581ad6265SDimitry Andric 
362681ad6265SDimitry Andric         types::ID Output = Args.hasArg(options::OPT_emit_llvm)
362781ad6265SDimitry Andric                                    ? types::TY_LLVM_BC
362881ad6265SDimitry Andric                                    : types::TY_Image;
362981ad6265SDimitry Andric 
363081ad6265SDimitry Andric         auto *DeviceLinkAction = C.MakeAction<LinkJobAction>(LI, Output);
36315ffd83dbSDimitry Andric         // Linking all inputs for the current GPU arch.
36325ffd83dbSDimitry Andric         // LI contains all the inputs for the linker.
36335ffd83dbSDimitry Andric         OffloadAction::DeviceDependences DeviceLinkDeps;
36345ffd83dbSDimitry Andric         DeviceLinkDeps.add(*DeviceLinkAction, *ToolChains[0],
3635e8d8bef9SDimitry Andric             GpuArchList[I], AssociatedOffloadKind);
363604eeddc0SDimitry Andric         Actions.push_back(C.MakeAction<OffloadAction>(
363704eeddc0SDimitry Andric             DeviceLinkDeps, DeviceLinkAction->getType()));
36380b57cec5SDimitry Andric         ++I;
36390b57cec5SDimitry Andric       }
36405ffd83dbSDimitry Andric       DeviceLinkerInputs.clear();
36415ffd83dbSDimitry Andric 
364281ad6265SDimitry Andric       // If emitting LLVM, do not generate final host/device compilation action
364381ad6265SDimitry Andric       if (Args.hasArg(options::OPT_emit_llvm)) {
364481ad6265SDimitry Andric           AL.append(Actions);
364581ad6265SDimitry Andric           return;
364681ad6265SDimitry Andric       }
364781ad6265SDimitry Andric 
36485ffd83dbSDimitry Andric       // Create a host object from all the device images by embedding them
364904eeddc0SDimitry Andric       // in a fat binary for mixed host-device compilation. For device-only
365004eeddc0SDimitry Andric       // compilation, creates a fat binary.
36515ffd83dbSDimitry Andric       OffloadAction::DeviceDependences DDeps;
365281ad6265SDimitry Andric       if (!CompileDeviceOnly || !BundleOutput || *BundleOutput) {
365304eeddc0SDimitry Andric         auto *TopDeviceLinkAction = C.MakeAction<LinkJobAction>(
365404eeddc0SDimitry Andric             Actions,
365504eeddc0SDimitry Andric             CompileDeviceOnly ? types::TY_HIP_FATBIN : types::TY_Object);
365604eeddc0SDimitry Andric         DDeps.add(*TopDeviceLinkAction, *ToolChains[0], nullptr,
365704eeddc0SDimitry Andric                   AssociatedOffloadKind);
36585ffd83dbSDimitry Andric         // Offload the host object to the host linker.
365904eeddc0SDimitry Andric         AL.push_back(
366004eeddc0SDimitry Andric             C.MakeAction<OffloadAction>(DDeps, TopDeviceLinkAction->getType()));
366104eeddc0SDimitry Andric       } else {
366204eeddc0SDimitry Andric         AL.append(Actions);
366304eeddc0SDimitry Andric       }
36640b57cec5SDimitry Andric     }
36655ffd83dbSDimitry Andric 
36665ffd83dbSDimitry Andric     Action* appendLinkHostActions(ActionList &AL) override { return AL.back(); }
36675ffd83dbSDimitry Andric 
36685ffd83dbSDimitry Andric     void appendLinkDependences(OffloadAction::DeviceDependences &DA) override {}
36690b57cec5SDimitry Andric   };
36700b57cec5SDimitry Andric 
36710b57cec5SDimitry Andric   ///
36720b57cec5SDimitry Andric   /// TODO: Add the implementation for other specialized builders here.
36730b57cec5SDimitry Andric   ///
36740b57cec5SDimitry Andric 
36750b57cec5SDimitry Andric   /// Specialized builders being used by this offloading action builder.
36760b57cec5SDimitry Andric   SmallVector<DeviceActionBuilder *, 4> SpecializedBuilders;
36770b57cec5SDimitry Andric 
36780b57cec5SDimitry Andric   /// Flag set to true if all valid builders allow file bundling/unbundling.
36790b57cec5SDimitry Andric   bool CanUseBundler;
36800b57cec5SDimitry Andric 
36810b57cec5SDimitry Andric public:
36820b57cec5SDimitry Andric   OffloadingActionBuilder(Compilation &C, DerivedArgList &Args,
36830b57cec5SDimitry Andric                           const Driver::InputList &Inputs)
36840b57cec5SDimitry Andric       : C(C) {
36850b57cec5SDimitry Andric     // Create a specialized builder for each device toolchain.
36860b57cec5SDimitry Andric 
36870b57cec5SDimitry Andric     IsValid = true;
36880b57cec5SDimitry Andric 
36890b57cec5SDimitry Andric     // Create a specialized builder for CUDA.
36900b57cec5SDimitry Andric     SpecializedBuilders.push_back(new CudaActionBuilder(C, Args, Inputs));
36910b57cec5SDimitry Andric 
36920b57cec5SDimitry Andric     // Create a specialized builder for HIP.
36930b57cec5SDimitry Andric     SpecializedBuilders.push_back(new HIPActionBuilder(C, Args, Inputs));
36940b57cec5SDimitry Andric 
36950b57cec5SDimitry Andric     //
36960b57cec5SDimitry Andric     // TODO: Build other specialized builders here.
36970b57cec5SDimitry Andric     //
36980b57cec5SDimitry Andric 
36990b57cec5SDimitry Andric     // Initialize all the builders, keeping track of errors. If all valid
37000b57cec5SDimitry Andric     // builders agree that we can use bundling, set the flag to true.
37010b57cec5SDimitry Andric     unsigned ValidBuilders = 0u;
37020b57cec5SDimitry Andric     unsigned ValidBuildersSupportingBundling = 0u;
37030b57cec5SDimitry Andric     for (auto *SB : SpecializedBuilders) {
37040b57cec5SDimitry Andric       IsValid = IsValid && !SB->initialize();
37050b57cec5SDimitry Andric 
37060b57cec5SDimitry Andric       // Update the counters if the builder is valid.
37070b57cec5SDimitry Andric       if (SB->isValid()) {
37080b57cec5SDimitry Andric         ++ValidBuilders;
37090b57cec5SDimitry Andric         if (SB->canUseBundlerUnbundler())
37100b57cec5SDimitry Andric           ++ValidBuildersSupportingBundling;
37110b57cec5SDimitry Andric       }
37120b57cec5SDimitry Andric     }
37130b57cec5SDimitry Andric     CanUseBundler =
37140b57cec5SDimitry Andric         ValidBuilders && ValidBuilders == ValidBuildersSupportingBundling;
37150b57cec5SDimitry Andric   }
37160b57cec5SDimitry Andric 
37170b57cec5SDimitry Andric   ~OffloadingActionBuilder() {
37180b57cec5SDimitry Andric     for (auto *SB : SpecializedBuilders)
37190b57cec5SDimitry Andric       delete SB;
37200b57cec5SDimitry Andric   }
37210b57cec5SDimitry Andric 
372281ad6265SDimitry Andric   /// Record a host action and its originating input argument.
372381ad6265SDimitry Andric   void recordHostAction(Action *HostAction, const Arg *InputArg) {
372481ad6265SDimitry Andric     assert(HostAction && "Invalid host action");
372581ad6265SDimitry Andric     assert(InputArg && "Invalid input argument");
372681ad6265SDimitry Andric     auto Loc = HostActionToInputArgMap.find(HostAction);
372781ad6265SDimitry Andric     if (Loc == HostActionToInputArgMap.end())
372881ad6265SDimitry Andric       HostActionToInputArgMap[HostAction] = InputArg;
372981ad6265SDimitry Andric     assert(HostActionToInputArgMap[HostAction] == InputArg &&
373081ad6265SDimitry Andric            "host action mapped to multiple input arguments");
373181ad6265SDimitry Andric   }
373281ad6265SDimitry Andric 
37330b57cec5SDimitry Andric   /// Generate an action that adds device dependences (if any) to a host action.
37340b57cec5SDimitry Andric   /// If no device dependence actions exist, just return the host action \a
37350b57cec5SDimitry Andric   /// HostAction. If an error is found or if no builder requires the host action
37360b57cec5SDimitry Andric   /// to be generated, return nullptr.
37370b57cec5SDimitry Andric   Action *
37380b57cec5SDimitry Andric   addDeviceDependencesToHostAction(Action *HostAction, const Arg *InputArg,
37390b57cec5SDimitry Andric                                    phases::ID CurPhase, phases::ID FinalPhase,
37400b57cec5SDimitry Andric                                    DeviceActionBuilder::PhasesTy &Phases) {
37410b57cec5SDimitry Andric     if (!IsValid)
37420b57cec5SDimitry Andric       return nullptr;
37430b57cec5SDimitry Andric 
37440b57cec5SDimitry Andric     if (SpecializedBuilders.empty())
37450b57cec5SDimitry Andric       return HostAction;
37460b57cec5SDimitry Andric 
37470b57cec5SDimitry Andric     assert(HostAction && "Invalid host action!");
374881ad6265SDimitry Andric     recordHostAction(HostAction, InputArg);
37490b57cec5SDimitry Andric 
37500b57cec5SDimitry Andric     OffloadAction::DeviceDependences DDeps;
37510b57cec5SDimitry Andric     // Check if all the programming models agree we should not emit the host
37520b57cec5SDimitry Andric     // action. Also, keep track of the offloading kinds employed.
37530b57cec5SDimitry Andric     auto &OffloadKind = InputArgToOffloadKindMap[InputArg];
37540b57cec5SDimitry Andric     unsigned InactiveBuilders = 0u;
37550b57cec5SDimitry Andric     unsigned IgnoringBuilders = 0u;
37560b57cec5SDimitry Andric     for (auto *SB : SpecializedBuilders) {
37570b57cec5SDimitry Andric       if (!SB->isValid()) {
37580b57cec5SDimitry Andric         ++InactiveBuilders;
37590b57cec5SDimitry Andric         continue;
37600b57cec5SDimitry Andric       }
37610b57cec5SDimitry Andric       auto RetCode =
37620b57cec5SDimitry Andric           SB->getDeviceDependences(DDeps, CurPhase, FinalPhase, Phases);
37630b57cec5SDimitry Andric 
37640b57cec5SDimitry Andric       // If the builder explicitly says the host action should be ignored,
37650b57cec5SDimitry Andric       // we need to increment the variable that tracks the builders that request
37660b57cec5SDimitry Andric       // the host object to be ignored.
37670b57cec5SDimitry Andric       if (RetCode == DeviceActionBuilder::ABRT_Ignore_Host)
37680b57cec5SDimitry Andric         ++IgnoringBuilders;
37690b57cec5SDimitry Andric 
37700b57cec5SDimitry Andric       // Unless the builder was inactive for this action, we have to record the
37710b57cec5SDimitry Andric       // offload kind because the host will have to use it.
37720b57cec5SDimitry Andric       if (RetCode != DeviceActionBuilder::ABRT_Inactive)
37730b57cec5SDimitry Andric         OffloadKind |= SB->getAssociatedOffloadKind();
37740b57cec5SDimitry Andric     }
37750b57cec5SDimitry Andric 
37760b57cec5SDimitry Andric     // If all builders agree that the host object should be ignored, just return
37770b57cec5SDimitry Andric     // nullptr.
37780b57cec5SDimitry Andric     if (IgnoringBuilders &&
37790b57cec5SDimitry Andric         SpecializedBuilders.size() == (InactiveBuilders + IgnoringBuilders))
37800b57cec5SDimitry Andric       return nullptr;
37810b57cec5SDimitry Andric 
37820b57cec5SDimitry Andric     if (DDeps.getActions().empty())
37830b57cec5SDimitry Andric       return HostAction;
37840b57cec5SDimitry Andric 
37850b57cec5SDimitry Andric     // We have dependences we need to bundle together. We use an offload action
37860b57cec5SDimitry Andric     // for that.
37870b57cec5SDimitry Andric     OffloadAction::HostDependence HDep(
37880b57cec5SDimitry Andric         *HostAction, *C.getSingleOffloadToolChain<Action::OFK_Host>(),
37890b57cec5SDimitry Andric         /*BoundArch=*/nullptr, DDeps);
37900b57cec5SDimitry Andric     return C.MakeAction<OffloadAction>(HDep, DDeps);
37910b57cec5SDimitry Andric   }
37920b57cec5SDimitry Andric 
37930b57cec5SDimitry Andric   /// Generate an action that adds a host dependence to a device action. The
37940b57cec5SDimitry Andric   /// results will be kept in this action builder. Return true if an error was
37950b57cec5SDimitry Andric   /// found.
37960b57cec5SDimitry Andric   bool addHostDependenceToDeviceActions(Action *&HostAction,
37970b57cec5SDimitry Andric                                         const Arg *InputArg) {
37980b57cec5SDimitry Andric     if (!IsValid)
37990b57cec5SDimitry Andric       return true;
38000b57cec5SDimitry Andric 
380181ad6265SDimitry Andric     recordHostAction(HostAction, InputArg);
380281ad6265SDimitry Andric 
38030b57cec5SDimitry Andric     // If we are supporting bundling/unbundling and the current action is an
38040b57cec5SDimitry Andric     // input action of non-source file, we replace the host action by the
38050b57cec5SDimitry Andric     // unbundling action. The bundler tool has the logic to detect if an input
38060b57cec5SDimitry Andric     // is a bundle or not and if the input is not a bundle it assumes it is a
38070b57cec5SDimitry Andric     // host file. Therefore it is safe to create an unbundling action even if
38080b57cec5SDimitry Andric     // the input is not a bundle.
38090b57cec5SDimitry Andric     if (CanUseBundler && isa<InputAction>(HostAction) &&
38100b57cec5SDimitry Andric         InputArg->getOption().getKind() == llvm::opt::Option::InputClass &&
3811e8d8bef9SDimitry Andric         (!types::isSrcFile(HostAction->getType()) ||
3812e8d8bef9SDimitry Andric          HostAction->getType() == types::TY_PP_HIP)) {
38130b57cec5SDimitry Andric       auto UnbundlingHostAction =
38140b57cec5SDimitry Andric           C.MakeAction<OffloadUnbundlingJobAction>(HostAction);
38150b57cec5SDimitry Andric       UnbundlingHostAction->registerDependentActionInfo(
38160b57cec5SDimitry Andric           C.getSingleOffloadToolChain<Action::OFK_Host>(),
38170b57cec5SDimitry Andric           /*BoundArch=*/StringRef(), Action::OFK_Host);
38180b57cec5SDimitry Andric       HostAction = UnbundlingHostAction;
381981ad6265SDimitry Andric       recordHostAction(HostAction, InputArg);
38200b57cec5SDimitry Andric     }
38210b57cec5SDimitry Andric 
38220b57cec5SDimitry Andric     assert(HostAction && "Invalid host action!");
38230b57cec5SDimitry Andric 
38240b57cec5SDimitry Andric     // Register the offload kinds that are used.
38250b57cec5SDimitry Andric     auto &OffloadKind = InputArgToOffloadKindMap[InputArg];
38260b57cec5SDimitry Andric     for (auto *SB : SpecializedBuilders) {
38270b57cec5SDimitry Andric       if (!SB->isValid())
38280b57cec5SDimitry Andric         continue;
38290b57cec5SDimitry Andric 
3830bdd1243dSDimitry Andric       auto RetCode = SB->addDeviceDependences(HostAction);
38310b57cec5SDimitry Andric 
38320b57cec5SDimitry Andric       // Host dependences for device actions are not compatible with that same
38330b57cec5SDimitry Andric       // action being ignored.
38340b57cec5SDimitry Andric       assert(RetCode != DeviceActionBuilder::ABRT_Ignore_Host &&
38350b57cec5SDimitry Andric              "Host dependence not expected to be ignored.!");
38360b57cec5SDimitry Andric 
38370b57cec5SDimitry Andric       // Unless the builder was inactive for this action, we have to record the
38380b57cec5SDimitry Andric       // offload kind because the host will have to use it.
38390b57cec5SDimitry Andric       if (RetCode != DeviceActionBuilder::ABRT_Inactive)
38400b57cec5SDimitry Andric         OffloadKind |= SB->getAssociatedOffloadKind();
38410b57cec5SDimitry Andric     }
38420b57cec5SDimitry Andric 
38430b57cec5SDimitry Andric     // Do not use unbundler if the Host does not depend on device action.
38440b57cec5SDimitry Andric     if (OffloadKind == Action::OFK_None && CanUseBundler)
38450b57cec5SDimitry Andric       if (auto *UA = dyn_cast<OffloadUnbundlingJobAction>(HostAction))
38460b57cec5SDimitry Andric         HostAction = UA->getInputs().back();
38470b57cec5SDimitry Andric 
38480b57cec5SDimitry Andric     return false;
38490b57cec5SDimitry Andric   }
38500b57cec5SDimitry Andric 
38510b57cec5SDimitry Andric   /// Add the offloading top level actions to the provided action list. This
38520b57cec5SDimitry Andric   /// function can replace the host action by a bundling action if the
38530b57cec5SDimitry Andric   /// programming models allow it.
38540b57cec5SDimitry Andric   bool appendTopLevelActions(ActionList &AL, Action *HostAction,
38550b57cec5SDimitry Andric                              const Arg *InputArg) {
385681ad6265SDimitry Andric     if (HostAction)
385781ad6265SDimitry Andric       recordHostAction(HostAction, InputArg);
385881ad6265SDimitry Andric 
38590b57cec5SDimitry Andric     // Get the device actions to be appended.
38600b57cec5SDimitry Andric     ActionList OffloadAL;
38610b57cec5SDimitry Andric     for (auto *SB : SpecializedBuilders) {
38620b57cec5SDimitry Andric       if (!SB->isValid())
38630b57cec5SDimitry Andric         continue;
38640b57cec5SDimitry Andric       SB->appendTopLevelActions(OffloadAL);
38650b57cec5SDimitry Andric     }
38660b57cec5SDimitry Andric 
38670b57cec5SDimitry Andric     // If we can use the bundler, replace the host action by the bundling one in
38680b57cec5SDimitry Andric     // the resulting list. Otherwise, just append the device actions. For
38690b57cec5SDimitry Andric     // device only compilation, HostAction is a null pointer, therefore only do
38700b57cec5SDimitry Andric     // this when HostAction is not a null pointer.
3871a7dea167SDimitry Andric     if (CanUseBundler && HostAction &&
3872a7dea167SDimitry Andric         HostAction->getType() != types::TY_Nothing && !OffloadAL.empty()) {
38730b57cec5SDimitry Andric       // Add the host action to the list in order to create the bundling action.
38740b57cec5SDimitry Andric       OffloadAL.push_back(HostAction);
38750b57cec5SDimitry Andric 
38760b57cec5SDimitry Andric       // We expect that the host action was just appended to the action list
38770b57cec5SDimitry Andric       // before this method was called.
38780b57cec5SDimitry Andric       assert(HostAction == AL.back() && "Host action not in the list??");
38790b57cec5SDimitry Andric       HostAction = C.MakeAction<OffloadBundlingJobAction>(OffloadAL);
388081ad6265SDimitry Andric       recordHostAction(HostAction, InputArg);
38810b57cec5SDimitry Andric       AL.back() = HostAction;
38820b57cec5SDimitry Andric     } else
38830b57cec5SDimitry Andric       AL.append(OffloadAL.begin(), OffloadAL.end());
38840b57cec5SDimitry Andric 
38850b57cec5SDimitry Andric     // Propagate to the current host action (if any) the offload information
38860b57cec5SDimitry Andric     // associated with the current input.
38870b57cec5SDimitry Andric     if (HostAction)
38880b57cec5SDimitry Andric       HostAction->propagateHostOffloadInfo(InputArgToOffloadKindMap[InputArg],
38890b57cec5SDimitry Andric                                            /*BoundArch=*/nullptr);
38900b57cec5SDimitry Andric     return false;
38910b57cec5SDimitry Andric   }
38920b57cec5SDimitry Andric 
389304eeddc0SDimitry Andric   void appendDeviceLinkActions(ActionList &AL) {
3894a7dea167SDimitry Andric     for (DeviceActionBuilder *SB : SpecializedBuilders) {
3895a7dea167SDimitry Andric       if (!SB->isValid())
3896a7dea167SDimitry Andric         continue;
389704eeddc0SDimitry Andric       SB->appendLinkDeviceActions(AL);
389804eeddc0SDimitry Andric     }
3899a7dea167SDimitry Andric   }
3900a7dea167SDimitry Andric 
390104eeddc0SDimitry Andric   Action *makeHostLinkAction() {
390204eeddc0SDimitry Andric     // Build a list of device linking actions.
390304eeddc0SDimitry Andric     ActionList DeviceAL;
390404eeddc0SDimitry Andric     appendDeviceLinkActions(DeviceAL);
3905a7dea167SDimitry Andric     if (DeviceAL.empty())
3906a7dea167SDimitry Andric       return nullptr;
3907a7dea167SDimitry Andric 
39085ffd83dbSDimitry Andric     // Let builders add host linking actions.
3909fe6060f1SDimitry Andric     Action* HA = nullptr;
39105ffd83dbSDimitry Andric     for (DeviceActionBuilder *SB : SpecializedBuilders) {
39115ffd83dbSDimitry Andric       if (!SB->isValid())
39125ffd83dbSDimitry Andric         continue;
39135ffd83dbSDimitry Andric       HA = SB->appendLinkHostActions(DeviceAL);
391481ad6265SDimitry Andric       // This created host action has no originating input argument, therefore
391581ad6265SDimitry Andric       // needs to set its offloading kind directly.
391681ad6265SDimitry Andric       if (HA)
391781ad6265SDimitry Andric         HA->propagateHostOffloadInfo(SB->getAssociatedOffloadKind(),
391881ad6265SDimitry Andric                                      /*BoundArch=*/nullptr);
39195ffd83dbSDimitry Andric     }
39205ffd83dbSDimitry Andric     return HA;
3921a7dea167SDimitry Andric   }
3922a7dea167SDimitry Andric 
39230b57cec5SDimitry Andric   /// Processes the host linker action. This currently consists of replacing it
39240b57cec5SDimitry Andric   /// with an offload action if there are device link objects and propagate to
39250b57cec5SDimitry Andric   /// the host action all the offload kinds used in the current compilation. The
39260b57cec5SDimitry Andric   /// resulting action is returned.
39270b57cec5SDimitry Andric   Action *processHostLinkAction(Action *HostAction) {
39280b57cec5SDimitry Andric     // Add all the dependences from the device linking actions.
39290b57cec5SDimitry Andric     OffloadAction::DeviceDependences DDeps;
39300b57cec5SDimitry Andric     for (auto *SB : SpecializedBuilders) {
39310b57cec5SDimitry Andric       if (!SB->isValid())
39320b57cec5SDimitry Andric         continue;
39330b57cec5SDimitry Andric 
39340b57cec5SDimitry Andric       SB->appendLinkDependences(DDeps);
39350b57cec5SDimitry Andric     }
39360b57cec5SDimitry Andric 
39370b57cec5SDimitry Andric     // Calculate all the offload kinds used in the current compilation.
39380b57cec5SDimitry Andric     unsigned ActiveOffloadKinds = 0u;
39390b57cec5SDimitry Andric     for (auto &I : InputArgToOffloadKindMap)
39400b57cec5SDimitry Andric       ActiveOffloadKinds |= I.second;
39410b57cec5SDimitry Andric 
39420b57cec5SDimitry Andric     // If we don't have device dependencies, we don't have to create an offload
39430b57cec5SDimitry Andric     // action.
39440b57cec5SDimitry Andric     if (DDeps.getActions().empty()) {
394581ad6265SDimitry Andric       // Set all the active offloading kinds to the link action. Given that it
394681ad6265SDimitry Andric       // is a link action it is assumed to depend on all actions generated so
394781ad6265SDimitry Andric       // far.
394881ad6265SDimitry Andric       HostAction->setHostOffloadInfo(ActiveOffloadKinds,
39490b57cec5SDimitry Andric                                      /*BoundArch=*/nullptr);
395081ad6265SDimitry Andric       // Propagate active offloading kinds for each input to the link action.
395181ad6265SDimitry Andric       // Each input may have different active offloading kind.
3952bdd1243dSDimitry Andric       for (auto *A : HostAction->inputs()) {
395381ad6265SDimitry Andric         auto ArgLoc = HostActionToInputArgMap.find(A);
395481ad6265SDimitry Andric         if (ArgLoc == HostActionToInputArgMap.end())
395581ad6265SDimitry Andric           continue;
395681ad6265SDimitry Andric         auto OFKLoc = InputArgToOffloadKindMap.find(ArgLoc->second);
395781ad6265SDimitry Andric         if (OFKLoc == InputArgToOffloadKindMap.end())
395881ad6265SDimitry Andric           continue;
395981ad6265SDimitry Andric         A->propagateHostOffloadInfo(OFKLoc->second, /*BoundArch=*/nullptr);
396081ad6265SDimitry Andric       }
39610b57cec5SDimitry Andric       return HostAction;
39620b57cec5SDimitry Andric     }
39630b57cec5SDimitry Andric 
39640b57cec5SDimitry Andric     // Create the offload action with all dependences. When an offload action
39650b57cec5SDimitry Andric     // is created the kinds are propagated to the host action, so we don't have
39660b57cec5SDimitry Andric     // to do that explicitly here.
39670b57cec5SDimitry Andric     OffloadAction::HostDependence HDep(
39680b57cec5SDimitry Andric         *HostAction, *C.getSingleOffloadToolChain<Action::OFK_Host>(),
39690b57cec5SDimitry Andric         /*BoundArch*/ nullptr, ActiveOffloadKinds);
39700b57cec5SDimitry Andric     return C.MakeAction<OffloadAction>(HDep, DDeps);
39710b57cec5SDimitry Andric   }
39720b57cec5SDimitry Andric };
39730b57cec5SDimitry Andric } // anonymous namespace.
39740b57cec5SDimitry Andric 
3975a7dea167SDimitry Andric void Driver::handleArguments(Compilation &C, DerivedArgList &Args,
3976a7dea167SDimitry Andric                              const InputList &Inputs,
3977a7dea167SDimitry Andric                              ActionList &Actions) const {
39780b57cec5SDimitry Andric 
3979a7dea167SDimitry Andric   // Ignore /Yc/Yu if both /Yc and /Yu passed but with different filenames.
3980a7dea167SDimitry Andric   Arg *YcArg = Args.getLastArg(options::OPT__SLASH_Yc);
3981a7dea167SDimitry Andric   Arg *YuArg = Args.getLastArg(options::OPT__SLASH_Yu);
3982a7dea167SDimitry Andric   if (YcArg && YuArg && strcmp(YcArg->getValue(), YuArg->getValue()) != 0) {
3983a7dea167SDimitry Andric     Diag(clang::diag::warn_drv_ycyu_different_arg_clang_cl);
3984a7dea167SDimitry Andric     Args.eraseArg(options::OPT__SLASH_Yc);
3985a7dea167SDimitry Andric     Args.eraseArg(options::OPT__SLASH_Yu);
3986a7dea167SDimitry Andric     YcArg = YuArg = nullptr;
3987a7dea167SDimitry Andric   }
3988a7dea167SDimitry Andric   if (YcArg && Inputs.size() > 1) {
3989a7dea167SDimitry Andric     Diag(clang::diag::warn_drv_yc_multiple_inputs_clang_cl);
3990a7dea167SDimitry Andric     Args.eraseArg(options::OPT__SLASH_Yc);
3991a7dea167SDimitry Andric     YcArg = nullptr;
39920b57cec5SDimitry Andric   }
39930b57cec5SDimitry Andric 
39940b57cec5SDimitry Andric   Arg *FinalPhaseArg;
39950b57cec5SDimitry Andric   phases::ID FinalPhase = getFinalPhase(Args, &FinalPhaseArg);
39960b57cec5SDimitry Andric 
39970b57cec5SDimitry Andric   if (FinalPhase == phases::Link) {
39985f757f3fSDimitry Andric     if (Args.hasArgNoClaim(options::OPT_hipstdpar)) {
39995f757f3fSDimitry Andric       Args.AddFlagArg(nullptr, getOpts().getOption(options::OPT_hip_link));
40005f757f3fSDimitry Andric       Args.AddFlagArg(nullptr,
40015f757f3fSDimitry Andric                       getOpts().getOption(options::OPT_frtlib_add_rpath));
40025f757f3fSDimitry Andric     }
400381ad6265SDimitry Andric     // Emitting LLVM while linking disabled except in HIPAMD Toolchain
400481ad6265SDimitry Andric     if (Args.hasArg(options::OPT_emit_llvm) && !Args.hasArg(options::OPT_hip_link))
40050b57cec5SDimitry Andric       Diag(clang::diag::err_drv_emit_llvm_link);
40060b57cec5SDimitry Andric     if (IsCLMode() && LTOMode != LTOK_None &&
4007fe6060f1SDimitry Andric         !Args.getLastArgValue(options::OPT_fuse_ld_EQ)
4008fe6060f1SDimitry Andric              .equals_insensitive("lld"))
40090b57cec5SDimitry Andric       Diag(clang::diag::err_drv_lto_without_lld);
401006c3fb27SDimitry Andric 
401106c3fb27SDimitry Andric     // If -dumpdir is not specified, give a default prefix derived from the link
401206c3fb27SDimitry Andric     // output filename. For example, `clang -g -gsplit-dwarf a.c -o x` passes
401306c3fb27SDimitry Andric     // `-dumpdir x-` to cc1. If -o is unspecified, use
401406c3fb27SDimitry Andric     // stem(getDefaultImageName()) (usually stem("a.out") = "a").
401506c3fb27SDimitry Andric     if (!Args.hasArg(options::OPT_dumpdir)) {
401606c3fb27SDimitry Andric       Arg *FinalOutput = Args.getLastArg(options::OPT_o, options::OPT__SLASH_o);
401706c3fb27SDimitry Andric       Arg *Arg = Args.MakeSeparateArg(
401806c3fb27SDimitry Andric           nullptr, getOpts().getOption(options::OPT_dumpdir),
401906c3fb27SDimitry Andric           Args.MakeArgString(
402006c3fb27SDimitry Andric               (FinalOutput ? FinalOutput->getValue()
402106c3fb27SDimitry Andric                            : llvm::sys::path::stem(getDefaultImageName())) +
402206c3fb27SDimitry Andric               "-"));
402306c3fb27SDimitry Andric       Arg->claim();
402406c3fb27SDimitry Andric       Args.append(Arg);
402506c3fb27SDimitry Andric     }
40260b57cec5SDimitry Andric   }
40270b57cec5SDimitry Andric 
4028a7dea167SDimitry Andric   if (FinalPhase == phases::Preprocess || Args.hasArg(options::OPT__SLASH_Y_)) {
4029a7dea167SDimitry Andric     // If only preprocessing or /Y- is used, all pch handling is disabled.
4030a7dea167SDimitry Andric     // Rather than check for it everywhere, just remove clang-cl pch-related
4031a7dea167SDimitry Andric     // flags here.
4032a7dea167SDimitry Andric     Args.eraseArg(options::OPT__SLASH_Fp);
4033a7dea167SDimitry Andric     Args.eraseArg(options::OPT__SLASH_Yc);
4034a7dea167SDimitry Andric     Args.eraseArg(options::OPT__SLASH_Yu);
4035a7dea167SDimitry Andric     YcArg = YuArg = nullptr;
4036a7dea167SDimitry Andric   }
4037a7dea167SDimitry Andric 
4038a7dea167SDimitry Andric   unsigned LastPLSize = 0;
4039a7dea167SDimitry Andric   for (auto &I : Inputs) {
4040a7dea167SDimitry Andric     types::ID InputType = I.first;
4041a7dea167SDimitry Andric     const Arg *InputArg = I.second;
4042a7dea167SDimitry Andric 
40435ffd83dbSDimitry Andric     auto PL = types::getCompilationPhases(InputType);
4044a7dea167SDimitry Andric     LastPLSize = PL.size();
4045a7dea167SDimitry Andric 
4046a7dea167SDimitry Andric     // If the first step comes after the final phase we are doing as part of
4047a7dea167SDimitry Andric     // this compilation, warn the user about it.
4048a7dea167SDimitry Andric     phases::ID InitialPhase = PL[0];
4049a7dea167SDimitry Andric     if (InitialPhase > FinalPhase) {
4050a7dea167SDimitry Andric       if (InputArg->isClaimed())
4051a7dea167SDimitry Andric         continue;
4052a7dea167SDimitry Andric 
4053a7dea167SDimitry Andric       // Claim here to avoid the more general unused warning.
4054a7dea167SDimitry Andric       InputArg->claim();
4055a7dea167SDimitry Andric 
4056a7dea167SDimitry Andric       // Suppress all unused style warnings with -Qunused-arguments
4057a7dea167SDimitry Andric       if (Args.hasArg(options::OPT_Qunused_arguments))
4058a7dea167SDimitry Andric         continue;
4059a7dea167SDimitry Andric 
4060a7dea167SDimitry Andric       // Special case when final phase determined by binary name, rather than
4061a7dea167SDimitry Andric       // by a command-line argument with a corresponding Arg.
4062a7dea167SDimitry Andric       if (CCCIsCPP())
4063a7dea167SDimitry Andric         Diag(clang::diag::warn_drv_input_file_unused_by_cpp)
4064a7dea167SDimitry Andric             << InputArg->getAsString(Args) << getPhaseName(InitialPhase);
4065a7dea167SDimitry Andric       // Special case '-E' warning on a previously preprocessed file to make
4066a7dea167SDimitry Andric       // more sense.
4067a7dea167SDimitry Andric       else if (InitialPhase == phases::Compile &&
4068a7dea167SDimitry Andric                (Args.getLastArg(options::OPT__SLASH_EP,
4069a7dea167SDimitry Andric                                 options::OPT__SLASH_P) ||
4070a7dea167SDimitry Andric                 Args.getLastArg(options::OPT_E) ||
4071a7dea167SDimitry Andric                 Args.getLastArg(options::OPT_M, options::OPT_MM)) &&
4072a7dea167SDimitry Andric                getPreprocessedType(InputType) == types::TY_INVALID)
4073a7dea167SDimitry Andric         Diag(clang::diag::warn_drv_preprocessed_input_file_unused)
4074a7dea167SDimitry Andric             << InputArg->getAsString(Args) << !!FinalPhaseArg
4075a7dea167SDimitry Andric             << (FinalPhaseArg ? FinalPhaseArg->getOption().getName() : "");
4076a7dea167SDimitry Andric       else
4077a7dea167SDimitry Andric         Diag(clang::diag::warn_drv_input_file_unused)
4078a7dea167SDimitry Andric             << InputArg->getAsString(Args) << getPhaseName(InitialPhase)
4079a7dea167SDimitry Andric             << !!FinalPhaseArg
4080a7dea167SDimitry Andric             << (FinalPhaseArg ? FinalPhaseArg->getOption().getName() : "");
4081a7dea167SDimitry Andric       continue;
4082a7dea167SDimitry Andric     }
4083a7dea167SDimitry Andric 
4084a7dea167SDimitry Andric     if (YcArg) {
4085a7dea167SDimitry Andric       // Add a separate precompile phase for the compile phase.
4086a7dea167SDimitry Andric       if (FinalPhase >= phases::Compile) {
4087a7dea167SDimitry Andric         const types::ID HeaderType = lookupHeaderTypeForSourceType(InputType);
4088a7dea167SDimitry Andric         // Build the pipeline for the pch file.
4089a7dea167SDimitry Andric         Action *ClangClPch = C.MakeAction<InputAction>(*InputArg, HeaderType);
40905ffd83dbSDimitry Andric         for (phases::ID Phase : types::getCompilationPhases(HeaderType))
4091a7dea167SDimitry Andric           ClangClPch = ConstructPhaseAction(C, Args, Phase, ClangClPch);
4092a7dea167SDimitry Andric         assert(ClangClPch);
4093a7dea167SDimitry Andric         Actions.push_back(ClangClPch);
4094a7dea167SDimitry Andric         // The driver currently exits after the first failed command.  This
4095a7dea167SDimitry Andric         // relies on that behavior, to make sure if the pch generation fails,
4096a7dea167SDimitry Andric         // the main compilation won't run.
4097a7dea167SDimitry Andric         // FIXME: If the main compilation fails, the PCH generation should
4098a7dea167SDimitry Andric         // probably not be considered successful either.
4099a7dea167SDimitry Andric       }
4100a7dea167SDimitry Andric     }
4101a7dea167SDimitry Andric   }
4102a7dea167SDimitry Andric 
4103a7dea167SDimitry Andric   // If we are linking, claim any options which are obviously only used for
4104a7dea167SDimitry Andric   // compilation.
4105a7dea167SDimitry Andric   // FIXME: Understand why the last Phase List length is used here.
4106a7dea167SDimitry Andric   if (FinalPhase == phases::Link && LastPLSize == 1) {
4107a7dea167SDimitry Andric     Args.ClaimAllArgs(options::OPT_CompileOnly_Group);
4108a7dea167SDimitry Andric     Args.ClaimAllArgs(options::OPT_cl_compile_Group);
4109a7dea167SDimitry Andric   }
4110a7dea167SDimitry Andric }
4111a7dea167SDimitry Andric 
4112a7dea167SDimitry Andric void Driver::BuildActions(Compilation &C, DerivedArgList &Args,
4113a7dea167SDimitry Andric                           const InputList &Inputs, ActionList &Actions) const {
4114a7dea167SDimitry Andric   llvm::PrettyStackTraceString CrashInfo("Building compilation actions");
4115a7dea167SDimitry Andric 
4116a7dea167SDimitry Andric   if (!SuppressMissingInputWarning && Inputs.empty()) {
4117a7dea167SDimitry Andric     Diag(clang::diag::err_drv_no_input_files);
4118a7dea167SDimitry Andric     return;
4119a7dea167SDimitry Andric   }
4120a7dea167SDimitry Andric 
41210b57cec5SDimitry Andric   // Diagnose misuse of /Fo.
41220b57cec5SDimitry Andric   if (Arg *A = Args.getLastArg(options::OPT__SLASH_Fo)) {
41230b57cec5SDimitry Andric     StringRef V = A->getValue();
41240b57cec5SDimitry Andric     if (Inputs.size() > 1 && !V.empty() &&
41250b57cec5SDimitry Andric         !llvm::sys::path::is_separator(V.back())) {
41260b57cec5SDimitry Andric       // Check whether /Fo tries to name an output file for multiple inputs.
41270b57cec5SDimitry Andric       Diag(clang::diag::err_drv_out_file_argument_with_multiple_sources)
41280b57cec5SDimitry Andric           << A->getSpelling() << V;
41290b57cec5SDimitry Andric       Args.eraseArg(options::OPT__SLASH_Fo);
41300b57cec5SDimitry Andric     }
41310b57cec5SDimitry Andric   }
41320b57cec5SDimitry Andric 
41330b57cec5SDimitry Andric   // Diagnose misuse of /Fa.
41340b57cec5SDimitry Andric   if (Arg *A = Args.getLastArg(options::OPT__SLASH_Fa)) {
41350b57cec5SDimitry Andric     StringRef V = A->getValue();
41360b57cec5SDimitry Andric     if (Inputs.size() > 1 && !V.empty() &&
41370b57cec5SDimitry Andric         !llvm::sys::path::is_separator(V.back())) {
41380b57cec5SDimitry Andric       // Check whether /Fa tries to name an asm file for multiple inputs.
41390b57cec5SDimitry Andric       Diag(clang::diag::err_drv_out_file_argument_with_multiple_sources)
41400b57cec5SDimitry Andric           << A->getSpelling() << V;
41410b57cec5SDimitry Andric       Args.eraseArg(options::OPT__SLASH_Fa);
41420b57cec5SDimitry Andric     }
41430b57cec5SDimitry Andric   }
41440b57cec5SDimitry Andric 
41450b57cec5SDimitry Andric   // Diagnose misuse of /o.
41460b57cec5SDimitry Andric   if (Arg *A = Args.getLastArg(options::OPT__SLASH_o)) {
41470b57cec5SDimitry Andric     if (A->getValue()[0] == '\0') {
41480b57cec5SDimitry Andric       // It has to have a value.
41490b57cec5SDimitry Andric       Diag(clang::diag::err_drv_missing_argument) << A->getSpelling() << 1;
41500b57cec5SDimitry Andric       Args.eraseArg(options::OPT__SLASH_o);
41510b57cec5SDimitry Andric     }
41520b57cec5SDimitry Andric   }
41530b57cec5SDimitry Andric 
4154a7dea167SDimitry Andric   handleArguments(C, Args, Inputs, Actions);
41550b57cec5SDimitry Andric 
415681ad6265SDimitry Andric   bool UseNewOffloadingDriver =
4157bdd1243dSDimitry Andric       C.isOffloadingHostKind(Action::OFK_OpenMP) ||
415881ad6265SDimitry Andric       Args.hasFlag(options::OPT_offload_new_driver,
415981ad6265SDimitry Andric                    options::OPT_no_offload_new_driver, false);
41601fd87a68SDimitry Andric 
4161bdd1243dSDimitry Andric   // Builder to be used to build offloading actions.
4162bdd1243dSDimitry Andric   std::unique_ptr<OffloadingActionBuilder> OffloadBuilder =
4163bdd1243dSDimitry Andric       !UseNewOffloadingDriver
4164bdd1243dSDimitry Andric           ? std::make_unique<OffloadingActionBuilder>(C, Args, Inputs)
4165bdd1243dSDimitry Andric           : nullptr;
4166bdd1243dSDimitry Andric 
41670b57cec5SDimitry Andric   // Construct the actions to perform.
416881ad6265SDimitry Andric   ExtractAPIJobAction *ExtractAPIAction = nullptr;
41690b57cec5SDimitry Andric   ActionList LinkerInputs;
4170a7dea167SDimitry Andric   ActionList MergerInputs;
41710b57cec5SDimitry Andric 
41720b57cec5SDimitry Andric   for (auto &I : Inputs) {
41730b57cec5SDimitry Andric     types::ID InputType = I.first;
41740b57cec5SDimitry Andric     const Arg *InputArg = I.second;
41750b57cec5SDimitry Andric 
41765ffd83dbSDimitry Andric     auto PL = types::getCompilationPhases(*this, Args, InputType);
4177a7dea167SDimitry Andric     if (PL.empty())
41780b57cec5SDimitry Andric       continue;
41790b57cec5SDimitry Andric 
41805ffd83dbSDimitry Andric     auto FullPL = types::getCompilationPhases(InputType);
41810b57cec5SDimitry Andric 
41820b57cec5SDimitry Andric     // Build the pipeline for this file.
41830b57cec5SDimitry Andric     Action *Current = C.MakeAction<InputAction>(*InputArg, InputType);
41840b57cec5SDimitry Andric 
41850b57cec5SDimitry Andric     // Use the current host action in any of the offloading actions, if
41860b57cec5SDimitry Andric     // required.
418781ad6265SDimitry Andric     if (!UseNewOffloadingDriver)
4188bdd1243dSDimitry Andric       if (OffloadBuilder->addHostDependenceToDeviceActions(Current, InputArg))
41890b57cec5SDimitry Andric         break;
41900b57cec5SDimitry Andric 
4191a7dea167SDimitry Andric     for (phases::ID Phase : PL) {
41920b57cec5SDimitry Andric 
41930b57cec5SDimitry Andric       // Add any offload action the host action depends on.
419481ad6265SDimitry Andric       if (!UseNewOffloadingDriver)
4195bdd1243dSDimitry Andric         Current = OffloadBuilder->addDeviceDependencesToHostAction(
4196a7dea167SDimitry Andric             Current, InputArg, Phase, PL.back(), FullPL);
41970b57cec5SDimitry Andric       if (!Current)
41980b57cec5SDimitry Andric         break;
41990b57cec5SDimitry Andric 
42000b57cec5SDimitry Andric       // Queue linker inputs.
42010b57cec5SDimitry Andric       if (Phase == phases::Link) {
4202a7dea167SDimitry Andric         assert(Phase == PL.back() && "linking must be final compilation step.");
420306c3fb27SDimitry Andric         // We don't need to generate additional link commands if emitting AMD
420406c3fb27SDimitry Andric         // bitcode or compiling only for the offload device
420581ad6265SDimitry Andric         if (!(C.getInputArgs().hasArg(options::OPT_hip_link) &&
420606c3fb27SDimitry Andric               (C.getInputArgs().hasArg(options::OPT_emit_llvm))) &&
420706c3fb27SDimitry Andric             !offloadDeviceOnly())
42080b57cec5SDimitry Andric           LinkerInputs.push_back(Current);
42090b57cec5SDimitry Andric         Current = nullptr;
42100b57cec5SDimitry Andric         break;
42110b57cec5SDimitry Andric       }
42120b57cec5SDimitry Andric 
4213a7dea167SDimitry Andric       // TODO: Consider removing this because the merged may not end up being
4214a7dea167SDimitry Andric       // the final Phase in the pipeline. Perhaps the merged could just merge
4215a7dea167SDimitry Andric       // and then pass an artifact of some sort to the Link Phase.
4216a7dea167SDimitry Andric       // Queue merger inputs.
4217a7dea167SDimitry Andric       if (Phase == phases::IfsMerge) {
4218a7dea167SDimitry Andric         assert(Phase == PL.back() && "merging must be final compilation step.");
4219a7dea167SDimitry Andric         MergerInputs.push_back(Current);
4220a7dea167SDimitry Andric         Current = nullptr;
4221a7dea167SDimitry Andric         break;
4222a7dea167SDimitry Andric       }
4223a7dea167SDimitry Andric 
422481ad6265SDimitry Andric       if (Phase == phases::Precompile && ExtractAPIAction) {
422581ad6265SDimitry Andric         ExtractAPIAction->addHeaderInput(Current);
422681ad6265SDimitry Andric         Current = nullptr;
422781ad6265SDimitry Andric         break;
422881ad6265SDimitry Andric       }
42291fd87a68SDimitry Andric 
42300b57cec5SDimitry Andric       // FIXME: Should we include any prior module file outputs as inputs of
42310b57cec5SDimitry Andric       // later actions in the same command line?
42320b57cec5SDimitry Andric 
42330b57cec5SDimitry Andric       // Otherwise construct the appropriate action.
42340b57cec5SDimitry Andric       Action *NewCurrent = ConstructPhaseAction(C, Args, Phase, Current);
42350b57cec5SDimitry Andric 
42360b57cec5SDimitry Andric       // We didn't create a new action, so we will just move to the next phase.
42370b57cec5SDimitry Andric       if (NewCurrent == Current)
42380b57cec5SDimitry Andric         continue;
42390b57cec5SDimitry Andric 
4240bdd1243dSDimitry Andric       if (auto *EAA = dyn_cast<ExtractAPIJobAction>(NewCurrent))
424181ad6265SDimitry Andric         ExtractAPIAction = EAA;
42420b57cec5SDimitry Andric 
42430b57cec5SDimitry Andric       Current = NewCurrent;
42440b57cec5SDimitry Andric 
424581ad6265SDimitry Andric       // Try to build the offloading actions and add the result as a dependency
424681ad6265SDimitry Andric       // to the host.
424781ad6265SDimitry Andric       if (UseNewOffloadingDriver)
424881ad6265SDimitry Andric         Current = BuildOffloadingActions(C, Args, I, Current);
424906c3fb27SDimitry Andric       // Use the current host action in any of the offloading actions, if
425006c3fb27SDimitry Andric       // required.
425106c3fb27SDimitry Andric       else if (OffloadBuilder->addHostDependenceToDeviceActions(Current,
425206c3fb27SDimitry Andric                                                                 InputArg))
425306c3fb27SDimitry Andric         break;
425481ad6265SDimitry Andric 
42550b57cec5SDimitry Andric       if (Current->getType() == types::TY_Nothing)
42560b57cec5SDimitry Andric         break;
42570b57cec5SDimitry Andric     }
42580b57cec5SDimitry Andric 
42590b57cec5SDimitry Andric     // If we ended with something, add to the output list.
42600b57cec5SDimitry Andric     if (Current)
42610b57cec5SDimitry Andric       Actions.push_back(Current);
42620b57cec5SDimitry Andric 
42630b57cec5SDimitry Andric     // Add any top level actions generated for offloading.
426481ad6265SDimitry Andric     if (!UseNewOffloadingDriver)
4265bdd1243dSDimitry Andric       OffloadBuilder->appendTopLevelActions(Actions, Current, InputArg);
42661fd87a68SDimitry Andric     else if (Current)
426781ad6265SDimitry Andric       Current->propagateHostOffloadInfo(C.getActiveOffloadKinds(),
42681fd87a68SDimitry Andric                                         /*BoundArch=*/nullptr);
42690b57cec5SDimitry Andric   }
42700b57cec5SDimitry Andric 
42710b57cec5SDimitry Andric   // Add a link action if necessary.
427204eeddc0SDimitry Andric 
427304eeddc0SDimitry Andric   if (LinkerInputs.empty()) {
427404eeddc0SDimitry Andric     Arg *FinalPhaseArg;
427504eeddc0SDimitry Andric     if (getFinalPhase(Args, &FinalPhaseArg) == phases::Link)
427681ad6265SDimitry Andric       if (!UseNewOffloadingDriver)
4277bdd1243dSDimitry Andric         OffloadBuilder->appendDeviceLinkActions(Actions);
427804eeddc0SDimitry Andric   }
427904eeddc0SDimitry Andric 
42800b57cec5SDimitry Andric   if (!LinkerInputs.empty()) {
428181ad6265SDimitry Andric     if (!UseNewOffloadingDriver)
4282bdd1243dSDimitry Andric       if (Action *Wrapper = OffloadBuilder->makeHostLinkAction())
4283a7dea167SDimitry Andric         LinkerInputs.push_back(Wrapper);
42845ffd83dbSDimitry Andric     Action *LA;
42855ffd83dbSDimitry Andric     // Check if this Linker Job should emit a static library.
42865ffd83dbSDimitry Andric     if (ShouldEmitStaticLibrary(Args)) {
42875ffd83dbSDimitry Andric       LA = C.MakeAction<StaticLibJobAction>(LinkerInputs, types::TY_Image);
428881ad6265SDimitry Andric     } else if (UseNewOffloadingDriver ||
428981ad6265SDimitry Andric                Args.hasArg(options::OPT_offload_link)) {
42901fd87a68SDimitry Andric       LA = C.MakeAction<LinkerWrapperJobAction>(LinkerInputs, types::TY_Image);
429181ad6265SDimitry Andric       LA->propagateHostOffloadInfo(C.getActiveOffloadKinds(),
42921fd87a68SDimitry Andric                                    /*BoundArch=*/nullptr);
42935ffd83dbSDimitry Andric     } else {
42945ffd83dbSDimitry Andric       LA = C.MakeAction<LinkJobAction>(LinkerInputs, types::TY_Image);
42955ffd83dbSDimitry Andric     }
429681ad6265SDimitry Andric     if (!UseNewOffloadingDriver)
4297bdd1243dSDimitry Andric       LA = OffloadBuilder->processHostLinkAction(LA);
42980b57cec5SDimitry Andric     Actions.push_back(LA);
42990b57cec5SDimitry Andric   }
43000b57cec5SDimitry Andric 
4301a7dea167SDimitry Andric   // Add an interface stubs merge action if necessary.
4302a7dea167SDimitry Andric   if (!MergerInputs.empty())
4303a7dea167SDimitry Andric     Actions.push_back(
4304a7dea167SDimitry Andric         C.MakeAction<IfsMergeJobAction>(MergerInputs, types::TY_Image));
43050b57cec5SDimitry Andric 
4306480093f4SDimitry Andric   if (Args.hasArg(options::OPT_emit_interface_stubs)) {
43075ffd83dbSDimitry Andric     auto PhaseList = types::getCompilationPhases(
43085ffd83dbSDimitry Andric         types::TY_IFS_CPP,
4309349cc55cSDimitry Andric         Args.hasArg(options::OPT_c) ? phases::Compile : phases::IfsMerge);
4310480093f4SDimitry Andric 
4311480093f4SDimitry Andric     ActionList MergerInputs;
4312480093f4SDimitry Andric 
4313480093f4SDimitry Andric     for (auto &I : Inputs) {
4314480093f4SDimitry Andric       types::ID InputType = I.first;
4315480093f4SDimitry Andric       const Arg *InputArg = I.second;
4316480093f4SDimitry Andric 
4317480093f4SDimitry Andric       // Currently clang and the llvm assembler do not support generating symbol
4318480093f4SDimitry Andric       // stubs from assembly, so we skip the input on asm files. For ifs files
4319480093f4SDimitry Andric       // we rely on the normal pipeline setup in the pipeline setup code above.
4320480093f4SDimitry Andric       if (InputType == types::TY_IFS || InputType == types::TY_PP_Asm ||
4321480093f4SDimitry Andric           InputType == types::TY_Asm)
4322480093f4SDimitry Andric         continue;
4323480093f4SDimitry Andric 
4324480093f4SDimitry Andric       Action *Current = C.MakeAction<InputAction>(*InputArg, InputType);
4325480093f4SDimitry Andric 
4326480093f4SDimitry Andric       for (auto Phase : PhaseList) {
4327480093f4SDimitry Andric         switch (Phase) {
4328480093f4SDimitry Andric         default:
4329480093f4SDimitry Andric           llvm_unreachable(
4330480093f4SDimitry Andric               "IFS Pipeline can only consist of Compile followed by IfsMerge.");
4331480093f4SDimitry Andric         case phases::Compile: {
4332480093f4SDimitry Andric           // Only IfsMerge (llvm-ifs) can handle .o files by looking for ifs
4333480093f4SDimitry Andric           // files where the .o file is located. The compile action can not
4334480093f4SDimitry Andric           // handle this.
4335480093f4SDimitry Andric           if (InputType == types::TY_Object)
4336480093f4SDimitry Andric             break;
4337480093f4SDimitry Andric 
4338480093f4SDimitry Andric           Current = C.MakeAction<CompileJobAction>(Current, types::TY_IFS_CPP);
4339480093f4SDimitry Andric           break;
4340480093f4SDimitry Andric         }
4341480093f4SDimitry Andric         case phases::IfsMerge: {
4342480093f4SDimitry Andric           assert(Phase == PhaseList.back() &&
4343480093f4SDimitry Andric                  "merging must be final compilation step.");
4344480093f4SDimitry Andric           MergerInputs.push_back(Current);
4345480093f4SDimitry Andric           Current = nullptr;
4346480093f4SDimitry Andric           break;
4347480093f4SDimitry Andric         }
4348480093f4SDimitry Andric         }
4349480093f4SDimitry Andric       }
4350480093f4SDimitry Andric 
4351480093f4SDimitry Andric       // If we ended with something, add to the output list.
4352480093f4SDimitry Andric       if (Current)
4353480093f4SDimitry Andric         Actions.push_back(Current);
4354480093f4SDimitry Andric     }
4355480093f4SDimitry Andric 
4356480093f4SDimitry Andric     // Add an interface stubs merge action if necessary.
4357480093f4SDimitry Andric     if (!MergerInputs.empty())
4358480093f4SDimitry Andric       Actions.push_back(
4359480093f4SDimitry Andric           C.MakeAction<IfsMergeJobAction>(MergerInputs, types::TY_Image));
4360480093f4SDimitry Andric   }
4361480093f4SDimitry Andric 
43625f757f3fSDimitry Andric   for (auto Opt : {options::OPT_print_supported_cpus,
43630fca6ea1SDimitry Andric                    options::OPT_print_supported_extensions,
43640fca6ea1SDimitry Andric                    options::OPT_print_enabled_extensions}) {
43655f757f3fSDimitry Andric     // If --print-supported-cpus, -mcpu=? or -mtune=? is specified, build a
43665f757f3fSDimitry Andric     // custom Compile phase that prints out supported cpu models and quits.
43675f757f3fSDimitry Andric     //
43680fca6ea1SDimitry Andric     // If either --print-supported-extensions or --print-enabled-extensions is
43690fca6ea1SDimitry Andric     // specified, call the corresponding helper function that prints out the
43700fca6ea1SDimitry Andric     // supported/enabled extensions and quits.
43715f757f3fSDimitry Andric     if (Arg *A = Args.getLastArg(Opt)) {
43725f757f3fSDimitry Andric       if (Opt == options::OPT_print_supported_extensions &&
43735f757f3fSDimitry Andric           !C.getDefaultToolChain().getTriple().isRISCV() &&
43745f757f3fSDimitry Andric           !C.getDefaultToolChain().getTriple().isAArch64() &&
43755f757f3fSDimitry Andric           !C.getDefaultToolChain().getTriple().isARM()) {
43765f757f3fSDimitry Andric         C.getDriver().Diag(diag::err_opt_not_valid_on_target)
43775f757f3fSDimitry Andric             << "--print-supported-extensions";
43785f757f3fSDimitry Andric         return;
43795f757f3fSDimitry Andric       }
43800fca6ea1SDimitry Andric       if (Opt == options::OPT_print_enabled_extensions &&
43810fca6ea1SDimitry Andric           !C.getDefaultToolChain().getTriple().isRISCV() &&
43820fca6ea1SDimitry Andric           !C.getDefaultToolChain().getTriple().isAArch64()) {
43830fca6ea1SDimitry Andric         C.getDriver().Diag(diag::err_opt_not_valid_on_target)
43840fca6ea1SDimitry Andric             << "--print-enabled-extensions";
43850fca6ea1SDimitry Andric         return;
43860fca6ea1SDimitry Andric       }
43875f757f3fSDimitry Andric 
43880b57cec5SDimitry Andric       // Use the -mcpu=? flag as the dummy input to cc1.
43890b57cec5SDimitry Andric       Actions.clear();
43900b57cec5SDimitry Andric       Action *InputAc = C.MakeAction<InputAction>(*A, types::TY_C);
43910b57cec5SDimitry Andric       Actions.push_back(
43920b57cec5SDimitry Andric           C.MakeAction<PrecompileJobAction>(InputAc, types::TY_Nothing));
43930b57cec5SDimitry Andric       for (auto &I : Inputs)
43940b57cec5SDimitry Andric         I.second->claim();
43950b57cec5SDimitry Andric     }
43965f757f3fSDimitry Andric   }
43970b57cec5SDimitry Andric 
439806c3fb27SDimitry Andric   // Call validator for dxil when -Vd not in Args.
439906c3fb27SDimitry Andric   if (C.getDefaultToolChain().getTriple().isDXIL()) {
440006c3fb27SDimitry Andric     // Only add action when needValidation.
440106c3fb27SDimitry Andric     const auto &TC =
440206c3fb27SDimitry Andric         static_cast<const toolchains::HLSLToolChain &>(C.getDefaultToolChain());
440306c3fb27SDimitry Andric     if (TC.requiresValidation(Args)) {
440406c3fb27SDimitry Andric       Action *LastAction = Actions.back();
440506c3fb27SDimitry Andric       Actions.push_back(C.MakeAction<BinaryAnalyzeJobAction>(
440606c3fb27SDimitry Andric           LastAction, types::TY_DX_CONTAINER));
440706c3fb27SDimitry Andric     }
440806c3fb27SDimitry Andric   }
440906c3fb27SDimitry Andric 
44100b57cec5SDimitry Andric   // Claim ignored clang-cl options.
44110b57cec5SDimitry Andric   Args.ClaimAllArgs(options::OPT_cl_ignored_Group);
441281ad6265SDimitry Andric }
44130b57cec5SDimitry Andric 
441481ad6265SDimitry Andric /// Returns the canonical name for the offloading architecture when using a HIP
441581ad6265SDimitry Andric /// or CUDA architecture.
441681ad6265SDimitry Andric static StringRef getCanonicalArchString(Compilation &C,
441781ad6265SDimitry Andric                                         const llvm::opt::DerivedArgList &Args,
441881ad6265SDimitry Andric                                         StringRef ArchStr,
4419bdd1243dSDimitry Andric                                         const llvm::Triple &Triple,
4420bdd1243dSDimitry Andric                                         bool SuppressError = false) {
442181ad6265SDimitry Andric   // Lookup the CUDA / HIP architecture string. Only report an error if we were
442281ad6265SDimitry Andric   // expecting the triple to be only NVPTX / AMDGPU.
44230fca6ea1SDimitry Andric   OffloadArch Arch =
44240fca6ea1SDimitry Andric       StringToOffloadArch(getProcessorFromTargetID(Triple, ArchStr));
4425bdd1243dSDimitry Andric   if (!SuppressError && Triple.isNVPTX() &&
44260fca6ea1SDimitry Andric       (Arch == OffloadArch::UNKNOWN || !IsNVIDIAOffloadArch(Arch))) {
442781ad6265SDimitry Andric     C.getDriver().Diag(clang::diag::err_drv_offload_bad_gpu_arch)
442881ad6265SDimitry Andric         << "CUDA" << ArchStr;
442981ad6265SDimitry Andric     return StringRef();
4430bdd1243dSDimitry Andric   } else if (!SuppressError && Triple.isAMDGPU() &&
44310fca6ea1SDimitry Andric              (Arch == OffloadArch::UNKNOWN || !IsAMDOffloadArch(Arch))) {
443281ad6265SDimitry Andric     C.getDriver().Diag(clang::diag::err_drv_offload_bad_gpu_arch)
443381ad6265SDimitry Andric         << "HIP" << ArchStr;
443481ad6265SDimitry Andric     return StringRef();
443581ad6265SDimitry Andric   }
443681ad6265SDimitry Andric 
44370fca6ea1SDimitry Andric   if (IsNVIDIAOffloadArch(Arch))
44380fca6ea1SDimitry Andric     return Args.MakeArgStringRef(OffloadArchToString(Arch));
443981ad6265SDimitry Andric 
44400fca6ea1SDimitry Andric   if (IsAMDOffloadArch(Arch)) {
444181ad6265SDimitry Andric     llvm::StringMap<bool> Features;
444281ad6265SDimitry Andric     auto HIPTriple = getHIPOffloadTargetTriple(C.getDriver(), C.getInputArgs());
444381ad6265SDimitry Andric     if (!HIPTriple)
444481ad6265SDimitry Andric       return StringRef();
444581ad6265SDimitry Andric     auto Arch = parseTargetID(*HIPTriple, ArchStr, &Features);
444681ad6265SDimitry Andric     if (!Arch) {
444781ad6265SDimitry Andric       C.getDriver().Diag(clang::diag::err_drv_bad_target_id) << ArchStr;
444881ad6265SDimitry Andric       C.setContainsError();
444981ad6265SDimitry Andric       return StringRef();
445081ad6265SDimitry Andric     }
445181ad6265SDimitry Andric     return Args.MakeArgStringRef(getCanonicalTargetID(*Arch, Features));
445281ad6265SDimitry Andric   }
445381ad6265SDimitry Andric 
445481ad6265SDimitry Andric   // If the input isn't CUDA or HIP just return the architecture.
445581ad6265SDimitry Andric   return ArchStr;
445681ad6265SDimitry Andric }
445781ad6265SDimitry Andric 
445881ad6265SDimitry Andric /// Checks if the set offloading architectures does not conflict. Returns the
445981ad6265SDimitry Andric /// incompatible pair if a conflict occurs.
4460bdd1243dSDimitry Andric static std::optional<std::pair<llvm::StringRef, llvm::StringRef>>
446181ad6265SDimitry Andric getConflictOffloadArchCombination(const llvm::DenseSet<StringRef> &Archs,
446206c3fb27SDimitry Andric                                   llvm::Triple Triple) {
446306c3fb27SDimitry Andric   if (!Triple.isAMDGPU())
4464bdd1243dSDimitry Andric     return std::nullopt;
446581ad6265SDimitry Andric 
446681ad6265SDimitry Andric   std::set<StringRef> ArchSet;
446781ad6265SDimitry Andric   llvm::copy(Archs, std::inserter(ArchSet, ArchSet.begin()));
446881ad6265SDimitry Andric   return getConflictTargetIDCombination(ArchSet);
446981ad6265SDimitry Andric }
447081ad6265SDimitry Andric 
447181ad6265SDimitry Andric llvm::DenseSet<StringRef>
447281ad6265SDimitry Andric Driver::getOffloadArchs(Compilation &C, const llvm::opt::DerivedArgList &Args,
4473bdd1243dSDimitry Andric                         Action::OffloadKind Kind, const ToolChain *TC,
4474bdd1243dSDimitry Andric                         bool SuppressError) const {
447581ad6265SDimitry Andric   if (!TC)
447681ad6265SDimitry Andric     TC = &C.getDefaultToolChain();
447781ad6265SDimitry Andric 
447881ad6265SDimitry Andric   // --offload and --offload-arch options are mutually exclusive.
447981ad6265SDimitry Andric   if (Args.hasArgNoClaim(options::OPT_offload_EQ) &&
448081ad6265SDimitry Andric       Args.hasArgNoClaim(options::OPT_offload_arch_EQ,
448181ad6265SDimitry Andric                          options::OPT_no_offload_arch_EQ)) {
448281ad6265SDimitry Andric     C.getDriver().Diag(diag::err_opt_not_valid_with_opt)
448381ad6265SDimitry Andric         << "--offload"
448481ad6265SDimitry Andric         << (Args.hasArgNoClaim(options::OPT_offload_arch_EQ)
448581ad6265SDimitry Andric                 ? "--offload-arch"
448681ad6265SDimitry Andric                 : "--no-offload-arch");
448781ad6265SDimitry Andric   }
448881ad6265SDimitry Andric 
448906c3fb27SDimitry Andric   if (KnownArchs.contains(TC))
449081ad6265SDimitry Andric     return KnownArchs.lookup(TC);
449181ad6265SDimitry Andric 
449281ad6265SDimitry Andric   llvm::DenseSet<StringRef> Archs;
4493753f127fSDimitry Andric   for (auto *Arg : Args) {
4494753f127fSDimitry Andric     // Extract any '--[no-]offload-arch' arguments intended for this toolchain.
4495753f127fSDimitry Andric     std::unique_ptr<llvm::opt::Arg> ExtractedArg = nullptr;
4496753f127fSDimitry Andric     if (Arg->getOption().matches(options::OPT_Xopenmp_target_EQ) &&
4497753f127fSDimitry Andric         ToolChain::getOpenMPTriple(Arg->getValue(0)) == TC->getTriple()) {
4498753f127fSDimitry Andric       Arg->claim();
4499753f127fSDimitry Andric       unsigned Index = Args.getBaseArgs().MakeIndex(Arg->getValue(1));
4500753f127fSDimitry Andric       ExtractedArg = getOpts().ParseOneArg(Args, Index);
4501753f127fSDimitry Andric       Arg = ExtractedArg.get();
4502753f127fSDimitry Andric     }
4503753f127fSDimitry Andric 
4504bdd1243dSDimitry Andric     // Add or remove the seen architectures in order of appearance. If an
4505bdd1243dSDimitry Andric     // invalid architecture is given we simply exit.
450681ad6265SDimitry Andric     if (Arg->getOption().matches(options::OPT_offload_arch_EQ)) {
4507bdd1243dSDimitry Andric       for (StringRef Arch : llvm::split(Arg->getValue(), ",")) {
4508bdd1243dSDimitry Andric         if (Arch == "native" || Arch.empty()) {
4509bdd1243dSDimitry Andric           auto GPUsOrErr = TC->getSystemGPUArchs(Args);
4510bdd1243dSDimitry Andric           if (!GPUsOrErr) {
4511bdd1243dSDimitry Andric             if (SuppressError)
4512bdd1243dSDimitry Andric               llvm::consumeError(GPUsOrErr.takeError());
4513bdd1243dSDimitry Andric             else
4514bdd1243dSDimitry Andric               TC->getDriver().Diag(diag::err_drv_undetermined_gpu_arch)
4515bdd1243dSDimitry Andric                   << llvm::Triple::getArchTypeName(TC->getArch())
4516bdd1243dSDimitry Andric                   << llvm::toString(GPUsOrErr.takeError()) << "--offload-arch";
4517bdd1243dSDimitry Andric             continue;
4518bdd1243dSDimitry Andric           }
4519bdd1243dSDimitry Andric 
4520bdd1243dSDimitry Andric           for (auto ArchStr : *GPUsOrErr) {
4521bdd1243dSDimitry Andric             Archs.insert(
4522bdd1243dSDimitry Andric                 getCanonicalArchString(C, Args, Args.MakeArgString(ArchStr),
4523bdd1243dSDimitry Andric                                        TC->getTriple(), SuppressError));
4524bdd1243dSDimitry Andric           }
4525bdd1243dSDimitry Andric         } else {
4526bdd1243dSDimitry Andric           StringRef ArchStr = getCanonicalArchString(
4527bdd1243dSDimitry Andric               C, Args, Arch, TC->getTriple(), SuppressError);
4528bdd1243dSDimitry Andric           if (ArchStr.empty())
4529bdd1243dSDimitry Andric             return Archs;
4530bdd1243dSDimitry Andric           Archs.insert(ArchStr);
4531bdd1243dSDimitry Andric         }
4532bdd1243dSDimitry Andric       }
453381ad6265SDimitry Andric     } else if (Arg->getOption().matches(options::OPT_no_offload_arch_EQ)) {
453481ad6265SDimitry Andric       for (StringRef Arch : llvm::split(Arg->getValue(), ",")) {
4535bdd1243dSDimitry Andric         if (Arch == "all") {
453681ad6265SDimitry Andric           Archs.clear();
4537bdd1243dSDimitry Andric         } else {
4538bdd1243dSDimitry Andric           StringRef ArchStr = getCanonicalArchString(
4539bdd1243dSDimitry Andric               C, Args, Arch, TC->getTriple(), SuppressError);
4540bdd1243dSDimitry Andric           if (ArchStr.empty())
4541bdd1243dSDimitry Andric             return Archs;
4542bdd1243dSDimitry Andric           Archs.erase(ArchStr);
4543bdd1243dSDimitry Andric         }
454481ad6265SDimitry Andric       }
454581ad6265SDimitry Andric     }
454681ad6265SDimitry Andric   }
454781ad6265SDimitry Andric 
454806c3fb27SDimitry Andric   if (auto ConflictingArchs =
454906c3fb27SDimitry Andric           getConflictOffloadArchCombination(Archs, TC->getTriple())) {
455081ad6265SDimitry Andric     C.getDriver().Diag(clang::diag::err_drv_bad_offload_arch_combo)
455181ad6265SDimitry Andric         << ConflictingArchs->first << ConflictingArchs->second;
455281ad6265SDimitry Andric     C.setContainsError();
455381ad6265SDimitry Andric   }
455481ad6265SDimitry Andric 
4555bdd1243dSDimitry Andric   // Skip filling defaults if we're just querying what is availible.
4556bdd1243dSDimitry Andric   if (SuppressError)
4557bdd1243dSDimitry Andric     return Archs;
4558bdd1243dSDimitry Andric 
455981ad6265SDimitry Andric   if (Archs.empty()) {
456081ad6265SDimitry Andric     if (Kind == Action::OFK_Cuda)
45610fca6ea1SDimitry Andric       Archs.insert(OffloadArchToString(OffloadArch::CudaDefault));
456281ad6265SDimitry Andric     else if (Kind == Action::OFK_HIP)
45630fca6ea1SDimitry Andric       Archs.insert(OffloadArchToString(OffloadArch::HIPDefault));
456481ad6265SDimitry Andric     else if (Kind == Action::OFK_OpenMP)
456581ad6265SDimitry Andric       Archs.insert(StringRef());
456681ad6265SDimitry Andric   } else {
456781ad6265SDimitry Andric     Args.ClaimAllArgs(options::OPT_offload_arch_EQ);
456881ad6265SDimitry Andric     Args.ClaimAllArgs(options::OPT_no_offload_arch_EQ);
456981ad6265SDimitry Andric   }
457081ad6265SDimitry Andric 
457181ad6265SDimitry Andric   return Archs;
45720b57cec5SDimitry Andric }
45730b57cec5SDimitry Andric 
45741fd87a68SDimitry Andric Action *Driver::BuildOffloadingActions(Compilation &C,
45751fd87a68SDimitry Andric                                        llvm::opt::DerivedArgList &Args,
45761fd87a68SDimitry Andric                                        const InputTy &Input,
45771fd87a68SDimitry Andric                                        Action *HostAction) const {
457881ad6265SDimitry Andric   // Don't build offloading actions if explicitly disabled or we do not have a
457981ad6265SDimitry Andric   // valid source input and compile action to embed it in. If preprocessing only
458081ad6265SDimitry Andric   // ignore embedding.
458181ad6265SDimitry Andric   if (offloadHostOnly() || !types::isSrcFile(Input.first) ||
458281ad6265SDimitry Andric       !(isa<CompileJobAction>(HostAction) ||
458381ad6265SDimitry Andric         getFinalPhase(Args) == phases::Preprocess))
45841fd87a68SDimitry Andric     return HostAction;
45851fd87a68SDimitry Andric 
458681ad6265SDimitry Andric   ActionList OffloadActions;
458781ad6265SDimitry Andric   OffloadAction::DeviceDependences DDeps;
458881ad6265SDimitry Andric 
458981ad6265SDimitry Andric   const Action::OffloadKind OffloadKinds[] = {
459081ad6265SDimitry Andric       Action::OFK_OpenMP, Action::OFK_Cuda, Action::OFK_HIP};
459181ad6265SDimitry Andric 
459281ad6265SDimitry Andric   for (Action::OffloadKind Kind : OffloadKinds) {
45931fd87a68SDimitry Andric     SmallVector<const ToolChain *, 2> ToolChains;
45941fd87a68SDimitry Andric     ActionList DeviceActions;
45951fd87a68SDimitry Andric 
459681ad6265SDimitry Andric     auto TCRange = C.getOffloadToolChains(Kind);
459781ad6265SDimitry Andric     for (auto TI = TCRange.first, TE = TCRange.second; TI != TE; ++TI)
459881ad6265SDimitry Andric       ToolChains.push_back(TI->second);
459981ad6265SDimitry Andric 
460081ad6265SDimitry Andric     if (ToolChains.empty())
460181ad6265SDimitry Andric       continue;
460281ad6265SDimitry Andric 
46031fd87a68SDimitry Andric     types::ID InputType = Input.first;
46041fd87a68SDimitry Andric     const Arg *InputArg = Input.second;
46051fd87a68SDimitry Andric 
4606fcaf7f86SDimitry Andric     // The toolchain can be active for unsupported file types.
4607fcaf7f86SDimitry Andric     if ((Kind == Action::OFK_Cuda && !types::isCuda(InputType)) ||
4608fcaf7f86SDimitry Andric         (Kind == Action::OFK_HIP && !types::isHIP(InputType)))
4609fcaf7f86SDimitry Andric       continue;
4610fcaf7f86SDimitry Andric 
461181ad6265SDimitry Andric     // Get the product of all bound architectures and toolchains.
461281ad6265SDimitry Andric     SmallVector<std::pair<const ToolChain *, StringRef>> TCAndArchs;
46130fca6ea1SDimitry Andric     for (const ToolChain *TC : ToolChains) {
46140fca6ea1SDimitry Andric       llvm::DenseSet<StringRef> Arches = getOffloadArchs(C, Args, Kind, TC);
46150fca6ea1SDimitry Andric       SmallVector<StringRef, 0> Sorted(Arches.begin(), Arches.end());
46160fca6ea1SDimitry Andric       llvm::sort(Sorted);
46170fca6ea1SDimitry Andric       for (StringRef Arch : Sorted)
461881ad6265SDimitry Andric         TCAndArchs.push_back(std::make_pair(TC, Arch));
46190fca6ea1SDimitry Andric     }
46201fd87a68SDimitry Andric 
462181ad6265SDimitry Andric     for (unsigned I = 0, E = TCAndArchs.size(); I != E; ++I)
46221fd87a68SDimitry Andric       DeviceActions.push_back(C.MakeAction<InputAction>(*InputArg, InputType));
46231fd87a68SDimitry Andric 
46241fd87a68SDimitry Andric     if (DeviceActions.empty())
46251fd87a68SDimitry Andric       return HostAction;
46261fd87a68SDimitry Andric 
46271fd87a68SDimitry Andric     auto PL = types::getCompilationPhases(*this, Args, InputType);
46281fd87a68SDimitry Andric 
46291fd87a68SDimitry Andric     for (phases::ID Phase : PL) {
46301fd87a68SDimitry Andric       if (Phase == phases::Link) {
46311fd87a68SDimitry Andric         assert(Phase == PL.back() && "linking must be final compilation step.");
46321fd87a68SDimitry Andric         break;
46331fd87a68SDimitry Andric       }
46341fd87a68SDimitry Andric 
463581ad6265SDimitry Andric       auto TCAndArch = TCAndArchs.begin();
46361fd87a68SDimitry Andric       for (Action *&A : DeviceActions) {
4637bdd1243dSDimitry Andric         if (A->getType() == types::TY_Nothing)
4638bdd1243dSDimitry Andric           continue;
4639bdd1243dSDimitry Andric 
4640bdd1243dSDimitry Andric         // Propagate the ToolChain so we can use it in ConstructPhaseAction.
4641bdd1243dSDimitry Andric         A->propagateDeviceOffloadInfo(Kind, TCAndArch->second.data(),
4642bdd1243dSDimitry Andric                                       TCAndArch->first);
464381ad6265SDimitry Andric         A = ConstructPhaseAction(C, Args, Phase, A, Kind);
46441fd87a68SDimitry Andric 
464581ad6265SDimitry Andric         if (isa<CompileJobAction>(A) && isa<CompileJobAction>(HostAction) &&
4646bdd1243dSDimitry Andric             Kind == Action::OFK_OpenMP &&
4647bdd1243dSDimitry Andric             HostAction->getType() != types::TY_Nothing) {
464881ad6265SDimitry Andric           // OpenMP offloading has a dependency on the host compile action to
464981ad6265SDimitry Andric           // identify which declarations need to be emitted. This shouldn't be
465081ad6265SDimitry Andric           // collapsed with any other actions so we can use it in the device.
46511fd87a68SDimitry Andric           HostAction->setCannotBeCollapsedWithNextDependentAction();
46521fd87a68SDimitry Andric           OffloadAction::HostDependence HDep(
46531fd87a68SDimitry Andric               *HostAction, *C.getSingleOffloadToolChain<Action::OFK_Host>(),
465481ad6265SDimitry Andric               TCAndArch->second.data(), Kind);
46551fd87a68SDimitry Andric           OffloadAction::DeviceDependences DDep;
465681ad6265SDimitry Andric           DDep.add(*A, *TCAndArch->first, TCAndArch->second.data(), Kind);
46571fd87a68SDimitry Andric           A = C.MakeAction<OffloadAction>(HDep, DDep);
46581fd87a68SDimitry Andric         }
4659bdd1243dSDimitry Andric 
466081ad6265SDimitry Andric         ++TCAndArch;
46611fd87a68SDimitry Andric       }
46621fd87a68SDimitry Andric     }
46631fd87a68SDimitry Andric 
4664fcaf7f86SDimitry Andric     // Compiling HIP in non-RDC mode requires linking each action individually.
4665fcaf7f86SDimitry Andric     for (Action *&A : DeviceActions) {
4666bdd1243dSDimitry Andric       if ((A->getType() != types::TY_Object &&
4667bdd1243dSDimitry Andric            A->getType() != types::TY_LTO_BC) ||
4668bdd1243dSDimitry Andric           Kind != Action::OFK_HIP ||
4669fcaf7f86SDimitry Andric           Args.hasFlag(options::OPT_fgpu_rdc, options::OPT_fno_gpu_rdc, false))
4670fcaf7f86SDimitry Andric         continue;
4671fcaf7f86SDimitry Andric       ActionList LinkerInput = {A};
4672fcaf7f86SDimitry Andric       A = C.MakeAction<LinkJobAction>(LinkerInput, types::TY_Image);
4673fcaf7f86SDimitry Andric     }
4674fcaf7f86SDimitry Andric 
467581ad6265SDimitry Andric     auto TCAndArch = TCAndArchs.begin();
46761fd87a68SDimitry Andric     for (Action *A : DeviceActions) {
467781ad6265SDimitry Andric       DDeps.add(*A, *TCAndArch->first, TCAndArch->second.data(), Kind);
467881ad6265SDimitry Andric       OffloadAction::DeviceDependences DDep;
467981ad6265SDimitry Andric       DDep.add(*A, *TCAndArch->first, TCAndArch->second.data(), Kind);
46800fca6ea1SDimitry Andric 
46810fca6ea1SDimitry Andric       // Compiling CUDA in non-RDC mode uses the PTX output if available.
46820fca6ea1SDimitry Andric       for (Action *Input : A->getInputs())
46830fca6ea1SDimitry Andric         if (Kind == Action::OFK_Cuda && A->getType() == types::TY_Object &&
46840fca6ea1SDimitry Andric             !Args.hasFlag(options::OPT_fgpu_rdc, options::OPT_fno_gpu_rdc,
46850fca6ea1SDimitry Andric                           false))
46860fca6ea1SDimitry Andric           DDep.add(*Input, *TCAndArch->first, TCAndArch->second.data(), Kind);
468781ad6265SDimitry Andric       OffloadActions.push_back(C.MakeAction<OffloadAction>(DDep, A->getType()));
46880fca6ea1SDimitry Andric 
468981ad6265SDimitry Andric       ++TCAndArch;
469081ad6265SDimitry Andric     }
46911fd87a68SDimitry Andric   }
46921fd87a68SDimitry Andric 
46930fca6ea1SDimitry Andric   // HIP code in non-RDC mode will bundle the output if it invoked the linker.
46940fca6ea1SDimitry Andric   bool ShouldBundleHIP =
46950fca6ea1SDimitry Andric       C.isOffloadingHostKind(Action::OFK_HIP) &&
46960fca6ea1SDimitry Andric       Args.hasFlag(options::OPT_gpu_bundle_output,
46970fca6ea1SDimitry Andric                    options::OPT_no_gpu_bundle_output, true) &&
46980fca6ea1SDimitry Andric       !Args.hasFlag(options::OPT_fgpu_rdc, options::OPT_fno_gpu_rdc, false) &&
46990fca6ea1SDimitry Andric       !llvm::any_of(OffloadActions,
47000fca6ea1SDimitry Andric                     [](Action *A) { return A->getType() != types::TY_Image; });
47010fca6ea1SDimitry Andric 
47020fca6ea1SDimitry Andric   // All kinds exit now in device-only mode except for non-RDC mode HIP.
47030fca6ea1SDimitry Andric   if (offloadDeviceOnly() && !ShouldBundleHIP)
470481ad6265SDimitry Andric     return C.MakeAction<OffloadAction>(DDeps, types::TY_Nothing);
470581ad6265SDimitry Andric 
4706fcaf7f86SDimitry Andric   if (OffloadActions.empty())
4707fcaf7f86SDimitry Andric     return HostAction;
4708fcaf7f86SDimitry Andric 
470981ad6265SDimitry Andric   OffloadAction::DeviceDependences DDep;
4710753f127fSDimitry Andric   if (C.isOffloadingHostKind(Action::OFK_Cuda) &&
4711753f127fSDimitry Andric       !Args.hasFlag(options::OPT_fgpu_rdc, options::OPT_fno_gpu_rdc, false)) {
4712fcaf7f86SDimitry Andric     // If we are not in RDC-mode we just emit the final CUDA fatbinary for
4713fcaf7f86SDimitry Andric     // each translation unit without requiring any linking.
4714753f127fSDimitry Andric     Action *FatbinAction =
4715753f127fSDimitry Andric         C.MakeAction<LinkJobAction>(OffloadActions, types::TY_CUDA_FATBIN);
4716753f127fSDimitry Andric     DDep.add(*FatbinAction, *C.getSingleOffloadToolChain<Action::OFK_Cuda>(),
4717753f127fSDimitry Andric              nullptr, Action::OFK_Cuda);
4718fcaf7f86SDimitry Andric   } else if (C.isOffloadingHostKind(Action::OFK_HIP) &&
4719fcaf7f86SDimitry Andric              !Args.hasFlag(options::OPT_fgpu_rdc, options::OPT_fno_gpu_rdc,
4720fcaf7f86SDimitry Andric                            false)) {
4721fcaf7f86SDimitry Andric     // If we are not in RDC-mode we just emit the final HIP fatbinary for each
4722fcaf7f86SDimitry Andric     // translation unit, linking each input individually.
4723fcaf7f86SDimitry Andric     Action *FatbinAction =
4724fcaf7f86SDimitry Andric         C.MakeAction<LinkJobAction>(OffloadActions, types::TY_HIP_FATBIN);
4725fcaf7f86SDimitry Andric     DDep.add(*FatbinAction, *C.getSingleOffloadToolChain<Action::OFK_HIP>(),
4726fcaf7f86SDimitry Andric              nullptr, Action::OFK_HIP);
4727753f127fSDimitry Andric   } else {
4728753f127fSDimitry Andric     // Package all the offloading actions into a single output that can be
4729753f127fSDimitry Andric     // embedded in the host and linked.
4730753f127fSDimitry Andric     Action *PackagerAction =
4731753f127fSDimitry Andric         C.MakeAction<OffloadPackagerJobAction>(OffloadActions, types::TY_Image);
4732753f127fSDimitry Andric     DDep.add(*PackagerAction, *C.getSingleOffloadToolChain<Action::OFK_Host>(),
4733bdd1243dSDimitry Andric              nullptr, C.getActiveOffloadKinds());
4734753f127fSDimitry Andric   }
4735fcaf7f86SDimitry Andric 
47360fca6ea1SDimitry Andric   // HIP wants '--offload-device-only' to create a fatbinary by default.
47370fca6ea1SDimitry Andric   if (offloadDeviceOnly())
47380fca6ea1SDimitry Andric     return C.MakeAction<OffloadAction>(DDep, types::TY_Nothing);
47390fca6ea1SDimitry Andric 
4740bdd1243dSDimitry Andric   // If we are unable to embed a single device output into the host, we need to
4741bdd1243dSDimitry Andric   // add each device output as a host dependency to ensure they are still built.
4742bdd1243dSDimitry Andric   bool SingleDeviceOutput = !llvm::any_of(OffloadActions, [](Action *A) {
4743bdd1243dSDimitry Andric     return A->getType() == types::TY_Nothing;
4744bdd1243dSDimitry Andric   }) && isa<CompileJobAction>(HostAction);
47451fd87a68SDimitry Andric   OffloadAction::HostDependence HDep(
47461fd87a68SDimitry Andric       *HostAction, *C.getSingleOffloadToolChain<Action::OFK_Host>(),
4747bdd1243dSDimitry Andric       /*BoundArch=*/nullptr, SingleDeviceOutput ? DDep : DDeps);
4748bdd1243dSDimitry Andric   return C.MakeAction<OffloadAction>(HDep, SingleDeviceOutput ? DDep : DDeps);
47491fd87a68SDimitry Andric }
47501fd87a68SDimitry Andric 
47510b57cec5SDimitry Andric Action *Driver::ConstructPhaseAction(
47520b57cec5SDimitry Andric     Compilation &C, const ArgList &Args, phases::ID Phase, Action *Input,
47530b57cec5SDimitry Andric     Action::OffloadKind TargetDeviceOffloadKind) const {
47540b57cec5SDimitry Andric   llvm::PrettyStackTraceString CrashInfo("Constructing phase actions");
47550b57cec5SDimitry Andric 
47560b57cec5SDimitry Andric   // Some types skip the assembler phase (e.g., llvm-bc), but we can't
47570b57cec5SDimitry Andric   // encode this in the steps because the intermediate type depends on
47580b57cec5SDimitry Andric   // arguments. Just special case here.
47590b57cec5SDimitry Andric   if (Phase == phases::Assemble && Input->getType() != types::TY_PP_Asm)
47600b57cec5SDimitry Andric     return Input;
47610b57cec5SDimitry Andric 
47620b57cec5SDimitry Andric   // Build the appropriate action.
47630b57cec5SDimitry Andric   switch (Phase) {
47640b57cec5SDimitry Andric   case phases::Link:
47650b57cec5SDimitry Andric     llvm_unreachable("link action invalid here.");
4766a7dea167SDimitry Andric   case phases::IfsMerge:
4767a7dea167SDimitry Andric     llvm_unreachable("ifsmerge action invalid here.");
47680b57cec5SDimitry Andric   case phases::Preprocess: {
47690b57cec5SDimitry Andric     types::ID OutputTy;
4770a7dea167SDimitry Andric     // -M and -MM specify the dependency file name by altering the output type,
4771a7dea167SDimitry Andric     // -if -MD and -MMD are not specified.
4772a7dea167SDimitry Andric     if (Args.hasArg(options::OPT_M, options::OPT_MM) &&
4773a7dea167SDimitry Andric         !Args.hasArg(options::OPT_MD, options::OPT_MMD)) {
47740b57cec5SDimitry Andric       OutputTy = types::TY_Dependencies;
47750b57cec5SDimitry Andric     } else {
47760b57cec5SDimitry Andric       OutputTy = Input->getType();
477781ad6265SDimitry Andric       // For these cases, the preprocessor is only translating forms, the Output
477881ad6265SDimitry Andric       // still needs preprocessing.
47790b57cec5SDimitry Andric       if (!Args.hasFlag(options::OPT_frewrite_includes,
47800b57cec5SDimitry Andric                         options::OPT_fno_rewrite_includes, false) &&
47810b57cec5SDimitry Andric           !Args.hasFlag(options::OPT_frewrite_imports,
47820b57cec5SDimitry Andric                         options::OPT_fno_rewrite_imports, false) &&
478381ad6265SDimitry Andric           !Args.hasFlag(options::OPT_fdirectives_only,
478481ad6265SDimitry Andric                         options::OPT_fno_directives_only, false) &&
47850b57cec5SDimitry Andric           !CCGenDiagnostics)
47860b57cec5SDimitry Andric         OutputTy = types::getPreprocessedType(OutputTy);
47870b57cec5SDimitry Andric       assert(OutputTy != types::TY_INVALID &&
47880b57cec5SDimitry Andric              "Cannot preprocess this input type!");
47890b57cec5SDimitry Andric     }
47900b57cec5SDimitry Andric     return C.MakeAction<PreprocessJobAction>(Input, OutputTy);
47910b57cec5SDimitry Andric   }
47920b57cec5SDimitry Andric   case phases::Precompile: {
479381ad6265SDimitry Andric     // API extraction should not generate an actual precompilation action.
479481ad6265SDimitry Andric     if (Args.hasArg(options::OPT_extract_api))
479581ad6265SDimitry Andric       return C.MakeAction<ExtractAPIJobAction>(Input, types::TY_API_INFO);
479681ad6265SDimitry Andric 
47970fca6ea1SDimitry Andric     // With 'fexperimental-modules-reduced-bmi', we don't want to run the
47980fca6ea1SDimitry Andric     // precompile phase unless the user specified '--precompile'. In the case
47990fca6ea1SDimitry Andric     // the '--precompile' flag is enabled, we will try to emit the reduced BMI
48000fca6ea1SDimitry Andric     // as a by product in GenerateModuleInterfaceAction.
48010fca6ea1SDimitry Andric     if (Args.hasArg(options::OPT_modules_reduced_bmi) &&
48020fca6ea1SDimitry Andric         !Args.getLastArg(options::OPT__precompile))
48030fca6ea1SDimitry Andric       return Input;
48040fca6ea1SDimitry Andric 
48050b57cec5SDimitry Andric     types::ID OutputTy = getPrecompiledType(Input->getType());
48060b57cec5SDimitry Andric     assert(OutputTy != types::TY_INVALID &&
48070b57cec5SDimitry Andric            "Cannot precompile this input type!");
48080b57cec5SDimitry Andric 
48090b57cec5SDimitry Andric     // If we're given a module name, precompile header file inputs as a
48100b57cec5SDimitry Andric     // module, not as a precompiled header.
48110b57cec5SDimitry Andric     const char *ModName = nullptr;
48120b57cec5SDimitry Andric     if (OutputTy == types::TY_PCH) {
48130b57cec5SDimitry Andric       if (Arg *A = Args.getLastArg(options::OPT_fmodule_name_EQ))
48140b57cec5SDimitry Andric         ModName = A->getValue();
48150b57cec5SDimitry Andric       if (ModName)
48160b57cec5SDimitry Andric         OutputTy = types::TY_ModuleFile;
48170b57cec5SDimitry Andric     }
48180b57cec5SDimitry Andric 
481981ad6265SDimitry Andric     if (Args.hasArg(options::OPT_fsyntax_only)) {
48200b57cec5SDimitry Andric       // Syntax checks should not emit a PCH file
48210b57cec5SDimitry Andric       OutputTy = types::TY_Nothing;
48220b57cec5SDimitry Andric     }
48230b57cec5SDimitry Andric 
48240b57cec5SDimitry Andric     return C.MakeAction<PrecompileJobAction>(Input, OutputTy);
48250b57cec5SDimitry Andric   }
48260b57cec5SDimitry Andric   case phases::Compile: {
48270b57cec5SDimitry Andric     if (Args.hasArg(options::OPT_fsyntax_only))
48280b57cec5SDimitry Andric       return C.MakeAction<CompileJobAction>(Input, types::TY_Nothing);
48290b57cec5SDimitry Andric     if (Args.hasArg(options::OPT_rewrite_objc))
48300b57cec5SDimitry Andric       return C.MakeAction<CompileJobAction>(Input, types::TY_RewrittenObjC);
48310b57cec5SDimitry Andric     if (Args.hasArg(options::OPT_rewrite_legacy_objc))
48320b57cec5SDimitry Andric       return C.MakeAction<CompileJobAction>(Input,
48330b57cec5SDimitry Andric                                             types::TY_RewrittenLegacyObjC);
4834a7dea167SDimitry Andric     if (Args.hasArg(options::OPT__analyze))
48350b57cec5SDimitry Andric       return C.MakeAction<AnalyzeJobAction>(Input, types::TY_Plist);
48360b57cec5SDimitry Andric     if (Args.hasArg(options::OPT__migrate))
48370b57cec5SDimitry Andric       return C.MakeAction<MigrateJobAction>(Input, types::TY_Remap);
48380b57cec5SDimitry Andric     if (Args.hasArg(options::OPT_emit_ast))
48390b57cec5SDimitry Andric       return C.MakeAction<CompileJobAction>(Input, types::TY_AST);
48400fca6ea1SDimitry Andric     if (Args.hasArg(options::OPT_emit_cir))
48410fca6ea1SDimitry Andric       return C.MakeAction<CompileJobAction>(Input, types::TY_CIR);
48420b57cec5SDimitry Andric     if (Args.hasArg(options::OPT_module_file_info))
48430b57cec5SDimitry Andric       return C.MakeAction<CompileJobAction>(Input, types::TY_ModuleFile);
48440b57cec5SDimitry Andric     if (Args.hasArg(options::OPT_verify_pch))
48450b57cec5SDimitry Andric       return C.MakeAction<VerifyPCHJobAction>(Input, types::TY_Nothing);
484604eeddc0SDimitry Andric     if (Args.hasArg(options::OPT_extract_api))
484781ad6265SDimitry Andric       return C.MakeAction<ExtractAPIJobAction>(Input, types::TY_API_INFO);
48480b57cec5SDimitry Andric     return C.MakeAction<CompileJobAction>(Input, types::TY_LLVM_BC);
48490b57cec5SDimitry Andric   }
48500b57cec5SDimitry Andric   case phases::Backend: {
48510b57cec5SDimitry Andric     if (isUsingLTO() && TargetDeviceOffloadKind == Action::OFK_None) {
48525f757f3fSDimitry Andric       types::ID Output;
4853b3edf446SDimitry Andric       if (Args.hasArg(options::OPT_ffat_lto_objects) &&
4854b3edf446SDimitry Andric           !Args.hasArg(options::OPT_emit_llvm))
4855b3edf446SDimitry Andric         Output = types::TY_PP_Asm;
48567a6dacacSDimitry Andric       else if (Args.hasArg(options::OPT_S))
48575f757f3fSDimitry Andric         Output = types::TY_LTO_IR;
48585f757f3fSDimitry Andric       else
48595f757f3fSDimitry Andric         Output = types::TY_LTO_BC;
48600b57cec5SDimitry Andric       return C.MakeAction<BackendJobAction>(Input, Output);
48610b57cec5SDimitry Andric     }
48621fd87a68SDimitry Andric     if (isUsingLTO(/* IsOffload */ true) &&
486381ad6265SDimitry Andric         TargetDeviceOffloadKind != Action::OFK_None) {
48641fd87a68SDimitry Andric       types::ID Output =
48651fd87a68SDimitry Andric           Args.hasArg(options::OPT_S) ? types::TY_LTO_IR : types::TY_LTO_BC;
48661fd87a68SDimitry Andric       return C.MakeAction<BackendJobAction>(Input, Output);
48671fd87a68SDimitry Andric     }
48685ffd83dbSDimitry Andric     if (Args.hasArg(options::OPT_emit_llvm) ||
4869bdd1243dSDimitry Andric         (((Input->getOffloadingToolChain() &&
4870bdd1243dSDimitry Andric            Input->getOffloadingToolChain()->getTriple().isAMDGPU()) ||
4871bdd1243dSDimitry Andric           TargetDeviceOffloadKind == Action::OFK_HIP) &&
4872bdd1243dSDimitry Andric          (Args.hasFlag(options::OPT_fgpu_rdc, options::OPT_fno_gpu_rdc,
4873bdd1243dSDimitry Andric                        false) ||
4874bdd1243dSDimitry Andric           TargetDeviceOffloadKind == Action::OFK_OpenMP))) {
48750b57cec5SDimitry Andric       types::ID Output =
4876bdd1243dSDimitry Andric           Args.hasArg(options::OPT_S) &&
4877bdd1243dSDimitry Andric                   (TargetDeviceOffloadKind == Action::OFK_None ||
4878bdd1243dSDimitry Andric                    offloadDeviceOnly() ||
4879bdd1243dSDimitry Andric                    (TargetDeviceOffloadKind == Action::OFK_HIP &&
4880bdd1243dSDimitry Andric                     !Args.hasFlag(options::OPT_offload_new_driver,
4881bdd1243dSDimitry Andric                                   options::OPT_no_offload_new_driver, false)))
4882bdd1243dSDimitry Andric               ? types::TY_LLVM_IR
4883bdd1243dSDimitry Andric               : types::TY_LLVM_BC;
48840b57cec5SDimitry Andric       return C.MakeAction<BackendJobAction>(Input, Output);
48850b57cec5SDimitry Andric     }
48860b57cec5SDimitry Andric     return C.MakeAction<BackendJobAction>(Input, types::TY_PP_Asm);
48870b57cec5SDimitry Andric   }
48880b57cec5SDimitry Andric   case phases::Assemble:
48890b57cec5SDimitry Andric     return C.MakeAction<AssembleJobAction>(std::move(Input), types::TY_Object);
48900b57cec5SDimitry Andric   }
48910b57cec5SDimitry Andric 
48920b57cec5SDimitry Andric   llvm_unreachable("invalid phase in ConstructPhaseAction");
48930b57cec5SDimitry Andric }
48940b57cec5SDimitry Andric 
48950b57cec5SDimitry Andric void Driver::BuildJobs(Compilation &C) const {
48960b57cec5SDimitry Andric   llvm::PrettyStackTraceString CrashInfo("Building compilation jobs");
48970b57cec5SDimitry Andric 
48980b57cec5SDimitry Andric   Arg *FinalOutput = C.getArgs().getLastArg(options::OPT_o);
48990b57cec5SDimitry Andric 
49000b57cec5SDimitry Andric   // It is an error to provide a -o option if we are making multiple output
4901480093f4SDimitry Andric   // files. There are exceptions:
4902480093f4SDimitry Andric   //
4903480093f4SDimitry Andric   // IfsMergeJob: when generating interface stubs enabled we want to be able to
4904480093f4SDimitry Andric   // generate the stub file at the same time that we generate the real
4905480093f4SDimitry Andric   // library/a.out. So when a .o, .so, etc are the output, with clang interface
4906480093f4SDimitry Andric   // stubs there will also be a .ifs and .ifso at the same location.
4907480093f4SDimitry Andric   //
4908480093f4SDimitry Andric   // CompileJob of type TY_IFS_CPP: when generating interface stubs is enabled
4909480093f4SDimitry Andric   // and -c is passed, we still want to be able to generate a .ifs file while
4910480093f4SDimitry Andric   // we are also generating .o files. So we allow more than one output file in
4911480093f4SDimitry Andric   // this case as well.
4912480093f4SDimitry Andric   //
4913bdd1243dSDimitry Andric   // OffloadClass of type TY_Nothing: device-only output will place many outputs
4914bdd1243dSDimitry Andric   // into a single offloading action. We should count all inputs to the action
4915bdd1243dSDimitry Andric   // as outputs. Also ignore device-only outputs if we're compiling with
4916bdd1243dSDimitry Andric   // -fsyntax-only.
49170b57cec5SDimitry Andric   if (FinalOutput) {
49180b57cec5SDimitry Andric     unsigned NumOutputs = 0;
4919480093f4SDimitry Andric     unsigned NumIfsOutputs = 0;
4920bdd1243dSDimitry Andric     for (const Action *A : C.getActions()) {
4921480093f4SDimitry Andric       if (A->getType() != types::TY_Nothing &&
492206c3fb27SDimitry Andric           A->getType() != types::TY_DX_CONTAINER &&
4923480093f4SDimitry Andric           !(A->getKind() == Action::IfsMergeJobClass ||
4924480093f4SDimitry Andric             (A->getType() == clang::driver::types::TY_IFS_CPP &&
4925480093f4SDimitry Andric              A->getKind() == clang::driver::Action::CompileJobClass &&
4926480093f4SDimitry Andric              0 == NumIfsOutputs++) ||
4927480093f4SDimitry Andric             (A->getKind() == Action::BindArchClass && A->getInputs().size() &&
4928480093f4SDimitry Andric              A->getInputs().front()->getKind() == Action::IfsMergeJobClass)))
49290b57cec5SDimitry Andric         ++NumOutputs;
4930bdd1243dSDimitry Andric       else if (A->getKind() == Action::OffloadClass &&
4931bdd1243dSDimitry Andric                A->getType() == types::TY_Nothing &&
4932bdd1243dSDimitry Andric                !C.getArgs().hasArg(options::OPT_fsyntax_only))
4933bdd1243dSDimitry Andric         NumOutputs += A->size();
4934bdd1243dSDimitry Andric     }
49350b57cec5SDimitry Andric 
49360b57cec5SDimitry Andric     if (NumOutputs > 1) {
49370b57cec5SDimitry Andric       Diag(clang::diag::err_drv_output_argument_with_multiple_files);
49380b57cec5SDimitry Andric       FinalOutput = nullptr;
49390b57cec5SDimitry Andric     }
49400b57cec5SDimitry Andric   }
49410b57cec5SDimitry Andric 
4942e8d8bef9SDimitry Andric   const llvm::Triple &RawTriple = C.getDefaultToolChain().getTriple();
4943e8d8bef9SDimitry Andric 
49440b57cec5SDimitry Andric   // Collect the list of architectures.
49450b57cec5SDimitry Andric   llvm::StringSet<> ArchNames;
4946e8d8bef9SDimitry Andric   if (RawTriple.isOSBinFormatMachO())
49470b57cec5SDimitry Andric     for (const Arg *A : C.getArgs())
49480b57cec5SDimitry Andric       if (A->getOption().matches(options::OPT_arch))
49490b57cec5SDimitry Andric         ArchNames.insert(A->getValue());
49500b57cec5SDimitry Andric 
49510b57cec5SDimitry Andric   // Set of (Action, canonical ToolChain triple) pairs we've built jobs for.
49521fd87a68SDimitry Andric   std::map<std::pair<const Action *, std::string>, InputInfoList> CachedResults;
49530b57cec5SDimitry Andric   for (Action *A : C.getActions()) {
49540b57cec5SDimitry Andric     // If we are linking an image for multiple archs then the linker wants
49550b57cec5SDimitry Andric     // -arch_multiple and -final_output <final image name>. Unfortunately, this
49560b57cec5SDimitry Andric     // doesn't fit in cleanly because we have to pass this information down.
49570b57cec5SDimitry Andric     //
49580b57cec5SDimitry Andric     // FIXME: This is a hack; find a cleaner way to integrate this into the
49590b57cec5SDimitry Andric     // process.
49600b57cec5SDimitry Andric     const char *LinkingOutput = nullptr;
49610b57cec5SDimitry Andric     if (isa<LipoJobAction>(A)) {
49620b57cec5SDimitry Andric       if (FinalOutput)
49630b57cec5SDimitry Andric         LinkingOutput = FinalOutput->getValue();
49640b57cec5SDimitry Andric       else
49650b57cec5SDimitry Andric         LinkingOutput = getDefaultImageName();
49660b57cec5SDimitry Andric     }
49670b57cec5SDimitry Andric 
49680b57cec5SDimitry Andric     BuildJobsForAction(C, A, &C.getDefaultToolChain(),
49690b57cec5SDimitry Andric                        /*BoundArch*/ StringRef(),
49700b57cec5SDimitry Andric                        /*AtTopLevel*/ true,
49710b57cec5SDimitry Andric                        /*MultipleArchs*/ ArchNames.size() > 1,
49720b57cec5SDimitry Andric                        /*LinkingOutput*/ LinkingOutput, CachedResults,
49730b57cec5SDimitry Andric                        /*TargetDeviceOffloadKind*/ Action::OFK_None);
49740b57cec5SDimitry Andric   }
49750b57cec5SDimitry Andric 
4976e8d8bef9SDimitry Andric   // If we have more than one job, then disable integrated-cc1 for now. Do this
4977e8d8bef9SDimitry Andric   // also when we need to report process execution statistics.
4978fe6060f1SDimitry Andric   if (C.getJobs().size() > 1 || CCPrintProcessStats)
497913138422SDimitry Andric     for (auto &J : C.getJobs())
498013138422SDimitry Andric       J.InProcess = false;
498113138422SDimitry Andric 
4982fe6060f1SDimitry Andric   if (CCPrintProcessStats) {
4983e8d8bef9SDimitry Andric     C.setPostCallback([=](const Command &Cmd, int Res) {
4984bdd1243dSDimitry Andric       std::optional<llvm::sys::ProcessStatistics> ProcStat =
4985e8d8bef9SDimitry Andric           Cmd.getProcessStatistics();
4986e8d8bef9SDimitry Andric       if (!ProcStat)
4987e8d8bef9SDimitry Andric         return;
4988fe6060f1SDimitry Andric 
4989fe6060f1SDimitry Andric       const char *LinkingOutput = nullptr;
4990fe6060f1SDimitry Andric       if (FinalOutput)
4991fe6060f1SDimitry Andric         LinkingOutput = FinalOutput->getValue();
4992fe6060f1SDimitry Andric       else if (!Cmd.getOutputFilenames().empty())
4993fe6060f1SDimitry Andric         LinkingOutput = Cmd.getOutputFilenames().front().c_str();
4994fe6060f1SDimitry Andric       else
4995fe6060f1SDimitry Andric         LinkingOutput = getDefaultImageName();
4996fe6060f1SDimitry Andric 
4997fe6060f1SDimitry Andric       if (CCPrintStatReportFilename.empty()) {
4998e8d8bef9SDimitry Andric         using namespace llvm;
4999e8d8bef9SDimitry Andric         // Human readable output.
5000e8d8bef9SDimitry Andric         outs() << sys::path::filename(Cmd.getExecutable()) << ": "
5001fe6060f1SDimitry Andric                << "output=" << LinkingOutput;
5002e8d8bef9SDimitry Andric         outs() << ", total="
5003e8d8bef9SDimitry Andric                << format("%.3f", ProcStat->TotalTime.count() / 1000.) << " ms"
5004e8d8bef9SDimitry Andric                << ", user="
5005e8d8bef9SDimitry Andric                << format("%.3f", ProcStat->UserTime.count() / 1000.) << " ms"
5006e8d8bef9SDimitry Andric                << ", mem=" << ProcStat->PeakMemory << " Kb\n";
5007fe6060f1SDimitry Andric       } else {
5008e8d8bef9SDimitry Andric         // CSV format.
5009e8d8bef9SDimitry Andric         std::string Buffer;
5010e8d8bef9SDimitry Andric         llvm::raw_string_ostream Out(Buffer);
5011e8d8bef9SDimitry Andric         llvm::sys::printArg(Out, llvm::sys::path::filename(Cmd.getExecutable()),
5012e8d8bef9SDimitry Andric                             /*Quote*/ true);
5013e8d8bef9SDimitry Andric         Out << ',';
5014fe6060f1SDimitry Andric         llvm::sys::printArg(Out, LinkingOutput, true);
5015e8d8bef9SDimitry Andric         Out << ',' << ProcStat->TotalTime.count() << ','
5016e8d8bef9SDimitry Andric             << ProcStat->UserTime.count() << ',' << ProcStat->PeakMemory
5017e8d8bef9SDimitry Andric             << '\n';
5018e8d8bef9SDimitry Andric         Out.flush();
5019e8d8bef9SDimitry Andric         std::error_code EC;
5020349cc55cSDimitry Andric         llvm::raw_fd_ostream OS(CCPrintStatReportFilename, EC,
5021fe6060f1SDimitry Andric                                 llvm::sys::fs::OF_Append |
5022fe6060f1SDimitry Andric                                     llvm::sys::fs::OF_Text);
5023e8d8bef9SDimitry Andric         if (EC)
5024e8d8bef9SDimitry Andric           return;
5025e8d8bef9SDimitry Andric         auto L = OS.lock();
5026e8d8bef9SDimitry Andric         if (!L) {
5027fe6060f1SDimitry Andric           llvm::errs() << "ERROR: Cannot lock file "
5028fe6060f1SDimitry Andric                        << CCPrintStatReportFilename << ": "
5029e8d8bef9SDimitry Andric                        << toString(L.takeError()) << "\n";
5030e8d8bef9SDimitry Andric           return;
5031e8d8bef9SDimitry Andric         }
5032e8d8bef9SDimitry Andric         OS << Buffer;
5033fe6060f1SDimitry Andric         OS.flush();
5034e8d8bef9SDimitry Andric       }
5035e8d8bef9SDimitry Andric     });
5036e8d8bef9SDimitry Andric   }
5037e8d8bef9SDimitry Andric 
50380b57cec5SDimitry Andric   // If the user passed -Qunused-arguments or there were errors, don't warn
50390b57cec5SDimitry Andric   // about any unused arguments.
50400b57cec5SDimitry Andric   if (Diags.hasErrorOccurred() ||
50410b57cec5SDimitry Andric       C.getArgs().hasArg(options::OPT_Qunused_arguments))
50420b57cec5SDimitry Andric     return;
50430b57cec5SDimitry Andric 
504481ad6265SDimitry Andric   // Claim -fdriver-only here.
504581ad6265SDimitry Andric   (void)C.getArgs().hasArg(options::OPT_fdriver_only);
50460b57cec5SDimitry Andric   // Claim -### here.
50470b57cec5SDimitry Andric   (void)C.getArgs().hasArg(options::OPT__HASH_HASH_HASH);
50480b57cec5SDimitry Andric 
50490b57cec5SDimitry Andric   // Claim --driver-mode, --rsp-quoting, it was handled earlier.
50500b57cec5SDimitry Andric   (void)C.getArgs().hasArg(options::OPT_driver_mode);
50510b57cec5SDimitry Andric   (void)C.getArgs().hasArg(options::OPT_rsp_quoting);
50520b57cec5SDimitry Andric 
50538a4dda33SDimitry Andric   bool HasAssembleJob = llvm::any_of(C.getJobs(), [](auto &J) {
50548a4dda33SDimitry Andric     // Match ClangAs and other derived assemblers of Tool. ClangAs uses a
50558a4dda33SDimitry Andric     // longer ShortName "clang integrated assembler" while other assemblers just
50568a4dda33SDimitry Andric     // use "assembler".
50578a4dda33SDimitry Andric     return strstr(J.getCreator().getShortName(), "assembler");
50588a4dda33SDimitry Andric   });
50590b57cec5SDimitry Andric   for (Arg *A : C.getArgs()) {
50600b57cec5SDimitry Andric     // FIXME: It would be nice to be able to send the argument to the
50610b57cec5SDimitry Andric     // DiagnosticsEngine, so that extra values, position, and so on could be
50620b57cec5SDimitry Andric     // printed.
50630b57cec5SDimitry Andric     if (!A->isClaimed()) {
50640b57cec5SDimitry Andric       if (A->getOption().hasFlag(options::NoArgumentUnused))
50650b57cec5SDimitry Andric         continue;
50660b57cec5SDimitry Andric 
50670b57cec5SDimitry Andric       // Suppress the warning automatically if this is just a flag, and it is an
50680b57cec5SDimitry Andric       // instance of an argument we already claimed.
50690b57cec5SDimitry Andric       const Option &Opt = A->getOption();
50700b57cec5SDimitry Andric       if (Opt.getKind() == Option::FlagClass) {
50710b57cec5SDimitry Andric         bool DuplicateClaimed = false;
50720b57cec5SDimitry Andric 
50730b57cec5SDimitry Andric         for (const Arg *AA : C.getArgs().filtered(&Opt)) {
50740b57cec5SDimitry Andric           if (AA->isClaimed()) {
50750b57cec5SDimitry Andric             DuplicateClaimed = true;
50760b57cec5SDimitry Andric             break;
50770b57cec5SDimitry Andric           }
50780b57cec5SDimitry Andric         }
50790b57cec5SDimitry Andric 
50800b57cec5SDimitry Andric         if (DuplicateClaimed)
50810b57cec5SDimitry Andric           continue;
50820b57cec5SDimitry Andric       }
50830b57cec5SDimitry Andric 
50840b57cec5SDimitry Andric       // In clang-cl, don't mention unknown arguments here since they have
50850b57cec5SDimitry Andric       // already been warned about.
508606c3fb27SDimitry Andric       if (!IsCLMode() || !A->getOption().matches(options::OPT_UNKNOWN)) {
508706c3fb27SDimitry Andric         if (A->getOption().hasFlag(options::TargetSpecific) &&
50885f757f3fSDimitry Andric             !A->isIgnoredTargetSpecific() && !HasAssembleJob &&
50895f757f3fSDimitry Andric             // When for example -### or -v is used
50905f757f3fSDimitry Andric             // without a file, target specific options are not
50915f757f3fSDimitry Andric             // consumed/validated.
50925f757f3fSDimitry Andric             // Instead emitting an error emit a warning instead.
50935f757f3fSDimitry Andric             !C.getActions().empty()) {
509406c3fb27SDimitry Andric           Diag(diag::err_drv_unsupported_opt_for_target)
509506c3fb27SDimitry Andric               << A->getSpelling() << getTargetTriple();
509606c3fb27SDimitry Andric         } else {
50970b57cec5SDimitry Andric           Diag(clang::diag::warn_drv_unused_argument)
50980b57cec5SDimitry Andric               << A->getAsString(C.getArgs());
50990b57cec5SDimitry Andric         }
51000b57cec5SDimitry Andric       }
51010b57cec5SDimitry Andric     }
510206c3fb27SDimitry Andric   }
510306c3fb27SDimitry Andric }
51040b57cec5SDimitry Andric 
51050b57cec5SDimitry Andric namespace {
51060b57cec5SDimitry Andric /// Utility class to control the collapse of dependent actions and select the
51070b57cec5SDimitry Andric /// tools accordingly.
51080b57cec5SDimitry Andric class ToolSelector final {
51090b57cec5SDimitry Andric   /// The tool chain this selector refers to.
51100b57cec5SDimitry Andric   const ToolChain &TC;
51110b57cec5SDimitry Andric 
51120b57cec5SDimitry Andric   /// The compilation this selector refers to.
51130b57cec5SDimitry Andric   const Compilation &C;
51140b57cec5SDimitry Andric 
51150b57cec5SDimitry Andric   /// The base action this selector refers to.
51160b57cec5SDimitry Andric   const JobAction *BaseAction;
51170b57cec5SDimitry Andric 
51180b57cec5SDimitry Andric   /// Set to true if the current toolchain refers to host actions.
51190b57cec5SDimitry Andric   bool IsHostSelector;
51200b57cec5SDimitry Andric 
51210b57cec5SDimitry Andric   /// Set to true if save-temps and embed-bitcode functionalities are active.
51220b57cec5SDimitry Andric   bool SaveTemps;
51230b57cec5SDimitry Andric   bool EmbedBitcode;
51240b57cec5SDimitry Andric 
51250b57cec5SDimitry Andric   /// Get previous dependent action or null if that does not exist. If
51260b57cec5SDimitry Andric   /// \a CanBeCollapsed is false, that action must be legal to collapse or
51270b57cec5SDimitry Andric   /// null will be returned.
51280b57cec5SDimitry Andric   const JobAction *getPrevDependentAction(const ActionList &Inputs,
51290b57cec5SDimitry Andric                                           ActionList &SavedOffloadAction,
51300b57cec5SDimitry Andric                                           bool CanBeCollapsed = true) {
51310b57cec5SDimitry Andric     // An option can be collapsed only if it has a single input.
51320b57cec5SDimitry Andric     if (Inputs.size() != 1)
51330b57cec5SDimitry Andric       return nullptr;
51340b57cec5SDimitry Andric 
51350b57cec5SDimitry Andric     Action *CurAction = *Inputs.begin();
51360b57cec5SDimitry Andric     if (CanBeCollapsed &&
51370b57cec5SDimitry Andric         !CurAction->isCollapsingWithNextDependentActionLegal())
51380b57cec5SDimitry Andric       return nullptr;
51390b57cec5SDimitry Andric 
51400b57cec5SDimitry Andric     // If the input action is an offload action. Look through it and save any
51410b57cec5SDimitry Andric     // offload action that can be dropped in the event of a collapse.
51420b57cec5SDimitry Andric     if (auto *OA = dyn_cast<OffloadAction>(CurAction)) {
51430b57cec5SDimitry Andric       // If the dependent action is a device action, we will attempt to collapse
51440b57cec5SDimitry Andric       // only with other device actions. Otherwise, we would do the same but
51450b57cec5SDimitry Andric       // with host actions only.
51460b57cec5SDimitry Andric       if (!IsHostSelector) {
51470b57cec5SDimitry Andric         if (OA->hasSingleDeviceDependence(/*DoNotConsiderHostActions=*/true)) {
51480b57cec5SDimitry Andric           CurAction =
51490b57cec5SDimitry Andric               OA->getSingleDeviceDependence(/*DoNotConsiderHostActions=*/true);
51500b57cec5SDimitry Andric           if (CanBeCollapsed &&
51510b57cec5SDimitry Andric               !CurAction->isCollapsingWithNextDependentActionLegal())
51520b57cec5SDimitry Andric             return nullptr;
51530b57cec5SDimitry Andric           SavedOffloadAction.push_back(OA);
51540b57cec5SDimitry Andric           return dyn_cast<JobAction>(CurAction);
51550b57cec5SDimitry Andric         }
51560b57cec5SDimitry Andric       } else if (OA->hasHostDependence()) {
51570b57cec5SDimitry Andric         CurAction = OA->getHostDependence();
51580b57cec5SDimitry Andric         if (CanBeCollapsed &&
51590b57cec5SDimitry Andric             !CurAction->isCollapsingWithNextDependentActionLegal())
51600b57cec5SDimitry Andric           return nullptr;
51610b57cec5SDimitry Andric         SavedOffloadAction.push_back(OA);
51620b57cec5SDimitry Andric         return dyn_cast<JobAction>(CurAction);
51630b57cec5SDimitry Andric       }
51640b57cec5SDimitry Andric       return nullptr;
51650b57cec5SDimitry Andric     }
51660b57cec5SDimitry Andric 
51670b57cec5SDimitry Andric     return dyn_cast<JobAction>(CurAction);
51680b57cec5SDimitry Andric   }
51690b57cec5SDimitry Andric 
51700b57cec5SDimitry Andric   /// Return true if an assemble action can be collapsed.
51710b57cec5SDimitry Andric   bool canCollapseAssembleAction() const {
51720b57cec5SDimitry Andric     return TC.useIntegratedAs() && !SaveTemps &&
51730b57cec5SDimitry Andric            !C.getArgs().hasArg(options::OPT_via_file_asm) &&
51740b57cec5SDimitry Andric            !C.getArgs().hasArg(options::OPT__SLASH_FA) &&
51755f757f3fSDimitry Andric            !C.getArgs().hasArg(options::OPT__SLASH_Fa) &&
51765f757f3fSDimitry Andric            !C.getArgs().hasArg(options::OPT_dxc_Fc);
51770b57cec5SDimitry Andric   }
51780b57cec5SDimitry Andric 
51790b57cec5SDimitry Andric   /// Return true if a preprocessor action can be collapsed.
51800b57cec5SDimitry Andric   bool canCollapsePreprocessorAction() const {
51810b57cec5SDimitry Andric     return !C.getArgs().hasArg(options::OPT_no_integrated_cpp) &&
51820b57cec5SDimitry Andric            !C.getArgs().hasArg(options::OPT_traditional_cpp) && !SaveTemps &&
51830b57cec5SDimitry Andric            !C.getArgs().hasArg(options::OPT_rewrite_objc);
51840b57cec5SDimitry Andric   }
51850b57cec5SDimitry Andric 
51860b57cec5SDimitry Andric   /// Struct that relates an action with the offload actions that would be
51870b57cec5SDimitry Andric   /// collapsed with it.
51880b57cec5SDimitry Andric   struct JobActionInfo final {
51890b57cec5SDimitry Andric     /// The action this info refers to.
51900b57cec5SDimitry Andric     const JobAction *JA = nullptr;
51910b57cec5SDimitry Andric     /// The offload actions we need to take care off if this action is
51920b57cec5SDimitry Andric     /// collapsed.
51930b57cec5SDimitry Andric     ActionList SavedOffloadAction;
51940b57cec5SDimitry Andric   };
51950b57cec5SDimitry Andric 
51960b57cec5SDimitry Andric   /// Append collapsed offload actions from the give nnumber of elements in the
51970b57cec5SDimitry Andric   /// action info array.
51980b57cec5SDimitry Andric   static void AppendCollapsedOffloadAction(ActionList &CollapsedOffloadAction,
51990b57cec5SDimitry Andric                                            ArrayRef<JobActionInfo> &ActionInfo,
52000b57cec5SDimitry Andric                                            unsigned ElementNum) {
52010b57cec5SDimitry Andric     assert(ElementNum <= ActionInfo.size() && "Invalid number of elements.");
52020b57cec5SDimitry Andric     for (unsigned I = 0; I < ElementNum; ++I)
52030b57cec5SDimitry Andric       CollapsedOffloadAction.append(ActionInfo[I].SavedOffloadAction.begin(),
52040b57cec5SDimitry Andric                                     ActionInfo[I].SavedOffloadAction.end());
52050b57cec5SDimitry Andric   }
52060b57cec5SDimitry Andric 
52070b57cec5SDimitry Andric   /// Functions that attempt to perform the combining. They detect if that is
52080b57cec5SDimitry Andric   /// legal, and if so they update the inputs \a Inputs and the offload action
52090b57cec5SDimitry Andric   /// that were collapsed in \a CollapsedOffloadAction. A tool that deals with
52100b57cec5SDimitry Andric   /// the combined action is returned. If the combining is not legal or if the
52110b57cec5SDimitry Andric   /// tool does not exist, null is returned.
52120b57cec5SDimitry Andric   /// Currently three kinds of collapsing are supported:
52130b57cec5SDimitry Andric   ///  - Assemble + Backend + Compile;
52140b57cec5SDimitry Andric   ///  - Assemble + Backend ;
52150b57cec5SDimitry Andric   ///  - Backend + Compile.
52160b57cec5SDimitry Andric   const Tool *
52170b57cec5SDimitry Andric   combineAssembleBackendCompile(ArrayRef<JobActionInfo> ActionInfo,
52180b57cec5SDimitry Andric                                 ActionList &Inputs,
52190b57cec5SDimitry Andric                                 ActionList &CollapsedOffloadAction) {
52200b57cec5SDimitry Andric     if (ActionInfo.size() < 3 || !canCollapseAssembleAction())
52210b57cec5SDimitry Andric       return nullptr;
52220b57cec5SDimitry Andric     auto *AJ = dyn_cast<AssembleJobAction>(ActionInfo[0].JA);
52230b57cec5SDimitry Andric     auto *BJ = dyn_cast<BackendJobAction>(ActionInfo[1].JA);
52240b57cec5SDimitry Andric     auto *CJ = dyn_cast<CompileJobAction>(ActionInfo[2].JA);
52250b57cec5SDimitry Andric     if (!AJ || !BJ || !CJ)
52260b57cec5SDimitry Andric       return nullptr;
52270b57cec5SDimitry Andric 
52280b57cec5SDimitry Andric     // Get compiler tool.
52290b57cec5SDimitry Andric     const Tool *T = TC.SelectTool(*CJ);
52300b57cec5SDimitry Andric     if (!T)
52310b57cec5SDimitry Andric       return nullptr;
52320b57cec5SDimitry Andric 
52330eae32dcSDimitry Andric     // Can't collapse if we don't have codegen support unless we are
52340eae32dcSDimitry Andric     // emitting LLVM IR.
52350eae32dcSDimitry Andric     bool OutputIsLLVM = types::isLLVMIR(ActionInfo[0].JA->getType());
52360eae32dcSDimitry Andric     if (!T->hasIntegratedBackend() && !(OutputIsLLVM && T->canEmitIR()))
52370eae32dcSDimitry Andric       return nullptr;
52380eae32dcSDimitry Andric 
52390b57cec5SDimitry Andric     // When using -fembed-bitcode, it is required to have the same tool (clang)
52400b57cec5SDimitry Andric     // for both CompilerJA and BackendJA. Otherwise, combine two stages.
52410b57cec5SDimitry Andric     if (EmbedBitcode) {
52420b57cec5SDimitry Andric       const Tool *BT = TC.SelectTool(*BJ);
52430b57cec5SDimitry Andric       if (BT == T)
52440b57cec5SDimitry Andric         return nullptr;
52450b57cec5SDimitry Andric     }
52460b57cec5SDimitry Andric 
52470b57cec5SDimitry Andric     if (!T->hasIntegratedAssembler())
52480b57cec5SDimitry Andric       return nullptr;
52490b57cec5SDimitry Andric 
52500b57cec5SDimitry Andric     Inputs = CJ->getInputs();
52510b57cec5SDimitry Andric     AppendCollapsedOffloadAction(CollapsedOffloadAction, ActionInfo,
52520b57cec5SDimitry Andric                                  /*NumElements=*/3);
52530b57cec5SDimitry Andric     return T;
52540b57cec5SDimitry Andric   }
52550b57cec5SDimitry Andric   const Tool *combineAssembleBackend(ArrayRef<JobActionInfo> ActionInfo,
52560b57cec5SDimitry Andric                                      ActionList &Inputs,
52570b57cec5SDimitry Andric                                      ActionList &CollapsedOffloadAction) {
52580b57cec5SDimitry Andric     if (ActionInfo.size() < 2 || !canCollapseAssembleAction())
52590b57cec5SDimitry Andric       return nullptr;
52600b57cec5SDimitry Andric     auto *AJ = dyn_cast<AssembleJobAction>(ActionInfo[0].JA);
52610b57cec5SDimitry Andric     auto *BJ = dyn_cast<BackendJobAction>(ActionInfo[1].JA);
52620b57cec5SDimitry Andric     if (!AJ || !BJ)
52630b57cec5SDimitry Andric       return nullptr;
52640b57cec5SDimitry Andric 
5265a7dea167SDimitry Andric     // Get backend tool.
5266a7dea167SDimitry Andric     const Tool *T = TC.SelectTool(*BJ);
52670b57cec5SDimitry Andric     if (!T)
52680b57cec5SDimitry Andric       return nullptr;
52690b57cec5SDimitry Andric 
52700b57cec5SDimitry Andric     if (!T->hasIntegratedAssembler())
52710b57cec5SDimitry Andric       return nullptr;
52720b57cec5SDimitry Andric 
52730b57cec5SDimitry Andric     Inputs = BJ->getInputs();
52740b57cec5SDimitry Andric     AppendCollapsedOffloadAction(CollapsedOffloadAction, ActionInfo,
52750b57cec5SDimitry Andric                                  /*NumElements=*/2);
52760b57cec5SDimitry Andric     return T;
52770b57cec5SDimitry Andric   }
52780b57cec5SDimitry Andric   const Tool *combineBackendCompile(ArrayRef<JobActionInfo> ActionInfo,
52790b57cec5SDimitry Andric                                     ActionList &Inputs,
52800b57cec5SDimitry Andric                                     ActionList &CollapsedOffloadAction) {
52810b57cec5SDimitry Andric     if (ActionInfo.size() < 2)
52820b57cec5SDimitry Andric       return nullptr;
52830b57cec5SDimitry Andric     auto *BJ = dyn_cast<BackendJobAction>(ActionInfo[0].JA);
52840b57cec5SDimitry Andric     auto *CJ = dyn_cast<CompileJobAction>(ActionInfo[1].JA);
52850b57cec5SDimitry Andric     if (!BJ || !CJ)
52860b57cec5SDimitry Andric       return nullptr;
52870b57cec5SDimitry Andric 
52880b57cec5SDimitry Andric     // Check if the initial input (to the compile job or its predessor if one
52890b57cec5SDimitry Andric     // exists) is LLVM bitcode. In that case, no preprocessor step is required
52900b57cec5SDimitry Andric     // and we can still collapse the compile and backend jobs when we have
52910b57cec5SDimitry Andric     // -save-temps. I.e. there is no need for a separate compile job just to
52920b57cec5SDimitry Andric     // emit unoptimized bitcode.
52930b57cec5SDimitry Andric     bool InputIsBitcode = true;
52940b57cec5SDimitry Andric     for (size_t i = 1; i < ActionInfo.size(); i++)
52950b57cec5SDimitry Andric       if (ActionInfo[i].JA->getType() != types::TY_LLVM_BC &&
52960b57cec5SDimitry Andric           ActionInfo[i].JA->getType() != types::TY_LTO_BC) {
52970b57cec5SDimitry Andric         InputIsBitcode = false;
52980b57cec5SDimitry Andric         break;
52990b57cec5SDimitry Andric       }
53000b57cec5SDimitry Andric     if (!InputIsBitcode && !canCollapsePreprocessorAction())
53010b57cec5SDimitry Andric       return nullptr;
53020b57cec5SDimitry Andric 
53030b57cec5SDimitry Andric     // Get compiler tool.
53040b57cec5SDimitry Andric     const Tool *T = TC.SelectTool(*CJ);
53050b57cec5SDimitry Andric     if (!T)
53060b57cec5SDimitry Andric       return nullptr;
53070b57cec5SDimitry Andric 
53080eae32dcSDimitry Andric     // Can't collapse if we don't have codegen support unless we are
53090eae32dcSDimitry Andric     // emitting LLVM IR.
53100eae32dcSDimitry Andric     bool OutputIsLLVM = types::isLLVMIR(ActionInfo[0].JA->getType());
53110eae32dcSDimitry Andric     if (!T->hasIntegratedBackend() && !(OutputIsLLVM && T->canEmitIR()))
53120eae32dcSDimitry Andric       return nullptr;
53130eae32dcSDimitry Andric 
53140b57cec5SDimitry Andric     if (T->canEmitIR() && ((SaveTemps && !InputIsBitcode) || EmbedBitcode))
53150b57cec5SDimitry Andric       return nullptr;
53160b57cec5SDimitry Andric 
53170b57cec5SDimitry Andric     Inputs = CJ->getInputs();
53180b57cec5SDimitry Andric     AppendCollapsedOffloadAction(CollapsedOffloadAction, ActionInfo,
53190b57cec5SDimitry Andric                                  /*NumElements=*/2);
53200b57cec5SDimitry Andric     return T;
53210b57cec5SDimitry Andric   }
53220b57cec5SDimitry Andric 
53230b57cec5SDimitry Andric   /// Updates the inputs if the obtained tool supports combining with
53240b57cec5SDimitry Andric   /// preprocessor action, and the current input is indeed a preprocessor
53250b57cec5SDimitry Andric   /// action. If combining results in the collapse of offloading actions, those
53260b57cec5SDimitry Andric   /// are appended to \a CollapsedOffloadAction.
53270b57cec5SDimitry Andric   void combineWithPreprocessor(const Tool *T, ActionList &Inputs,
53280b57cec5SDimitry Andric                                ActionList &CollapsedOffloadAction) {
53290b57cec5SDimitry Andric     if (!T || !canCollapsePreprocessorAction() || !T->hasIntegratedCPP())
53300b57cec5SDimitry Andric       return;
53310b57cec5SDimitry Andric 
53320b57cec5SDimitry Andric     // Attempt to get a preprocessor action dependence.
53330b57cec5SDimitry Andric     ActionList PreprocessJobOffloadActions;
53340b57cec5SDimitry Andric     ActionList NewInputs;
53350b57cec5SDimitry Andric     for (Action *A : Inputs) {
53360b57cec5SDimitry Andric       auto *PJ = getPrevDependentAction({A}, PreprocessJobOffloadActions);
53370b57cec5SDimitry Andric       if (!PJ || !isa<PreprocessJobAction>(PJ)) {
53380b57cec5SDimitry Andric         NewInputs.push_back(A);
53390b57cec5SDimitry Andric         continue;
53400b57cec5SDimitry Andric       }
53410b57cec5SDimitry Andric 
53420b57cec5SDimitry Andric       // This is legal to combine. Append any offload action we found and add the
53430b57cec5SDimitry Andric       // current input to preprocessor inputs.
53440b57cec5SDimitry Andric       CollapsedOffloadAction.append(PreprocessJobOffloadActions.begin(),
53450b57cec5SDimitry Andric                                     PreprocessJobOffloadActions.end());
53460b57cec5SDimitry Andric       NewInputs.append(PJ->input_begin(), PJ->input_end());
53470b57cec5SDimitry Andric     }
53480b57cec5SDimitry Andric     Inputs = NewInputs;
53490b57cec5SDimitry Andric   }
53500b57cec5SDimitry Andric 
53510b57cec5SDimitry Andric public:
53520b57cec5SDimitry Andric   ToolSelector(const JobAction *BaseAction, const ToolChain &TC,
53530b57cec5SDimitry Andric                const Compilation &C, bool SaveTemps, bool EmbedBitcode)
53540b57cec5SDimitry Andric       : TC(TC), C(C), BaseAction(BaseAction), SaveTemps(SaveTemps),
53550b57cec5SDimitry Andric         EmbedBitcode(EmbedBitcode) {
53560b57cec5SDimitry Andric     assert(BaseAction && "Invalid base action.");
53570b57cec5SDimitry Andric     IsHostSelector = BaseAction->getOffloadingDeviceKind() == Action::OFK_None;
53580b57cec5SDimitry Andric   }
53590b57cec5SDimitry Andric 
53600b57cec5SDimitry Andric   /// Check if a chain of actions can be combined and return the tool that can
53610b57cec5SDimitry Andric   /// handle the combination of actions. The pointer to the current inputs \a
53620b57cec5SDimitry Andric   /// Inputs and the list of offload actions \a CollapsedOffloadActions
53630b57cec5SDimitry Andric   /// connected to collapsed actions are updated accordingly. The latter enables
53640b57cec5SDimitry Andric   /// the caller of the selector to process them afterwards instead of just
53650b57cec5SDimitry Andric   /// dropping them. If no suitable tool is found, null will be returned.
53660b57cec5SDimitry Andric   const Tool *getTool(ActionList &Inputs,
53670b57cec5SDimitry Andric                       ActionList &CollapsedOffloadAction) {
53680b57cec5SDimitry Andric     //
53690b57cec5SDimitry Andric     // Get the largest chain of actions that we could combine.
53700b57cec5SDimitry Andric     //
53710b57cec5SDimitry Andric 
53720b57cec5SDimitry Andric     SmallVector<JobActionInfo, 5> ActionChain(1);
53730b57cec5SDimitry Andric     ActionChain.back().JA = BaseAction;
53740b57cec5SDimitry Andric     while (ActionChain.back().JA) {
53750b57cec5SDimitry Andric       const Action *CurAction = ActionChain.back().JA;
53760b57cec5SDimitry Andric 
53770b57cec5SDimitry Andric       // Grow the chain by one element.
53780b57cec5SDimitry Andric       ActionChain.resize(ActionChain.size() + 1);
53790b57cec5SDimitry Andric       JobActionInfo &AI = ActionChain.back();
53800b57cec5SDimitry Andric 
53810b57cec5SDimitry Andric       // Attempt to fill it with the
53820b57cec5SDimitry Andric       AI.JA =
53830b57cec5SDimitry Andric           getPrevDependentAction(CurAction->getInputs(), AI.SavedOffloadAction);
53840b57cec5SDimitry Andric     }
53850b57cec5SDimitry Andric 
53860b57cec5SDimitry Andric     // Pop the last action info as it could not be filled.
53870b57cec5SDimitry Andric     ActionChain.pop_back();
53880b57cec5SDimitry Andric 
53890b57cec5SDimitry Andric     //
53900b57cec5SDimitry Andric     // Attempt to combine actions. If all combining attempts failed, just return
53910b57cec5SDimitry Andric     // the tool of the provided action. At the end we attempt to combine the
53920b57cec5SDimitry Andric     // action with any preprocessor action it may depend on.
53930b57cec5SDimitry Andric     //
53940b57cec5SDimitry Andric 
53950b57cec5SDimitry Andric     const Tool *T = combineAssembleBackendCompile(ActionChain, Inputs,
53960b57cec5SDimitry Andric                                                   CollapsedOffloadAction);
53970b57cec5SDimitry Andric     if (!T)
53980b57cec5SDimitry Andric       T = combineAssembleBackend(ActionChain, Inputs, CollapsedOffloadAction);
53990b57cec5SDimitry Andric     if (!T)
54000b57cec5SDimitry Andric       T = combineBackendCompile(ActionChain, Inputs, CollapsedOffloadAction);
54010b57cec5SDimitry Andric     if (!T) {
54020b57cec5SDimitry Andric       Inputs = BaseAction->getInputs();
54030b57cec5SDimitry Andric       T = TC.SelectTool(*BaseAction);
54040b57cec5SDimitry Andric     }
54050b57cec5SDimitry Andric 
54060b57cec5SDimitry Andric     combineWithPreprocessor(T, Inputs, CollapsedOffloadAction);
54070b57cec5SDimitry Andric     return T;
54080b57cec5SDimitry Andric   }
54090b57cec5SDimitry Andric };
54100b57cec5SDimitry Andric }
54110b57cec5SDimitry Andric 
54120b57cec5SDimitry Andric /// Return a string that uniquely identifies the result of a job. The bound arch
54130b57cec5SDimitry Andric /// is not necessarily represented in the toolchain's triple -- for example,
54140b57cec5SDimitry Andric /// armv7 and armv7s both map to the same triple -- so we need both in our map.
54150b57cec5SDimitry Andric /// Also, we need to add the offloading device kind, as the same tool chain can
54160b57cec5SDimitry Andric /// be used for host and device for some programming models, e.g. OpenMP.
54170b57cec5SDimitry Andric static std::string GetTriplePlusArchString(const ToolChain *TC,
54180b57cec5SDimitry Andric                                            StringRef BoundArch,
54190b57cec5SDimitry Andric                                            Action::OffloadKind OffloadKind) {
54200b57cec5SDimitry Andric   std::string TriplePlusArch = TC->getTriple().normalize();
54210b57cec5SDimitry Andric   if (!BoundArch.empty()) {
54220b57cec5SDimitry Andric     TriplePlusArch += "-";
54230b57cec5SDimitry Andric     TriplePlusArch += BoundArch;
54240b57cec5SDimitry Andric   }
54250b57cec5SDimitry Andric   TriplePlusArch += "-";
54260b57cec5SDimitry Andric   TriplePlusArch += Action::GetOffloadKindName(OffloadKind);
54270b57cec5SDimitry Andric   return TriplePlusArch;
54280b57cec5SDimitry Andric }
54290b57cec5SDimitry Andric 
54301fd87a68SDimitry Andric InputInfoList Driver::BuildJobsForAction(
54310b57cec5SDimitry Andric     Compilation &C, const Action *A, const ToolChain *TC, StringRef BoundArch,
54320b57cec5SDimitry Andric     bool AtTopLevel, bool MultipleArchs, const char *LinkingOutput,
54331fd87a68SDimitry Andric     std::map<std::pair<const Action *, std::string>, InputInfoList>
54341fd87a68SDimitry Andric         &CachedResults,
54350b57cec5SDimitry Andric     Action::OffloadKind TargetDeviceOffloadKind) const {
54360b57cec5SDimitry Andric   std::pair<const Action *, std::string> ActionTC = {
54370b57cec5SDimitry Andric       A, GetTriplePlusArchString(TC, BoundArch, TargetDeviceOffloadKind)};
54380b57cec5SDimitry Andric   auto CachedResult = CachedResults.find(ActionTC);
54390b57cec5SDimitry Andric   if (CachedResult != CachedResults.end()) {
54400b57cec5SDimitry Andric     return CachedResult->second;
54410b57cec5SDimitry Andric   }
54421fd87a68SDimitry Andric   InputInfoList Result = BuildJobsForActionNoCache(
54430b57cec5SDimitry Andric       C, A, TC, BoundArch, AtTopLevel, MultipleArchs, LinkingOutput,
54440b57cec5SDimitry Andric       CachedResults, TargetDeviceOffloadKind);
54450b57cec5SDimitry Andric   CachedResults[ActionTC] = Result;
54460b57cec5SDimitry Andric   return Result;
54470b57cec5SDimitry Andric }
54480b57cec5SDimitry Andric 
544906c3fb27SDimitry Andric static void handleTimeTrace(Compilation &C, const ArgList &Args,
545006c3fb27SDimitry Andric                             const JobAction *JA, const char *BaseInput,
545106c3fb27SDimitry Andric                             const InputInfo &Result) {
545206c3fb27SDimitry Andric   Arg *A =
545306c3fb27SDimitry Andric       Args.getLastArg(options::OPT_ftime_trace, options::OPT_ftime_trace_EQ);
545406c3fb27SDimitry Andric   if (!A)
545506c3fb27SDimitry Andric     return;
545606c3fb27SDimitry Andric   SmallString<128> Path;
545706c3fb27SDimitry Andric   if (A->getOption().matches(options::OPT_ftime_trace_EQ)) {
545806c3fb27SDimitry Andric     Path = A->getValue();
545906c3fb27SDimitry Andric     if (llvm::sys::fs::is_directory(Path)) {
546006c3fb27SDimitry Andric       SmallString<128> Tmp(Result.getFilename());
546106c3fb27SDimitry Andric       llvm::sys::path::replace_extension(Tmp, "json");
546206c3fb27SDimitry Andric       llvm::sys::path::append(Path, llvm::sys::path::filename(Tmp));
546306c3fb27SDimitry Andric     }
546406c3fb27SDimitry Andric   } else {
546506c3fb27SDimitry Andric     if (Arg *DumpDir = Args.getLastArgNoClaim(options::OPT_dumpdir)) {
546606c3fb27SDimitry Andric       // The trace file is ${dumpdir}${basename}.json. Note that dumpdir may not
546706c3fb27SDimitry Andric       // end with a path separator.
546806c3fb27SDimitry Andric       Path = DumpDir->getValue();
546906c3fb27SDimitry Andric       Path += llvm::sys::path::filename(BaseInput);
547006c3fb27SDimitry Andric     } else {
547106c3fb27SDimitry Andric       Path = Result.getFilename();
547206c3fb27SDimitry Andric     }
547306c3fb27SDimitry Andric     llvm::sys::path::replace_extension(Path, "json");
547406c3fb27SDimitry Andric   }
547506c3fb27SDimitry Andric   const char *ResultFile = C.getArgs().MakeArgString(Path);
547606c3fb27SDimitry Andric   C.addTimeTraceFile(ResultFile, JA);
547706c3fb27SDimitry Andric   C.addResultFile(ResultFile, JA);
547806c3fb27SDimitry Andric }
547906c3fb27SDimitry Andric 
54801fd87a68SDimitry Andric InputInfoList Driver::BuildJobsForActionNoCache(
54810b57cec5SDimitry Andric     Compilation &C, const Action *A, const ToolChain *TC, StringRef BoundArch,
54820b57cec5SDimitry Andric     bool AtTopLevel, bool MultipleArchs, const char *LinkingOutput,
54831fd87a68SDimitry Andric     std::map<std::pair<const Action *, std::string>, InputInfoList>
54841fd87a68SDimitry Andric         &CachedResults,
54850b57cec5SDimitry Andric     Action::OffloadKind TargetDeviceOffloadKind) const {
54860b57cec5SDimitry Andric   llvm::PrettyStackTraceString CrashInfo("Building compilation jobs");
54870b57cec5SDimitry Andric 
54880b57cec5SDimitry Andric   InputInfoList OffloadDependencesInputInfo;
54890b57cec5SDimitry Andric   bool BuildingForOffloadDevice = TargetDeviceOffloadKind != Action::OFK_None;
54900b57cec5SDimitry Andric   if (const OffloadAction *OA = dyn_cast<OffloadAction>(A)) {
54910b57cec5SDimitry Andric     // The 'Darwin' toolchain is initialized only when its arguments are
54920b57cec5SDimitry Andric     // computed. Get the default arguments for OFK_None to ensure that
54930b57cec5SDimitry Andric     // initialization is performed before processing the offload action.
54940b57cec5SDimitry Andric     // FIXME: Remove when darwin's toolchain is initialized during construction.
54950b57cec5SDimitry Andric     C.getArgsForToolChain(TC, BoundArch, Action::OFK_None);
54960b57cec5SDimitry Andric 
54970b57cec5SDimitry Andric     // The offload action is expected to be used in four different situations.
54980b57cec5SDimitry Andric     //
54990b57cec5SDimitry Andric     // a) Set a toolchain/architecture/kind for a host action:
55000b57cec5SDimitry Andric     //    Host Action 1 -> OffloadAction -> Host Action 2
55010b57cec5SDimitry Andric     //
55020b57cec5SDimitry Andric     // b) Set a toolchain/architecture/kind for a device action;
55030b57cec5SDimitry Andric     //    Device Action 1 -> OffloadAction -> Device Action 2
55040b57cec5SDimitry Andric     //
55050b57cec5SDimitry Andric     // c) Specify a device dependence to a host action;
55060b57cec5SDimitry Andric     //    Device Action 1  _
55070b57cec5SDimitry Andric     //                      \
55080b57cec5SDimitry Andric     //      Host Action 1  ---> OffloadAction -> Host Action 2
55090b57cec5SDimitry Andric     //
55100b57cec5SDimitry Andric     // d) Specify a host dependence to a device action.
55110b57cec5SDimitry Andric     //      Host Action 1  _
55120b57cec5SDimitry Andric     //                      \
55130b57cec5SDimitry Andric     //    Device Action 1  ---> OffloadAction -> Device Action 2
55140b57cec5SDimitry Andric     //
5515bdd1243dSDimitry Andric     // For a) and b), we just return the job generated for the dependences. For
55160b57cec5SDimitry Andric     // c) and d) we override the current action with the host/device dependence
55170b57cec5SDimitry Andric     // if the current toolchain is host/device and set the offload dependences
55180b57cec5SDimitry Andric     // info with the jobs obtained from the device/host dependence(s).
55190b57cec5SDimitry Andric 
5520bdd1243dSDimitry Andric     // If there is a single device option or has no host action, just generate
5521bdd1243dSDimitry Andric     // the job for it.
5522bdd1243dSDimitry Andric     if (OA->hasSingleDeviceDependence() || !OA->hasHostDependence()) {
55231fd87a68SDimitry Andric       InputInfoList DevA;
55240b57cec5SDimitry Andric       OA->doOnEachDeviceDependence([&](Action *DepA, const ToolChain *DepTC,
55250b57cec5SDimitry Andric                                        const char *DepBoundArch) {
5526bdd1243dSDimitry Andric         DevA.append(BuildJobsForAction(C, DepA, DepTC, DepBoundArch, AtTopLevel,
5527bdd1243dSDimitry Andric                                        /*MultipleArchs*/ !!DepBoundArch,
5528bdd1243dSDimitry Andric                                        LinkingOutput, CachedResults,
5529bdd1243dSDimitry Andric                                        DepA->getOffloadingDeviceKind()));
55300b57cec5SDimitry Andric       });
55310b57cec5SDimitry Andric       return DevA;
55320b57cec5SDimitry Andric     }
55330b57cec5SDimitry Andric 
55340b57cec5SDimitry Andric     // If 'Action 2' is host, we generate jobs for the device dependences and
55350b57cec5SDimitry Andric     // override the current action with the host dependence. Otherwise, we
55360b57cec5SDimitry Andric     // generate the host dependences and override the action with the device
55370b57cec5SDimitry Andric     // dependence. The dependences can't therefore be a top-level action.
55380b57cec5SDimitry Andric     OA->doOnEachDependence(
55390b57cec5SDimitry Andric         /*IsHostDependence=*/BuildingForOffloadDevice,
55400b57cec5SDimitry Andric         [&](Action *DepA, const ToolChain *DepTC, const char *DepBoundArch) {
55411fd87a68SDimitry Andric           OffloadDependencesInputInfo.append(BuildJobsForAction(
55420b57cec5SDimitry Andric               C, DepA, DepTC, DepBoundArch, /*AtTopLevel=*/false,
55430b57cec5SDimitry Andric               /*MultipleArchs*/ !!DepBoundArch, LinkingOutput, CachedResults,
55440b57cec5SDimitry Andric               DepA->getOffloadingDeviceKind()));
55450b57cec5SDimitry Andric         });
55460b57cec5SDimitry Andric 
55470b57cec5SDimitry Andric     A = BuildingForOffloadDevice
55480b57cec5SDimitry Andric             ? OA->getSingleDeviceDependence(/*DoNotConsiderHostActions=*/true)
55490b57cec5SDimitry Andric             : OA->getHostDependence();
55501fd87a68SDimitry Andric 
55511fd87a68SDimitry Andric     // We may have already built this action as a part of the offloading
55521fd87a68SDimitry Andric     // toolchain, return the cached input if so.
55531fd87a68SDimitry Andric     std::pair<const Action *, std::string> ActionTC = {
55541fd87a68SDimitry Andric         OA->getHostDependence(),
55551fd87a68SDimitry Andric         GetTriplePlusArchString(TC, BoundArch, TargetDeviceOffloadKind)};
55561fd87a68SDimitry Andric     if (CachedResults.find(ActionTC) != CachedResults.end()) {
55571fd87a68SDimitry Andric       InputInfoList Inputs = CachedResults[ActionTC];
55581fd87a68SDimitry Andric       Inputs.append(OffloadDependencesInputInfo);
55591fd87a68SDimitry Andric       return Inputs;
55601fd87a68SDimitry Andric     }
55610b57cec5SDimitry Andric   }
55620b57cec5SDimitry Andric 
55630b57cec5SDimitry Andric   if (const InputAction *IA = dyn_cast<InputAction>(A)) {
55640b57cec5SDimitry Andric     // FIXME: It would be nice to not claim this here; maybe the old scheme of
55650b57cec5SDimitry Andric     // just using Args was better?
55660b57cec5SDimitry Andric     const Arg &Input = IA->getInputArg();
55670b57cec5SDimitry Andric     Input.claim();
55680b57cec5SDimitry Andric     if (Input.getOption().matches(options::OPT_INPUT)) {
55690b57cec5SDimitry Andric       const char *Name = Input.getValue();
55701fd87a68SDimitry Andric       return {InputInfo(A, Name, /* _BaseInput = */ Name)};
55710b57cec5SDimitry Andric     }
55721fd87a68SDimitry Andric     return {InputInfo(A, &Input, /* _BaseInput = */ "")};
55730b57cec5SDimitry Andric   }
55740b57cec5SDimitry Andric 
55750b57cec5SDimitry Andric   if (const BindArchAction *BAA = dyn_cast<BindArchAction>(A)) {
55760b57cec5SDimitry Andric     const ToolChain *TC;
55770b57cec5SDimitry Andric     StringRef ArchName = BAA->getArchName();
55780b57cec5SDimitry Andric 
55790b57cec5SDimitry Andric     if (!ArchName.empty())
55800b57cec5SDimitry Andric       TC = &getToolChain(C.getArgs(),
55810b57cec5SDimitry Andric                          computeTargetTriple(*this, TargetTriple,
55820b57cec5SDimitry Andric                                              C.getArgs(), ArchName));
55830b57cec5SDimitry Andric     else
55840b57cec5SDimitry Andric       TC = &C.getDefaultToolChain();
55850b57cec5SDimitry Andric 
55860b57cec5SDimitry Andric     return BuildJobsForAction(C, *BAA->input_begin(), TC, ArchName, AtTopLevel,
55870b57cec5SDimitry Andric                               MultipleArchs, LinkingOutput, CachedResults,
55880b57cec5SDimitry Andric                               TargetDeviceOffloadKind);
55890b57cec5SDimitry Andric   }
55900b57cec5SDimitry Andric 
55910b57cec5SDimitry Andric 
55920b57cec5SDimitry Andric   ActionList Inputs = A->getInputs();
55930b57cec5SDimitry Andric 
55940b57cec5SDimitry Andric   const JobAction *JA = cast<JobAction>(A);
55950b57cec5SDimitry Andric   ActionList CollapsedOffloadActions;
55960b57cec5SDimitry Andric 
55970b57cec5SDimitry Andric   ToolSelector TS(JA, *TC, C, isSaveTempsEnabled(),
55980b57cec5SDimitry Andric                   embedBitcodeInObject() && !isUsingLTO());
55990b57cec5SDimitry Andric   const Tool *T = TS.getTool(Inputs, CollapsedOffloadActions);
56000b57cec5SDimitry Andric 
56010b57cec5SDimitry Andric   if (!T)
56021fd87a68SDimitry Andric     return {InputInfo()};
56030b57cec5SDimitry Andric 
56040b57cec5SDimitry Andric   // If we've collapsed action list that contained OffloadAction we
56050b57cec5SDimitry Andric   // need to build jobs for host/device-side inputs it may have held.
56060b57cec5SDimitry Andric   for (const auto *OA : CollapsedOffloadActions)
56070b57cec5SDimitry Andric     cast<OffloadAction>(OA)->doOnEachDependence(
56080b57cec5SDimitry Andric         /*IsHostDependence=*/BuildingForOffloadDevice,
56090b57cec5SDimitry Andric         [&](Action *DepA, const ToolChain *DepTC, const char *DepBoundArch) {
56101fd87a68SDimitry Andric           OffloadDependencesInputInfo.append(BuildJobsForAction(
56110b57cec5SDimitry Andric               C, DepA, DepTC, DepBoundArch, /* AtTopLevel */ false,
56120b57cec5SDimitry Andric               /*MultipleArchs=*/!!DepBoundArch, LinkingOutput, CachedResults,
56130b57cec5SDimitry Andric               DepA->getOffloadingDeviceKind()));
56140b57cec5SDimitry Andric         });
56150b57cec5SDimitry Andric 
56160b57cec5SDimitry Andric   // Only use pipes when there is exactly one input.
56170b57cec5SDimitry Andric   InputInfoList InputInfos;
56180b57cec5SDimitry Andric   for (const Action *Input : Inputs) {
56190b57cec5SDimitry Andric     // Treat dsymutil and verify sub-jobs as being at the top-level too, they
56200b57cec5SDimitry Andric     // shouldn't get temporary output names.
56210b57cec5SDimitry Andric     // FIXME: Clean this up.
56220b57cec5SDimitry Andric     bool SubJobAtTopLevel =
56230b57cec5SDimitry Andric         AtTopLevel && (isa<DsymutilJobAction>(A) || isa<VerifyJobAction>(A));
56241fd87a68SDimitry Andric     InputInfos.append(BuildJobsForAction(
56250b57cec5SDimitry Andric         C, Input, TC, BoundArch, SubJobAtTopLevel, MultipleArchs, LinkingOutput,
56260b57cec5SDimitry Andric         CachedResults, A->getOffloadingDeviceKind()));
56270b57cec5SDimitry Andric   }
56280b57cec5SDimitry Andric 
5629349cc55cSDimitry Andric   // Always use the first file input as the base input.
56300b57cec5SDimitry Andric   const char *BaseInput = InputInfos[0].getBaseInput();
5631349cc55cSDimitry Andric   for (auto &Info : InputInfos) {
5632349cc55cSDimitry Andric     if (Info.isFilename()) {
5633349cc55cSDimitry Andric       BaseInput = Info.getBaseInput();
5634349cc55cSDimitry Andric       break;
5635349cc55cSDimitry Andric     }
5636349cc55cSDimitry Andric   }
56370b57cec5SDimitry Andric 
56380b57cec5SDimitry Andric   // ... except dsymutil actions, which use their actual input as the base
56390b57cec5SDimitry Andric   // input.
56400b57cec5SDimitry Andric   if (JA->getType() == types::TY_dSYM)
56410b57cec5SDimitry Andric     BaseInput = InputInfos[0].getFilename();
56420b57cec5SDimitry Andric 
56430b57cec5SDimitry Andric   // Append outputs of offload device jobs to the input list
56440b57cec5SDimitry Andric   if (!OffloadDependencesInputInfo.empty())
56450b57cec5SDimitry Andric     InputInfos.append(OffloadDependencesInputInfo.begin(),
56460b57cec5SDimitry Andric                       OffloadDependencesInputInfo.end());
56470b57cec5SDimitry Andric 
56480b57cec5SDimitry Andric   // Set the effective triple of the toolchain for the duration of this job.
56490b57cec5SDimitry Andric   llvm::Triple EffectiveTriple;
56500b57cec5SDimitry Andric   const ToolChain &ToolTC = T->getToolChain();
56510b57cec5SDimitry Andric   const ArgList &Args =
56520b57cec5SDimitry Andric       C.getArgsForToolChain(TC, BoundArch, A->getOffloadingDeviceKind());
56530b57cec5SDimitry Andric   if (InputInfos.size() != 1) {
56540b57cec5SDimitry Andric     EffectiveTriple = llvm::Triple(ToolTC.ComputeEffectiveClangTriple(Args));
56550b57cec5SDimitry Andric   } else {
56560b57cec5SDimitry Andric     // Pass along the input type if it can be unambiguously determined.
56570b57cec5SDimitry Andric     EffectiveTriple = llvm::Triple(
56580b57cec5SDimitry Andric         ToolTC.ComputeEffectiveClangTriple(Args, InputInfos[0].getType()));
56590b57cec5SDimitry Andric   }
56600b57cec5SDimitry Andric   RegisterEffectiveTriple TripleRAII(ToolTC, EffectiveTriple);
56610b57cec5SDimitry Andric 
56620b57cec5SDimitry Andric   // Determine the place to write output to, if any.
56630b57cec5SDimitry Andric   InputInfo Result;
56640b57cec5SDimitry Andric   InputInfoList UnbundlingResults;
56650b57cec5SDimitry Andric   if (auto *UA = dyn_cast<OffloadUnbundlingJobAction>(JA)) {
56660b57cec5SDimitry Andric     // If we have an unbundling job, we need to create results for all the
56670b57cec5SDimitry Andric     // outputs. We also update the results cache so that other actions using
56680b57cec5SDimitry Andric     // this unbundling action can get the right results.
56690b57cec5SDimitry Andric     for (auto &UI : UA->getDependentActionsInfo()) {
56700b57cec5SDimitry Andric       assert(UI.DependentOffloadKind != Action::OFK_None &&
56710b57cec5SDimitry Andric              "Unbundling with no offloading??");
56720b57cec5SDimitry Andric 
56730b57cec5SDimitry Andric       // Unbundling actions are never at the top level. When we generate the
56740b57cec5SDimitry Andric       // offloading prefix, we also do that for the host file because the
56750b57cec5SDimitry Andric       // unbundling action does not change the type of the output which can
56760b57cec5SDimitry Andric       // cause a overwrite.
56770b57cec5SDimitry Andric       std::string OffloadingPrefix = Action::GetOffloadingFileNamePrefix(
56780b57cec5SDimitry Andric           UI.DependentOffloadKind,
56790b57cec5SDimitry Andric           UI.DependentToolChain->getTriple().normalize(),
56800b57cec5SDimitry Andric           /*CreatePrefixForHost=*/true);
56810b57cec5SDimitry Andric       auto CurI = InputInfo(
56820b57cec5SDimitry Andric           UA,
56830b57cec5SDimitry Andric           GetNamedOutputPath(C, *UA, BaseInput, UI.DependentBoundArch,
56840b57cec5SDimitry Andric                              /*AtTopLevel=*/false,
56850b57cec5SDimitry Andric                              MultipleArchs ||
56860b57cec5SDimitry Andric                                  UI.DependentOffloadKind == Action::OFK_HIP,
56870b57cec5SDimitry Andric                              OffloadingPrefix),
56880b57cec5SDimitry Andric           BaseInput);
56890b57cec5SDimitry Andric       // Save the unbundling result.
56900b57cec5SDimitry Andric       UnbundlingResults.push_back(CurI);
56910b57cec5SDimitry Andric 
56920b57cec5SDimitry Andric       // Get the unique string identifier for this dependence and cache the
56930b57cec5SDimitry Andric       // result.
56940b57cec5SDimitry Andric       StringRef Arch;
56950b57cec5SDimitry Andric       if (TargetDeviceOffloadKind == Action::OFK_HIP) {
56960b57cec5SDimitry Andric         if (UI.DependentOffloadKind == Action::OFK_Host)
56970b57cec5SDimitry Andric           Arch = StringRef();
56980b57cec5SDimitry Andric         else
56990b57cec5SDimitry Andric           Arch = UI.DependentBoundArch;
57000b57cec5SDimitry Andric       } else
57010b57cec5SDimitry Andric         Arch = BoundArch;
57020b57cec5SDimitry Andric 
57030b57cec5SDimitry Andric       CachedResults[{A, GetTriplePlusArchString(UI.DependentToolChain, Arch,
57041fd87a68SDimitry Andric                                                 UI.DependentOffloadKind)}] = {
57051fd87a68SDimitry Andric           CurI};
57060b57cec5SDimitry Andric     }
57070b57cec5SDimitry Andric 
57080b57cec5SDimitry Andric     // Now that we have all the results generated, select the one that should be
57090b57cec5SDimitry Andric     // returned for the current depending action.
57100b57cec5SDimitry Andric     std::pair<const Action *, std::string> ActionTC = {
57110b57cec5SDimitry Andric         A, GetTriplePlusArchString(TC, BoundArch, TargetDeviceOffloadKind)};
57120b57cec5SDimitry Andric     assert(CachedResults.find(ActionTC) != CachedResults.end() &&
57130b57cec5SDimitry Andric            "Result does not exist??");
57141fd87a68SDimitry Andric     Result = CachedResults[ActionTC].front();
57150b57cec5SDimitry Andric   } else if (JA->getType() == types::TY_Nothing)
57161fd87a68SDimitry Andric     Result = {InputInfo(A, BaseInput)};
57170b57cec5SDimitry Andric   else {
57180b57cec5SDimitry Andric     // We only have to generate a prefix for the host if this is not a top-level
57190b57cec5SDimitry Andric     // action.
57200b57cec5SDimitry Andric     std::string OffloadingPrefix = Action::GetOffloadingFileNamePrefix(
57210b57cec5SDimitry Andric         A->getOffloadingDeviceKind(), TC->getTriple().normalize(),
572281ad6265SDimitry Andric         /*CreatePrefixForHost=*/isa<OffloadPackagerJobAction>(A) ||
572381ad6265SDimitry Andric             !(A->getOffloadingHostActiveKinds() == Action::OFK_None ||
572481ad6265SDimitry Andric               AtTopLevel));
57250b57cec5SDimitry Andric     Result = InputInfo(A, GetNamedOutputPath(C, *JA, BaseInput, BoundArch,
57260b57cec5SDimitry Andric                                              AtTopLevel, MultipleArchs,
57270b57cec5SDimitry Andric                                              OffloadingPrefix),
57280b57cec5SDimitry Andric                        BaseInput);
572906c3fb27SDimitry Andric     if (T->canEmitIR() && OffloadingPrefix.empty())
573006c3fb27SDimitry Andric       handleTimeTrace(C, Args, JA, BaseInput, Result);
57310b57cec5SDimitry Andric   }
57320b57cec5SDimitry Andric 
57330b57cec5SDimitry Andric   if (CCCPrintBindings && !CCGenDiagnostics) {
57340b57cec5SDimitry Andric     llvm::errs() << "# \"" << T->getToolChain().getTripleString() << '"'
57350b57cec5SDimitry Andric                  << " - \"" << T->getName() << "\", inputs: [";
57360b57cec5SDimitry Andric     for (unsigned i = 0, e = InputInfos.size(); i != e; ++i) {
57370b57cec5SDimitry Andric       llvm::errs() << InputInfos[i].getAsString();
57380b57cec5SDimitry Andric       if (i + 1 != e)
57390b57cec5SDimitry Andric         llvm::errs() << ", ";
57400b57cec5SDimitry Andric     }
57410b57cec5SDimitry Andric     if (UnbundlingResults.empty())
57420b57cec5SDimitry Andric       llvm::errs() << "], output: " << Result.getAsString() << "\n";
57430b57cec5SDimitry Andric     else {
57440b57cec5SDimitry Andric       llvm::errs() << "], outputs: [";
57450b57cec5SDimitry Andric       for (unsigned i = 0, e = UnbundlingResults.size(); i != e; ++i) {
57460b57cec5SDimitry Andric         llvm::errs() << UnbundlingResults[i].getAsString();
57470b57cec5SDimitry Andric         if (i + 1 != e)
57480b57cec5SDimitry Andric           llvm::errs() << ", ";
57490b57cec5SDimitry Andric       }
57500b57cec5SDimitry Andric       llvm::errs() << "] \n";
57510b57cec5SDimitry Andric     }
57520b57cec5SDimitry Andric   } else {
57530b57cec5SDimitry Andric     if (UnbundlingResults.empty())
57540b57cec5SDimitry Andric       T->ConstructJob(
57550b57cec5SDimitry Andric           C, *JA, Result, InputInfos,
57560b57cec5SDimitry Andric           C.getArgsForToolChain(TC, BoundArch, JA->getOffloadingDeviceKind()),
57570b57cec5SDimitry Andric           LinkingOutput);
57580b57cec5SDimitry Andric     else
57590b57cec5SDimitry Andric       T->ConstructJobMultipleOutputs(
57600b57cec5SDimitry Andric           C, *JA, UnbundlingResults, InputInfos,
57610b57cec5SDimitry Andric           C.getArgsForToolChain(TC, BoundArch, JA->getOffloadingDeviceKind()),
57620b57cec5SDimitry Andric           LinkingOutput);
57630b57cec5SDimitry Andric   }
57641fd87a68SDimitry Andric   return {Result};
57650b57cec5SDimitry Andric }
57660b57cec5SDimitry Andric 
57670b57cec5SDimitry Andric const char *Driver::getDefaultImageName() const {
57680b57cec5SDimitry Andric   llvm::Triple Target(llvm::Triple::normalize(TargetTriple));
57690b57cec5SDimitry Andric   return Target.isOSWindows() ? "a.exe" : "a.out";
57700b57cec5SDimitry Andric }
57710b57cec5SDimitry Andric 
57720b57cec5SDimitry Andric /// Create output filename based on ArgValue, which could either be a
57730b57cec5SDimitry Andric /// full filename, filename without extension, or a directory. If ArgValue
57740b57cec5SDimitry Andric /// does not provide a filename, then use BaseName, and use the extension
57750b57cec5SDimitry Andric /// suitable for FileType.
57760b57cec5SDimitry Andric static const char *MakeCLOutputFilename(const ArgList &Args, StringRef ArgValue,
57770b57cec5SDimitry Andric                                         StringRef BaseName,
57780b57cec5SDimitry Andric                                         types::ID FileType) {
57790b57cec5SDimitry Andric   SmallString<128> Filename = ArgValue;
57800b57cec5SDimitry Andric 
57810b57cec5SDimitry Andric   if (ArgValue.empty()) {
57820b57cec5SDimitry Andric     // If the argument is empty, output to BaseName in the current dir.
57830b57cec5SDimitry Andric     Filename = BaseName;
57840b57cec5SDimitry Andric   } else if (llvm::sys::path::is_separator(Filename.back())) {
57850b57cec5SDimitry Andric     // If the argument is a directory, output to BaseName in that dir.
57860b57cec5SDimitry Andric     llvm::sys::path::append(Filename, BaseName);
57870b57cec5SDimitry Andric   }
57880b57cec5SDimitry Andric 
57890b57cec5SDimitry Andric   if (!llvm::sys::path::has_extension(ArgValue)) {
57900b57cec5SDimitry Andric     // If the argument didn't provide an extension, then set it.
57910b57cec5SDimitry Andric     const char *Extension = types::getTypeTempSuffix(FileType, true);
57920b57cec5SDimitry Andric 
57930b57cec5SDimitry Andric     if (FileType == types::TY_Image &&
57940b57cec5SDimitry Andric         Args.hasArg(options::OPT__SLASH_LD, options::OPT__SLASH_LDd)) {
57950b57cec5SDimitry Andric       // The output file is a dll.
57960b57cec5SDimitry Andric       Extension = "dll";
57970b57cec5SDimitry Andric     }
57980b57cec5SDimitry Andric 
57990b57cec5SDimitry Andric     llvm::sys::path::replace_extension(Filename, Extension);
58000b57cec5SDimitry Andric   }
58010b57cec5SDimitry Andric 
58020b57cec5SDimitry Andric   return Args.MakeArgString(Filename.c_str());
58030b57cec5SDimitry Andric }
58040b57cec5SDimitry Andric 
5805e8d8bef9SDimitry Andric static bool HasPreprocessOutput(const Action &JA) {
5806e8d8bef9SDimitry Andric   if (isa<PreprocessJobAction>(JA))
5807e8d8bef9SDimitry Andric     return true;
5808e8d8bef9SDimitry Andric   if (isa<OffloadAction>(JA) && isa<PreprocessJobAction>(JA.getInputs()[0]))
5809e8d8bef9SDimitry Andric     return true;
5810e8d8bef9SDimitry Andric   if (isa<OffloadBundlingJobAction>(JA) &&
5811e8d8bef9SDimitry Andric       HasPreprocessOutput(*(JA.getInputs()[0])))
5812e8d8bef9SDimitry Andric     return true;
5813e8d8bef9SDimitry Andric   return false;
5814e8d8bef9SDimitry Andric }
5815e8d8bef9SDimitry Andric 
5816bdd1243dSDimitry Andric const char *Driver::CreateTempFile(Compilation &C, StringRef Prefix,
5817bdd1243dSDimitry Andric                                    StringRef Suffix, bool MultipleArchs,
581806c3fb27SDimitry Andric                                    StringRef BoundArch,
581906c3fb27SDimitry Andric                                    bool NeedUniqueDirectory) const {
5820bdd1243dSDimitry Andric   SmallString<128> TmpName;
5821bdd1243dSDimitry Andric   Arg *A = C.getArgs().getLastArg(options::OPT_fcrash_diagnostics_dir);
5822bdd1243dSDimitry Andric   std::optional<std::string> CrashDirectory =
5823bdd1243dSDimitry Andric       CCGenDiagnostics && A
5824bdd1243dSDimitry Andric           ? std::string(A->getValue())
5825bdd1243dSDimitry Andric           : llvm::sys::Process::GetEnv("CLANG_CRASH_DIAGNOSTICS_DIR");
5826bdd1243dSDimitry Andric   if (CrashDirectory) {
5827bdd1243dSDimitry Andric     if (!getVFS().exists(*CrashDirectory))
5828bdd1243dSDimitry Andric       llvm::sys::fs::create_directories(*CrashDirectory);
5829bdd1243dSDimitry Andric     SmallString<128> Path(*CrashDirectory);
5830bdd1243dSDimitry Andric     llvm::sys::path::append(Path, Prefix);
5831bdd1243dSDimitry Andric     const char *Middle = !Suffix.empty() ? "-%%%%%%." : "-%%%%%%";
5832bdd1243dSDimitry Andric     if (std::error_code EC =
5833bdd1243dSDimitry Andric             llvm::sys::fs::createUniqueFile(Path + Middle + Suffix, TmpName)) {
5834bdd1243dSDimitry Andric       Diag(clang::diag::err_unable_to_make_temp) << EC.message();
5835bdd1243dSDimitry Andric       return "";
5836bdd1243dSDimitry Andric     }
5837bdd1243dSDimitry Andric   } else {
5838bdd1243dSDimitry Andric     if (MultipleArchs && !BoundArch.empty()) {
583906c3fb27SDimitry Andric       if (NeedUniqueDirectory) {
5840bdd1243dSDimitry Andric         TmpName = GetTemporaryDirectory(Prefix);
5841bdd1243dSDimitry Andric         llvm::sys::path::append(TmpName,
5842bdd1243dSDimitry Andric                                 Twine(Prefix) + "-" + BoundArch + "." + Suffix);
5843bdd1243dSDimitry Andric       } else {
584406c3fb27SDimitry Andric         TmpName =
584506c3fb27SDimitry Andric             GetTemporaryPath((Twine(Prefix) + "-" + BoundArch).str(), Suffix);
584606c3fb27SDimitry Andric       }
584706c3fb27SDimitry Andric 
584806c3fb27SDimitry Andric     } else {
5849bdd1243dSDimitry Andric       TmpName = GetTemporaryPath(Prefix, Suffix);
5850bdd1243dSDimitry Andric     }
5851bdd1243dSDimitry Andric   }
5852bdd1243dSDimitry Andric   return C.addTempFile(C.getArgs().MakeArgString(TmpName));
5853bdd1243dSDimitry Andric }
5854bdd1243dSDimitry Andric 
5855bdd1243dSDimitry Andric // Calculate the output path of the module file when compiling a module unit
5856bdd1243dSDimitry Andric // with the `-fmodule-output` option or `-fmodule-output=` option specified.
5857bdd1243dSDimitry Andric // The behavior is:
5858bdd1243dSDimitry Andric // - If `-fmodule-output=` is specfied, then the module file is
5859bdd1243dSDimitry Andric //   writing to the value.
5860bdd1243dSDimitry Andric // - Otherwise if the output object file of the module unit is specified, the
5861bdd1243dSDimitry Andric // output path
5862bdd1243dSDimitry Andric //   of the module file should be the same with the output object file except
5863bdd1243dSDimitry Andric //   the corresponding suffix. This requires both `-o` and `-c` are specified.
5864bdd1243dSDimitry Andric // - Otherwise, the output path of the module file will be the same with the
5865bdd1243dSDimitry Andric //   input with the corresponding suffix.
5866bdd1243dSDimitry Andric static const char *GetModuleOutputPath(Compilation &C, const JobAction &JA,
5867bdd1243dSDimitry Andric                                        const char *BaseInput) {
5868bdd1243dSDimitry Andric   assert(isa<PrecompileJobAction>(JA) && JA.getType() == types::TY_ModuleFile &&
5869bdd1243dSDimitry Andric          (C.getArgs().hasArg(options::OPT_fmodule_output) ||
5870bdd1243dSDimitry Andric           C.getArgs().hasArg(options::OPT_fmodule_output_EQ)));
5871bdd1243dSDimitry Andric 
58720fca6ea1SDimitry Andric   SmallString<256> OutputPath =
58730fca6ea1SDimitry Andric       tools::getCXX20NamedModuleOutputPath(C.getArgs(), BaseInput);
5874bdd1243dSDimitry Andric 
5875bdd1243dSDimitry Andric   return C.addResultFile(C.getArgs().MakeArgString(OutputPath.c_str()), &JA);
5876bdd1243dSDimitry Andric }
5877bdd1243dSDimitry Andric 
58780b57cec5SDimitry Andric const char *Driver::GetNamedOutputPath(Compilation &C, const JobAction &JA,
58790b57cec5SDimitry Andric                                        const char *BaseInput,
5880e8d8bef9SDimitry Andric                                        StringRef OrigBoundArch, bool AtTopLevel,
58810b57cec5SDimitry Andric                                        bool MultipleArchs,
58820b57cec5SDimitry Andric                                        StringRef OffloadingPrefix) const {
5883e8d8bef9SDimitry Andric   std::string BoundArch = OrigBoundArch.str();
5884349cc55cSDimitry Andric   if (is_style_windows(llvm::sys::path::Style::native)) {
5885e8d8bef9SDimitry Andric     // BoundArch may contains ':', which is invalid in file names on Windows,
5886e8d8bef9SDimitry Andric     // therefore replace it with '%'.
5887e8d8bef9SDimitry Andric     std::replace(BoundArch.begin(), BoundArch.end(), ':', '@');
5888349cc55cSDimitry Andric   }
5889e8d8bef9SDimitry Andric 
58900b57cec5SDimitry Andric   llvm::PrettyStackTraceString CrashInfo("Computing output path");
58910b57cec5SDimitry Andric   // Output to a user requested destination?
58920b57cec5SDimitry Andric   if (AtTopLevel && !isa<DsymutilJobAction>(JA) && !isa<VerifyJobAction>(JA)) {
58930b57cec5SDimitry Andric     if (Arg *FinalOutput = C.getArgs().getLastArg(options::OPT_o))
58940b57cec5SDimitry Andric       return C.addResultFile(FinalOutput->getValue(), &JA);
58950b57cec5SDimitry Andric   }
58960b57cec5SDimitry Andric 
58970b57cec5SDimitry Andric   // For /P, preprocess to file named after BaseInput.
58980b57cec5SDimitry Andric   if (C.getArgs().hasArg(options::OPT__SLASH_P)) {
58990b57cec5SDimitry Andric     assert(AtTopLevel && isa<PreprocessJobAction>(JA));
59000b57cec5SDimitry Andric     StringRef BaseName = llvm::sys::path::filename(BaseInput);
59010b57cec5SDimitry Andric     StringRef NameArg;
59020b57cec5SDimitry Andric     if (Arg *A = C.getArgs().getLastArg(options::OPT__SLASH_Fi))
59030b57cec5SDimitry Andric       NameArg = A->getValue();
59040b57cec5SDimitry Andric     return C.addResultFile(
59050b57cec5SDimitry Andric         MakeCLOutputFilename(C.getArgs(), NameArg, BaseName, types::TY_PP_C),
59060b57cec5SDimitry Andric         &JA);
59070b57cec5SDimitry Andric   }
59080b57cec5SDimitry Andric 
59090b57cec5SDimitry Andric   // Default to writing to stdout?
5910e8d8bef9SDimitry Andric   if (AtTopLevel && !CCGenDiagnostics && HasPreprocessOutput(JA)) {
59110b57cec5SDimitry Andric     return "-";
5912e8d8bef9SDimitry Andric   }
59130b57cec5SDimitry Andric 
5914fe6060f1SDimitry Andric   if (JA.getType() == types::TY_ModuleFile &&
5915fe6060f1SDimitry Andric       C.getArgs().getLastArg(options::OPT_module_file_info)) {
5916fe6060f1SDimitry Andric     return "-";
5917fe6060f1SDimitry Andric   }
5918fe6060f1SDimitry Andric 
59195f757f3fSDimitry Andric   if (JA.getType() == types::TY_PP_Asm &&
59205f757f3fSDimitry Andric       C.getArgs().hasArg(options::OPT_dxc_Fc)) {
59215f757f3fSDimitry Andric     StringRef FcValue = C.getArgs().getLastArgValue(options::OPT_dxc_Fc);
59225f757f3fSDimitry Andric     // TODO: Should we use `MakeCLOutputFilename` here? If so, we can probably
59235f757f3fSDimitry Andric     // handle this as part of the SLASH_Fa handling below.
59245f757f3fSDimitry Andric     return C.addResultFile(C.getArgs().MakeArgString(FcValue.str()), &JA);
59255f757f3fSDimitry Andric   }
59265f757f3fSDimitry Andric 
59275f757f3fSDimitry Andric   if (JA.getType() == types::TY_Object &&
59285f757f3fSDimitry Andric       C.getArgs().hasArg(options::OPT_dxc_Fo)) {
59295f757f3fSDimitry Andric     StringRef FoValue = C.getArgs().getLastArgValue(options::OPT_dxc_Fo);
59305f757f3fSDimitry Andric     // TODO: Should we use `MakeCLOutputFilename` here? If so, we can probably
59315f757f3fSDimitry Andric     // handle this as part of the SLASH_Fo handling below.
59325f757f3fSDimitry Andric     return C.addResultFile(C.getArgs().MakeArgString(FoValue.str()), &JA);
59335f757f3fSDimitry Andric   }
5934bdd1243dSDimitry Andric 
59350b57cec5SDimitry Andric   // Is this the assembly listing for /FA?
59360b57cec5SDimitry Andric   if (JA.getType() == types::TY_PP_Asm &&
59370b57cec5SDimitry Andric       (C.getArgs().hasArg(options::OPT__SLASH_FA) ||
59380b57cec5SDimitry Andric        C.getArgs().hasArg(options::OPT__SLASH_Fa))) {
59390b57cec5SDimitry Andric     // Use /Fa and the input filename to determine the asm file name.
59400b57cec5SDimitry Andric     StringRef BaseName = llvm::sys::path::filename(BaseInput);
59410b57cec5SDimitry Andric     StringRef FaValue = C.getArgs().getLastArgValue(options::OPT__SLASH_Fa);
59420b57cec5SDimitry Andric     return C.addResultFile(
59430b57cec5SDimitry Andric         MakeCLOutputFilename(C.getArgs(), FaValue, BaseName, JA.getType()),
59440b57cec5SDimitry Andric         &JA);
59450b57cec5SDimitry Andric   }
59460b57cec5SDimitry Andric 
59470fca6ea1SDimitry Andric   if (JA.getType() == types::TY_API_INFO &&
59480fca6ea1SDimitry Andric       C.getArgs().hasArg(options::OPT_emit_extension_symbol_graphs) &&
59490fca6ea1SDimitry Andric       C.getArgs().hasArg(options::OPT_o))
59500fca6ea1SDimitry Andric     Diag(clang::diag::err_drv_unexpected_symbol_graph_output)
59510fca6ea1SDimitry Andric         << C.getArgs().getLastArgValue(options::OPT_o);
59520fca6ea1SDimitry Andric 
59535f757f3fSDimitry Andric   // DXC defaults to standard out when generating assembly. We check this after
59545f757f3fSDimitry Andric   // any DXC flags that might specify a file.
59555f757f3fSDimitry Andric   if (AtTopLevel && JA.getType() == types::TY_PP_Asm && IsDXCMode())
59565f757f3fSDimitry Andric     return "-";
59575f757f3fSDimitry Andric 
5958bdd1243dSDimitry Andric   bool SpecifiedModuleOutput =
5959bdd1243dSDimitry Andric       C.getArgs().hasArg(options::OPT_fmodule_output) ||
5960bdd1243dSDimitry Andric       C.getArgs().hasArg(options::OPT_fmodule_output_EQ);
5961bdd1243dSDimitry Andric   if (MultipleArchs && SpecifiedModuleOutput)
5962bdd1243dSDimitry Andric     Diag(clang::diag::err_drv_module_output_with_multiple_arch);
5963bdd1243dSDimitry Andric 
5964bdd1243dSDimitry Andric   // If we're emitting a module output with the specified option
5965bdd1243dSDimitry Andric   // `-fmodule-output`.
5966bdd1243dSDimitry Andric   if (!AtTopLevel && isa<PrecompileJobAction>(JA) &&
59670fca6ea1SDimitry Andric       JA.getType() == types::TY_ModuleFile && SpecifiedModuleOutput) {
59680fca6ea1SDimitry Andric     assert(!C.getArgs().hasArg(options::OPT_modules_reduced_bmi));
5969bdd1243dSDimitry Andric     return GetModuleOutputPath(C, JA, BaseInput);
59700fca6ea1SDimitry Andric   }
5971bdd1243dSDimitry Andric 
59720b57cec5SDimitry Andric   // Output to a temporary file?
59730b57cec5SDimitry Andric   if ((!AtTopLevel && !isSaveTempsEnabled() &&
59740b57cec5SDimitry Andric        !C.getArgs().hasArg(options::OPT__SLASH_Fo)) ||
59750b57cec5SDimitry Andric       CCGenDiagnostics) {
59760b57cec5SDimitry Andric     StringRef Name = llvm::sys::path::filename(BaseInput);
59770b57cec5SDimitry Andric     std::pair<StringRef, StringRef> Split = Name.split('.');
59785f757f3fSDimitry Andric     const char *Suffix =
59795f757f3fSDimitry Andric         types::getTypeTempSuffix(JA.getType(), IsCLMode() || IsDXCMode());
598006c3fb27SDimitry Andric     // The non-offloading toolchain on Darwin requires deterministic input
598106c3fb27SDimitry Andric     // file name for binaries to be deterministic, therefore it needs unique
598206c3fb27SDimitry Andric     // directory.
598306c3fb27SDimitry Andric     llvm::Triple Triple(C.getDriver().getTargetTriple());
598406c3fb27SDimitry Andric     bool NeedUniqueDirectory =
598506c3fb27SDimitry Andric         (JA.getOffloadingDeviceKind() == Action::OFK_None ||
598606c3fb27SDimitry Andric          JA.getOffloadingDeviceKind() == Action::OFK_Host) &&
598706c3fb27SDimitry Andric         Triple.isOSDarwin();
598806c3fb27SDimitry Andric     return CreateTempFile(C, Split.first, Suffix, MultipleArchs, BoundArch,
598906c3fb27SDimitry Andric                           NeedUniqueDirectory);
59900b57cec5SDimitry Andric   }
59910b57cec5SDimitry Andric 
59920b57cec5SDimitry Andric   SmallString<128> BasePath(BaseInput);
5993e8d8bef9SDimitry Andric   SmallString<128> ExternalPath("");
59940b57cec5SDimitry Andric   StringRef BaseName;
59950b57cec5SDimitry Andric 
59960b57cec5SDimitry Andric   // Dsymutil actions should use the full path.
5997e8d8bef9SDimitry Andric   if (isa<DsymutilJobAction>(JA) && C.getArgs().hasArg(options::OPT_dsym_dir)) {
5998e8d8bef9SDimitry Andric     ExternalPath += C.getArgs().getLastArg(options::OPT_dsym_dir)->getValue();
5999e8d8bef9SDimitry Andric     // We use posix style here because the tests (specifically
6000e8d8bef9SDimitry Andric     // darwin-dsymutil.c) demonstrate that posix style paths are acceptable
6001e8d8bef9SDimitry Andric     // even on Windows and if we don't then the similar test covering this
6002e8d8bef9SDimitry Andric     // fails.
6003e8d8bef9SDimitry Andric     llvm::sys::path::append(ExternalPath, llvm::sys::path::Style::posix,
6004e8d8bef9SDimitry Andric                             llvm::sys::path::filename(BasePath));
6005e8d8bef9SDimitry Andric     BaseName = ExternalPath;
6006e8d8bef9SDimitry Andric   } else if (isa<DsymutilJobAction>(JA) || isa<VerifyJobAction>(JA))
60070b57cec5SDimitry Andric     BaseName = BasePath;
60080b57cec5SDimitry Andric   else
60090b57cec5SDimitry Andric     BaseName = llvm::sys::path::filename(BasePath);
60100b57cec5SDimitry Andric 
60110b57cec5SDimitry Andric   // Determine what the derived output name should be.
60120b57cec5SDimitry Andric   const char *NamedOutput;
60130b57cec5SDimitry Andric 
60140b57cec5SDimitry Andric   if ((JA.getType() == types::TY_Object || JA.getType() == types::TY_LTO_BC) &&
60150b57cec5SDimitry Andric       C.getArgs().hasArg(options::OPT__SLASH_Fo, options::OPT__SLASH_o)) {
60160b57cec5SDimitry Andric     // The /Fo or /o flag decides the object filename.
60170b57cec5SDimitry Andric     StringRef Val =
60180b57cec5SDimitry Andric         C.getArgs()
60190b57cec5SDimitry Andric             .getLastArg(options::OPT__SLASH_Fo, options::OPT__SLASH_o)
60200b57cec5SDimitry Andric             ->getValue();
60210b57cec5SDimitry Andric     NamedOutput =
60220b57cec5SDimitry Andric         MakeCLOutputFilename(C.getArgs(), Val, BaseName, types::TY_Object);
60230b57cec5SDimitry Andric   } else if (JA.getType() == types::TY_Image &&
60240b57cec5SDimitry Andric              C.getArgs().hasArg(options::OPT__SLASH_Fe,
60250b57cec5SDimitry Andric                                 options::OPT__SLASH_o)) {
60260b57cec5SDimitry Andric     // The /Fe or /o flag names the linked file.
60270b57cec5SDimitry Andric     StringRef Val =
60280b57cec5SDimitry Andric         C.getArgs()
60290b57cec5SDimitry Andric             .getLastArg(options::OPT__SLASH_Fe, options::OPT__SLASH_o)
60300b57cec5SDimitry Andric             ->getValue();
60310b57cec5SDimitry Andric     NamedOutput =
60320b57cec5SDimitry Andric         MakeCLOutputFilename(C.getArgs(), Val, BaseName, types::TY_Image);
60330b57cec5SDimitry Andric   } else if (JA.getType() == types::TY_Image) {
60340b57cec5SDimitry Andric     if (IsCLMode()) {
60350b57cec5SDimitry Andric       // clang-cl uses BaseName for the executable name.
60360b57cec5SDimitry Andric       NamedOutput =
60370b57cec5SDimitry Andric           MakeCLOutputFilename(C.getArgs(), "", BaseName, types::TY_Image);
60380b57cec5SDimitry Andric     } else {
60390b57cec5SDimitry Andric       SmallString<128> Output(getDefaultImageName());
6040a7dea167SDimitry Andric       // HIP image for device compilation with -fno-gpu-rdc is per compilation
6041a7dea167SDimitry Andric       // unit.
6042a7dea167SDimitry Andric       bool IsHIPNoRDC = JA.getOffloadingDeviceKind() == Action::OFK_HIP &&
6043a7dea167SDimitry Andric                         !C.getArgs().hasFlag(options::OPT_fgpu_rdc,
6044a7dea167SDimitry Andric                                              options::OPT_fno_gpu_rdc, false);
604581ad6265SDimitry Andric       bool UseOutExtension = IsHIPNoRDC || isa<OffloadPackagerJobAction>(JA);
604681ad6265SDimitry Andric       if (UseOutExtension) {
6047a7dea167SDimitry Andric         Output = BaseName;
6048a7dea167SDimitry Andric         llvm::sys::path::replace_extension(Output, "");
6049a7dea167SDimitry Andric       }
60500b57cec5SDimitry Andric       Output += OffloadingPrefix;
60510b57cec5SDimitry Andric       if (MultipleArchs && !BoundArch.empty()) {
60520b57cec5SDimitry Andric         Output += "-";
60530b57cec5SDimitry Andric         Output.append(BoundArch);
60540b57cec5SDimitry Andric       }
605581ad6265SDimitry Andric       if (UseOutExtension)
6056a7dea167SDimitry Andric         Output += ".out";
60570b57cec5SDimitry Andric       NamedOutput = C.getArgs().MakeArgString(Output.c_str());
60580b57cec5SDimitry Andric     }
60590b57cec5SDimitry Andric   } else if (JA.getType() == types::TY_PCH && IsCLMode()) {
60600b57cec5SDimitry Andric     NamedOutput = C.getArgs().MakeArgString(GetClPchPath(C, BaseName));
606181ad6265SDimitry Andric   } else if ((JA.getType() == types::TY_Plist || JA.getType() == types::TY_AST) &&
606281ad6265SDimitry Andric              C.getArgs().hasArg(options::OPT__SLASH_o)) {
606381ad6265SDimitry Andric     StringRef Val =
606481ad6265SDimitry Andric         C.getArgs()
606581ad6265SDimitry Andric             .getLastArg(options::OPT__SLASH_o)
606681ad6265SDimitry Andric             ->getValue();
606781ad6265SDimitry Andric     NamedOutput =
606881ad6265SDimitry Andric         MakeCLOutputFilename(C.getArgs(), Val, BaseName, types::TY_Object);
60690b57cec5SDimitry Andric   } else {
60705f757f3fSDimitry Andric     const char *Suffix =
60715f757f3fSDimitry Andric         types::getTypeTempSuffix(JA.getType(), IsCLMode() || IsDXCMode());
60720b57cec5SDimitry Andric     assert(Suffix && "All types used for output should have a suffix.");
60730b57cec5SDimitry Andric 
60740b57cec5SDimitry Andric     std::string::size_type End = std::string::npos;
60750b57cec5SDimitry Andric     if (!types::appendSuffixForType(JA.getType()))
60760b57cec5SDimitry Andric       End = BaseName.rfind('.');
60770b57cec5SDimitry Andric     SmallString<128> Suffixed(BaseName.substr(0, End));
60780b57cec5SDimitry Andric     Suffixed += OffloadingPrefix;
60790b57cec5SDimitry Andric     if (MultipleArchs && !BoundArch.empty()) {
60800b57cec5SDimitry Andric       Suffixed += "-";
60810b57cec5SDimitry Andric       Suffixed.append(BoundArch);
60820b57cec5SDimitry Andric     }
60830b57cec5SDimitry Andric     // When using both -save-temps and -emit-llvm, use a ".tmp.bc" suffix for
60840b57cec5SDimitry Andric     // the unoptimized bitcode so that it does not get overwritten by the ".bc"
60850b57cec5SDimitry Andric     // optimized bitcode output.
6086bdd1243dSDimitry Andric     auto IsAMDRDCInCompilePhase = [](const JobAction &JA,
60875ffd83dbSDimitry Andric                                      const llvm::opt::DerivedArgList &Args) {
6088bdd1243dSDimitry Andric       // The relocatable compilation in HIP and OpenMP implies -emit-llvm.
6089bdd1243dSDimitry Andric       // Similarly, use a ".tmp.bc" suffix for the unoptimized bitcode
6090bdd1243dSDimitry Andric       // (generated in the compile phase.)
6091bdd1243dSDimitry Andric       const ToolChain *TC = JA.getOffloadingToolChain();
60925ffd83dbSDimitry Andric       return isa<CompileJobAction>(JA) &&
6093bdd1243dSDimitry Andric              ((JA.getOffloadingDeviceKind() == Action::OFK_HIP &&
60945ffd83dbSDimitry Andric                Args.hasFlag(options::OPT_fgpu_rdc, options::OPT_fno_gpu_rdc,
6095bdd1243dSDimitry Andric                             false)) ||
6096bdd1243dSDimitry Andric               (JA.getOffloadingDeviceKind() == Action::OFK_OpenMP && TC &&
6097bdd1243dSDimitry Andric                TC->getTriple().isAMDGPU()));
60985ffd83dbSDimitry Andric     };
60995ffd83dbSDimitry Andric     if (!AtTopLevel && JA.getType() == types::TY_LLVM_BC &&
61005ffd83dbSDimitry Andric         (C.getArgs().hasArg(options::OPT_emit_llvm) ||
6101bdd1243dSDimitry Andric          IsAMDRDCInCompilePhase(JA, C.getArgs())))
61020b57cec5SDimitry Andric       Suffixed += ".tmp";
61030b57cec5SDimitry Andric     Suffixed += '.';
61040b57cec5SDimitry Andric     Suffixed += Suffix;
61050b57cec5SDimitry Andric     NamedOutput = C.getArgs().MakeArgString(Suffixed.c_str());
61060b57cec5SDimitry Andric   }
61070b57cec5SDimitry Andric 
61080b57cec5SDimitry Andric   // Prepend object file path if -save-temps=obj
61090b57cec5SDimitry Andric   if (!AtTopLevel && isSaveTempsObj() && C.getArgs().hasArg(options::OPT_o) &&
61100b57cec5SDimitry Andric       JA.getType() != types::TY_PCH) {
61110b57cec5SDimitry Andric     Arg *FinalOutput = C.getArgs().getLastArg(options::OPT_o);
61120b57cec5SDimitry Andric     SmallString<128> TempPath(FinalOutput->getValue());
61130b57cec5SDimitry Andric     llvm::sys::path::remove_filename(TempPath);
61140b57cec5SDimitry Andric     StringRef OutputFileName = llvm::sys::path::filename(NamedOutput);
61150b57cec5SDimitry Andric     llvm::sys::path::append(TempPath, OutputFileName);
61160b57cec5SDimitry Andric     NamedOutput = C.getArgs().MakeArgString(TempPath.c_str());
61170b57cec5SDimitry Andric   }
61180b57cec5SDimitry Andric 
61190b57cec5SDimitry Andric   // If we're saving temps and the temp file conflicts with the input file,
61200b57cec5SDimitry Andric   // then avoid overwriting input file.
61210b57cec5SDimitry Andric   if (!AtTopLevel && isSaveTempsEnabled() && NamedOutput == BaseName) {
61220b57cec5SDimitry Andric     bool SameFile = false;
61230b57cec5SDimitry Andric     SmallString<256> Result;
61240b57cec5SDimitry Andric     llvm::sys::fs::current_path(Result);
61250b57cec5SDimitry Andric     llvm::sys::path::append(Result, BaseName);
61260b57cec5SDimitry Andric     llvm::sys::fs::equivalent(BaseInput, Result.c_str(), SameFile);
61270b57cec5SDimitry Andric     // Must share the same path to conflict.
61280b57cec5SDimitry Andric     if (SameFile) {
61290b57cec5SDimitry Andric       StringRef Name = llvm::sys::path::filename(BaseInput);
61300b57cec5SDimitry Andric       std::pair<StringRef, StringRef> Split = Name.split('.');
61310b57cec5SDimitry Andric       std::string TmpName = GetTemporaryPath(
61325f757f3fSDimitry Andric           Split.first,
61335f757f3fSDimitry Andric           types::getTypeTempSuffix(JA.getType(), IsCLMode() || IsDXCMode()));
61340b57cec5SDimitry Andric       return C.addTempFile(C.getArgs().MakeArgString(TmpName));
61350b57cec5SDimitry Andric     }
61360b57cec5SDimitry Andric   }
61370b57cec5SDimitry Andric 
61380b57cec5SDimitry Andric   // As an annoying special case, PCH generation doesn't strip the pathname.
61390b57cec5SDimitry Andric   if (JA.getType() == types::TY_PCH && !IsCLMode()) {
61400b57cec5SDimitry Andric     llvm::sys::path::remove_filename(BasePath);
61410b57cec5SDimitry Andric     if (BasePath.empty())
61420b57cec5SDimitry Andric       BasePath = NamedOutput;
61430b57cec5SDimitry Andric     else
61440b57cec5SDimitry Andric       llvm::sys::path::append(BasePath, NamedOutput);
61450b57cec5SDimitry Andric     return C.addResultFile(C.getArgs().MakeArgString(BasePath.c_str()), &JA);
61460b57cec5SDimitry Andric   }
6147bdd1243dSDimitry Andric 
6148bdd1243dSDimitry Andric   return C.addResultFile(NamedOutput, &JA);
61490b57cec5SDimitry Andric }
61500b57cec5SDimitry Andric 
61510b57cec5SDimitry Andric std::string Driver::GetFilePath(StringRef Name, const ToolChain &TC) const {
61520b57cec5SDimitry Andric   // Search for Name in a list of paths.
61530b57cec5SDimitry Andric   auto SearchPaths = [&](const llvm::SmallVectorImpl<std::string> &P)
6154bdd1243dSDimitry Andric       -> std::optional<std::string> {
61550b57cec5SDimitry Andric     // Respect a limited subset of the '-Bprefix' functionality in GCC by
61560b57cec5SDimitry Andric     // attempting to use this prefix when looking for file paths.
61570b57cec5SDimitry Andric     for (const auto &Dir : P) {
61580b57cec5SDimitry Andric       if (Dir.empty())
61590b57cec5SDimitry Andric         continue;
61600b57cec5SDimitry Andric       SmallString<128> P(Dir[0] == '=' ? SysRoot + Dir.substr(1) : Dir);
61610b57cec5SDimitry Andric       llvm::sys::path::append(P, Name);
61620b57cec5SDimitry Andric       if (llvm::sys::fs::exists(Twine(P)))
61635ffd83dbSDimitry Andric         return std::string(P);
61640b57cec5SDimitry Andric     }
6165bdd1243dSDimitry Andric     return std::nullopt;
61660b57cec5SDimitry Andric   };
61670b57cec5SDimitry Andric 
61680b57cec5SDimitry Andric   if (auto P = SearchPaths(PrefixDirs))
61690b57cec5SDimitry Andric     return *P;
61700b57cec5SDimitry Andric 
61710b57cec5SDimitry Andric   SmallString<128> R(ResourceDir);
61720b57cec5SDimitry Andric   llvm::sys::path::append(R, Name);
61730b57cec5SDimitry Andric   if (llvm::sys::fs::exists(Twine(R)))
61747a6dacacSDimitry Andric     return std::string(R);
61750b57cec5SDimitry Andric 
61760b57cec5SDimitry Andric   SmallString<128> P(TC.getCompilerRTPath());
61770b57cec5SDimitry Andric   llvm::sys::path::append(P, Name);
61780b57cec5SDimitry Andric   if (llvm::sys::fs::exists(Twine(P)))
61797a6dacacSDimitry Andric     return std::string(P);
61800b57cec5SDimitry Andric 
61810b57cec5SDimitry Andric   SmallString<128> D(Dir);
61820b57cec5SDimitry Andric   llvm::sys::path::append(D, "..", Name);
61830b57cec5SDimitry Andric   if (llvm::sys::fs::exists(Twine(D)))
61847a6dacacSDimitry Andric     return std::string(D);
61850b57cec5SDimitry Andric 
61860b57cec5SDimitry Andric   if (auto P = SearchPaths(TC.getLibraryPaths()))
61870b57cec5SDimitry Andric     return *P;
61880b57cec5SDimitry Andric 
61890b57cec5SDimitry Andric   if (auto P = SearchPaths(TC.getFilePaths()))
61900b57cec5SDimitry Andric     return *P;
61910b57cec5SDimitry Andric 
6192*6c05f3a7SDimitry Andric   SmallString<128> R2(ResourceDir);
6193*6c05f3a7SDimitry Andric   llvm::sys::path::append(R2, "..", "..", Name);
6194*6c05f3a7SDimitry Andric   if (llvm::sys::fs::exists(Twine(R2)))
6195*6c05f3a7SDimitry Andric     return std::string(R2);
6196*6c05f3a7SDimitry Andric 
61975ffd83dbSDimitry Andric   return std::string(Name);
61980b57cec5SDimitry Andric }
61990b57cec5SDimitry Andric 
62000b57cec5SDimitry Andric void Driver::generatePrefixedToolNames(
62010b57cec5SDimitry Andric     StringRef Tool, const ToolChain &TC,
62020b57cec5SDimitry Andric     SmallVectorImpl<std::string> &Names) const {
62030b57cec5SDimitry Andric   // FIXME: Needs a better variable than TargetTriple
62040b57cec5SDimitry Andric   Names.emplace_back((TargetTriple + "-" + Tool).str());
62050b57cec5SDimitry Andric   Names.emplace_back(Tool);
62060b57cec5SDimitry Andric }
62070b57cec5SDimitry Andric 
6208e8d8bef9SDimitry Andric static bool ScanDirForExecutable(SmallString<128> &Dir, StringRef Name) {
62090b57cec5SDimitry Andric   llvm::sys::path::append(Dir, Name);
62100b57cec5SDimitry Andric   if (llvm::sys::fs::can_execute(Twine(Dir)))
62110b57cec5SDimitry Andric     return true;
62120b57cec5SDimitry Andric   llvm::sys::path::remove_filename(Dir);
62130b57cec5SDimitry Andric   return false;
62140b57cec5SDimitry Andric }
62150b57cec5SDimitry Andric 
62160b57cec5SDimitry Andric std::string Driver::GetProgramPath(StringRef Name, const ToolChain &TC) const {
62170b57cec5SDimitry Andric   SmallVector<std::string, 2> TargetSpecificExecutables;
62180b57cec5SDimitry Andric   generatePrefixedToolNames(Name, TC, TargetSpecificExecutables);
62190b57cec5SDimitry Andric 
62200b57cec5SDimitry Andric   // Respect a limited subset of the '-Bprefix' functionality in GCC by
62210b57cec5SDimitry Andric   // attempting to use this prefix when looking for program paths.
62220b57cec5SDimitry Andric   for (const auto &PrefixDir : PrefixDirs) {
62230b57cec5SDimitry Andric     if (llvm::sys::fs::is_directory(PrefixDir)) {
62240b57cec5SDimitry Andric       SmallString<128> P(PrefixDir);
6225e8d8bef9SDimitry Andric       if (ScanDirForExecutable(P, Name))
62267a6dacacSDimitry Andric         return std::string(P);
62270b57cec5SDimitry Andric     } else {
62280b57cec5SDimitry Andric       SmallString<128> P((PrefixDir + Name).str());
62290b57cec5SDimitry Andric       if (llvm::sys::fs::can_execute(Twine(P)))
62307a6dacacSDimitry Andric         return std::string(P);
62310b57cec5SDimitry Andric     }
62320b57cec5SDimitry Andric   }
62330b57cec5SDimitry Andric 
62340b57cec5SDimitry Andric   const ToolChain::path_list &List = TC.getProgramPaths();
62355ffd83dbSDimitry Andric   for (const auto &TargetSpecificExecutable : TargetSpecificExecutables) {
62365ffd83dbSDimitry Andric     // For each possible name of the tool look for it in
62375ffd83dbSDimitry Andric     // program paths first, then the path.
62385ffd83dbSDimitry Andric     // Higher priority names will be first, meaning that
62395ffd83dbSDimitry Andric     // a higher priority name in the path will be found
62405ffd83dbSDimitry Andric     // instead of a lower priority name in the program path.
62415ffd83dbSDimitry Andric     // E.g. <triple>-gcc on the path will be found instead
62425ffd83dbSDimitry Andric     // of gcc in the program path
62430b57cec5SDimitry Andric     for (const auto &Path : List) {
62440b57cec5SDimitry Andric       SmallString<128> P(Path);
62455ffd83dbSDimitry Andric       if (ScanDirForExecutable(P, TargetSpecificExecutable))
62467a6dacacSDimitry Andric         return std::string(P);
62470b57cec5SDimitry Andric     }
62480b57cec5SDimitry Andric 
62495ffd83dbSDimitry Andric     // Fall back to the path
62500b57cec5SDimitry Andric     if (llvm::ErrorOr<std::string> P =
62510b57cec5SDimitry Andric             llvm::sys::findProgramByName(TargetSpecificExecutable))
62520b57cec5SDimitry Andric       return *P;
62535ffd83dbSDimitry Andric   }
62540b57cec5SDimitry Andric 
62555ffd83dbSDimitry Andric   return std::string(Name);
62560b57cec5SDimitry Andric }
62570b57cec5SDimitry Andric 
62580fca6ea1SDimitry Andric std::string Driver::GetStdModuleManifestPath(const Compilation &C,
62590fca6ea1SDimitry Andric                                              const ToolChain &TC) const {
62600fca6ea1SDimitry Andric   std::string error = "<NOT PRESENT>";
62610fca6ea1SDimitry Andric 
62620fca6ea1SDimitry Andric   switch (TC.GetCXXStdlibType(C.getArgs())) {
62630fca6ea1SDimitry Andric   case ToolChain::CST_Libcxx: {
62640fca6ea1SDimitry Andric     auto evaluate = [&](const char *library) -> std::optional<std::string> {
62650fca6ea1SDimitry Andric       std::string lib = GetFilePath(library, TC);
62660fca6ea1SDimitry Andric 
62670fca6ea1SDimitry Andric       // Note when there are multiple flavours of libc++ the module json needs
62680fca6ea1SDimitry Andric       // to look at the command-line arguments for the proper json. These
62690fca6ea1SDimitry Andric       // flavours do not exist at the moment, but there are plans to provide a
62700fca6ea1SDimitry Andric       // variant that is built with sanitizer instrumentation enabled.
62710fca6ea1SDimitry Andric 
62720fca6ea1SDimitry Andric       // For example
62730fca6ea1SDimitry Andric       //  StringRef modules = [&] {
62740fca6ea1SDimitry Andric       //    const SanitizerArgs &Sanitize = TC.getSanitizerArgs(C.getArgs());
62750fca6ea1SDimitry Andric       //    if (Sanitize.needsAsanRt())
62760fca6ea1SDimitry Andric       //      return "libc++.modules-asan.json";
62770fca6ea1SDimitry Andric       //    return "libc++.modules.json";
62780fca6ea1SDimitry Andric       //  }();
62790fca6ea1SDimitry Andric 
62800fca6ea1SDimitry Andric       SmallString<128> path(lib.begin(), lib.end());
62810fca6ea1SDimitry Andric       llvm::sys::path::remove_filename(path);
62820fca6ea1SDimitry Andric       llvm::sys::path::append(path, "libc++.modules.json");
62830fca6ea1SDimitry Andric       if (TC.getVFS().exists(path))
62840fca6ea1SDimitry Andric         return static_cast<std::string>(path);
62850fca6ea1SDimitry Andric 
62860fca6ea1SDimitry Andric       return {};
62870fca6ea1SDimitry Andric     };
62880fca6ea1SDimitry Andric 
62890fca6ea1SDimitry Andric     if (std::optional<std::string> result = evaluate("libc++.so"); result)
62900fca6ea1SDimitry Andric       return *result;
62910fca6ea1SDimitry Andric 
62920fca6ea1SDimitry Andric     return evaluate("libc++.a").value_or(error);
62930fca6ea1SDimitry Andric   }
62940fca6ea1SDimitry Andric 
62950fca6ea1SDimitry Andric   case ToolChain::CST_Libstdcxx:
62960fca6ea1SDimitry Andric     // libstdc++ does not provide Standard library modules yet.
62970fca6ea1SDimitry Andric     return error;
62980fca6ea1SDimitry Andric   }
62990fca6ea1SDimitry Andric 
63000fca6ea1SDimitry Andric   return error;
63010fca6ea1SDimitry Andric }
63020fca6ea1SDimitry Andric 
63030b57cec5SDimitry Andric std::string Driver::GetTemporaryPath(StringRef Prefix, StringRef Suffix) const {
63040b57cec5SDimitry Andric   SmallString<128> Path;
63050b57cec5SDimitry Andric   std::error_code EC = llvm::sys::fs::createTemporaryFile(Prefix, Suffix, Path);
63060b57cec5SDimitry Andric   if (EC) {
63070b57cec5SDimitry Andric     Diag(clang::diag::err_unable_to_make_temp) << EC.message();
63080b57cec5SDimitry Andric     return "";
63090b57cec5SDimitry Andric   }
63100b57cec5SDimitry Andric 
63117a6dacacSDimitry Andric   return std::string(Path);
63120b57cec5SDimitry Andric }
63130b57cec5SDimitry Andric 
63140b57cec5SDimitry Andric std::string Driver::GetTemporaryDirectory(StringRef Prefix) const {
63150b57cec5SDimitry Andric   SmallString<128> Path;
63160b57cec5SDimitry Andric   std::error_code EC = llvm::sys::fs::createUniqueDirectory(Prefix, Path);
63170b57cec5SDimitry Andric   if (EC) {
63180b57cec5SDimitry Andric     Diag(clang::diag::err_unable_to_make_temp) << EC.message();
63190b57cec5SDimitry Andric     return "";
63200b57cec5SDimitry Andric   }
63210b57cec5SDimitry Andric 
63227a6dacacSDimitry Andric   return std::string(Path);
63230b57cec5SDimitry Andric }
63240b57cec5SDimitry Andric 
63250b57cec5SDimitry Andric std::string Driver::GetClPchPath(Compilation &C, StringRef BaseName) const {
63260b57cec5SDimitry Andric   SmallString<128> Output;
63270b57cec5SDimitry Andric   if (Arg *FpArg = C.getArgs().getLastArg(options::OPT__SLASH_Fp)) {
63280b57cec5SDimitry Andric     // FIXME: If anybody needs it, implement this obscure rule:
63290b57cec5SDimitry Andric     // "If you specify a directory without a file name, the default file name
63300b57cec5SDimitry Andric     // is VCx0.pch., where x is the major version of Visual C++ in use."
63310b57cec5SDimitry Andric     Output = FpArg->getValue();
63320b57cec5SDimitry Andric 
63330b57cec5SDimitry Andric     // "If you do not specify an extension as part of the path name, an
63340b57cec5SDimitry Andric     // extension of .pch is assumed. "
63350b57cec5SDimitry Andric     if (!llvm::sys::path::has_extension(Output))
63360b57cec5SDimitry Andric       Output += ".pch";
63370b57cec5SDimitry Andric   } else {
63380b57cec5SDimitry Andric     if (Arg *YcArg = C.getArgs().getLastArg(options::OPT__SLASH_Yc))
63390b57cec5SDimitry Andric       Output = YcArg->getValue();
63400b57cec5SDimitry Andric     if (Output.empty())
63410b57cec5SDimitry Andric       Output = BaseName;
63420b57cec5SDimitry Andric     llvm::sys::path::replace_extension(Output, ".pch");
63430b57cec5SDimitry Andric   }
63447a6dacacSDimitry Andric   return std::string(Output);
63450b57cec5SDimitry Andric }
63460b57cec5SDimitry Andric 
63470b57cec5SDimitry Andric const ToolChain &Driver::getToolChain(const ArgList &Args,
63480b57cec5SDimitry Andric                                       const llvm::Triple &Target) const {
63490b57cec5SDimitry Andric 
63500b57cec5SDimitry Andric   auto &TC = ToolChains[Target.str()];
63510b57cec5SDimitry Andric   if (!TC) {
63520b57cec5SDimitry Andric     switch (Target.getOS()) {
6353480093f4SDimitry Andric     case llvm::Triple::AIX:
6354480093f4SDimitry Andric       TC = std::make_unique<toolchains::AIX>(*this, Target, Args);
6355480093f4SDimitry Andric       break;
63560b57cec5SDimitry Andric     case llvm::Triple::Haiku:
6357a7dea167SDimitry Andric       TC = std::make_unique<toolchains::Haiku>(*this, Target, Args);
63580b57cec5SDimitry Andric       break;
63590b57cec5SDimitry Andric     case llvm::Triple::Darwin:
63600b57cec5SDimitry Andric     case llvm::Triple::MacOSX:
63610b57cec5SDimitry Andric     case llvm::Triple::IOS:
63620b57cec5SDimitry Andric     case llvm::Triple::TvOS:
63630b57cec5SDimitry Andric     case llvm::Triple::WatchOS:
63647a6dacacSDimitry Andric     case llvm::Triple::XROS:
636581ad6265SDimitry Andric     case llvm::Triple::DriverKit:
6366a7dea167SDimitry Andric       TC = std::make_unique<toolchains::DarwinClang>(*this, Target, Args);
63670b57cec5SDimitry Andric       break;
63680b57cec5SDimitry Andric     case llvm::Triple::DragonFly:
6369a7dea167SDimitry Andric       TC = std::make_unique<toolchains::DragonFly>(*this, Target, Args);
63700b57cec5SDimitry Andric       break;
63710b57cec5SDimitry Andric     case llvm::Triple::OpenBSD:
6372a7dea167SDimitry Andric       TC = std::make_unique<toolchains::OpenBSD>(*this, Target, Args);
63730b57cec5SDimitry Andric       break;
63740b57cec5SDimitry Andric     case llvm::Triple::NetBSD:
6375a7dea167SDimitry Andric       TC = std::make_unique<toolchains::NetBSD>(*this, Target, Args);
63760b57cec5SDimitry Andric       break;
63770b57cec5SDimitry Andric     case llvm::Triple::FreeBSD:
63784824e7fdSDimitry Andric       if (Target.isPPC())
63794824e7fdSDimitry Andric         TC = std::make_unique<toolchains::PPCFreeBSDToolChain>(*this, Target,
63804824e7fdSDimitry Andric                                                                Args);
63814824e7fdSDimitry Andric       else
6382a7dea167SDimitry Andric         TC = std::make_unique<toolchains::FreeBSD>(*this, Target, Args);
63830b57cec5SDimitry Andric       break;
63840b57cec5SDimitry Andric     case llvm::Triple::Linux:
63850b57cec5SDimitry Andric     case llvm::Triple::ELFIAMCU:
63860b57cec5SDimitry Andric       if (Target.getArch() == llvm::Triple::hexagon)
6387a7dea167SDimitry Andric         TC = std::make_unique<toolchains::HexagonToolChain>(*this, Target,
63880b57cec5SDimitry Andric                                                              Args);
63890b57cec5SDimitry Andric       else if ((Target.getVendor() == llvm::Triple::MipsTechnologies) &&
63900b57cec5SDimitry Andric                !Target.hasEnvironment())
6391a7dea167SDimitry Andric         TC = std::make_unique<toolchains::MipsLLVMToolChain>(*this, Target,
63920b57cec5SDimitry Andric                                                               Args);
6393e8d8bef9SDimitry Andric       else if (Target.isPPC())
6394a7dea167SDimitry Andric         TC = std::make_unique<toolchains::PPCLinuxToolChain>(*this, Target,
63950b57cec5SDimitry Andric                                                               Args);
63965ffd83dbSDimitry Andric       else if (Target.getArch() == llvm::Triple::ve)
63975ffd83dbSDimitry Andric         TC = std::make_unique<toolchains::VEToolChain>(*this, Target, Args);
639806c3fb27SDimitry Andric       else if (Target.isOHOSFamily())
639906c3fb27SDimitry Andric         TC = std::make_unique<toolchains::OHOS>(*this, Target, Args);
64000b57cec5SDimitry Andric       else
6401a7dea167SDimitry Andric         TC = std::make_unique<toolchains::Linux>(*this, Target, Args);
64020b57cec5SDimitry Andric       break;
64030b57cec5SDimitry Andric     case llvm::Triple::NaCl:
6404a7dea167SDimitry Andric       TC = std::make_unique<toolchains::NaClToolChain>(*this, Target, Args);
64050b57cec5SDimitry Andric       break;
64060b57cec5SDimitry Andric     case llvm::Triple::Fuchsia:
6407a7dea167SDimitry Andric       TC = std::make_unique<toolchains::Fuchsia>(*this, Target, Args);
64080b57cec5SDimitry Andric       break;
64090b57cec5SDimitry Andric     case llvm::Triple::Solaris:
6410a7dea167SDimitry Andric       TC = std::make_unique<toolchains::Solaris>(*this, Target, Args);
64110b57cec5SDimitry Andric       break;
6412bdd1243dSDimitry Andric     case llvm::Triple::CUDA:
6413bdd1243dSDimitry Andric       TC = std::make_unique<toolchains::NVPTXToolChain>(*this, Target, Args);
6414bdd1243dSDimitry Andric       break;
64150b57cec5SDimitry Andric     case llvm::Triple::AMDHSA:
64165ffd83dbSDimitry Andric       TC = std::make_unique<toolchains::ROCMToolChain>(*this, Target, Args);
64175ffd83dbSDimitry Andric       break;
64180b57cec5SDimitry Andric     case llvm::Triple::AMDPAL:
64190b57cec5SDimitry Andric     case llvm::Triple::Mesa3D:
6420a7dea167SDimitry Andric       TC = std::make_unique<toolchains::AMDGPUToolChain>(*this, Target, Args);
64210b57cec5SDimitry Andric       break;
64220b57cec5SDimitry Andric     case llvm::Triple::Win32:
64230b57cec5SDimitry Andric       switch (Target.getEnvironment()) {
64240b57cec5SDimitry Andric       default:
64250b57cec5SDimitry Andric         if (Target.isOSBinFormatELF())
6426a7dea167SDimitry Andric           TC = std::make_unique<toolchains::Generic_ELF>(*this, Target, Args);
64270b57cec5SDimitry Andric         else if (Target.isOSBinFormatMachO())
6428a7dea167SDimitry Andric           TC = std::make_unique<toolchains::MachO>(*this, Target, Args);
64290b57cec5SDimitry Andric         else
6430a7dea167SDimitry Andric           TC = std::make_unique<toolchains::Generic_GCC>(*this, Target, Args);
64310b57cec5SDimitry Andric         break;
64320b57cec5SDimitry Andric       case llvm::Triple::GNU:
6433a7dea167SDimitry Andric         TC = std::make_unique<toolchains::MinGW>(*this, Target, Args);
64340b57cec5SDimitry Andric         break;
64350b57cec5SDimitry Andric       case llvm::Triple::Itanium:
6436a7dea167SDimitry Andric         TC = std::make_unique<toolchains::CrossWindowsToolChain>(*this, Target,
64370b57cec5SDimitry Andric                                                                   Args);
64380b57cec5SDimitry Andric         break;
64390b57cec5SDimitry Andric       case llvm::Triple::MSVC:
64400b57cec5SDimitry Andric       case llvm::Triple::UnknownEnvironment:
64410b57cec5SDimitry Andric         if (Args.getLastArgValue(options::OPT_fuse_ld_EQ)
644206c3fb27SDimitry Andric                 .starts_with_insensitive("bfd"))
6443a7dea167SDimitry Andric           TC = std::make_unique<toolchains::CrossWindowsToolChain>(
64440b57cec5SDimitry Andric               *this, Target, Args);
64450b57cec5SDimitry Andric         else
64460b57cec5SDimitry Andric           TC =
6447a7dea167SDimitry Andric               std::make_unique<toolchains::MSVCToolChain>(*this, Target, Args);
64480b57cec5SDimitry Andric         break;
64490b57cec5SDimitry Andric       }
64500b57cec5SDimitry Andric       break;
64510b57cec5SDimitry Andric     case llvm::Triple::PS4:
6452a7dea167SDimitry Andric       TC = std::make_unique<toolchains::PS4CPU>(*this, Target, Args);
64530b57cec5SDimitry Andric       break;
645481ad6265SDimitry Andric     case llvm::Triple::PS5:
645581ad6265SDimitry Andric       TC = std::make_unique<toolchains::PS5CPU>(*this, Target, Args);
645681ad6265SDimitry Andric       break;
64570b57cec5SDimitry Andric     case llvm::Triple::Hurd:
6458a7dea167SDimitry Andric       TC = std::make_unique<toolchains::Hurd>(*this, Target, Args);
64590b57cec5SDimitry Andric       break;
646006c3fb27SDimitry Andric     case llvm::Triple::LiteOS:
646106c3fb27SDimitry Andric       TC = std::make_unique<toolchains::OHOS>(*this, Target, Args);
646206c3fb27SDimitry Andric       break;
6463e8d8bef9SDimitry Andric     case llvm::Triple::ZOS:
6464e8d8bef9SDimitry Andric       TC = std::make_unique<toolchains::ZOS>(*this, Target, Args);
6465e8d8bef9SDimitry Andric       break;
646681ad6265SDimitry Andric     case llvm::Triple::ShaderModel:
646781ad6265SDimitry Andric       TC = std::make_unique<toolchains::HLSLToolChain>(*this, Target, Args);
646881ad6265SDimitry Andric       break;
64690b57cec5SDimitry Andric     default:
64700b57cec5SDimitry Andric       // Of these targets, Hexagon is the only one that might have
64710b57cec5SDimitry Andric       // an OS of Linux, in which case it got handled above already.
64720b57cec5SDimitry Andric       switch (Target.getArch()) {
64730b57cec5SDimitry Andric       case llvm::Triple::tce:
6474a7dea167SDimitry Andric         TC = std::make_unique<toolchains::TCEToolChain>(*this, Target, Args);
64750b57cec5SDimitry Andric         break;
64760b57cec5SDimitry Andric       case llvm::Triple::tcele:
6477a7dea167SDimitry Andric         TC = std::make_unique<toolchains::TCELEToolChain>(*this, Target, Args);
64780b57cec5SDimitry Andric         break;
64790b57cec5SDimitry Andric       case llvm::Triple::hexagon:
6480a7dea167SDimitry Andric         TC = std::make_unique<toolchains::HexagonToolChain>(*this, Target,
64810b57cec5SDimitry Andric                                                              Args);
64820b57cec5SDimitry Andric         break;
64830b57cec5SDimitry Andric       case llvm::Triple::lanai:
6484a7dea167SDimitry Andric         TC = std::make_unique<toolchains::LanaiToolChain>(*this, Target, Args);
64850b57cec5SDimitry Andric         break;
64860b57cec5SDimitry Andric       case llvm::Triple::xcore:
6487a7dea167SDimitry Andric         TC = std::make_unique<toolchains::XCoreToolChain>(*this, Target, Args);
64880b57cec5SDimitry Andric         break;
64890b57cec5SDimitry Andric       case llvm::Triple::wasm32:
64900b57cec5SDimitry Andric       case llvm::Triple::wasm64:
6491a7dea167SDimitry Andric         TC = std::make_unique<toolchains::WebAssembly>(*this, Target, Args);
64920b57cec5SDimitry Andric         break;
64930b57cec5SDimitry Andric       case llvm::Triple::avr:
6494a7dea167SDimitry Andric         TC = std::make_unique<toolchains::AVRToolChain>(*this, Target, Args);
64950b57cec5SDimitry Andric         break;
64960b57cec5SDimitry Andric       case llvm::Triple::msp430:
64970b57cec5SDimitry Andric         TC =
6498a7dea167SDimitry Andric             std::make_unique<toolchains::MSP430ToolChain>(*this, Target, Args);
64990b57cec5SDimitry Andric         break;
65000b57cec5SDimitry Andric       case llvm::Triple::riscv32:
65010b57cec5SDimitry Andric       case llvm::Triple::riscv64:
6502e8d8bef9SDimitry Andric         if (toolchains::RISCVToolChain::hasGCCToolchain(*this, Args))
6503e8d8bef9SDimitry Andric           TC =
6504e8d8bef9SDimitry Andric               std::make_unique<toolchains::RISCVToolChain>(*this, Target, Args);
6505e8d8bef9SDimitry Andric         else
6506e8d8bef9SDimitry Andric           TC = std::make_unique<toolchains::BareMetal>(*this, Target, Args);
65070b57cec5SDimitry Andric         break;
65085ffd83dbSDimitry Andric       case llvm::Triple::ve:
65095ffd83dbSDimitry Andric         TC = std::make_unique<toolchains::VEToolChain>(*this, Target, Args);
65105ffd83dbSDimitry Andric         break;
65110eae32dcSDimitry Andric       case llvm::Triple::spirv32:
65120eae32dcSDimitry Andric       case llvm::Triple::spirv64:
65130eae32dcSDimitry Andric         TC = std::make_unique<toolchains::SPIRVToolChain>(*this, Target, Args);
65140eae32dcSDimitry Andric         break;
651581ad6265SDimitry Andric       case llvm::Triple::csky:
651681ad6265SDimitry Andric         TC = std::make_unique<toolchains::CSKYToolChain>(*this, Target, Args);
651781ad6265SDimitry Andric         break;
65180b57cec5SDimitry Andric       default:
65195f757f3fSDimitry Andric         if (toolchains::BareMetal::handlesTarget(Target))
6520a7dea167SDimitry Andric           TC = std::make_unique<toolchains::BareMetal>(*this, Target, Args);
65210b57cec5SDimitry Andric         else if (Target.isOSBinFormatELF())
6522a7dea167SDimitry Andric           TC = std::make_unique<toolchains::Generic_ELF>(*this, Target, Args);
65230b57cec5SDimitry Andric         else if (Target.isOSBinFormatMachO())
6524a7dea167SDimitry Andric           TC = std::make_unique<toolchains::MachO>(*this, Target, Args);
65250b57cec5SDimitry Andric         else
6526a7dea167SDimitry Andric           TC = std::make_unique<toolchains::Generic_GCC>(*this, Target, Args);
65270b57cec5SDimitry Andric       }
65280b57cec5SDimitry Andric     }
65290b57cec5SDimitry Andric   }
65300b57cec5SDimitry Andric 
65310b57cec5SDimitry Andric   return *TC;
65320b57cec5SDimitry Andric }
65330b57cec5SDimitry Andric 
65340eae32dcSDimitry Andric const ToolChain &Driver::getOffloadingDeviceToolChain(
65350eae32dcSDimitry Andric     const ArgList &Args, const llvm::Triple &Target, const ToolChain &HostTC,
65360eae32dcSDimitry Andric     const Action::OffloadKind &TargetDeviceOffloadKind) const {
65370eae32dcSDimitry Andric   // Use device / host triples as the key into the ToolChains map because the
65380eae32dcSDimitry Andric   // device ToolChain we create depends on both.
65390eae32dcSDimitry Andric   auto &TC = ToolChains[Target.str() + "/" + HostTC.getTriple().str()];
65400eae32dcSDimitry Andric   if (!TC) {
65410eae32dcSDimitry Andric     // Categorized by offload kind > arch rather than OS > arch like
65420eae32dcSDimitry Andric     // the normal getToolChain call, as it seems a reasonable way to categorize
65430eae32dcSDimitry Andric     // things.
65440eae32dcSDimitry Andric     switch (TargetDeviceOffloadKind) {
65450eae32dcSDimitry Andric     case Action::OFK_HIP: {
65460fca6ea1SDimitry Andric       if (((Target.getArch() == llvm::Triple::amdgcn ||
65470fca6ea1SDimitry Andric             Target.getArch() == llvm::Triple::spirv64) &&
65480eae32dcSDimitry Andric            Target.getVendor() == llvm::Triple::AMD &&
65490fca6ea1SDimitry Andric            Target.getOS() == llvm::Triple::AMDHSA) ||
65500fca6ea1SDimitry Andric           !Args.hasArgNoClaim(options::OPT_offload_EQ))
65510eae32dcSDimitry Andric         TC = std::make_unique<toolchains::HIPAMDToolChain>(*this, Target,
65520eae32dcSDimitry Andric                                                            HostTC, Args);
65530eae32dcSDimitry Andric       else if (Target.getArch() == llvm::Triple::spirv64 &&
65540eae32dcSDimitry Andric                Target.getVendor() == llvm::Triple::UnknownVendor &&
65550eae32dcSDimitry Andric                Target.getOS() == llvm::Triple::UnknownOS)
65560eae32dcSDimitry Andric         TC = std::make_unique<toolchains::HIPSPVToolChain>(*this, Target,
65570eae32dcSDimitry Andric                                                            HostTC, Args);
65580eae32dcSDimitry Andric       break;
65590eae32dcSDimitry Andric     }
65600eae32dcSDimitry Andric     default:
65610eae32dcSDimitry Andric       break;
65620eae32dcSDimitry Andric     }
65630eae32dcSDimitry Andric   }
65640eae32dcSDimitry Andric 
65650eae32dcSDimitry Andric   return *TC;
65660eae32dcSDimitry Andric }
65670eae32dcSDimitry Andric 
65680b57cec5SDimitry Andric bool Driver::ShouldUseClangCompiler(const JobAction &JA) const {
65690b57cec5SDimitry Andric   // Say "no" if there is not exactly one input of a type clang understands.
65700b57cec5SDimitry Andric   if (JA.size() != 1 ||
65710b57cec5SDimitry Andric       !types::isAcceptedByClang((*JA.input_begin())->getType()))
65720b57cec5SDimitry Andric     return false;
65730b57cec5SDimitry Andric 
65740b57cec5SDimitry Andric   // And say "no" if this is not a kind of action clang understands.
65750b57cec5SDimitry Andric   if (!isa<PreprocessJobAction>(JA) && !isa<PrecompileJobAction>(JA) &&
657681ad6265SDimitry Andric       !isa<CompileJobAction>(JA) && !isa<BackendJobAction>(JA) &&
657781ad6265SDimitry Andric       !isa<ExtractAPIJobAction>(JA))
65780b57cec5SDimitry Andric     return false;
65790b57cec5SDimitry Andric 
65800b57cec5SDimitry Andric   return true;
65810b57cec5SDimitry Andric }
65820b57cec5SDimitry Andric 
6583480093f4SDimitry Andric bool Driver::ShouldUseFlangCompiler(const JobAction &JA) const {
6584480093f4SDimitry Andric   // Say "no" if there is not exactly one input of a type flang understands.
6585480093f4SDimitry Andric   if (JA.size() != 1 ||
658681ad6265SDimitry Andric       !types::isAcceptedByFlang((*JA.input_begin())->getType()))
6587480093f4SDimitry Andric     return false;
6588480093f4SDimitry Andric 
6589480093f4SDimitry Andric   // And say "no" if this is not a kind of action flang understands.
659081ad6265SDimitry Andric   if (!isa<PreprocessJobAction>(JA) && !isa<CompileJobAction>(JA) &&
659181ad6265SDimitry Andric       !isa<BackendJobAction>(JA))
6592480093f4SDimitry Andric     return false;
6593480093f4SDimitry Andric 
6594480093f4SDimitry Andric   return true;
6595480093f4SDimitry Andric }
6596480093f4SDimitry Andric 
65975ffd83dbSDimitry Andric bool Driver::ShouldEmitStaticLibrary(const ArgList &Args) const {
65985ffd83dbSDimitry Andric   // Only emit static library if the flag is set explicitly.
65995ffd83dbSDimitry Andric   if (Args.hasArg(options::OPT_emit_static_lib))
66005ffd83dbSDimitry Andric     return true;
66015ffd83dbSDimitry Andric   return false;
66025ffd83dbSDimitry Andric }
66035ffd83dbSDimitry Andric 
66040b57cec5SDimitry Andric /// GetReleaseVersion - Parse (([0-9]+)(.([0-9]+)(.([0-9]+)?))?)? and return the
66050b57cec5SDimitry Andric /// grouped values as integers. Numbers which are not provided are set to 0.
66060b57cec5SDimitry Andric ///
66070b57cec5SDimitry Andric /// \return True if the entire string was parsed (9.2), or all groups were
66080b57cec5SDimitry Andric /// parsed (10.3.5extrastuff).
66090b57cec5SDimitry Andric bool Driver::GetReleaseVersion(StringRef Str, unsigned &Major, unsigned &Minor,
66100b57cec5SDimitry Andric                                unsigned &Micro, bool &HadExtra) {
66110b57cec5SDimitry Andric   HadExtra = false;
66120b57cec5SDimitry Andric 
66130b57cec5SDimitry Andric   Major = Minor = Micro = 0;
66140b57cec5SDimitry Andric   if (Str.empty())
66150b57cec5SDimitry Andric     return false;
66160b57cec5SDimitry Andric 
66170b57cec5SDimitry Andric   if (Str.consumeInteger(10, Major))
66180b57cec5SDimitry Andric     return false;
66190b57cec5SDimitry Andric   if (Str.empty())
66200b57cec5SDimitry Andric     return true;
66210fca6ea1SDimitry Andric   if (!Str.consume_front("."))
66220b57cec5SDimitry Andric     return false;
66230b57cec5SDimitry Andric 
66240b57cec5SDimitry Andric   if (Str.consumeInteger(10, Minor))
66250b57cec5SDimitry Andric     return false;
66260b57cec5SDimitry Andric   if (Str.empty())
66270b57cec5SDimitry Andric     return true;
66280fca6ea1SDimitry Andric   if (!Str.consume_front("."))
66290b57cec5SDimitry Andric     return false;
66300b57cec5SDimitry Andric 
66310b57cec5SDimitry Andric   if (Str.consumeInteger(10, Micro))
66320b57cec5SDimitry Andric     return false;
66330b57cec5SDimitry Andric   if (!Str.empty())
66340b57cec5SDimitry Andric     HadExtra = true;
66350b57cec5SDimitry Andric   return true;
66360b57cec5SDimitry Andric }
66370b57cec5SDimitry Andric 
66380b57cec5SDimitry Andric /// Parse digits from a string \p Str and fulfill \p Digits with
66390b57cec5SDimitry Andric /// the parsed numbers. This method assumes that the max number of
66400b57cec5SDimitry Andric /// digits to look for is equal to Digits.size().
66410b57cec5SDimitry Andric ///
66420b57cec5SDimitry Andric /// \return True if the entire string was parsed and there are
66430b57cec5SDimitry Andric /// no extra characters remaining at the end.
66440b57cec5SDimitry Andric bool Driver::GetReleaseVersion(StringRef Str,
66450b57cec5SDimitry Andric                                MutableArrayRef<unsigned> Digits) {
66460b57cec5SDimitry Andric   if (Str.empty())
66470b57cec5SDimitry Andric     return false;
66480b57cec5SDimitry Andric 
66490b57cec5SDimitry Andric   unsigned CurDigit = 0;
66500b57cec5SDimitry Andric   while (CurDigit < Digits.size()) {
66510b57cec5SDimitry Andric     unsigned Digit;
66520b57cec5SDimitry Andric     if (Str.consumeInteger(10, Digit))
66530b57cec5SDimitry Andric       return false;
66540b57cec5SDimitry Andric     Digits[CurDigit] = Digit;
66550b57cec5SDimitry Andric     if (Str.empty())
66560b57cec5SDimitry Andric       return true;
66570fca6ea1SDimitry Andric     if (!Str.consume_front("."))
66580b57cec5SDimitry Andric       return false;
66590b57cec5SDimitry Andric     CurDigit++;
66600b57cec5SDimitry Andric   }
66610b57cec5SDimitry Andric 
66620b57cec5SDimitry Andric   // More digits than requested, bail out...
66630b57cec5SDimitry Andric   return false;
66640b57cec5SDimitry Andric }
66650b57cec5SDimitry Andric 
66665f757f3fSDimitry Andric llvm::opt::Visibility
66675f757f3fSDimitry Andric Driver::getOptionVisibilityMask(bool UseDriverMode) const {
66685f757f3fSDimitry Andric   if (!UseDriverMode)
66695f757f3fSDimitry Andric     return llvm::opt::Visibility(options::ClangOption);
66705f757f3fSDimitry Andric   if (IsCLMode())
66715f757f3fSDimitry Andric     return llvm::opt::Visibility(options::CLOption);
66725f757f3fSDimitry Andric   if (IsDXCMode())
66735f757f3fSDimitry Andric     return llvm::opt::Visibility(options::DXCOption);
66745f757f3fSDimitry Andric   if (IsFlangMode())  {
66755f757f3fSDimitry Andric     return llvm::opt::Visibility(options::FlangOption);
66760b57cec5SDimitry Andric   }
66775f757f3fSDimitry Andric   return llvm::opt::Visibility(options::ClangOption);
66780b57cec5SDimitry Andric }
66790b57cec5SDimitry Andric 
6680bdd1243dSDimitry Andric const char *Driver::getExecutableForDriverMode(DriverMode Mode) {
6681bdd1243dSDimitry Andric   switch (Mode) {
6682bdd1243dSDimitry Andric   case GCCMode:
6683bdd1243dSDimitry Andric     return "clang";
6684bdd1243dSDimitry Andric   case GXXMode:
6685bdd1243dSDimitry Andric     return "clang++";
6686bdd1243dSDimitry Andric   case CPPMode:
6687bdd1243dSDimitry Andric     return "clang-cpp";
6688bdd1243dSDimitry Andric   case CLMode:
6689bdd1243dSDimitry Andric     return "clang-cl";
6690bdd1243dSDimitry Andric   case FlangMode:
6691bdd1243dSDimitry Andric     return "flang";
6692bdd1243dSDimitry Andric   case DXCMode:
6693bdd1243dSDimitry Andric     return "clang-dxc";
6694bdd1243dSDimitry Andric   }
6695bdd1243dSDimitry Andric 
6696bdd1243dSDimitry Andric   llvm_unreachable("Unhandled Mode");
6697bdd1243dSDimitry Andric }
6698bdd1243dSDimitry Andric 
66990b57cec5SDimitry Andric bool clang::driver::isOptimizationLevelFast(const ArgList &Args) {
67000b57cec5SDimitry Andric   return Args.hasFlag(options::OPT_Ofast, options::OPT_O_Group, false);
67010b57cec5SDimitry Andric }
6702480093f4SDimitry Andric 
6703480093f4SDimitry Andric bool clang::driver::willEmitRemarks(const ArgList &Args) {
6704480093f4SDimitry Andric   // -fsave-optimization-record enables it.
6705480093f4SDimitry Andric   if (Args.hasFlag(options::OPT_fsave_optimization_record,
6706480093f4SDimitry Andric                    options::OPT_fno_save_optimization_record, false))
6707480093f4SDimitry Andric     return true;
6708480093f4SDimitry Andric 
6709480093f4SDimitry Andric   // -fsave-optimization-record=<format> enables it as well.
6710480093f4SDimitry Andric   if (Args.hasFlag(options::OPT_fsave_optimization_record_EQ,
6711480093f4SDimitry Andric                    options::OPT_fno_save_optimization_record, false))
6712480093f4SDimitry Andric     return true;
6713480093f4SDimitry Andric 
6714480093f4SDimitry Andric   // -foptimization-record-file alone enables it too.
6715480093f4SDimitry Andric   if (Args.hasFlag(options::OPT_foptimization_record_file_EQ,
6716480093f4SDimitry Andric                    options::OPT_fno_save_optimization_record, false))
6717480093f4SDimitry Andric     return true;
6718480093f4SDimitry Andric 
6719480093f4SDimitry Andric   // -foptimization-record-passes alone enables it too.
6720480093f4SDimitry Andric   if (Args.hasFlag(options::OPT_foptimization_record_passes_EQ,
6721480093f4SDimitry Andric                    options::OPT_fno_save_optimization_record, false))
6722480093f4SDimitry Andric     return true;
6723480093f4SDimitry Andric   return false;
6724480093f4SDimitry Andric }
6725fe6060f1SDimitry Andric 
6726fe6060f1SDimitry Andric llvm::StringRef clang::driver::getDriverMode(StringRef ProgName,
6727fe6060f1SDimitry Andric                                              ArrayRef<const char *> Args) {
67285f757f3fSDimitry Andric   static StringRef OptName =
6729fe6060f1SDimitry Andric       getDriverOptTable().getOption(options::OPT_driver_mode).getPrefixedName();
6730fe6060f1SDimitry Andric   llvm::StringRef Opt;
6731fe6060f1SDimitry Andric   for (StringRef Arg : Args) {
67325f757f3fSDimitry Andric     if (!Arg.starts_with(OptName))
6733fe6060f1SDimitry Andric       continue;
6734fe6060f1SDimitry Andric     Opt = Arg;
6735fe6060f1SDimitry Andric   }
6736fe6060f1SDimitry Andric   if (Opt.empty())
6737fe6060f1SDimitry Andric     Opt = ToolChain::getTargetAndModeFromProgramName(ProgName).DriverMode;
6738fe6060f1SDimitry Andric   return Opt.consume_front(OptName) ? Opt : "";
6739fe6060f1SDimitry Andric }
6740fe6060f1SDimitry Andric 
67410fca6ea1SDimitry Andric bool driver::IsClangCL(StringRef DriverMode) { return DriverMode == "cl"; }
674206c3fb27SDimitry Andric 
674306c3fb27SDimitry Andric llvm::Error driver::expandResponseFiles(SmallVectorImpl<const char *> &Args,
674406c3fb27SDimitry Andric                                         bool ClangCLMode,
674506c3fb27SDimitry Andric                                         llvm::BumpPtrAllocator &Alloc,
674606c3fb27SDimitry Andric                                         llvm::vfs::FileSystem *FS) {
674706c3fb27SDimitry Andric   // Parse response files using the GNU syntax, unless we're in CL mode. There
674806c3fb27SDimitry Andric   // are two ways to put clang in CL compatibility mode: ProgName is either
674906c3fb27SDimitry Andric   // clang-cl or cl, or --driver-mode=cl is on the command line. The normal
675006c3fb27SDimitry Andric   // command line parsing can't happen until after response file parsing, so we
675106c3fb27SDimitry Andric   // have to manually search for a --driver-mode=cl argument the hard way.
675206c3fb27SDimitry Andric   // Finally, our -cc1 tools don't care which tokenization mode we use because
675306c3fb27SDimitry Andric   // response files written by clang will tokenize the same way in either mode.
675406c3fb27SDimitry Andric   enum { Default, POSIX, Windows } RSPQuoting = Default;
675506c3fb27SDimitry Andric   for (const char *F : Args) {
675606c3fb27SDimitry Andric     if (strcmp(F, "--rsp-quoting=posix") == 0)
675706c3fb27SDimitry Andric       RSPQuoting = POSIX;
675806c3fb27SDimitry Andric     else if (strcmp(F, "--rsp-quoting=windows") == 0)
675906c3fb27SDimitry Andric       RSPQuoting = Windows;
676006c3fb27SDimitry Andric   }
676106c3fb27SDimitry Andric 
676206c3fb27SDimitry Andric   // Determines whether we want nullptr markers in Args to indicate response
676306c3fb27SDimitry Andric   // files end-of-lines. We only use this for the /LINK driver argument with
676406c3fb27SDimitry Andric   // clang-cl.exe on Windows.
676506c3fb27SDimitry Andric   bool MarkEOLs = ClangCLMode;
676606c3fb27SDimitry Andric 
676706c3fb27SDimitry Andric   llvm::cl::TokenizerCallback Tokenizer;
676806c3fb27SDimitry Andric   if (RSPQuoting == Windows || (RSPQuoting == Default && ClangCLMode))
676906c3fb27SDimitry Andric     Tokenizer = &llvm::cl::TokenizeWindowsCommandLine;
677006c3fb27SDimitry Andric   else
677106c3fb27SDimitry Andric     Tokenizer = &llvm::cl::TokenizeGNUCommandLine;
677206c3fb27SDimitry Andric 
67735f757f3fSDimitry Andric   if (MarkEOLs && Args.size() > 1 && StringRef(Args[1]).starts_with("-cc1"))
677406c3fb27SDimitry Andric     MarkEOLs = false;
677506c3fb27SDimitry Andric 
677606c3fb27SDimitry Andric   llvm::cl::ExpansionContext ECtx(Alloc, Tokenizer);
677706c3fb27SDimitry Andric   ECtx.setMarkEOLs(MarkEOLs);
677806c3fb27SDimitry Andric   if (FS)
677906c3fb27SDimitry Andric     ECtx.setVFS(FS);
678006c3fb27SDimitry Andric 
678106c3fb27SDimitry Andric   if (llvm::Error Err = ECtx.expandResponseFiles(Args))
678206c3fb27SDimitry Andric     return Err;
678306c3fb27SDimitry Andric 
678406c3fb27SDimitry Andric   // If -cc1 came from a response file, remove the EOL sentinels.
678506c3fb27SDimitry Andric   auto FirstArg = llvm::find_if(llvm::drop_begin(Args),
678606c3fb27SDimitry Andric                                 [](const char *A) { return A != nullptr; });
67875f757f3fSDimitry Andric   if (FirstArg != Args.end() && StringRef(*FirstArg).starts_with("-cc1")) {
678806c3fb27SDimitry Andric     // If -cc1 came from a response file, remove the EOL sentinels.
678906c3fb27SDimitry Andric     if (MarkEOLs) {
679006c3fb27SDimitry Andric       auto newEnd = std::remove(Args.begin(), Args.end(), nullptr);
679106c3fb27SDimitry Andric       Args.resize(newEnd - Args.begin());
679206c3fb27SDimitry Andric     }
679306c3fb27SDimitry Andric   }
679406c3fb27SDimitry Andric 
679506c3fb27SDimitry Andric   return llvm::Error::success();
679606c3fb27SDimitry Andric }
67970fca6ea1SDimitry Andric 
67980fca6ea1SDimitry Andric static const char *GetStableCStr(llvm::StringSet<> &SavedStrings, StringRef S) {
67990fca6ea1SDimitry Andric   return SavedStrings.insert(S).first->getKeyData();
68000fca6ea1SDimitry Andric }
68010fca6ea1SDimitry Andric 
68020fca6ea1SDimitry Andric /// Apply a list of edits to the input argument lists.
68030fca6ea1SDimitry Andric ///
68040fca6ea1SDimitry Andric /// The input string is a space separated list of edits to perform,
68050fca6ea1SDimitry Andric /// they are applied in order to the input argument lists. Edits
68060fca6ea1SDimitry Andric /// should be one of the following forms:
68070fca6ea1SDimitry Andric ///
68080fca6ea1SDimitry Andric ///  '#': Silence information about the changes to the command line arguments.
68090fca6ea1SDimitry Andric ///
68100fca6ea1SDimitry Andric ///  '^': Add FOO as a new argument at the beginning of the command line.
68110fca6ea1SDimitry Andric ///
68120fca6ea1SDimitry Andric ///  '+': Add FOO as a new argument at the end of the command line.
68130fca6ea1SDimitry Andric ///
68140fca6ea1SDimitry Andric ///  's/XXX/YYY/': Substitute the regular expression XXX with YYY in the command
68150fca6ea1SDimitry Andric ///  line.
68160fca6ea1SDimitry Andric ///
68170fca6ea1SDimitry Andric ///  'xOPTION': Removes all instances of the literal argument OPTION.
68180fca6ea1SDimitry Andric ///
68190fca6ea1SDimitry Andric ///  'XOPTION': Removes all instances of the literal argument OPTION,
68200fca6ea1SDimitry Andric ///  and the following argument.
68210fca6ea1SDimitry Andric ///
68220fca6ea1SDimitry Andric ///  'Ox': Removes all flags matching 'O' or 'O[sz0-9]' and adds 'Ox'
68230fca6ea1SDimitry Andric ///  at the end of the command line.
68240fca6ea1SDimitry Andric ///
68250fca6ea1SDimitry Andric /// \param OS - The stream to write edit information to.
68260fca6ea1SDimitry Andric /// \param Args - The vector of command line arguments.
68270fca6ea1SDimitry Andric /// \param Edit - The override command to perform.
68280fca6ea1SDimitry Andric /// \param SavedStrings - Set to use for storing string representations.
68290fca6ea1SDimitry Andric static void applyOneOverrideOption(raw_ostream &OS,
68300fca6ea1SDimitry Andric                                    SmallVectorImpl<const char *> &Args,
68310fca6ea1SDimitry Andric                                    StringRef Edit,
68320fca6ea1SDimitry Andric                                    llvm::StringSet<> &SavedStrings) {
68330fca6ea1SDimitry Andric   // This does not need to be efficient.
68340fca6ea1SDimitry Andric 
68350fca6ea1SDimitry Andric   if (Edit[0] == '^') {
68360fca6ea1SDimitry Andric     const char *Str = GetStableCStr(SavedStrings, Edit.substr(1));
68370fca6ea1SDimitry Andric     OS << "### Adding argument " << Str << " at beginning\n";
68380fca6ea1SDimitry Andric     Args.insert(Args.begin() + 1, Str);
68390fca6ea1SDimitry Andric   } else if (Edit[0] == '+') {
68400fca6ea1SDimitry Andric     const char *Str = GetStableCStr(SavedStrings, Edit.substr(1));
68410fca6ea1SDimitry Andric     OS << "### Adding argument " << Str << " at end\n";
68420fca6ea1SDimitry Andric     Args.push_back(Str);
68430fca6ea1SDimitry Andric   } else if (Edit[0] == 's' && Edit[1] == '/' && Edit.ends_with("/") &&
68440fca6ea1SDimitry Andric              Edit.slice(2, Edit.size() - 1).contains('/')) {
68450fca6ea1SDimitry Andric     StringRef MatchPattern = Edit.substr(2).split('/').first;
68460fca6ea1SDimitry Andric     StringRef ReplPattern = Edit.substr(2).split('/').second;
68470fca6ea1SDimitry Andric     ReplPattern = ReplPattern.slice(0, ReplPattern.size() - 1);
68480fca6ea1SDimitry Andric 
68490fca6ea1SDimitry Andric     for (unsigned i = 1, e = Args.size(); i != e; ++i) {
68500fca6ea1SDimitry Andric       // Ignore end-of-line response file markers
68510fca6ea1SDimitry Andric       if (Args[i] == nullptr)
68520fca6ea1SDimitry Andric         continue;
68530fca6ea1SDimitry Andric       std::string Repl = llvm::Regex(MatchPattern).sub(ReplPattern, Args[i]);
68540fca6ea1SDimitry Andric 
68550fca6ea1SDimitry Andric       if (Repl != Args[i]) {
68560fca6ea1SDimitry Andric         OS << "### Replacing '" << Args[i] << "' with '" << Repl << "'\n";
68570fca6ea1SDimitry Andric         Args[i] = GetStableCStr(SavedStrings, Repl);
68580fca6ea1SDimitry Andric       }
68590fca6ea1SDimitry Andric     }
68600fca6ea1SDimitry Andric   } else if (Edit[0] == 'x' || Edit[0] == 'X') {
68610fca6ea1SDimitry Andric     auto Option = Edit.substr(1);
68620fca6ea1SDimitry Andric     for (unsigned i = 1; i < Args.size();) {
68630fca6ea1SDimitry Andric       if (Option == Args[i]) {
68640fca6ea1SDimitry Andric         OS << "### Deleting argument " << Args[i] << '\n';
68650fca6ea1SDimitry Andric         Args.erase(Args.begin() + i);
68660fca6ea1SDimitry Andric         if (Edit[0] == 'X') {
68670fca6ea1SDimitry Andric           if (i < Args.size()) {
68680fca6ea1SDimitry Andric             OS << "### Deleting argument " << Args[i] << '\n';
68690fca6ea1SDimitry Andric             Args.erase(Args.begin() + i);
68700fca6ea1SDimitry Andric           } else
68710fca6ea1SDimitry Andric             OS << "### Invalid X edit, end of command line!\n";
68720fca6ea1SDimitry Andric         }
68730fca6ea1SDimitry Andric       } else
68740fca6ea1SDimitry Andric         ++i;
68750fca6ea1SDimitry Andric     }
68760fca6ea1SDimitry Andric   } else if (Edit[0] == 'O') {
68770fca6ea1SDimitry Andric     for (unsigned i = 1; i < Args.size();) {
68780fca6ea1SDimitry Andric       const char *A = Args[i];
68790fca6ea1SDimitry Andric       // Ignore end-of-line response file markers
68800fca6ea1SDimitry Andric       if (A == nullptr)
68810fca6ea1SDimitry Andric         continue;
68820fca6ea1SDimitry Andric       if (A[0] == '-' && A[1] == 'O' &&
68830fca6ea1SDimitry Andric           (A[2] == '\0' || (A[3] == '\0' && (A[2] == 's' || A[2] == 'z' ||
68840fca6ea1SDimitry Andric                                              ('0' <= A[2] && A[2] <= '9'))))) {
68850fca6ea1SDimitry Andric         OS << "### Deleting argument " << Args[i] << '\n';
68860fca6ea1SDimitry Andric         Args.erase(Args.begin() + i);
68870fca6ea1SDimitry Andric       } else
68880fca6ea1SDimitry Andric         ++i;
68890fca6ea1SDimitry Andric     }
68900fca6ea1SDimitry Andric     OS << "### Adding argument " << Edit << " at end\n";
68910fca6ea1SDimitry Andric     Args.push_back(GetStableCStr(SavedStrings, '-' + Edit.str()));
68920fca6ea1SDimitry Andric   } else {
68930fca6ea1SDimitry Andric     OS << "### Unrecognized edit: " << Edit << "\n";
68940fca6ea1SDimitry Andric   }
68950fca6ea1SDimitry Andric }
68960fca6ea1SDimitry Andric 
68970fca6ea1SDimitry Andric void driver::applyOverrideOptions(SmallVectorImpl<const char *> &Args,
68980fca6ea1SDimitry Andric                                   const char *OverrideStr,
68990fca6ea1SDimitry Andric                                   llvm::StringSet<> &SavedStrings,
69000fca6ea1SDimitry Andric                                   raw_ostream *OS) {
69010fca6ea1SDimitry Andric   if (!OS)
69020fca6ea1SDimitry Andric     OS = &llvm::nulls();
69030fca6ea1SDimitry Andric 
69040fca6ea1SDimitry Andric   if (OverrideStr[0] == '#') {
69050fca6ea1SDimitry Andric     ++OverrideStr;
69060fca6ea1SDimitry Andric     OS = &llvm::nulls();
69070fca6ea1SDimitry Andric   }
69080fca6ea1SDimitry Andric 
69090fca6ea1SDimitry Andric   *OS << "### CCC_OVERRIDE_OPTIONS: " << OverrideStr << "\n";
69100fca6ea1SDimitry Andric 
69110fca6ea1SDimitry Andric   // This does not need to be efficient.
69120fca6ea1SDimitry Andric 
69130fca6ea1SDimitry Andric   const char *S = OverrideStr;
69140fca6ea1SDimitry Andric   while (*S) {
69150fca6ea1SDimitry Andric     const char *End = ::strchr(S, ' ');
69160fca6ea1SDimitry Andric     if (!End)
69170fca6ea1SDimitry Andric       End = S + strlen(S);
69180fca6ea1SDimitry Andric     if (End != S)
69190fca6ea1SDimitry Andric       applyOneOverrideOption(*OS, Args, std::string(S, End), SavedStrings);
69200fca6ea1SDimitry Andric     S = End;
69210fca6ea1SDimitry Andric     if (*S != '\0')
69220fca6ea1SDimitry Andric       ++S;
69230fca6ea1SDimitry Andric   }
69240fca6ea1SDimitry Andric }
6925