17330f729Sjoerg //===--- Driver.cpp - Clang GCC Compatible Driver -------------------------===//
27330f729Sjoerg //
37330f729Sjoerg // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
47330f729Sjoerg // See https://llvm.org/LICENSE.txt for license information.
57330f729Sjoerg // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
67330f729Sjoerg //
77330f729Sjoerg //===----------------------------------------------------------------------===//
87330f729Sjoerg
97330f729Sjoerg #include "clang/Driver/Driver.h"
107330f729Sjoerg #include "InputInfo.h"
117330f729Sjoerg #include "ToolChains/AIX.h"
127330f729Sjoerg #include "ToolChains/AMDGPU.h"
13*e038c9c4Sjoerg #include "ToolChains/AMDGPUOpenMP.h"
147330f729Sjoerg #include "ToolChains/AVR.h"
157330f729Sjoerg #include "ToolChains/Ananas.h"
167330f729Sjoerg #include "ToolChains/BareMetal.h"
177330f729Sjoerg #include "ToolChains/Clang.h"
187330f729Sjoerg #include "ToolChains/CloudABI.h"
197330f729Sjoerg #include "ToolChains/Contiki.h"
207330f729Sjoerg #include "ToolChains/CrossWindows.h"
217330f729Sjoerg #include "ToolChains/Cuda.h"
227330f729Sjoerg #include "ToolChains/Darwin.h"
237330f729Sjoerg #include "ToolChains/DragonFly.h"
247330f729Sjoerg #include "ToolChains/FreeBSD.h"
257330f729Sjoerg #include "ToolChains/Fuchsia.h"
267330f729Sjoerg #include "ToolChains/Gnu.h"
277330f729Sjoerg #include "ToolChains/HIP.h"
287330f729Sjoerg #include "ToolChains/Haiku.h"
297330f729Sjoerg #include "ToolChains/Hexagon.h"
307330f729Sjoerg #include "ToolChains/Hurd.h"
317330f729Sjoerg #include "ToolChains/Lanai.h"
327330f729Sjoerg #include "ToolChains/Linux.h"
337330f729Sjoerg #include "ToolChains/MSP430.h"
347330f729Sjoerg #include "ToolChains/MSVC.h"
357330f729Sjoerg #include "ToolChains/MinGW.h"
367330f729Sjoerg #include "ToolChains/Minix.h"
377330f729Sjoerg #include "ToolChains/MipsLinux.h"
387330f729Sjoerg #include "ToolChains/Myriad.h"
397330f729Sjoerg #include "ToolChains/NaCl.h"
407330f729Sjoerg #include "ToolChains/NetBSD.h"
417330f729Sjoerg #include "ToolChains/OpenBSD.h"
427330f729Sjoerg #include "ToolChains/PPCLinux.h"
43*e038c9c4Sjoerg #include "ToolChains/PS4CPU.h"
447330f729Sjoerg #include "ToolChains/RISCVToolchain.h"
457330f729Sjoerg #include "ToolChains/Solaris.h"
467330f729Sjoerg #include "ToolChains/TCE.h"
47*e038c9c4Sjoerg #include "ToolChains/VEToolchain.h"
487330f729Sjoerg #include "ToolChains/WebAssembly.h"
497330f729Sjoerg #include "ToolChains/XCore.h"
50*e038c9c4Sjoerg #include "ToolChains/ZOS.h"
51*e038c9c4Sjoerg #include "clang/Basic/TargetID.h"
527330f729Sjoerg #include "clang/Basic/Version.h"
537330f729Sjoerg #include "clang/Config/config.h"
547330f729Sjoerg #include "clang/Driver/Action.h"
557330f729Sjoerg #include "clang/Driver/Compilation.h"
567330f729Sjoerg #include "clang/Driver/DriverDiagnostic.h"
577330f729Sjoerg #include "clang/Driver/Job.h"
587330f729Sjoerg #include "clang/Driver/Options.h"
597330f729Sjoerg #include "clang/Driver/SanitizerArgs.h"
607330f729Sjoerg #include "clang/Driver/Tool.h"
617330f729Sjoerg #include "clang/Driver/ToolChain.h"
627330f729Sjoerg #include "llvm/ADT/ArrayRef.h"
637330f729Sjoerg #include "llvm/ADT/STLExtras.h"
647330f729Sjoerg #include "llvm/ADT/SmallSet.h"
657330f729Sjoerg #include "llvm/ADT/StringExtras.h"
667330f729Sjoerg #include "llvm/ADT/StringSet.h"
677330f729Sjoerg #include "llvm/ADT/StringSwitch.h"
687330f729Sjoerg #include "llvm/Config/llvm-config.h"
697330f729Sjoerg #include "llvm/Option/Arg.h"
707330f729Sjoerg #include "llvm/Option/ArgList.h"
717330f729Sjoerg #include "llvm/Option/OptSpecifier.h"
727330f729Sjoerg #include "llvm/Option/OptTable.h"
737330f729Sjoerg #include "llvm/Option/Option.h"
747330f729Sjoerg #include "llvm/Support/CommandLine.h"
757330f729Sjoerg #include "llvm/Support/ErrorHandling.h"
76*e038c9c4Sjoerg #include "llvm/Support/ExitCodes.h"
777330f729Sjoerg #include "llvm/Support/FileSystem.h"
787330f729Sjoerg #include "llvm/Support/FormatVariadic.h"
79*e038c9c4Sjoerg #include "llvm/Support/Host.h"
80*e038c9c4Sjoerg #include "llvm/Support/MD5.h"
817330f729Sjoerg #include "llvm/Support/Path.h"
827330f729Sjoerg #include "llvm/Support/PrettyStackTrace.h"
837330f729Sjoerg #include "llvm/Support/Process.h"
847330f729Sjoerg #include "llvm/Support/Program.h"
857330f729Sjoerg #include "llvm/Support/StringSaver.h"
867330f729Sjoerg #include "llvm/Support/TargetRegistry.h"
877330f729Sjoerg #include "llvm/Support/VirtualFileSystem.h"
887330f729Sjoerg #include "llvm/Support/raw_ostream.h"
897330f729Sjoerg #include <map>
907330f729Sjoerg #include <memory>
917330f729Sjoerg #include <utility>
927330f729Sjoerg #if LLVM_ON_UNIX
937330f729Sjoerg #include <unistd.h> // getpid
947330f729Sjoerg #endif
957330f729Sjoerg
967330f729Sjoerg using namespace clang::driver;
977330f729Sjoerg using namespace clang;
987330f729Sjoerg using namespace llvm::opt;
997330f729Sjoerg
getHIPOffloadTargetTriple()100*e038c9c4Sjoerg static llvm::Triple getHIPOffloadTargetTriple() {
101*e038c9c4Sjoerg static const llvm::Triple T("amdgcn-amd-amdhsa");
102*e038c9c4Sjoerg return T;
103*e038c9c4Sjoerg }
104*e038c9c4Sjoerg
1057330f729Sjoerg // static
GetResourcesPath(StringRef BinaryPath,StringRef CustomResourceDir)1067330f729Sjoerg std::string Driver::GetResourcesPath(StringRef BinaryPath,
1077330f729Sjoerg StringRef CustomResourceDir) {
1087330f729Sjoerg // Since the resource directory is embedded in the module hash, it's important
1097330f729Sjoerg // that all places that need it call this function, so that they get the
1107330f729Sjoerg // exact same string ("a/../b/" and "b/" get different hashes, for example).
1117330f729Sjoerg
1127330f729Sjoerg // Dir is bin/ or lib/, depending on where BinaryPath is.
113*e038c9c4Sjoerg std::string Dir = std::string(llvm::sys::path::parent_path(BinaryPath));
1147330f729Sjoerg
1157330f729Sjoerg SmallString<128> P(Dir);
1167330f729Sjoerg if (CustomResourceDir != "") {
1177330f729Sjoerg llvm::sys::path::append(P, CustomResourceDir);
1187330f729Sjoerg } else {
1197330f729Sjoerg // On Windows, libclang.dll is in bin/.
1207330f729Sjoerg // On non-Windows, libclang.so/.dylib is in lib/.
1217330f729Sjoerg // With a static-library build of libclang, LibClangPath will contain the
1227330f729Sjoerg // path of the embedding binary, which for LLVM binaries will be in bin/.
1237330f729Sjoerg // ../lib gets us to lib/ in both cases.
1247330f729Sjoerg P = llvm::sys::path::parent_path(Dir);
1257330f729Sjoerg llvm::sys::path::append(P, Twine("lib") + CLANG_LIBDIR_SUFFIX, "clang",
1267330f729Sjoerg CLANG_VERSION_STRING);
1277330f729Sjoerg }
1287330f729Sjoerg
129*e038c9c4Sjoerg return std::string(P.str());
1307330f729Sjoerg }
1317330f729Sjoerg
Driver(StringRef ClangExecutable,StringRef TargetTriple,DiagnosticsEngine & Diags,std::string Title,IntrusiveRefCntPtr<llvm::vfs::FileSystem> VFS)1327330f729Sjoerg Driver::Driver(StringRef ClangExecutable, StringRef TargetTriple,
133*e038c9c4Sjoerg DiagnosticsEngine &Diags, std::string Title,
1347330f729Sjoerg IntrusiveRefCntPtr<llvm::vfs::FileSystem> VFS)
1357330f729Sjoerg : Diags(Diags), VFS(std::move(VFS)), Mode(GCCMode),
1367330f729Sjoerg SaveTemps(SaveTempsNone), BitcodeEmbed(EmbedNone), LTOMode(LTOK_None),
1377330f729Sjoerg ClangExecutable(ClangExecutable), SysRoot(DEFAULT_SYSROOT),
138*e038c9c4Sjoerg DriverTitle(Title), CCPrintStatReportFilename(), CCPrintOptionsFilename(),
139*e038c9c4Sjoerg CCPrintHeadersFilename(), CCLogDiagnosticsFilename(),
1407330f729Sjoerg CCCPrintBindings(false), CCPrintOptions(false), CCPrintHeaders(false),
1417330f729Sjoerg CCLogDiagnostics(false), CCGenDiagnostics(false),
142*e038c9c4Sjoerg CCPrintProcessStats(false), TargetTriple(TargetTriple),
143*e038c9c4Sjoerg CCCGenericGCCName(""), Saver(Alloc), CheckInputsExist(true),
144*e038c9c4Sjoerg GenReproducer(false), SuppressMissingInputWarning(false) {
1457330f729Sjoerg // Provide a sane fallback if no VFS is specified.
1467330f729Sjoerg if (!this->VFS)
1477330f729Sjoerg this->VFS = llvm::vfs::getRealFileSystem();
1487330f729Sjoerg
149*e038c9c4Sjoerg Name = std::string(llvm::sys::path::filename(ClangExecutable));
150*e038c9c4Sjoerg Dir = std::string(llvm::sys::path::parent_path(ClangExecutable));
1517330f729Sjoerg InstalledDir = Dir; // Provide a sensible default installed dir.
1527330f729Sjoerg
153*e038c9c4Sjoerg if ((!SysRoot.empty()) && llvm::sys::path::is_relative(SysRoot)) {
154*e038c9c4Sjoerg // Prepend InstalledDir if SysRoot is relative
155*e038c9c4Sjoerg SmallString<128> P(InstalledDir);
156*e038c9c4Sjoerg llvm::sys::path::append(P, SysRoot);
157*e038c9c4Sjoerg SysRoot = std::string(P);
158*e038c9c4Sjoerg }
159*e038c9c4Sjoerg
1607330f729Sjoerg #if defined(CLANG_CONFIG_FILE_SYSTEM_DIR)
1617330f729Sjoerg SystemConfigDir = CLANG_CONFIG_FILE_SYSTEM_DIR;
1627330f729Sjoerg #endif
1637330f729Sjoerg #if defined(CLANG_CONFIG_FILE_USER_DIR)
1647330f729Sjoerg UserConfigDir = CLANG_CONFIG_FILE_USER_DIR;
1657330f729Sjoerg #endif
1667330f729Sjoerg
1677330f729Sjoerg // Compute the path to the resource directory.
1687330f729Sjoerg ResourceDir = GetResourcesPath(ClangExecutable, CLANG_RESOURCE_DIR);
1697330f729Sjoerg }
1707330f729Sjoerg
ParseDriverMode(StringRef ProgramName,ArrayRef<const char * > Args)1717330f729Sjoerg void Driver::ParseDriverMode(StringRef ProgramName,
1727330f729Sjoerg ArrayRef<const char *> Args) {
1737330f729Sjoerg if (ClangNameParts.isEmpty())
1747330f729Sjoerg ClangNameParts = ToolChain::getTargetAndModeFromProgramName(ProgramName);
1757330f729Sjoerg setDriverModeFromOption(ClangNameParts.DriverMode);
1767330f729Sjoerg
1777330f729Sjoerg for (const char *ArgPtr : Args) {
1787330f729Sjoerg // Ignore nullptrs, they are the response file's EOL markers.
1797330f729Sjoerg if (ArgPtr == nullptr)
1807330f729Sjoerg continue;
1817330f729Sjoerg const StringRef Arg = ArgPtr;
1827330f729Sjoerg setDriverModeFromOption(Arg);
1837330f729Sjoerg }
1847330f729Sjoerg }
1857330f729Sjoerg
setDriverModeFromOption(StringRef Opt)1867330f729Sjoerg void Driver::setDriverModeFromOption(StringRef Opt) {
1877330f729Sjoerg const std::string OptName =
1887330f729Sjoerg getOpts().getOption(options::OPT_driver_mode).getPrefixedName();
1897330f729Sjoerg if (!Opt.startswith(OptName))
1907330f729Sjoerg return;
1917330f729Sjoerg StringRef Value = Opt.drop_front(OptName.size());
1927330f729Sjoerg
1937330f729Sjoerg if (auto M = llvm::StringSwitch<llvm::Optional<DriverMode>>(Value)
1947330f729Sjoerg .Case("gcc", GCCMode)
1957330f729Sjoerg .Case("g++", GXXMode)
1967330f729Sjoerg .Case("cpp", CPPMode)
1977330f729Sjoerg .Case("cl", CLMode)
198*e038c9c4Sjoerg .Case("flang", FlangMode)
1997330f729Sjoerg .Default(None))
2007330f729Sjoerg Mode = *M;
2017330f729Sjoerg else
2027330f729Sjoerg Diag(diag::err_drv_unsupported_option_argument) << OptName << Value;
2037330f729Sjoerg }
2047330f729Sjoerg
ParseArgStrings(ArrayRef<const char * > ArgStrings,bool IsClCompatMode,bool & ContainsError)2057330f729Sjoerg InputArgList Driver::ParseArgStrings(ArrayRef<const char *> ArgStrings,
2067330f729Sjoerg bool IsClCompatMode,
2077330f729Sjoerg bool &ContainsError) {
2087330f729Sjoerg llvm::PrettyStackTraceString CrashInfo("Command line argument parsing");
2097330f729Sjoerg ContainsError = false;
2107330f729Sjoerg
2117330f729Sjoerg unsigned IncludedFlagsBitmask;
2127330f729Sjoerg unsigned ExcludedFlagsBitmask;
2137330f729Sjoerg std::tie(IncludedFlagsBitmask, ExcludedFlagsBitmask) =
2147330f729Sjoerg getIncludeExcludeOptionFlagMasks(IsClCompatMode);
2157330f729Sjoerg
216*e038c9c4Sjoerg // Make sure that Flang-only options don't pollute the Clang output
217*e038c9c4Sjoerg // TODO: Make sure that Clang-only options don't pollute Flang output
218*e038c9c4Sjoerg if (!IsFlangMode())
219*e038c9c4Sjoerg ExcludedFlagsBitmask |= options::FlangOnlyOption;
220*e038c9c4Sjoerg
2217330f729Sjoerg unsigned MissingArgIndex, MissingArgCount;
2227330f729Sjoerg InputArgList Args =
2237330f729Sjoerg getOpts().ParseArgs(ArgStrings, MissingArgIndex, MissingArgCount,
2247330f729Sjoerg IncludedFlagsBitmask, ExcludedFlagsBitmask);
2257330f729Sjoerg
2267330f729Sjoerg // Check for missing argument error.
2277330f729Sjoerg if (MissingArgCount) {
2287330f729Sjoerg Diag(diag::err_drv_missing_argument)
2297330f729Sjoerg << Args.getArgString(MissingArgIndex) << MissingArgCount;
2307330f729Sjoerg ContainsError |=
2317330f729Sjoerg Diags.getDiagnosticLevel(diag::err_drv_missing_argument,
2327330f729Sjoerg SourceLocation()) > DiagnosticsEngine::Warning;
2337330f729Sjoerg }
2347330f729Sjoerg
2357330f729Sjoerg // Check for unsupported options.
2367330f729Sjoerg for (const Arg *A : Args) {
2377330f729Sjoerg if (A->getOption().hasFlag(options::Unsupported)) {
2387330f729Sjoerg unsigned DiagID;
2397330f729Sjoerg auto ArgString = A->getAsString(Args);
2407330f729Sjoerg std::string Nearest;
2417330f729Sjoerg if (getOpts().findNearest(
2427330f729Sjoerg ArgString, Nearest, IncludedFlagsBitmask,
2437330f729Sjoerg ExcludedFlagsBitmask | options::Unsupported) > 1) {
2447330f729Sjoerg DiagID = diag::err_drv_unsupported_opt;
2457330f729Sjoerg Diag(DiagID) << ArgString;
2467330f729Sjoerg } else {
2477330f729Sjoerg DiagID = diag::err_drv_unsupported_opt_with_suggestion;
2487330f729Sjoerg Diag(DiagID) << ArgString << Nearest;
2497330f729Sjoerg }
2507330f729Sjoerg ContainsError |= Diags.getDiagnosticLevel(DiagID, SourceLocation()) >
2517330f729Sjoerg DiagnosticsEngine::Warning;
2527330f729Sjoerg continue;
2537330f729Sjoerg }
2547330f729Sjoerg
2557330f729Sjoerg // Warn about -mcpu= without an argument.
2567330f729Sjoerg if (A->getOption().matches(options::OPT_mcpu_EQ) && A->containsValue("")) {
2577330f729Sjoerg Diag(diag::warn_drv_empty_joined_argument) << A->getAsString(Args);
2587330f729Sjoerg ContainsError |= Diags.getDiagnosticLevel(
2597330f729Sjoerg diag::warn_drv_empty_joined_argument,
2607330f729Sjoerg SourceLocation()) > DiagnosticsEngine::Warning;
2617330f729Sjoerg }
2627330f729Sjoerg }
2637330f729Sjoerg
2647330f729Sjoerg for (const Arg *A : Args.filtered(options::OPT_UNKNOWN)) {
2657330f729Sjoerg unsigned DiagID;
2667330f729Sjoerg auto ArgString = A->getAsString(Args);
2677330f729Sjoerg std::string Nearest;
2687330f729Sjoerg if (getOpts().findNearest(
2697330f729Sjoerg ArgString, Nearest, IncludedFlagsBitmask, ExcludedFlagsBitmask) > 1) {
2707330f729Sjoerg DiagID = IsCLMode() ? diag::warn_drv_unknown_argument_clang_cl
2717330f729Sjoerg : diag::err_drv_unknown_argument;
2727330f729Sjoerg Diags.Report(DiagID) << ArgString;
2737330f729Sjoerg } else {
2747330f729Sjoerg DiagID = IsCLMode()
2757330f729Sjoerg ? diag::warn_drv_unknown_argument_clang_cl_with_suggestion
2767330f729Sjoerg : diag::err_drv_unknown_argument_with_suggestion;
2777330f729Sjoerg Diags.Report(DiagID) << ArgString << Nearest;
2787330f729Sjoerg }
2797330f729Sjoerg ContainsError |= Diags.getDiagnosticLevel(DiagID, SourceLocation()) >
2807330f729Sjoerg DiagnosticsEngine::Warning;
2817330f729Sjoerg }
2827330f729Sjoerg
2837330f729Sjoerg return Args;
2847330f729Sjoerg }
2857330f729Sjoerg
2867330f729Sjoerg // Determine which compilation mode we are in. We look for options which
2877330f729Sjoerg // affect the phase, starting with the earliest phases, and record which
2887330f729Sjoerg // option we used to determine the final phase.
getFinalPhase(const DerivedArgList & DAL,Arg ** FinalPhaseArg) const2897330f729Sjoerg phases::ID Driver::getFinalPhase(const DerivedArgList &DAL,
2907330f729Sjoerg Arg **FinalPhaseArg) const {
2917330f729Sjoerg Arg *PhaseArg = nullptr;
2927330f729Sjoerg phases::ID FinalPhase;
2937330f729Sjoerg
2947330f729Sjoerg // -{E,EP,P,M,MM} only run the preprocessor.
2957330f729Sjoerg if (CCCIsCPP() || (PhaseArg = DAL.getLastArg(options::OPT_E)) ||
2967330f729Sjoerg (PhaseArg = DAL.getLastArg(options::OPT__SLASH_EP)) ||
2977330f729Sjoerg (PhaseArg = DAL.getLastArg(options::OPT_M, options::OPT_MM)) ||
2987330f729Sjoerg (PhaseArg = DAL.getLastArg(options::OPT__SLASH_P))) {
2997330f729Sjoerg FinalPhase = phases::Preprocess;
3007330f729Sjoerg
3017330f729Sjoerg // --precompile only runs up to precompilation.
3027330f729Sjoerg } else if ((PhaseArg = DAL.getLastArg(options::OPT__precompile))) {
3037330f729Sjoerg FinalPhase = phases::Precompile;
3047330f729Sjoerg
3057330f729Sjoerg // -{fsyntax-only,-analyze,emit-ast} only run up to the compiler.
3067330f729Sjoerg } else if ((PhaseArg = DAL.getLastArg(options::OPT_fsyntax_only)) ||
3077330f729Sjoerg (PhaseArg = DAL.getLastArg(options::OPT_print_supported_cpus)) ||
3087330f729Sjoerg (PhaseArg = DAL.getLastArg(options::OPT_module_file_info)) ||
3097330f729Sjoerg (PhaseArg = DAL.getLastArg(options::OPT_verify_pch)) ||
3107330f729Sjoerg (PhaseArg = DAL.getLastArg(options::OPT_rewrite_objc)) ||
3117330f729Sjoerg (PhaseArg = DAL.getLastArg(options::OPT_rewrite_legacy_objc)) ||
3127330f729Sjoerg (PhaseArg = DAL.getLastArg(options::OPT__migrate)) ||
3137330f729Sjoerg (PhaseArg = DAL.getLastArg(options::OPT__analyze)) ||
3147330f729Sjoerg (PhaseArg = DAL.getLastArg(options::OPT_emit_ast))) {
3157330f729Sjoerg FinalPhase = phases::Compile;
3167330f729Sjoerg
3177330f729Sjoerg // -S only runs up to the backend.
3187330f729Sjoerg } else if ((PhaseArg = DAL.getLastArg(options::OPT_S))) {
3197330f729Sjoerg FinalPhase = phases::Backend;
3207330f729Sjoerg
3217330f729Sjoerg // -c compilation only runs up to the assembler.
3227330f729Sjoerg } else if ((PhaseArg = DAL.getLastArg(options::OPT_c))) {
3237330f729Sjoerg FinalPhase = phases::Assemble;
3247330f729Sjoerg
3257330f729Sjoerg // Otherwise do everything.
3267330f729Sjoerg } else
3277330f729Sjoerg FinalPhase = phases::Link;
3287330f729Sjoerg
3297330f729Sjoerg if (FinalPhaseArg)
3307330f729Sjoerg *FinalPhaseArg = PhaseArg;
3317330f729Sjoerg
3327330f729Sjoerg return FinalPhase;
3337330f729Sjoerg }
3347330f729Sjoerg
MakeInputArg(DerivedArgList & Args,const OptTable & Opts,StringRef Value,bool Claim=true)3357330f729Sjoerg static Arg *MakeInputArg(DerivedArgList &Args, const OptTable &Opts,
3367330f729Sjoerg StringRef Value, bool Claim = true) {
3377330f729Sjoerg Arg *A = new Arg(Opts.getOption(options::OPT_INPUT), Value,
3387330f729Sjoerg Args.getBaseArgs().MakeIndex(Value), Value.data());
3397330f729Sjoerg Args.AddSynthesizedArg(A);
3407330f729Sjoerg if (Claim)
3417330f729Sjoerg A->claim();
3427330f729Sjoerg return A;
3437330f729Sjoerg }
3447330f729Sjoerg
TranslateInputArgs(const InputArgList & Args) const3457330f729Sjoerg DerivedArgList *Driver::TranslateInputArgs(const InputArgList &Args) const {
3467330f729Sjoerg const llvm::opt::OptTable &Opts = getOpts();
3477330f729Sjoerg DerivedArgList *DAL = new DerivedArgList(Args);
3487330f729Sjoerg
3497330f729Sjoerg bool HasNostdlib = Args.hasArg(options::OPT_nostdlib);
3507330f729Sjoerg bool HasNostdlibxx = Args.hasArg(options::OPT_nostdlibxx);
3517330f729Sjoerg bool HasNodefaultlib = Args.hasArg(options::OPT_nodefaultlibs);
3527330f729Sjoerg for (Arg *A : Args) {
3537330f729Sjoerg // Unfortunately, we have to parse some forwarding options (-Xassembler,
3547330f729Sjoerg // -Xlinker, -Xpreprocessor) because we either integrate their functionality
3557330f729Sjoerg // (assembler and preprocessor), or bypass a previous driver ('collect2').
3567330f729Sjoerg
3577330f729Sjoerg // Rewrite linker options, to replace --no-demangle with a custom internal
3587330f729Sjoerg // option.
3597330f729Sjoerg if ((A->getOption().matches(options::OPT_Wl_COMMA) ||
3607330f729Sjoerg A->getOption().matches(options::OPT_Xlinker)) &&
3617330f729Sjoerg A->containsValue("--no-demangle")) {
3627330f729Sjoerg // Add the rewritten no-demangle argument.
3637330f729Sjoerg DAL->AddFlagArg(A, Opts.getOption(options::OPT_Z_Xlinker__no_demangle));
3647330f729Sjoerg
3657330f729Sjoerg // Add the remaining values as Xlinker arguments.
3667330f729Sjoerg for (StringRef Val : A->getValues())
3677330f729Sjoerg if (Val != "--no-demangle")
3687330f729Sjoerg DAL->AddSeparateArg(A, Opts.getOption(options::OPT_Xlinker), Val);
3697330f729Sjoerg
3707330f729Sjoerg continue;
3717330f729Sjoerg }
3727330f729Sjoerg
3737330f729Sjoerg // Rewrite preprocessor options, to replace -Wp,-MD,FOO which is used by
3747330f729Sjoerg // some build systems. We don't try to be complete here because we don't
3757330f729Sjoerg // care to encourage this usage model.
3767330f729Sjoerg if (A->getOption().matches(options::OPT_Wp_COMMA) &&
3777330f729Sjoerg (A->getValue(0) == StringRef("-MD") ||
3787330f729Sjoerg A->getValue(0) == StringRef("-MMD"))) {
3797330f729Sjoerg // Rewrite to -MD/-MMD along with -MF.
3807330f729Sjoerg if (A->getValue(0) == StringRef("-MD"))
3817330f729Sjoerg DAL->AddFlagArg(A, Opts.getOption(options::OPT_MD));
3827330f729Sjoerg else
3837330f729Sjoerg DAL->AddFlagArg(A, Opts.getOption(options::OPT_MMD));
3847330f729Sjoerg if (A->getNumValues() == 2)
3857330f729Sjoerg DAL->AddSeparateArg(A, Opts.getOption(options::OPT_MF), A->getValue(1));
3867330f729Sjoerg continue;
3877330f729Sjoerg }
3887330f729Sjoerg
3897330f729Sjoerg // Rewrite reserved library names.
3907330f729Sjoerg if (A->getOption().matches(options::OPT_l)) {
3917330f729Sjoerg StringRef Value = A->getValue();
3927330f729Sjoerg
3937330f729Sjoerg // Rewrite unless -nostdlib is present.
3947330f729Sjoerg if (!HasNostdlib && !HasNodefaultlib && !HasNostdlibxx &&
3957330f729Sjoerg Value == "stdc++") {
3967330f729Sjoerg DAL->AddFlagArg(A, Opts.getOption(options::OPT_Z_reserved_lib_stdcxx));
3977330f729Sjoerg continue;
3987330f729Sjoerg }
3997330f729Sjoerg
4007330f729Sjoerg // Rewrite unconditionally.
4017330f729Sjoerg if (Value == "cc_kext") {
4027330f729Sjoerg DAL->AddFlagArg(A, Opts.getOption(options::OPT_Z_reserved_lib_cckext));
4037330f729Sjoerg continue;
4047330f729Sjoerg }
4057330f729Sjoerg }
4067330f729Sjoerg
4077330f729Sjoerg // Pick up inputs via the -- option.
4087330f729Sjoerg if (A->getOption().matches(options::OPT__DASH_DASH)) {
4097330f729Sjoerg A->claim();
4107330f729Sjoerg for (StringRef Val : A->getValues())
4117330f729Sjoerg DAL->append(MakeInputArg(*DAL, Opts, Val, false));
4127330f729Sjoerg continue;
4137330f729Sjoerg }
4147330f729Sjoerg
4157330f729Sjoerg DAL->append(A);
4167330f729Sjoerg }
4177330f729Sjoerg
4187330f729Sjoerg // Enforce -static if -miamcu is present.
4197330f729Sjoerg if (Args.hasFlag(options::OPT_miamcu, options::OPT_mno_iamcu, false))
4207330f729Sjoerg DAL->AddFlagArg(0, Opts.getOption(options::OPT_static));
4217330f729Sjoerg
4227330f729Sjoerg // Add a default value of -mlinker-version=, if one was given and the user
4237330f729Sjoerg // didn't specify one.
4247330f729Sjoerg #if defined(HOST_LINK_VERSION)
4257330f729Sjoerg if (!Args.hasArg(options::OPT_mlinker_version_EQ) &&
4267330f729Sjoerg strlen(HOST_LINK_VERSION) > 0) {
4277330f729Sjoerg DAL->AddJoinedArg(0, Opts.getOption(options::OPT_mlinker_version_EQ),
4287330f729Sjoerg HOST_LINK_VERSION);
4297330f729Sjoerg DAL->getLastArg(options::OPT_mlinker_version_EQ)->claim();
4307330f729Sjoerg }
4317330f729Sjoerg #endif
4327330f729Sjoerg
4337330f729Sjoerg return DAL;
4347330f729Sjoerg }
4357330f729Sjoerg
4367330f729Sjoerg /// Compute target triple from args.
4377330f729Sjoerg ///
4387330f729Sjoerg /// This routine provides the logic to compute a target triple from various
4397330f729Sjoerg /// args passed to the driver and the default triple string.
computeTargetTriple(const Driver & D,StringRef TargetTriple,const ArgList & Args,StringRef DarwinArchName="")4407330f729Sjoerg static llvm::Triple computeTargetTriple(const Driver &D,
4417330f729Sjoerg StringRef TargetTriple,
4427330f729Sjoerg const ArgList &Args,
4437330f729Sjoerg StringRef DarwinArchName = "") {
4447330f729Sjoerg // FIXME: Already done in Compilation *Driver::BuildCompilation
4457330f729Sjoerg if (const Arg *A = Args.getLastArg(options::OPT_target))
4467330f729Sjoerg TargetTriple = A->getValue();
4477330f729Sjoerg
4487330f729Sjoerg llvm::Triple Target(llvm::Triple::normalize(TargetTriple));
4497330f729Sjoerg
4507330f729Sjoerg // GNU/Hurd's triples should have been -hurd-gnu*, but were historically made
4517330f729Sjoerg // -gnu* only, and we can not change this, so we have to detect that case as
4527330f729Sjoerg // being the Hurd OS.
4537330f729Sjoerg if (TargetTriple.find("-unknown-gnu") != StringRef::npos ||
4547330f729Sjoerg TargetTriple.find("-pc-gnu") != StringRef::npos)
4557330f729Sjoerg Target.setOSName("hurd");
4567330f729Sjoerg
4577330f729Sjoerg // Handle Apple-specific options available here.
4587330f729Sjoerg if (Target.isOSBinFormatMachO()) {
4597330f729Sjoerg // If an explicit Darwin arch name is given, that trumps all.
4607330f729Sjoerg if (!DarwinArchName.empty()) {
4617330f729Sjoerg tools::darwin::setTripleTypeForMachOArchName(Target, DarwinArchName);
4627330f729Sjoerg return Target;
4637330f729Sjoerg }
4647330f729Sjoerg
4657330f729Sjoerg // Handle the Darwin '-arch' flag.
4667330f729Sjoerg if (Arg *A = Args.getLastArg(options::OPT_arch)) {
4677330f729Sjoerg StringRef ArchName = A->getValue();
4687330f729Sjoerg tools::darwin::setTripleTypeForMachOArchName(Target, ArchName);
4697330f729Sjoerg }
4707330f729Sjoerg }
4717330f729Sjoerg
4727330f729Sjoerg // Handle pseudo-target flags '-mlittle-endian'/'-EL' and
4737330f729Sjoerg // '-mbig-endian'/'-EB'.
4747330f729Sjoerg if (Arg *A = Args.getLastArg(options::OPT_mlittle_endian,
4757330f729Sjoerg options::OPT_mbig_endian)) {
4767330f729Sjoerg if (A->getOption().matches(options::OPT_mlittle_endian)) {
4777330f729Sjoerg llvm::Triple LE = Target.getLittleEndianArchVariant();
4787330f729Sjoerg if (LE.getArch() != llvm::Triple::UnknownArch)
4797330f729Sjoerg Target = std::move(LE);
4807330f729Sjoerg } else {
4817330f729Sjoerg llvm::Triple BE = Target.getBigEndianArchVariant();
4827330f729Sjoerg if (BE.getArch() != llvm::Triple::UnknownArch)
4837330f729Sjoerg Target = std::move(BE);
4847330f729Sjoerg }
4857330f729Sjoerg }
4867330f729Sjoerg
4877330f729Sjoerg // Skip further flag support on OSes which don't support '-m32' or '-m64'.
4887330f729Sjoerg if (Target.getArch() == llvm::Triple::tce ||
4897330f729Sjoerg Target.getOS() == llvm::Triple::Minix)
4907330f729Sjoerg return Target;
4917330f729Sjoerg
492*e038c9c4Sjoerg // On AIX, the env OBJECT_MODE may affect the resulting arch variant.
493*e038c9c4Sjoerg if (Target.isOSAIX()) {
494*e038c9c4Sjoerg if (Optional<std::string> ObjectModeValue =
495*e038c9c4Sjoerg llvm::sys::Process::GetEnv("OBJECT_MODE")) {
496*e038c9c4Sjoerg StringRef ObjectMode = *ObjectModeValue;
497*e038c9c4Sjoerg llvm::Triple::ArchType AT = llvm::Triple::UnknownArch;
498*e038c9c4Sjoerg
499*e038c9c4Sjoerg if (ObjectMode.equals("64")) {
500*e038c9c4Sjoerg AT = Target.get64BitArchVariant().getArch();
501*e038c9c4Sjoerg } else if (ObjectMode.equals("32")) {
502*e038c9c4Sjoerg AT = Target.get32BitArchVariant().getArch();
503*e038c9c4Sjoerg } else {
504*e038c9c4Sjoerg D.Diag(diag::err_drv_invalid_object_mode) << ObjectMode;
505*e038c9c4Sjoerg }
506*e038c9c4Sjoerg
507*e038c9c4Sjoerg if (AT != llvm::Triple::UnknownArch && AT != Target.getArch())
508*e038c9c4Sjoerg Target.setArch(AT);
509*e038c9c4Sjoerg }
510*e038c9c4Sjoerg }
511*e038c9c4Sjoerg
5127330f729Sjoerg // Handle pseudo-target flags '-m64', '-mx32', '-m32' and '-m16'.
5137330f729Sjoerg Arg *A = Args.getLastArg(options::OPT_m64, options::OPT_mx32,
5147330f729Sjoerg options::OPT_m32, options::OPT_m16);
5157330f729Sjoerg if (A) {
5167330f729Sjoerg llvm::Triple::ArchType AT = llvm::Triple::UnknownArch;
5177330f729Sjoerg
5187330f729Sjoerg if (A->getOption().matches(options::OPT_m64)) {
5197330f729Sjoerg AT = Target.get64BitArchVariant().getArch();
5207330f729Sjoerg if (Target.getEnvironment() == llvm::Triple::GNUX32)
5217330f729Sjoerg Target.setEnvironment(llvm::Triple::GNU);
5227330f729Sjoerg } else if (A->getOption().matches(options::OPT_mx32) &&
5237330f729Sjoerg Target.get64BitArchVariant().getArch() == llvm::Triple::x86_64) {
5247330f729Sjoerg AT = llvm::Triple::x86_64;
5257330f729Sjoerg Target.setEnvironment(llvm::Triple::GNUX32);
5267330f729Sjoerg } else if (A->getOption().matches(options::OPT_m32)) {
5277330f729Sjoerg AT = Target.get32BitArchVariant().getArch();
5287330f729Sjoerg if (Target.getEnvironment() == llvm::Triple::GNUX32)
5297330f729Sjoerg Target.setEnvironment(llvm::Triple::GNU);
5307330f729Sjoerg } else if (A->getOption().matches(options::OPT_m16) &&
5317330f729Sjoerg Target.get32BitArchVariant().getArch() == llvm::Triple::x86) {
5327330f729Sjoerg AT = llvm::Triple::x86;
5337330f729Sjoerg Target.setEnvironment(llvm::Triple::CODE16);
5347330f729Sjoerg }
5357330f729Sjoerg
5367330f729Sjoerg if (AT != llvm::Triple::UnknownArch && AT != Target.getArch())
5377330f729Sjoerg Target.setArch(AT);
5387330f729Sjoerg }
5397330f729Sjoerg
5407330f729Sjoerg // Handle -miamcu flag.
5417330f729Sjoerg if (Args.hasFlag(options::OPT_miamcu, options::OPT_mno_iamcu, false)) {
5427330f729Sjoerg if (Target.get32BitArchVariant().getArch() != llvm::Triple::x86)
5437330f729Sjoerg D.Diag(diag::err_drv_unsupported_opt_for_target) << "-miamcu"
5447330f729Sjoerg << Target.str();
5457330f729Sjoerg
5467330f729Sjoerg if (A && !A->getOption().matches(options::OPT_m32))
5477330f729Sjoerg D.Diag(diag::err_drv_argument_not_allowed_with)
5487330f729Sjoerg << "-miamcu" << A->getBaseArg().getAsString(Args);
5497330f729Sjoerg
5507330f729Sjoerg Target.setArch(llvm::Triple::x86);
5517330f729Sjoerg Target.setArchName("i586");
5527330f729Sjoerg Target.setEnvironment(llvm::Triple::UnknownEnvironment);
5537330f729Sjoerg Target.setEnvironmentName("");
5547330f729Sjoerg Target.setOS(llvm::Triple::ELFIAMCU);
5557330f729Sjoerg Target.setVendor(llvm::Triple::UnknownVendor);
5567330f729Sjoerg Target.setVendorName("intel");
5577330f729Sjoerg }
5587330f729Sjoerg
5597330f729Sjoerg // If target is MIPS adjust the target triple
5607330f729Sjoerg // accordingly to provided ABI name.
5617330f729Sjoerg A = Args.getLastArg(options::OPT_mabi_EQ);
5627330f729Sjoerg if (A && Target.isMIPS()) {
5637330f729Sjoerg StringRef ABIName = A->getValue();
5647330f729Sjoerg if (ABIName == "32") {
5657330f729Sjoerg Target = Target.get32BitArchVariant();
5667330f729Sjoerg if (Target.getEnvironment() == llvm::Triple::GNUABI64 ||
5677330f729Sjoerg Target.getEnvironment() == llvm::Triple::GNUABIN32)
5687330f729Sjoerg Target.setEnvironment(llvm::Triple::GNU);
5697330f729Sjoerg } else if (ABIName == "n32") {
5707330f729Sjoerg Target = Target.get64BitArchVariant();
5717330f729Sjoerg if (Target.getEnvironment() == llvm::Triple::GNU ||
5727330f729Sjoerg Target.getEnvironment() == llvm::Triple::GNUABI64)
5737330f729Sjoerg Target.setEnvironment(llvm::Triple::GNUABIN32);
5747330f729Sjoerg } else if (ABIName == "64") {
5757330f729Sjoerg Target = Target.get64BitArchVariant();
5767330f729Sjoerg if (Target.getEnvironment() == llvm::Triple::GNU ||
5777330f729Sjoerg Target.getEnvironment() == llvm::Triple::GNUABIN32)
5787330f729Sjoerg Target.setEnvironment(llvm::Triple::GNUABI64);
5797330f729Sjoerg }
5807330f729Sjoerg }
5817330f729Sjoerg
582*e038c9c4Sjoerg // If target is RISC-V adjust the target triple according to
583*e038c9c4Sjoerg // provided architecture name
584*e038c9c4Sjoerg A = Args.getLastArg(options::OPT_march_EQ);
585*e038c9c4Sjoerg if (A && Target.isRISCV()) {
586*e038c9c4Sjoerg StringRef ArchName = A->getValue();
587*e038c9c4Sjoerg if (ArchName.startswith_lower("rv32"))
588*e038c9c4Sjoerg Target.setArch(llvm::Triple::riscv32);
589*e038c9c4Sjoerg else if (ArchName.startswith_lower("rv64"))
590*e038c9c4Sjoerg Target.setArch(llvm::Triple::riscv64);
591*e038c9c4Sjoerg }
592*e038c9c4Sjoerg
5937330f729Sjoerg return Target;
5947330f729Sjoerg }
5957330f729Sjoerg
5967330f729Sjoerg // Parse the LTO options and record the type of LTO compilation
597*e038c9c4Sjoerg // based on which -f(no-)?lto(=.*)? or -f(no-)?offload-lto(=.*)?
598*e038c9c4Sjoerg // option occurs last.
599*e038c9c4Sjoerg static llvm::Optional<driver::LTOKind>
parseLTOMode(Driver & D,const llvm::opt::ArgList & Args,OptSpecifier OptPos,OptSpecifier OptNeg,OptSpecifier OptEq,bool IsOffload)600*e038c9c4Sjoerg parseLTOMode(Driver &D, const llvm::opt::ArgList &Args, OptSpecifier OptPos,
601*e038c9c4Sjoerg OptSpecifier OptNeg, OptSpecifier OptEq, bool IsOffload) {
602*e038c9c4Sjoerg driver::LTOKind LTOMode = LTOK_None;
603*e038c9c4Sjoerg // Non-offload LTO allows -flto=auto and -flto=jobserver. Offload LTO does
604*e038c9c4Sjoerg // not support those options.
605*e038c9c4Sjoerg if (!Args.hasFlag(OptPos, OptEq, OptNeg, false) &&
606*e038c9c4Sjoerg (IsOffload ||
607*e038c9c4Sjoerg (!Args.hasFlag(options::OPT_flto_EQ_auto, options::OPT_fno_lto, false) &&
608*e038c9c4Sjoerg !Args.hasFlag(options::OPT_flto_EQ_jobserver, options::OPT_fno_lto,
609*e038c9c4Sjoerg false))))
610*e038c9c4Sjoerg return None;
6117330f729Sjoerg
6127330f729Sjoerg StringRef LTOName("full");
6137330f729Sjoerg
614*e038c9c4Sjoerg const Arg *A = Args.getLastArg(OptEq);
6157330f729Sjoerg if (A)
6167330f729Sjoerg LTOName = A->getValue();
6177330f729Sjoerg
6187330f729Sjoerg LTOMode = llvm::StringSwitch<LTOKind>(LTOName)
6197330f729Sjoerg .Case("full", LTOK_Full)
6207330f729Sjoerg .Case("thin", LTOK_Thin)
6217330f729Sjoerg .Default(LTOK_Unknown);
6227330f729Sjoerg
6237330f729Sjoerg if (LTOMode == LTOK_Unknown) {
6247330f729Sjoerg assert(A);
625*e038c9c4Sjoerg D.Diag(diag::err_drv_unsupported_option_argument)
626*e038c9c4Sjoerg << A->getOption().getName() << A->getValue();
627*e038c9c4Sjoerg return None;
6287330f729Sjoerg }
629*e038c9c4Sjoerg return LTOMode;
630*e038c9c4Sjoerg }
631*e038c9c4Sjoerg
632*e038c9c4Sjoerg // Parse the LTO options.
setLTOMode(const llvm::opt::ArgList & Args)633*e038c9c4Sjoerg void Driver::setLTOMode(const llvm::opt::ArgList &Args) {
634*e038c9c4Sjoerg LTOMode = LTOK_None;
635*e038c9c4Sjoerg if (auto M = parseLTOMode(*this, Args, options::OPT_flto,
636*e038c9c4Sjoerg options::OPT_fno_lto, options::OPT_flto_EQ,
637*e038c9c4Sjoerg /*IsOffload=*/false))
638*e038c9c4Sjoerg LTOMode = M.getValue();
639*e038c9c4Sjoerg
640*e038c9c4Sjoerg OffloadLTOMode = LTOK_None;
641*e038c9c4Sjoerg if (auto M = parseLTOMode(*this, Args, options::OPT_foffload_lto,
642*e038c9c4Sjoerg options::OPT_fno_offload_lto,
643*e038c9c4Sjoerg options::OPT_foffload_lto_EQ,
644*e038c9c4Sjoerg /*IsOffload=*/true))
645*e038c9c4Sjoerg OffloadLTOMode = M.getValue();
6467330f729Sjoerg }
6477330f729Sjoerg
6487330f729Sjoerg /// Compute the desired OpenMP runtime from the flags provided.
getOpenMPRuntime(const ArgList & Args) const6497330f729Sjoerg Driver::OpenMPRuntimeKind Driver::getOpenMPRuntime(const ArgList &Args) const {
6507330f729Sjoerg StringRef RuntimeName(CLANG_DEFAULT_OPENMP_RUNTIME);
6517330f729Sjoerg
6527330f729Sjoerg const Arg *A = Args.getLastArg(options::OPT_fopenmp_EQ);
6537330f729Sjoerg if (A)
6547330f729Sjoerg RuntimeName = A->getValue();
6557330f729Sjoerg
6567330f729Sjoerg auto RT = llvm::StringSwitch<OpenMPRuntimeKind>(RuntimeName)
6577330f729Sjoerg .Case("libomp", OMPRT_OMP)
6587330f729Sjoerg .Case("libgomp", OMPRT_GOMP)
6597330f729Sjoerg .Case("libiomp5", OMPRT_IOMP5)
6607330f729Sjoerg .Default(OMPRT_Unknown);
6617330f729Sjoerg
6627330f729Sjoerg if (RT == OMPRT_Unknown) {
6637330f729Sjoerg if (A)
6647330f729Sjoerg Diag(diag::err_drv_unsupported_option_argument)
6657330f729Sjoerg << A->getOption().getName() << A->getValue();
6667330f729Sjoerg else
6677330f729Sjoerg // FIXME: We could use a nicer diagnostic here.
6687330f729Sjoerg Diag(diag::err_drv_unsupported_opt) << "-fopenmp";
6697330f729Sjoerg }
6707330f729Sjoerg
6717330f729Sjoerg return RT;
6727330f729Sjoerg }
6737330f729Sjoerg
CreateOffloadingDeviceToolChains(Compilation & C,InputList & Inputs)6747330f729Sjoerg void Driver::CreateOffloadingDeviceToolChains(Compilation &C,
6757330f729Sjoerg InputList &Inputs) {
6767330f729Sjoerg
6777330f729Sjoerg //
6787330f729Sjoerg // CUDA/HIP
6797330f729Sjoerg //
6807330f729Sjoerg // We need to generate a CUDA/HIP toolchain if any of the inputs has a CUDA
6817330f729Sjoerg // or HIP type. However, mixed CUDA/HIP compilation is not supported.
6827330f729Sjoerg bool IsCuda =
6837330f729Sjoerg llvm::any_of(Inputs, [](std::pair<types::ID, const llvm::opt::Arg *> &I) {
6847330f729Sjoerg return types::isCuda(I.first);
6857330f729Sjoerg });
6867330f729Sjoerg bool IsHIP =
6877330f729Sjoerg llvm::any_of(Inputs,
6887330f729Sjoerg [](std::pair<types::ID, const llvm::opt::Arg *> &I) {
6897330f729Sjoerg return types::isHIP(I.first);
6907330f729Sjoerg }) ||
6917330f729Sjoerg C.getInputArgs().hasArg(options::OPT_hip_link);
6927330f729Sjoerg if (IsCuda && IsHIP) {
6937330f729Sjoerg Diag(clang::diag::err_drv_mix_cuda_hip);
6947330f729Sjoerg return;
6957330f729Sjoerg }
6967330f729Sjoerg if (IsCuda) {
6977330f729Sjoerg const ToolChain *HostTC = C.getSingleOffloadToolChain<Action::OFK_Host>();
6987330f729Sjoerg const llvm::Triple &HostTriple = HostTC->getTriple();
6997330f729Sjoerg StringRef DeviceTripleStr;
7007330f729Sjoerg auto OFK = Action::OFK_Cuda;
7017330f729Sjoerg DeviceTripleStr =
7027330f729Sjoerg HostTriple.isArch64Bit() ? "nvptx64-nvidia-cuda" : "nvptx-nvidia-cuda";
7037330f729Sjoerg llvm::Triple CudaTriple(DeviceTripleStr);
7047330f729Sjoerg // Use the CUDA and host triples as the key into the ToolChains map,
7057330f729Sjoerg // because the device toolchain we create depends on both.
7067330f729Sjoerg auto &CudaTC = ToolChains[CudaTriple.str() + "/" + HostTriple.str()];
7077330f729Sjoerg if (!CudaTC) {
7087330f729Sjoerg CudaTC = std::make_unique<toolchains::CudaToolChain>(
7097330f729Sjoerg *this, CudaTriple, *HostTC, C.getInputArgs(), OFK);
7107330f729Sjoerg }
7117330f729Sjoerg C.addOffloadDeviceToolChain(CudaTC.get(), OFK);
7127330f729Sjoerg } else if (IsHIP) {
7137330f729Sjoerg const ToolChain *HostTC = C.getSingleOffloadToolChain<Action::OFK_Host>();
7147330f729Sjoerg const llvm::Triple &HostTriple = HostTC->getTriple();
7157330f729Sjoerg auto OFK = Action::OFK_HIP;
716*e038c9c4Sjoerg llvm::Triple HIPTriple = getHIPOffloadTargetTriple();
7177330f729Sjoerg // Use the HIP and host triples as the key into the ToolChains map,
7187330f729Sjoerg // because the device toolchain we create depends on both.
7197330f729Sjoerg auto &HIPTC = ToolChains[HIPTriple.str() + "/" + HostTriple.str()];
7207330f729Sjoerg if (!HIPTC) {
7217330f729Sjoerg HIPTC = std::make_unique<toolchains::HIPToolChain>(
7227330f729Sjoerg *this, HIPTriple, *HostTC, C.getInputArgs());
7237330f729Sjoerg }
7247330f729Sjoerg C.addOffloadDeviceToolChain(HIPTC.get(), OFK);
7257330f729Sjoerg }
7267330f729Sjoerg
7277330f729Sjoerg //
7287330f729Sjoerg // OpenMP
7297330f729Sjoerg //
7307330f729Sjoerg // We need to generate an OpenMP toolchain if the user specified targets with
7317330f729Sjoerg // the -fopenmp-targets option.
7327330f729Sjoerg if (Arg *OpenMPTargets =
7337330f729Sjoerg C.getInputArgs().getLastArg(options::OPT_fopenmp_targets_EQ)) {
7347330f729Sjoerg if (OpenMPTargets->getNumValues()) {
7357330f729Sjoerg // We expect that -fopenmp-targets is always used in conjunction with the
7367330f729Sjoerg // option -fopenmp specifying a valid runtime with offloading support,
7377330f729Sjoerg // i.e. libomp or libiomp.
7387330f729Sjoerg bool HasValidOpenMPRuntime = C.getInputArgs().hasFlag(
7397330f729Sjoerg options::OPT_fopenmp, options::OPT_fopenmp_EQ,
7407330f729Sjoerg options::OPT_fno_openmp, false);
7417330f729Sjoerg if (HasValidOpenMPRuntime) {
7427330f729Sjoerg OpenMPRuntimeKind OpenMPKind = getOpenMPRuntime(C.getInputArgs());
7437330f729Sjoerg HasValidOpenMPRuntime =
7447330f729Sjoerg OpenMPKind == OMPRT_OMP || OpenMPKind == OMPRT_IOMP5;
7457330f729Sjoerg }
7467330f729Sjoerg
7477330f729Sjoerg if (HasValidOpenMPRuntime) {
7487330f729Sjoerg llvm::StringMap<const char *> FoundNormalizedTriples;
7497330f729Sjoerg for (const char *Val : OpenMPTargets->getValues()) {
7507330f729Sjoerg llvm::Triple TT(Val);
7517330f729Sjoerg std::string NormalizedName = TT.normalize();
7527330f729Sjoerg
7537330f729Sjoerg // Make sure we don't have a duplicate triple.
7547330f729Sjoerg auto Duplicate = FoundNormalizedTriples.find(NormalizedName);
7557330f729Sjoerg if (Duplicate != FoundNormalizedTriples.end()) {
7567330f729Sjoerg Diag(clang::diag::warn_drv_omp_offload_target_duplicate)
7577330f729Sjoerg << Val << Duplicate->second;
7587330f729Sjoerg continue;
7597330f729Sjoerg }
7607330f729Sjoerg
7617330f729Sjoerg // Store the current triple so that we can check for duplicates in the
7627330f729Sjoerg // following iterations.
7637330f729Sjoerg FoundNormalizedTriples[NormalizedName] = Val;
7647330f729Sjoerg
7657330f729Sjoerg // If the specified target is invalid, emit a diagnostic.
7667330f729Sjoerg if (TT.getArch() == llvm::Triple::UnknownArch)
7677330f729Sjoerg Diag(clang::diag::err_drv_invalid_omp_target) << Val;
7687330f729Sjoerg else {
7697330f729Sjoerg const ToolChain *TC;
770*e038c9c4Sjoerg // Device toolchains have to be selected differently. They pair host
7717330f729Sjoerg // and device in their implementation.
772*e038c9c4Sjoerg if (TT.isNVPTX() || TT.isAMDGCN()) {
7737330f729Sjoerg const ToolChain *HostTC =
7747330f729Sjoerg C.getSingleOffloadToolChain<Action::OFK_Host>();
7757330f729Sjoerg assert(HostTC && "Host toolchain should be always defined.");
776*e038c9c4Sjoerg auto &DeviceTC =
7777330f729Sjoerg ToolChains[TT.str() + "/" + HostTC->getTriple().normalize()];
778*e038c9c4Sjoerg if (!DeviceTC) {
779*e038c9c4Sjoerg if (TT.isNVPTX())
780*e038c9c4Sjoerg DeviceTC = std::make_unique<toolchains::CudaToolChain>(
7817330f729Sjoerg *this, TT, *HostTC, C.getInputArgs(), Action::OFK_OpenMP);
782*e038c9c4Sjoerg else if (TT.isAMDGCN())
783*e038c9c4Sjoerg DeviceTC =
784*e038c9c4Sjoerg std::make_unique<toolchains::AMDGPUOpenMPToolChain>(
785*e038c9c4Sjoerg *this, TT, *HostTC, C.getInputArgs());
786*e038c9c4Sjoerg else
787*e038c9c4Sjoerg assert(DeviceTC && "Device toolchain not defined.");
788*e038c9c4Sjoerg }
789*e038c9c4Sjoerg
790*e038c9c4Sjoerg TC = DeviceTC.get();
7917330f729Sjoerg } else
7927330f729Sjoerg TC = &getToolChain(C.getInputArgs(), TT);
7937330f729Sjoerg C.addOffloadDeviceToolChain(TC, Action::OFK_OpenMP);
7947330f729Sjoerg }
7957330f729Sjoerg }
7967330f729Sjoerg } else
7977330f729Sjoerg Diag(clang::diag::err_drv_expecting_fopenmp_with_fopenmp_targets);
7987330f729Sjoerg } else
7997330f729Sjoerg Diag(clang::diag::warn_drv_empty_joined_argument)
8007330f729Sjoerg << OpenMPTargets->getAsString(C.getInputArgs());
8017330f729Sjoerg }
8027330f729Sjoerg
8037330f729Sjoerg //
8047330f729Sjoerg // TODO: Add support for other offloading programming models here.
8057330f729Sjoerg //
8067330f729Sjoerg }
8077330f729Sjoerg
8087330f729Sjoerg /// Looks the given directories for the specified file.
8097330f729Sjoerg ///
8107330f729Sjoerg /// \param[out] FilePath File path, if the file was found.
8117330f729Sjoerg /// \param[in] Dirs Directories used for the search.
8127330f729Sjoerg /// \param[in] FileName Name of the file to search for.
8137330f729Sjoerg /// \return True if file was found.
8147330f729Sjoerg ///
8157330f729Sjoerg /// Looks for file specified by FileName sequentially in directories specified
8167330f729Sjoerg /// by Dirs.
8177330f729Sjoerg ///
searchForFile(SmallVectorImpl<char> & FilePath,ArrayRef<StringRef> Dirs,StringRef FileName)8187330f729Sjoerg static bool searchForFile(SmallVectorImpl<char> &FilePath,
819*e038c9c4Sjoerg ArrayRef<StringRef> Dirs, StringRef FileName) {
8207330f729Sjoerg SmallString<128> WPath;
8217330f729Sjoerg for (const StringRef &Dir : Dirs) {
8227330f729Sjoerg if (Dir.empty())
8237330f729Sjoerg continue;
8247330f729Sjoerg WPath.clear();
8257330f729Sjoerg llvm::sys::path::append(WPath, Dir, FileName);
8267330f729Sjoerg llvm::sys::path::native(WPath);
8277330f729Sjoerg if (llvm::sys::fs::is_regular_file(WPath)) {
8287330f729Sjoerg FilePath = std::move(WPath);
8297330f729Sjoerg return true;
8307330f729Sjoerg }
8317330f729Sjoerg }
8327330f729Sjoerg return false;
8337330f729Sjoerg }
8347330f729Sjoerg
readConfigFile(StringRef FileName)8357330f729Sjoerg bool Driver::readConfigFile(StringRef FileName) {
8367330f729Sjoerg // Try reading the given file.
8377330f729Sjoerg SmallVector<const char *, 32> NewCfgArgs;
8387330f729Sjoerg if (!llvm::cl::readConfigFile(FileName, Saver, NewCfgArgs)) {
8397330f729Sjoerg Diag(diag::err_drv_cannot_read_config_file) << FileName;
8407330f729Sjoerg return true;
8417330f729Sjoerg }
8427330f729Sjoerg
8437330f729Sjoerg // Read options from config file.
8447330f729Sjoerg llvm::SmallString<128> CfgFileName(FileName);
8457330f729Sjoerg llvm::sys::path::native(CfgFileName);
846*e038c9c4Sjoerg ConfigFile = std::string(CfgFileName);
8477330f729Sjoerg bool ContainErrors;
8487330f729Sjoerg CfgOptions = std::make_unique<InputArgList>(
8497330f729Sjoerg ParseArgStrings(NewCfgArgs, IsCLMode(), ContainErrors));
8507330f729Sjoerg if (ContainErrors) {
8517330f729Sjoerg CfgOptions.reset();
8527330f729Sjoerg return true;
8537330f729Sjoerg }
8547330f729Sjoerg
8557330f729Sjoerg if (CfgOptions->hasArg(options::OPT_config)) {
8567330f729Sjoerg CfgOptions.reset();
8577330f729Sjoerg Diag(diag::err_drv_nested_config_file);
8587330f729Sjoerg return true;
8597330f729Sjoerg }
8607330f729Sjoerg
8617330f729Sjoerg // Claim all arguments that come from a configuration file so that the driver
8627330f729Sjoerg // does not warn on any that is unused.
8637330f729Sjoerg for (Arg *A : *CfgOptions)
8647330f729Sjoerg A->claim();
8657330f729Sjoerg return false;
8667330f729Sjoerg }
8677330f729Sjoerg
loadConfigFile()8687330f729Sjoerg bool Driver::loadConfigFile() {
8697330f729Sjoerg std::string CfgFileName;
8707330f729Sjoerg bool FileSpecifiedExplicitly = false;
8717330f729Sjoerg
8727330f729Sjoerg // Process options that change search path for config files.
8737330f729Sjoerg if (CLOptions) {
8747330f729Sjoerg if (CLOptions->hasArg(options::OPT_config_system_dir_EQ)) {
8757330f729Sjoerg SmallString<128> CfgDir;
8767330f729Sjoerg CfgDir.append(
8777330f729Sjoerg CLOptions->getLastArgValue(options::OPT_config_system_dir_EQ));
8787330f729Sjoerg if (!CfgDir.empty()) {
8797330f729Sjoerg if (llvm::sys::fs::make_absolute(CfgDir).value() != 0)
8807330f729Sjoerg SystemConfigDir.clear();
8817330f729Sjoerg else
8827330f729Sjoerg SystemConfigDir = std::string(CfgDir.begin(), CfgDir.end());
8837330f729Sjoerg }
8847330f729Sjoerg }
8857330f729Sjoerg if (CLOptions->hasArg(options::OPT_config_user_dir_EQ)) {
8867330f729Sjoerg SmallString<128> CfgDir;
8877330f729Sjoerg CfgDir.append(
8887330f729Sjoerg CLOptions->getLastArgValue(options::OPT_config_user_dir_EQ));
8897330f729Sjoerg if (!CfgDir.empty()) {
8907330f729Sjoerg if (llvm::sys::fs::make_absolute(CfgDir).value() != 0)
8917330f729Sjoerg UserConfigDir.clear();
8927330f729Sjoerg else
8937330f729Sjoerg UserConfigDir = std::string(CfgDir.begin(), CfgDir.end());
8947330f729Sjoerg }
8957330f729Sjoerg }
8967330f729Sjoerg }
8977330f729Sjoerg
8987330f729Sjoerg // First try to find config file specified in command line.
8997330f729Sjoerg if (CLOptions) {
9007330f729Sjoerg std::vector<std::string> ConfigFiles =
9017330f729Sjoerg CLOptions->getAllArgValues(options::OPT_config);
9027330f729Sjoerg if (ConfigFiles.size() > 1) {
903*e038c9c4Sjoerg if (!std::all_of(ConfigFiles.begin(), ConfigFiles.end(),
904*e038c9c4Sjoerg [ConfigFiles](const std::string &s) {
905*e038c9c4Sjoerg return s == ConfigFiles[0];
906*e038c9c4Sjoerg })) {
9077330f729Sjoerg Diag(diag::err_drv_duplicate_config);
9087330f729Sjoerg return true;
9097330f729Sjoerg }
910*e038c9c4Sjoerg }
9117330f729Sjoerg
9127330f729Sjoerg if (!ConfigFiles.empty()) {
9137330f729Sjoerg CfgFileName = ConfigFiles.front();
9147330f729Sjoerg assert(!CfgFileName.empty());
9157330f729Sjoerg
9167330f729Sjoerg // If argument contains directory separator, treat it as a path to
9177330f729Sjoerg // configuration file.
9187330f729Sjoerg if (llvm::sys::path::has_parent_path(CfgFileName)) {
9197330f729Sjoerg SmallString<128> CfgFilePath;
9207330f729Sjoerg if (llvm::sys::path::is_relative(CfgFileName))
9217330f729Sjoerg llvm::sys::fs::current_path(CfgFilePath);
9227330f729Sjoerg llvm::sys::path::append(CfgFilePath, CfgFileName);
9237330f729Sjoerg if (!llvm::sys::fs::is_regular_file(CfgFilePath)) {
9247330f729Sjoerg Diag(diag::err_drv_config_file_not_exist) << CfgFilePath;
9257330f729Sjoerg return true;
9267330f729Sjoerg }
9277330f729Sjoerg return readConfigFile(CfgFilePath);
9287330f729Sjoerg }
9297330f729Sjoerg
9307330f729Sjoerg FileSpecifiedExplicitly = true;
9317330f729Sjoerg }
9327330f729Sjoerg }
9337330f729Sjoerg
9347330f729Sjoerg // If config file is not specified explicitly, try to deduce configuration
9357330f729Sjoerg // from executable name. For instance, an executable 'armv7l-clang' will
9367330f729Sjoerg // search for config file 'armv7l-clang.cfg'.
9377330f729Sjoerg if (CfgFileName.empty() && !ClangNameParts.TargetPrefix.empty())
9387330f729Sjoerg CfgFileName = ClangNameParts.TargetPrefix + '-' + ClangNameParts.ModeSuffix;
9397330f729Sjoerg
9407330f729Sjoerg if (CfgFileName.empty())
9417330f729Sjoerg return false;
9427330f729Sjoerg
9437330f729Sjoerg // Determine architecture part of the file name, if it is present.
9447330f729Sjoerg StringRef CfgFileArch = CfgFileName;
9457330f729Sjoerg size_t ArchPrefixLen = CfgFileArch.find('-');
9467330f729Sjoerg if (ArchPrefixLen == StringRef::npos)
9477330f729Sjoerg ArchPrefixLen = CfgFileArch.size();
9487330f729Sjoerg llvm::Triple CfgTriple;
9497330f729Sjoerg CfgFileArch = CfgFileArch.take_front(ArchPrefixLen);
9507330f729Sjoerg CfgTriple = llvm::Triple(llvm::Triple::normalize(CfgFileArch));
9517330f729Sjoerg if (CfgTriple.getArch() == llvm::Triple::ArchType::UnknownArch)
9527330f729Sjoerg ArchPrefixLen = 0;
9537330f729Sjoerg
9547330f729Sjoerg if (!StringRef(CfgFileName).endswith(".cfg"))
9557330f729Sjoerg CfgFileName += ".cfg";
9567330f729Sjoerg
9577330f729Sjoerg // If config file starts with architecture name and command line options
9587330f729Sjoerg // redefine architecture (with options like -m32 -LE etc), try finding new
9597330f729Sjoerg // config file with that architecture.
9607330f729Sjoerg SmallString<128> FixedConfigFile;
9617330f729Sjoerg size_t FixedArchPrefixLen = 0;
9627330f729Sjoerg if (ArchPrefixLen) {
9637330f729Sjoerg // Get architecture name from config file name like 'i386.cfg' or
9647330f729Sjoerg // 'armv7l-clang.cfg'.
9657330f729Sjoerg // Check if command line options changes effective triple.
9667330f729Sjoerg llvm::Triple EffectiveTriple = computeTargetTriple(*this,
9677330f729Sjoerg CfgTriple.getTriple(), *CLOptions);
9687330f729Sjoerg if (CfgTriple.getArch() != EffectiveTriple.getArch()) {
9697330f729Sjoerg FixedConfigFile = EffectiveTriple.getArchName();
9707330f729Sjoerg FixedArchPrefixLen = FixedConfigFile.size();
9717330f729Sjoerg // Append the rest of original file name so that file name transforms
9727330f729Sjoerg // like: i386-clang.cfg -> x86_64-clang.cfg.
9737330f729Sjoerg if (ArchPrefixLen < CfgFileName.size())
9747330f729Sjoerg FixedConfigFile += CfgFileName.substr(ArchPrefixLen);
9757330f729Sjoerg }
9767330f729Sjoerg }
9777330f729Sjoerg
9787330f729Sjoerg // Prepare list of directories where config file is searched for.
979*e038c9c4Sjoerg StringRef CfgFileSearchDirs[] = {UserConfigDir, SystemConfigDir, Dir};
9807330f729Sjoerg
9817330f729Sjoerg // Try to find config file. First try file with corrected architecture.
9827330f729Sjoerg llvm::SmallString<128> CfgFilePath;
9837330f729Sjoerg if (!FixedConfigFile.empty()) {
9847330f729Sjoerg if (searchForFile(CfgFilePath, CfgFileSearchDirs, FixedConfigFile))
9857330f729Sjoerg return readConfigFile(CfgFilePath);
9867330f729Sjoerg // If 'x86_64-clang.cfg' was not found, try 'x86_64.cfg'.
9877330f729Sjoerg FixedConfigFile.resize(FixedArchPrefixLen);
9887330f729Sjoerg FixedConfigFile.append(".cfg");
9897330f729Sjoerg if (searchForFile(CfgFilePath, CfgFileSearchDirs, FixedConfigFile))
9907330f729Sjoerg return readConfigFile(CfgFilePath);
9917330f729Sjoerg }
9927330f729Sjoerg
9937330f729Sjoerg // Then try original file name.
9947330f729Sjoerg if (searchForFile(CfgFilePath, CfgFileSearchDirs, CfgFileName))
9957330f729Sjoerg return readConfigFile(CfgFilePath);
9967330f729Sjoerg
9977330f729Sjoerg // Finally try removing driver mode part: 'x86_64-clang.cfg' -> 'x86_64.cfg'.
9987330f729Sjoerg if (!ClangNameParts.ModeSuffix.empty() &&
9997330f729Sjoerg !ClangNameParts.TargetPrefix.empty()) {
10007330f729Sjoerg CfgFileName.assign(ClangNameParts.TargetPrefix);
10017330f729Sjoerg CfgFileName.append(".cfg");
10027330f729Sjoerg if (searchForFile(CfgFilePath, CfgFileSearchDirs, CfgFileName))
10037330f729Sjoerg return readConfigFile(CfgFilePath);
10047330f729Sjoerg }
10057330f729Sjoerg
10067330f729Sjoerg // Report error but only if config file was specified explicitly, by option
10077330f729Sjoerg // --config. If it was deduced from executable name, it is not an error.
10087330f729Sjoerg if (FileSpecifiedExplicitly) {
10097330f729Sjoerg Diag(diag::err_drv_config_file_not_found) << CfgFileName;
1010*e038c9c4Sjoerg for (const StringRef &SearchDir : CfgFileSearchDirs)
10117330f729Sjoerg if (!SearchDir.empty())
10127330f729Sjoerg Diag(diag::note_drv_config_file_searched_in) << SearchDir;
10137330f729Sjoerg return true;
10147330f729Sjoerg }
10157330f729Sjoerg
10167330f729Sjoerg return false;
10177330f729Sjoerg }
10187330f729Sjoerg
BuildCompilation(ArrayRef<const char * > ArgList)10197330f729Sjoerg Compilation *Driver::BuildCompilation(ArrayRef<const char *> ArgList) {
10207330f729Sjoerg llvm::PrettyStackTraceString CrashInfo("Compilation construction");
10217330f729Sjoerg
10227330f729Sjoerg // FIXME: Handle environment options which affect driver behavior, somewhere
10237330f729Sjoerg // (client?). GCC_EXEC_PREFIX, LPATH, CC_PRINT_OPTIONS.
10247330f729Sjoerg
10257330f729Sjoerg // We look for the driver mode option early, because the mode can affect
10267330f729Sjoerg // how other options are parsed.
10277330f729Sjoerg ParseDriverMode(ClangExecutable, ArgList.slice(1));
10287330f729Sjoerg
10297330f729Sjoerg // FIXME: What are we going to do with -V and -b?
10307330f729Sjoerg
10317330f729Sjoerg // Arguments specified in command line.
10327330f729Sjoerg bool ContainsError;
10337330f729Sjoerg CLOptions = std::make_unique<InputArgList>(
10347330f729Sjoerg ParseArgStrings(ArgList.slice(1), IsCLMode(), ContainsError));
10357330f729Sjoerg
10367330f729Sjoerg // Try parsing configuration file.
10377330f729Sjoerg if (!ContainsError)
10387330f729Sjoerg ContainsError = loadConfigFile();
10397330f729Sjoerg bool HasConfigFile = !ContainsError && (CfgOptions.get() != nullptr);
10407330f729Sjoerg
10417330f729Sjoerg // All arguments, from both config file and command line.
10427330f729Sjoerg InputArgList Args = std::move(HasConfigFile ? std::move(*CfgOptions)
10437330f729Sjoerg : std::move(*CLOptions));
10447330f729Sjoerg
10457330f729Sjoerg // The args for config files or /clang: flags belong to different InputArgList
10467330f729Sjoerg // objects than Args. This copies an Arg from one of those other InputArgLists
10477330f729Sjoerg // to the ownership of Args.
10487330f729Sjoerg auto appendOneArg = [&Args](const Arg *Opt, const Arg *BaseArg) {
10497330f729Sjoerg unsigned Index = Args.MakeIndex(Opt->getSpelling());
1050*e038c9c4Sjoerg Arg *Copy = new llvm::opt::Arg(Opt->getOption(), Args.getArgString(Index),
10517330f729Sjoerg Index, BaseArg);
10527330f729Sjoerg Copy->getValues() = Opt->getValues();
10537330f729Sjoerg if (Opt->isClaimed())
10547330f729Sjoerg Copy->claim();
1055*e038c9c4Sjoerg Copy->setOwnsValues(Opt->getOwnsValues());
1056*e038c9c4Sjoerg Opt->setOwnsValues(false);
10577330f729Sjoerg Args.append(Copy);
10587330f729Sjoerg };
10597330f729Sjoerg
10607330f729Sjoerg if (HasConfigFile)
10617330f729Sjoerg for (auto *Opt : *CLOptions) {
10627330f729Sjoerg if (Opt->getOption().matches(options::OPT_config))
10637330f729Sjoerg continue;
10647330f729Sjoerg const Arg *BaseArg = &Opt->getBaseArg();
10657330f729Sjoerg if (BaseArg == Opt)
10667330f729Sjoerg BaseArg = nullptr;
10677330f729Sjoerg appendOneArg(Opt, BaseArg);
10687330f729Sjoerg }
10697330f729Sjoerg
10707330f729Sjoerg // In CL mode, look for any pass-through arguments
10717330f729Sjoerg if (IsCLMode() && !ContainsError) {
10727330f729Sjoerg SmallVector<const char *, 16> CLModePassThroughArgList;
10737330f729Sjoerg for (const auto *A : Args.filtered(options::OPT__SLASH_clang)) {
10747330f729Sjoerg A->claim();
10757330f729Sjoerg CLModePassThroughArgList.push_back(A->getValue());
10767330f729Sjoerg }
10777330f729Sjoerg
10787330f729Sjoerg if (!CLModePassThroughArgList.empty()) {
10797330f729Sjoerg // Parse any pass through args using default clang processing rather
10807330f729Sjoerg // than clang-cl processing.
10817330f729Sjoerg auto CLModePassThroughOptions = std::make_unique<InputArgList>(
10827330f729Sjoerg ParseArgStrings(CLModePassThroughArgList, false, ContainsError));
10837330f729Sjoerg
10847330f729Sjoerg if (!ContainsError)
10857330f729Sjoerg for (auto *Opt : *CLModePassThroughOptions) {
10867330f729Sjoerg appendOneArg(Opt, nullptr);
10877330f729Sjoerg }
10887330f729Sjoerg }
10897330f729Sjoerg }
10907330f729Sjoerg
10917330f729Sjoerg // Check for working directory option before accessing any files
10927330f729Sjoerg if (Arg *WD = Args.getLastArg(options::OPT_working_directory))
10937330f729Sjoerg if (VFS->setCurrentWorkingDirectory(WD->getValue()))
10947330f729Sjoerg Diag(diag::err_drv_unable_to_set_working_directory) << WD->getValue();
10957330f729Sjoerg
10967330f729Sjoerg // FIXME: This stuff needs to go into the Compilation, not the driver.
10977330f729Sjoerg bool CCCPrintPhases;
10987330f729Sjoerg
10997330f729Sjoerg // Silence driver warnings if requested
11007330f729Sjoerg Diags.setIgnoreAllWarnings(Args.hasArg(options::OPT_w));
11017330f729Sjoerg
11027330f729Sjoerg // -no-canonical-prefixes is used very early in main.
11037330f729Sjoerg Args.ClaimAllArgs(options::OPT_no_canonical_prefixes);
11047330f729Sjoerg
1105*e038c9c4Sjoerg // f(no-)integated-cc1 is also used very early in main.
1106*e038c9c4Sjoerg Args.ClaimAllArgs(options::OPT_fintegrated_cc1);
1107*e038c9c4Sjoerg Args.ClaimAllArgs(options::OPT_fno_integrated_cc1);
1108*e038c9c4Sjoerg
11097330f729Sjoerg // Ignore -pipe.
11107330f729Sjoerg Args.ClaimAllArgs(options::OPT_pipe);
11117330f729Sjoerg
11127330f729Sjoerg // Extract -ccc args.
11137330f729Sjoerg //
11147330f729Sjoerg // FIXME: We need to figure out where this behavior should live. Most of it
11157330f729Sjoerg // should be outside in the client; the parts that aren't should have proper
11167330f729Sjoerg // options, either by introducing new ones or by overloading gcc ones like -V
11177330f729Sjoerg // or -b.
11187330f729Sjoerg CCCPrintPhases = Args.hasArg(options::OPT_ccc_print_phases);
11197330f729Sjoerg CCCPrintBindings = Args.hasArg(options::OPT_ccc_print_bindings);
11207330f729Sjoerg if (const Arg *A = Args.getLastArg(options::OPT_ccc_gcc_name))
11217330f729Sjoerg CCCGenericGCCName = A->getValue();
11227330f729Sjoerg GenReproducer = Args.hasFlag(options::OPT_gen_reproducer,
11237330f729Sjoerg options::OPT_fno_crash_diagnostics,
11247330f729Sjoerg !!::getenv("FORCE_CLANG_DIAGNOSTICS_CRASH"));
1125*e038c9c4Sjoerg
1126*e038c9c4Sjoerg // Process -fproc-stat-report options.
1127*e038c9c4Sjoerg if (const Arg *A = Args.getLastArg(options::OPT_fproc_stat_report_EQ)) {
1128*e038c9c4Sjoerg CCPrintProcessStats = true;
1129*e038c9c4Sjoerg CCPrintStatReportFilename = A->getValue();
1130*e038c9c4Sjoerg }
1131*e038c9c4Sjoerg if (Args.hasArg(options::OPT_fproc_stat_report))
1132*e038c9c4Sjoerg CCPrintProcessStats = true;
1133*e038c9c4Sjoerg
11347330f729Sjoerg // FIXME: TargetTriple is used by the target-prefixed calls to as/ld
11357330f729Sjoerg // and getToolChain is const.
11367330f729Sjoerg if (IsCLMode()) {
11377330f729Sjoerg // clang-cl targets MSVC-style Win32.
11387330f729Sjoerg llvm::Triple T(TargetTriple);
11397330f729Sjoerg T.setOS(llvm::Triple::Win32);
11407330f729Sjoerg T.setVendor(llvm::Triple::PC);
11417330f729Sjoerg T.setEnvironment(llvm::Triple::MSVC);
11427330f729Sjoerg T.setObjectFormat(llvm::Triple::COFF);
11437330f729Sjoerg TargetTriple = T.str();
11447330f729Sjoerg }
11457330f729Sjoerg if (const Arg *A = Args.getLastArg(options::OPT_target))
11467330f729Sjoerg TargetTriple = A->getValue();
11477330f729Sjoerg if (const Arg *A = Args.getLastArg(options::OPT_ccc_install_dir))
11487330f729Sjoerg Dir = InstalledDir = A->getValue();
11497330f729Sjoerg for (const Arg *A : Args.filtered(options::OPT_B)) {
11507330f729Sjoerg A->claim();
11517330f729Sjoerg PrefixDirs.push_back(A->getValue(0));
11527330f729Sjoerg }
1153*e038c9c4Sjoerg if (Optional<std::string> CompilerPathValue =
1154*e038c9c4Sjoerg llvm::sys::Process::GetEnv("COMPILER_PATH")) {
1155*e038c9c4Sjoerg StringRef CompilerPath = *CompilerPathValue;
1156*e038c9c4Sjoerg while (!CompilerPath.empty()) {
1157*e038c9c4Sjoerg std::pair<StringRef, StringRef> Split =
1158*e038c9c4Sjoerg CompilerPath.split(llvm::sys::EnvPathSeparator);
1159*e038c9c4Sjoerg PrefixDirs.push_back(std::string(Split.first));
1160*e038c9c4Sjoerg CompilerPath = Split.second;
1161*e038c9c4Sjoerg }
1162*e038c9c4Sjoerg }
11637330f729Sjoerg if (const Arg *A = Args.getLastArg(options::OPT__sysroot_EQ))
11647330f729Sjoerg SysRoot = A->getValue();
11657330f729Sjoerg if (const Arg *A = Args.getLastArg(options::OPT__dyld_prefix_EQ))
11667330f729Sjoerg DyldPrefix = A->getValue();
11677330f729Sjoerg
11687330f729Sjoerg if (const Arg *A = Args.getLastArg(options::OPT_resource_dir))
11697330f729Sjoerg ResourceDir = A->getValue();
11707330f729Sjoerg
11717330f729Sjoerg if (const Arg *A = Args.getLastArg(options::OPT_save_temps_EQ)) {
11727330f729Sjoerg SaveTemps = llvm::StringSwitch<SaveTempsMode>(A->getValue())
11737330f729Sjoerg .Case("cwd", SaveTempsCwd)
11747330f729Sjoerg .Case("obj", SaveTempsObj)
11757330f729Sjoerg .Default(SaveTempsCwd);
11767330f729Sjoerg }
11777330f729Sjoerg
11787330f729Sjoerg setLTOMode(Args);
11797330f729Sjoerg
11807330f729Sjoerg // Process -fembed-bitcode= flags.
11817330f729Sjoerg if (Arg *A = Args.getLastArg(options::OPT_fembed_bitcode_EQ)) {
11827330f729Sjoerg StringRef Name = A->getValue();
11837330f729Sjoerg unsigned Model = llvm::StringSwitch<unsigned>(Name)
11847330f729Sjoerg .Case("off", EmbedNone)
11857330f729Sjoerg .Case("all", EmbedBitcode)
11867330f729Sjoerg .Case("bitcode", EmbedBitcode)
11877330f729Sjoerg .Case("marker", EmbedMarker)
11887330f729Sjoerg .Default(~0U);
11897330f729Sjoerg if (Model == ~0U) {
11907330f729Sjoerg Diags.Report(diag::err_drv_invalid_value) << A->getAsString(Args)
11917330f729Sjoerg << Name;
11927330f729Sjoerg } else
11937330f729Sjoerg BitcodeEmbed = static_cast<BitcodeEmbedMode>(Model);
11947330f729Sjoerg }
11957330f729Sjoerg
11967330f729Sjoerg std::unique_ptr<llvm::opt::InputArgList> UArgs =
11977330f729Sjoerg std::make_unique<InputArgList>(std::move(Args));
11987330f729Sjoerg
11997330f729Sjoerg // Perform the default argument translations.
12007330f729Sjoerg DerivedArgList *TranslatedArgs = TranslateInputArgs(*UArgs);
12017330f729Sjoerg
12027330f729Sjoerg // Owned by the host.
12037330f729Sjoerg const ToolChain &TC = getToolChain(
12047330f729Sjoerg *UArgs, computeTargetTriple(*this, TargetTriple, *UArgs));
12057330f729Sjoerg
12067330f729Sjoerg // The compilation takes ownership of Args.
12077330f729Sjoerg Compilation *C = new Compilation(*this, TC, UArgs.release(), TranslatedArgs,
12087330f729Sjoerg ContainsError);
12097330f729Sjoerg
12107330f729Sjoerg if (!HandleImmediateArgs(*C))
12117330f729Sjoerg return C;
12127330f729Sjoerg
12137330f729Sjoerg // Construct the list of inputs.
12147330f729Sjoerg InputList Inputs;
12157330f729Sjoerg BuildInputs(C->getDefaultToolChain(), *TranslatedArgs, Inputs);
12167330f729Sjoerg
12177330f729Sjoerg // Populate the tool chains for the offloading devices, if any.
12187330f729Sjoerg CreateOffloadingDeviceToolChains(*C, Inputs);
12197330f729Sjoerg
12207330f729Sjoerg // Construct the list of abstract actions to perform for this compilation. On
12217330f729Sjoerg // MachO targets this uses the driver-driver and universal actions.
12227330f729Sjoerg if (TC.getTriple().isOSBinFormatMachO())
12237330f729Sjoerg BuildUniversalActions(*C, C->getDefaultToolChain(), Inputs);
12247330f729Sjoerg else
12257330f729Sjoerg BuildActions(*C, C->getArgs(), Inputs, C->getActions());
12267330f729Sjoerg
12277330f729Sjoerg if (CCCPrintPhases) {
12287330f729Sjoerg PrintActions(*C);
12297330f729Sjoerg return C;
12307330f729Sjoerg }
12317330f729Sjoerg
12327330f729Sjoerg BuildJobs(*C);
12337330f729Sjoerg
12347330f729Sjoerg return C;
12357330f729Sjoerg }
12367330f729Sjoerg
printArgList(raw_ostream & OS,const llvm::opt::ArgList & Args)12377330f729Sjoerg static void printArgList(raw_ostream &OS, const llvm::opt::ArgList &Args) {
12387330f729Sjoerg llvm::opt::ArgStringList ASL;
12397330f729Sjoerg for (const auto *A : Args)
12407330f729Sjoerg A->render(Args, ASL);
12417330f729Sjoerg
12427330f729Sjoerg for (auto I = ASL.begin(), E = ASL.end(); I != E; ++I) {
12437330f729Sjoerg if (I != ASL.begin())
12447330f729Sjoerg OS << ' ';
1245*e038c9c4Sjoerg llvm::sys::printArg(OS, *I, true);
12467330f729Sjoerg }
12477330f729Sjoerg OS << '\n';
12487330f729Sjoerg }
12497330f729Sjoerg
getCrashDiagnosticFile(StringRef ReproCrashFilename,SmallString<128> & CrashDiagDir)12507330f729Sjoerg bool Driver::getCrashDiagnosticFile(StringRef ReproCrashFilename,
12517330f729Sjoerg SmallString<128> &CrashDiagDir) {
12527330f729Sjoerg using namespace llvm::sys;
12537330f729Sjoerg assert(llvm::Triple(llvm::sys::getProcessTriple()).isOSDarwin() &&
12547330f729Sjoerg "Only knows about .crash files on Darwin");
12557330f729Sjoerg
12567330f729Sjoerg // The .crash file can be found on at ~/Library/Logs/DiagnosticReports/
12577330f729Sjoerg // (or /Library/Logs/DiagnosticReports for root) and has the filename pattern
12587330f729Sjoerg // clang-<VERSION>_<YYYY-MM-DD-HHMMSS>_<hostname>.crash.
12597330f729Sjoerg path::home_directory(CrashDiagDir);
12607330f729Sjoerg if (CrashDiagDir.startswith("/var/root"))
12617330f729Sjoerg CrashDiagDir = "/";
12627330f729Sjoerg path::append(CrashDiagDir, "Library/Logs/DiagnosticReports");
12637330f729Sjoerg int PID =
12647330f729Sjoerg #if LLVM_ON_UNIX
12657330f729Sjoerg getpid();
12667330f729Sjoerg #else
12677330f729Sjoerg 0;
12687330f729Sjoerg #endif
12697330f729Sjoerg std::error_code EC;
12707330f729Sjoerg fs::file_status FileStatus;
12717330f729Sjoerg TimePoint<> LastAccessTime;
12727330f729Sjoerg SmallString<128> CrashFilePath;
12737330f729Sjoerg // Lookup the .crash files and get the one generated by a subprocess spawned
12747330f729Sjoerg // by this driver invocation.
12757330f729Sjoerg for (fs::directory_iterator File(CrashDiagDir, EC), FileEnd;
12767330f729Sjoerg File != FileEnd && !EC; File.increment(EC)) {
12777330f729Sjoerg StringRef FileName = path::filename(File->path());
12787330f729Sjoerg if (!FileName.startswith(Name))
12797330f729Sjoerg continue;
12807330f729Sjoerg if (fs::status(File->path(), FileStatus))
12817330f729Sjoerg continue;
12827330f729Sjoerg llvm::ErrorOr<std::unique_ptr<llvm::MemoryBuffer>> CrashFile =
12837330f729Sjoerg llvm::MemoryBuffer::getFile(File->path());
12847330f729Sjoerg if (!CrashFile)
12857330f729Sjoerg continue;
12867330f729Sjoerg // The first line should start with "Process:", otherwise this isn't a real
12877330f729Sjoerg // .crash file.
12887330f729Sjoerg StringRef Data = CrashFile.get()->getBuffer();
12897330f729Sjoerg if (!Data.startswith("Process:"))
12907330f729Sjoerg continue;
12917330f729Sjoerg // Parse parent process pid line, e.g: "Parent Process: clang-4.0 [79141]"
12927330f729Sjoerg size_t ParentProcPos = Data.find("Parent Process:");
12937330f729Sjoerg if (ParentProcPos == StringRef::npos)
12947330f729Sjoerg continue;
12957330f729Sjoerg size_t LineEnd = Data.find_first_of("\n", ParentProcPos);
12967330f729Sjoerg if (LineEnd == StringRef::npos)
12977330f729Sjoerg continue;
12987330f729Sjoerg StringRef ParentProcess = Data.slice(ParentProcPos+15, LineEnd).trim();
12997330f729Sjoerg int OpenBracket = -1, CloseBracket = -1;
13007330f729Sjoerg for (size_t i = 0, e = ParentProcess.size(); i < e; ++i) {
13017330f729Sjoerg if (ParentProcess[i] == '[')
13027330f729Sjoerg OpenBracket = i;
13037330f729Sjoerg if (ParentProcess[i] == ']')
13047330f729Sjoerg CloseBracket = i;
13057330f729Sjoerg }
13067330f729Sjoerg // Extract the parent process PID from the .crash file and check whether
13077330f729Sjoerg // it matches this driver invocation pid.
13087330f729Sjoerg int CrashPID;
13097330f729Sjoerg if (OpenBracket < 0 || CloseBracket < 0 ||
13107330f729Sjoerg ParentProcess.slice(OpenBracket + 1, CloseBracket)
13117330f729Sjoerg .getAsInteger(10, CrashPID) || CrashPID != PID) {
13127330f729Sjoerg continue;
13137330f729Sjoerg }
13147330f729Sjoerg
13157330f729Sjoerg // Found a .crash file matching the driver pid. To avoid getting an older
13167330f729Sjoerg // and misleading crash file, continue looking for the most recent.
13177330f729Sjoerg // FIXME: the driver can dispatch multiple cc1 invocations, leading to
13187330f729Sjoerg // multiple crashes poiting to the same parent process. Since the driver
13197330f729Sjoerg // does not collect pid information for the dispatched invocation there's
13207330f729Sjoerg // currently no way to distinguish among them.
13217330f729Sjoerg const auto FileAccessTime = FileStatus.getLastModificationTime();
13227330f729Sjoerg if (FileAccessTime > LastAccessTime) {
13237330f729Sjoerg CrashFilePath.assign(File->path());
13247330f729Sjoerg LastAccessTime = FileAccessTime;
13257330f729Sjoerg }
13267330f729Sjoerg }
13277330f729Sjoerg
13287330f729Sjoerg // If found, copy it over to the location of other reproducer files.
13297330f729Sjoerg if (!CrashFilePath.empty()) {
13307330f729Sjoerg EC = fs::copy_file(CrashFilePath, ReproCrashFilename);
13317330f729Sjoerg if (EC)
13327330f729Sjoerg return false;
13337330f729Sjoerg return true;
13347330f729Sjoerg }
13357330f729Sjoerg
13367330f729Sjoerg return false;
13377330f729Sjoerg }
13387330f729Sjoerg
13397330f729Sjoerg // When clang crashes, produce diagnostic information including the fully
13407330f729Sjoerg // preprocessed source file(s). Request that the developer attach the
13417330f729Sjoerg // diagnostic information to a bug report.
generateCompilationDiagnostics(Compilation & C,const Command & FailingCommand,StringRef AdditionalInformation,CompilationDiagnosticReport * Report)13427330f729Sjoerg void Driver::generateCompilationDiagnostics(
13437330f729Sjoerg Compilation &C, const Command &FailingCommand,
13447330f729Sjoerg StringRef AdditionalInformation, CompilationDiagnosticReport *Report) {
13457330f729Sjoerg if (C.getArgs().hasArg(options::OPT_fno_crash_diagnostics))
13467330f729Sjoerg return;
13477330f729Sjoerg
13487330f729Sjoerg // Don't try to generate diagnostics for link or dsymutil jobs.
13497330f729Sjoerg if (FailingCommand.getCreator().isLinkJob() ||
13507330f729Sjoerg FailingCommand.getCreator().isDsymutilJob())
13517330f729Sjoerg return;
13527330f729Sjoerg
13537330f729Sjoerg // Print the version of the compiler.
13547330f729Sjoerg PrintVersion(C, llvm::errs());
13557330f729Sjoerg
13567330f729Sjoerg // Suppress driver output and emit preprocessor output to temp file.
13577330f729Sjoerg Mode = CPPMode;
13587330f729Sjoerg CCGenDiagnostics = true;
13597330f729Sjoerg
13607330f729Sjoerg // Save the original job command(s).
13617330f729Sjoerg Command Cmd = FailingCommand;
13627330f729Sjoerg
13637330f729Sjoerg // Keep track of whether we produce any errors while trying to produce
13647330f729Sjoerg // preprocessed sources.
13657330f729Sjoerg DiagnosticErrorTrap Trap(Diags);
13667330f729Sjoerg
13677330f729Sjoerg // Suppress tool output.
13687330f729Sjoerg C.initCompilationForDiagnostics();
13697330f729Sjoerg
13707330f729Sjoerg // Construct the list of inputs.
13717330f729Sjoerg InputList Inputs;
13727330f729Sjoerg BuildInputs(C.getDefaultToolChain(), C.getArgs(), Inputs);
13737330f729Sjoerg
13747330f729Sjoerg for (InputList::iterator it = Inputs.begin(), ie = Inputs.end(); it != ie;) {
13757330f729Sjoerg bool IgnoreInput = false;
13767330f729Sjoerg
13777330f729Sjoerg // Ignore input from stdin or any inputs that cannot be preprocessed.
13787330f729Sjoerg // Check type first as not all linker inputs have a value.
13797330f729Sjoerg if (types::getPreprocessedType(it->first) == types::TY_INVALID) {
13807330f729Sjoerg IgnoreInput = true;
13817330f729Sjoerg } else if (!strcmp(it->second->getValue(), "-")) {
13827330f729Sjoerg Diag(clang::diag::note_drv_command_failed_diag_msg)
13837330f729Sjoerg << "Error generating preprocessed source(s) - "
13847330f729Sjoerg "ignoring input from stdin.";
13857330f729Sjoerg IgnoreInput = true;
13867330f729Sjoerg }
13877330f729Sjoerg
13887330f729Sjoerg if (IgnoreInput) {
13897330f729Sjoerg it = Inputs.erase(it);
13907330f729Sjoerg ie = Inputs.end();
13917330f729Sjoerg } else {
13927330f729Sjoerg ++it;
13937330f729Sjoerg }
13947330f729Sjoerg }
13957330f729Sjoerg
13967330f729Sjoerg if (Inputs.empty()) {
13977330f729Sjoerg Diag(clang::diag::note_drv_command_failed_diag_msg)
13987330f729Sjoerg << "Error generating preprocessed source(s) - "
13997330f729Sjoerg "no preprocessable inputs.";
14007330f729Sjoerg return;
14017330f729Sjoerg }
14027330f729Sjoerg
14037330f729Sjoerg // Don't attempt to generate preprocessed files if multiple -arch options are
14047330f729Sjoerg // used, unless they're all duplicates.
14057330f729Sjoerg llvm::StringSet<> ArchNames;
14067330f729Sjoerg for (const Arg *A : C.getArgs()) {
14077330f729Sjoerg if (A->getOption().matches(options::OPT_arch)) {
14087330f729Sjoerg StringRef ArchName = A->getValue();
14097330f729Sjoerg ArchNames.insert(ArchName);
14107330f729Sjoerg }
14117330f729Sjoerg }
14127330f729Sjoerg if (ArchNames.size() > 1) {
14137330f729Sjoerg Diag(clang::diag::note_drv_command_failed_diag_msg)
14147330f729Sjoerg << "Error generating preprocessed source(s) - cannot generate "
14157330f729Sjoerg "preprocessed source with multiple -arch options.";
14167330f729Sjoerg return;
14177330f729Sjoerg }
14187330f729Sjoerg
14197330f729Sjoerg // Construct the list of abstract actions to perform for this compilation. On
14207330f729Sjoerg // Darwin OSes this uses the driver-driver and builds universal actions.
14217330f729Sjoerg const ToolChain &TC = C.getDefaultToolChain();
14227330f729Sjoerg if (TC.getTriple().isOSBinFormatMachO())
14237330f729Sjoerg BuildUniversalActions(C, TC, Inputs);
14247330f729Sjoerg else
14257330f729Sjoerg BuildActions(C, C.getArgs(), Inputs, C.getActions());
14267330f729Sjoerg
14277330f729Sjoerg BuildJobs(C);
14287330f729Sjoerg
14297330f729Sjoerg // If there were errors building the compilation, quit now.
14307330f729Sjoerg if (Trap.hasErrorOccurred()) {
14317330f729Sjoerg Diag(clang::diag::note_drv_command_failed_diag_msg)
14327330f729Sjoerg << "Error generating preprocessed source(s).";
14337330f729Sjoerg return;
14347330f729Sjoerg }
14357330f729Sjoerg
14367330f729Sjoerg // Generate preprocessed output.
14377330f729Sjoerg SmallVector<std::pair<int, const Command *>, 4> FailingCommands;
14387330f729Sjoerg C.ExecuteJobs(C.getJobs(), FailingCommands);
14397330f729Sjoerg
14407330f729Sjoerg // If any of the preprocessing commands failed, clean up and exit.
14417330f729Sjoerg if (!FailingCommands.empty()) {
14427330f729Sjoerg Diag(clang::diag::note_drv_command_failed_diag_msg)
14437330f729Sjoerg << "Error generating preprocessed source(s).";
14447330f729Sjoerg return;
14457330f729Sjoerg }
14467330f729Sjoerg
14477330f729Sjoerg const ArgStringList &TempFiles = C.getTempFiles();
14487330f729Sjoerg if (TempFiles.empty()) {
14497330f729Sjoerg Diag(clang::diag::note_drv_command_failed_diag_msg)
14507330f729Sjoerg << "Error generating preprocessed source(s).";
14517330f729Sjoerg return;
14527330f729Sjoerg }
14537330f729Sjoerg
14547330f729Sjoerg Diag(clang::diag::note_drv_command_failed_diag_msg)
14557330f729Sjoerg << "\n********************\n\n"
14567330f729Sjoerg "PLEASE ATTACH THE FOLLOWING FILES TO THE BUG REPORT:\n"
14577330f729Sjoerg "Preprocessed source(s) and associated run script(s) are located at:";
14587330f729Sjoerg
14597330f729Sjoerg SmallString<128> VFS;
14607330f729Sjoerg SmallString<128> ReproCrashFilename;
14617330f729Sjoerg for (const char *TempFile : TempFiles) {
14627330f729Sjoerg Diag(clang::diag::note_drv_command_failed_diag_msg) << TempFile;
14637330f729Sjoerg if (Report)
14647330f729Sjoerg Report->TemporaryFiles.push_back(TempFile);
14657330f729Sjoerg if (ReproCrashFilename.empty()) {
14667330f729Sjoerg ReproCrashFilename = TempFile;
14677330f729Sjoerg llvm::sys::path::replace_extension(ReproCrashFilename, ".crash");
14687330f729Sjoerg }
14697330f729Sjoerg if (StringRef(TempFile).endswith(".cache")) {
14707330f729Sjoerg // In some cases (modules) we'll dump extra data to help with reproducing
14717330f729Sjoerg // the crash into a directory next to the output.
14727330f729Sjoerg VFS = llvm::sys::path::filename(TempFile);
14737330f729Sjoerg llvm::sys::path::append(VFS, "vfs", "vfs.yaml");
14747330f729Sjoerg }
14757330f729Sjoerg }
14767330f729Sjoerg
14777330f729Sjoerg // Assume associated files are based off of the first temporary file.
14787330f729Sjoerg CrashReportInfo CrashInfo(TempFiles[0], VFS);
14797330f729Sjoerg
14807330f729Sjoerg llvm::SmallString<128> Script(CrashInfo.Filename);
14817330f729Sjoerg llvm::sys::path::replace_extension(Script, "sh");
14827330f729Sjoerg std::error_code EC;
1483*e038c9c4Sjoerg llvm::raw_fd_ostream ScriptOS(Script, EC, llvm::sys::fs::CD_CreateNew,
1484*e038c9c4Sjoerg llvm::sys::fs::FA_Write,
1485*e038c9c4Sjoerg llvm::sys::fs::OF_Text);
14867330f729Sjoerg if (EC) {
14877330f729Sjoerg Diag(clang::diag::note_drv_command_failed_diag_msg)
14887330f729Sjoerg << "Error generating run script: " << Script << " " << EC.message();
14897330f729Sjoerg } else {
14907330f729Sjoerg ScriptOS << "# Crash reproducer for " << getClangFullVersion() << "\n"
14917330f729Sjoerg << "# Driver args: ";
14927330f729Sjoerg printArgList(ScriptOS, C.getInputArgs());
14937330f729Sjoerg ScriptOS << "# Original command: ";
14947330f729Sjoerg Cmd.Print(ScriptOS, "\n", /*Quote=*/true);
14957330f729Sjoerg Cmd.Print(ScriptOS, "\n", /*Quote=*/true, &CrashInfo);
14967330f729Sjoerg if (!AdditionalInformation.empty())
14977330f729Sjoerg ScriptOS << "\n# Additional information: " << AdditionalInformation
14987330f729Sjoerg << "\n";
14997330f729Sjoerg if (Report)
1500*e038c9c4Sjoerg Report->TemporaryFiles.push_back(std::string(Script.str()));
15017330f729Sjoerg Diag(clang::diag::note_drv_command_failed_diag_msg) << Script;
15027330f729Sjoerg }
15037330f729Sjoerg
15047330f729Sjoerg // On darwin, provide information about the .crash diagnostic report.
15057330f729Sjoerg if (llvm::Triple(llvm::sys::getProcessTriple()).isOSDarwin()) {
15067330f729Sjoerg SmallString<128> CrashDiagDir;
15077330f729Sjoerg if (getCrashDiagnosticFile(ReproCrashFilename, CrashDiagDir)) {
15087330f729Sjoerg Diag(clang::diag::note_drv_command_failed_diag_msg)
15097330f729Sjoerg << ReproCrashFilename.str();
15107330f729Sjoerg } else { // Suggest a directory for the user to look for .crash files.
15117330f729Sjoerg llvm::sys::path::append(CrashDiagDir, Name);
15127330f729Sjoerg CrashDiagDir += "_<YYYY-MM-DD-HHMMSS>_<hostname>.crash";
15137330f729Sjoerg Diag(clang::diag::note_drv_command_failed_diag_msg)
15147330f729Sjoerg << "Crash backtrace is located in";
15157330f729Sjoerg Diag(clang::diag::note_drv_command_failed_diag_msg)
15167330f729Sjoerg << CrashDiagDir.str();
15177330f729Sjoerg Diag(clang::diag::note_drv_command_failed_diag_msg)
15187330f729Sjoerg << "(choose the .crash file that corresponds to your crash)";
15197330f729Sjoerg }
15207330f729Sjoerg }
15217330f729Sjoerg
1522*e038c9c4Sjoerg for (const auto &A : C.getArgs().filtered(options::OPT_frewrite_map_file_EQ))
15237330f729Sjoerg Diag(clang::diag::note_drv_command_failed_diag_msg) << A->getValue();
15247330f729Sjoerg
15257330f729Sjoerg Diag(clang::diag::note_drv_command_failed_diag_msg)
15267330f729Sjoerg << "\n\n********************";
15277330f729Sjoerg }
15287330f729Sjoerg
setUpResponseFiles(Compilation & C,Command & Cmd)15297330f729Sjoerg void Driver::setUpResponseFiles(Compilation &C, Command &Cmd) {
15307330f729Sjoerg // Since commandLineFitsWithinSystemLimits() may underestimate system's
15317330f729Sjoerg // capacity if the tool does not support response files, there is a chance/
15327330f729Sjoerg // that things will just work without a response file, so we silently just
15337330f729Sjoerg // skip it.
1534*e038c9c4Sjoerg if (Cmd.getResponseFileSupport().ResponseKind ==
1535*e038c9c4Sjoerg ResponseFileSupport::RF_None ||
15367330f729Sjoerg llvm::sys::commandLineFitsWithinSystemLimits(Cmd.getExecutable(),
15377330f729Sjoerg Cmd.getArguments()))
15387330f729Sjoerg return;
15397330f729Sjoerg
15407330f729Sjoerg std::string TmpName = GetTemporaryPath("response", "txt");
15417330f729Sjoerg Cmd.setResponseFile(C.addTempFile(C.getArgs().MakeArgString(TmpName)));
15427330f729Sjoerg }
15437330f729Sjoerg
ExecuteCompilation(Compilation & C,SmallVectorImpl<std::pair<int,const Command * >> & FailingCommands)15447330f729Sjoerg int Driver::ExecuteCompilation(
15457330f729Sjoerg Compilation &C,
15467330f729Sjoerg SmallVectorImpl<std::pair<int, const Command *>> &FailingCommands) {
15477330f729Sjoerg // Just print if -### was present.
15487330f729Sjoerg if (C.getArgs().hasArg(options::OPT__HASH_HASH_HASH)) {
15497330f729Sjoerg C.getJobs().Print(llvm::errs(), "\n", true);
15507330f729Sjoerg return 0;
15517330f729Sjoerg }
15527330f729Sjoerg
15537330f729Sjoerg // If there were errors building the compilation, quit now.
15547330f729Sjoerg if (Diags.hasErrorOccurred())
15557330f729Sjoerg return 1;
15567330f729Sjoerg
15577330f729Sjoerg // Set up response file names for each command, if necessary
15587330f729Sjoerg for (auto &Job : C.getJobs())
15597330f729Sjoerg setUpResponseFiles(C, Job);
15607330f729Sjoerg
15617330f729Sjoerg C.ExecuteJobs(C.getJobs(), FailingCommands);
15627330f729Sjoerg
15637330f729Sjoerg // If the command succeeded, we are done.
15647330f729Sjoerg if (FailingCommands.empty())
15657330f729Sjoerg return 0;
15667330f729Sjoerg
15677330f729Sjoerg // Otherwise, remove result files and print extra information about abnormal
15687330f729Sjoerg // failures.
15697330f729Sjoerg int Res = 0;
15707330f729Sjoerg for (const auto &CmdPair : FailingCommands) {
15717330f729Sjoerg int CommandRes = CmdPair.first;
15727330f729Sjoerg const Command *FailingCommand = CmdPair.second;
15737330f729Sjoerg
15747330f729Sjoerg // Remove result files if we're not saving temps.
15757330f729Sjoerg if (!isSaveTempsEnabled()) {
15767330f729Sjoerg const JobAction *JA = cast<JobAction>(&FailingCommand->getSource());
15777330f729Sjoerg C.CleanupFileMap(C.getResultFiles(), JA, true);
15787330f729Sjoerg
15797330f729Sjoerg // Failure result files are valid unless we crashed.
15807330f729Sjoerg if (CommandRes < 0)
15817330f729Sjoerg C.CleanupFileMap(C.getFailureResultFiles(), JA, true);
15827330f729Sjoerg }
15837330f729Sjoerg
15847330f729Sjoerg #if LLVM_ON_UNIX
15857330f729Sjoerg // llvm/lib/Support/Unix/Signals.inc will exit with a special return code
15867330f729Sjoerg // for SIGPIPE. Do not print diagnostics for this case.
15877330f729Sjoerg if (CommandRes == EX_IOERR) {
15887330f729Sjoerg Res = CommandRes;
15897330f729Sjoerg continue;
15907330f729Sjoerg }
15917330f729Sjoerg #endif
15927330f729Sjoerg
15937330f729Sjoerg // Print extra information about abnormal failures, if possible.
15947330f729Sjoerg //
15957330f729Sjoerg // This is ad-hoc, but we don't want to be excessively noisy. If the result
15967330f729Sjoerg // status was 1, assume the command failed normally. In particular, if it
15977330f729Sjoerg // was the compiler then assume it gave a reasonable error code. Failures
15987330f729Sjoerg // in other tools are less common, and they generally have worse
15997330f729Sjoerg // diagnostics, so always print the diagnostic there.
16007330f729Sjoerg const Tool &FailingTool = FailingCommand->getCreator();
16017330f729Sjoerg
16027330f729Sjoerg if (!FailingCommand->getCreator().hasGoodDiagnostics() || CommandRes != 1) {
16037330f729Sjoerg // FIXME: See FIXME above regarding result code interpretation.
16047330f729Sjoerg if (CommandRes < 0)
16057330f729Sjoerg Diag(clang::diag::err_drv_command_signalled)
16067330f729Sjoerg << FailingTool.getShortName();
16077330f729Sjoerg else
16087330f729Sjoerg Diag(clang::diag::err_drv_command_failed)
16097330f729Sjoerg << FailingTool.getShortName() << CommandRes;
16107330f729Sjoerg }
16117330f729Sjoerg }
16127330f729Sjoerg return Res;
16137330f729Sjoerg }
16147330f729Sjoerg
PrintHelp(bool ShowHidden) const16157330f729Sjoerg void Driver::PrintHelp(bool ShowHidden) const {
16167330f729Sjoerg unsigned IncludedFlagsBitmask;
16177330f729Sjoerg unsigned ExcludedFlagsBitmask;
16187330f729Sjoerg std::tie(IncludedFlagsBitmask, ExcludedFlagsBitmask) =
16197330f729Sjoerg getIncludeExcludeOptionFlagMasks(IsCLMode());
16207330f729Sjoerg
16217330f729Sjoerg ExcludedFlagsBitmask |= options::NoDriverOption;
16227330f729Sjoerg if (!ShowHidden)
16237330f729Sjoerg ExcludedFlagsBitmask |= HelpHidden;
16247330f729Sjoerg
1625*e038c9c4Sjoerg if (IsFlangMode())
1626*e038c9c4Sjoerg IncludedFlagsBitmask |= options::FlangOption;
1627*e038c9c4Sjoerg else
1628*e038c9c4Sjoerg ExcludedFlagsBitmask |= options::FlangOnlyOption;
1629*e038c9c4Sjoerg
16307330f729Sjoerg std::string Usage = llvm::formatv("{0} [options] file...", Name).str();
16317330f729Sjoerg getOpts().PrintHelp(llvm::outs(), Usage.c_str(), DriverTitle.c_str(),
16327330f729Sjoerg IncludedFlagsBitmask, ExcludedFlagsBitmask,
16337330f729Sjoerg /*ShowAllAliases=*/false);
16347330f729Sjoerg }
16357330f729Sjoerg
PrintVersion(const Compilation & C,raw_ostream & OS) const16367330f729Sjoerg void Driver::PrintVersion(const Compilation &C, raw_ostream &OS) const {
1637*e038c9c4Sjoerg if (IsFlangMode()) {
1638*e038c9c4Sjoerg OS << getClangToolFullVersion("flang-new") << '\n';
1639*e038c9c4Sjoerg } else {
16407330f729Sjoerg // FIXME: The following handlers should use a callback mechanism, we don't
16417330f729Sjoerg // know what the client would like to do.
16427330f729Sjoerg OS << getClangFullVersion() << '\n';
1643*e038c9c4Sjoerg }
16447330f729Sjoerg const ToolChain &TC = C.getDefaultToolChain();
16457330f729Sjoerg OS << "Target: " << TC.getTripleString() << '\n';
16467330f729Sjoerg
16477330f729Sjoerg // Print the threading model.
16487330f729Sjoerg if (Arg *A = C.getArgs().getLastArg(options::OPT_mthread_model)) {
16497330f729Sjoerg // Don't print if the ToolChain would have barfed on it already
16507330f729Sjoerg if (TC.isThreadModelSupported(A->getValue()))
16517330f729Sjoerg OS << "Thread model: " << A->getValue();
16527330f729Sjoerg } else
16537330f729Sjoerg OS << "Thread model: " << TC.getThreadModel();
16547330f729Sjoerg OS << '\n';
16557330f729Sjoerg
16567330f729Sjoerg // Print out the install directory.
16577330f729Sjoerg OS << "InstalledDir: " << InstalledDir << '\n';
16587330f729Sjoerg
16597330f729Sjoerg // If configuration file was used, print its path.
16607330f729Sjoerg if (!ConfigFile.empty())
16617330f729Sjoerg OS << "Configuration file: " << ConfigFile << '\n';
16627330f729Sjoerg }
16637330f729Sjoerg
16647330f729Sjoerg /// PrintDiagnosticCategories - Implement the --print-diagnostic-categories
16657330f729Sjoerg /// option.
PrintDiagnosticCategories(raw_ostream & OS)16667330f729Sjoerg static void PrintDiagnosticCategories(raw_ostream &OS) {
16677330f729Sjoerg // Skip the empty category.
16687330f729Sjoerg for (unsigned i = 1, max = DiagnosticIDs::getNumberOfCategories(); i != max;
16697330f729Sjoerg ++i)
16707330f729Sjoerg OS << i << ',' << DiagnosticIDs::getCategoryNameFromID(i) << '\n';
16717330f729Sjoerg }
16727330f729Sjoerg
HandleAutocompletions(StringRef PassedFlags) const16737330f729Sjoerg void Driver::HandleAutocompletions(StringRef PassedFlags) const {
16747330f729Sjoerg if (PassedFlags == "")
16757330f729Sjoerg return;
16767330f729Sjoerg // Print out all options that start with a given argument. This is used for
16777330f729Sjoerg // shell autocompletion.
16787330f729Sjoerg std::vector<std::string> SuggestedCompletions;
16797330f729Sjoerg std::vector<std::string> Flags;
16807330f729Sjoerg
1681*e038c9c4Sjoerg unsigned int DisableFlags =
16827330f729Sjoerg options::NoDriverOption | options::Unsupported | options::Ignored;
16837330f729Sjoerg
1684*e038c9c4Sjoerg // Make sure that Flang-only options don't pollute the Clang output
1685*e038c9c4Sjoerg // TODO: Make sure that Clang-only options don't pollute Flang output
1686*e038c9c4Sjoerg if (!IsFlangMode())
1687*e038c9c4Sjoerg DisableFlags |= options::FlangOnlyOption;
1688*e038c9c4Sjoerg
16897330f729Sjoerg // Distinguish "--autocomplete=-someflag" and "--autocomplete=-someflag,"
16907330f729Sjoerg // because the latter indicates that the user put space before pushing tab
16917330f729Sjoerg // which should end up in a file completion.
16927330f729Sjoerg const bool HasSpace = PassedFlags.endswith(",");
16937330f729Sjoerg
16947330f729Sjoerg // Parse PassedFlags by "," as all the command-line flags are passed to this
16957330f729Sjoerg // function separated by ","
16967330f729Sjoerg StringRef TargetFlags = PassedFlags;
16977330f729Sjoerg while (TargetFlags != "") {
16987330f729Sjoerg StringRef CurFlag;
16997330f729Sjoerg std::tie(CurFlag, TargetFlags) = TargetFlags.split(",");
17007330f729Sjoerg Flags.push_back(std::string(CurFlag));
17017330f729Sjoerg }
17027330f729Sjoerg
17037330f729Sjoerg // We want to show cc1-only options only when clang is invoked with -cc1 or
17047330f729Sjoerg // -Xclang.
17057330f729Sjoerg if (llvm::is_contained(Flags, "-Xclang") || llvm::is_contained(Flags, "-cc1"))
17067330f729Sjoerg DisableFlags &= ~options::NoDriverOption;
17077330f729Sjoerg
17087330f729Sjoerg const llvm::opt::OptTable &Opts = getOpts();
17097330f729Sjoerg StringRef Cur;
17107330f729Sjoerg Cur = Flags.at(Flags.size() - 1);
17117330f729Sjoerg StringRef Prev;
17127330f729Sjoerg if (Flags.size() >= 2) {
17137330f729Sjoerg Prev = Flags.at(Flags.size() - 2);
17147330f729Sjoerg SuggestedCompletions = Opts.suggestValueCompletions(Prev, Cur);
17157330f729Sjoerg }
17167330f729Sjoerg
17177330f729Sjoerg if (SuggestedCompletions.empty())
17187330f729Sjoerg SuggestedCompletions = Opts.suggestValueCompletions(Cur, "");
17197330f729Sjoerg
17207330f729Sjoerg // If Flags were empty, it means the user typed `clang [tab]` where we should
17217330f729Sjoerg // list all possible flags. If there was no value completion and the user
17227330f729Sjoerg // pressed tab after a space, we should fall back to a file completion.
17237330f729Sjoerg // We're printing a newline to be consistent with what we print at the end of
17247330f729Sjoerg // this function.
17257330f729Sjoerg if (SuggestedCompletions.empty() && HasSpace && !Flags.empty()) {
17267330f729Sjoerg llvm::outs() << '\n';
17277330f729Sjoerg return;
17287330f729Sjoerg }
17297330f729Sjoerg
17307330f729Sjoerg // When flag ends with '=' and there was no value completion, return empty
17317330f729Sjoerg // string and fall back to the file autocompletion.
17327330f729Sjoerg if (SuggestedCompletions.empty() && !Cur.endswith("=")) {
17337330f729Sjoerg // If the flag is in the form of "--autocomplete=-foo",
17347330f729Sjoerg // we were requested to print out all option names that start with "-foo".
17357330f729Sjoerg // For example, "--autocomplete=-fsyn" is expanded to "-fsyntax-only".
17367330f729Sjoerg SuggestedCompletions = Opts.findByPrefix(Cur, DisableFlags);
17377330f729Sjoerg
17387330f729Sjoerg // We have to query the -W flags manually as they're not in the OptTable.
17397330f729Sjoerg // TODO: Find a good way to add them to OptTable instead and them remove
17407330f729Sjoerg // this code.
17417330f729Sjoerg for (StringRef S : DiagnosticIDs::getDiagnosticFlags())
17427330f729Sjoerg if (S.startswith(Cur))
1743*e038c9c4Sjoerg SuggestedCompletions.push_back(std::string(S));
17447330f729Sjoerg }
17457330f729Sjoerg
17467330f729Sjoerg // Sort the autocomplete candidates so that shells print them out in a
17477330f729Sjoerg // deterministic order. We could sort in any way, but we chose
17487330f729Sjoerg // case-insensitive sorting for consistency with the -help option
17497330f729Sjoerg // which prints out options in the case-insensitive alphabetical order.
17507330f729Sjoerg llvm::sort(SuggestedCompletions, [](StringRef A, StringRef B) {
17517330f729Sjoerg if (int X = A.compare_lower(B))
17527330f729Sjoerg return X < 0;
17537330f729Sjoerg return A.compare(B) > 0;
17547330f729Sjoerg });
17557330f729Sjoerg
17567330f729Sjoerg llvm::outs() << llvm::join(SuggestedCompletions, "\n") << '\n';
17577330f729Sjoerg }
17587330f729Sjoerg
HandleImmediateArgs(const Compilation & C)17597330f729Sjoerg bool Driver::HandleImmediateArgs(const Compilation &C) {
17607330f729Sjoerg // The order these options are handled in gcc is all over the place, but we
17617330f729Sjoerg // don't expect inconsistencies w.r.t. that to matter in practice.
17627330f729Sjoerg
17637330f729Sjoerg if (C.getArgs().hasArg(options::OPT_dumpmachine)) {
17647330f729Sjoerg llvm::outs() << C.getDefaultToolChain().getTripleString() << '\n';
17657330f729Sjoerg return false;
17667330f729Sjoerg }
17677330f729Sjoerg
17687330f729Sjoerg if (C.getArgs().hasArg(options::OPT_dumpversion)) {
17697330f729Sjoerg // Since -dumpversion is only implemented for pedantic GCC compatibility, we
17707330f729Sjoerg // return an answer which matches our definition of __VERSION__.
17717330f729Sjoerg llvm::outs() << CLANG_VERSION_STRING << "\n";
17727330f729Sjoerg return false;
17737330f729Sjoerg }
17747330f729Sjoerg
17757330f729Sjoerg if (C.getArgs().hasArg(options::OPT__print_diagnostic_categories)) {
17767330f729Sjoerg PrintDiagnosticCategories(llvm::outs());
17777330f729Sjoerg return false;
17787330f729Sjoerg }
17797330f729Sjoerg
17807330f729Sjoerg if (C.getArgs().hasArg(options::OPT_help) ||
17817330f729Sjoerg C.getArgs().hasArg(options::OPT__help_hidden)) {
17827330f729Sjoerg PrintHelp(C.getArgs().hasArg(options::OPT__help_hidden));
17837330f729Sjoerg return false;
17847330f729Sjoerg }
17857330f729Sjoerg
17867330f729Sjoerg if (C.getArgs().hasArg(options::OPT__version)) {
17877330f729Sjoerg // Follow gcc behavior and use stdout for --version and stderr for -v.
17887330f729Sjoerg PrintVersion(C, llvm::outs());
17897330f729Sjoerg return false;
17907330f729Sjoerg }
17917330f729Sjoerg
17927330f729Sjoerg if (C.getArgs().hasArg(options::OPT_v) ||
17937330f729Sjoerg C.getArgs().hasArg(options::OPT__HASH_HASH_HASH) ||
17947330f729Sjoerg C.getArgs().hasArg(options::OPT_print_supported_cpus)) {
17957330f729Sjoerg PrintVersion(C, llvm::errs());
17967330f729Sjoerg SuppressMissingInputWarning = true;
17977330f729Sjoerg }
17987330f729Sjoerg
17997330f729Sjoerg if (C.getArgs().hasArg(options::OPT_v)) {
18007330f729Sjoerg if (!SystemConfigDir.empty())
18017330f729Sjoerg llvm::errs() << "System configuration file directory: "
18027330f729Sjoerg << SystemConfigDir << "\n";
18037330f729Sjoerg if (!UserConfigDir.empty())
18047330f729Sjoerg llvm::errs() << "User configuration file directory: "
18057330f729Sjoerg << UserConfigDir << "\n";
18067330f729Sjoerg }
18077330f729Sjoerg
18087330f729Sjoerg const ToolChain &TC = C.getDefaultToolChain();
18097330f729Sjoerg
18107330f729Sjoerg if (C.getArgs().hasArg(options::OPT_v))
18117330f729Sjoerg TC.printVerboseInfo(llvm::errs());
18127330f729Sjoerg
18137330f729Sjoerg if (C.getArgs().hasArg(options::OPT_print_resource_dir)) {
18147330f729Sjoerg llvm::outs() << ResourceDir << '\n';
18157330f729Sjoerg return false;
18167330f729Sjoerg }
18177330f729Sjoerg
18187330f729Sjoerg if (C.getArgs().hasArg(options::OPT_print_search_dirs)) {
18197330f729Sjoerg llvm::outs() << "programs: =";
18207330f729Sjoerg bool separator = false;
1821*e038c9c4Sjoerg // Print -B and COMPILER_PATH.
1822*e038c9c4Sjoerg for (const std::string &Path : PrefixDirs) {
1823*e038c9c4Sjoerg if (separator)
1824*e038c9c4Sjoerg llvm::outs() << llvm::sys::EnvPathSeparator;
1825*e038c9c4Sjoerg llvm::outs() << Path;
1826*e038c9c4Sjoerg separator = true;
1827*e038c9c4Sjoerg }
18287330f729Sjoerg for (const std::string &Path : TC.getProgramPaths()) {
18297330f729Sjoerg if (separator)
18307330f729Sjoerg llvm::outs() << llvm::sys::EnvPathSeparator;
18317330f729Sjoerg llvm::outs() << Path;
18327330f729Sjoerg separator = true;
18337330f729Sjoerg }
18347330f729Sjoerg llvm::outs() << "\n";
18357330f729Sjoerg llvm::outs() << "libraries: =" << ResourceDir;
18367330f729Sjoerg
18377330f729Sjoerg StringRef sysroot = C.getSysRoot();
18387330f729Sjoerg
18397330f729Sjoerg for (const std::string &Path : TC.getFilePaths()) {
18407330f729Sjoerg // Always print a separator. ResourceDir was the first item shown.
18417330f729Sjoerg llvm::outs() << llvm::sys::EnvPathSeparator;
18427330f729Sjoerg // Interpretation of leading '=' is needed only for NetBSD.
18437330f729Sjoerg if (Path[0] == '=')
18447330f729Sjoerg llvm::outs() << sysroot << Path.substr(1);
18457330f729Sjoerg else
18467330f729Sjoerg llvm::outs() << Path;
18477330f729Sjoerg }
18487330f729Sjoerg llvm::outs() << "\n";
18497330f729Sjoerg return false;
18507330f729Sjoerg }
18517330f729Sjoerg
1852*e038c9c4Sjoerg if (C.getArgs().hasArg(options::OPT_print_runtime_dir)) {
1853*e038c9c4Sjoerg std::string CandidateRuntimePath = TC.getRuntimePath();
1854*e038c9c4Sjoerg if (getVFS().exists(CandidateRuntimePath))
1855*e038c9c4Sjoerg llvm::outs() << CandidateRuntimePath << '\n';
1856*e038c9c4Sjoerg else
1857*e038c9c4Sjoerg llvm::outs() << TC.getCompilerRTPath() << '\n';
1858*e038c9c4Sjoerg return false;
1859*e038c9c4Sjoerg }
1860*e038c9c4Sjoerg
18617330f729Sjoerg // FIXME: The following handlers should use a callback mechanism, we don't
18627330f729Sjoerg // know what the client would like to do.
18637330f729Sjoerg if (Arg *A = C.getArgs().getLastArg(options::OPT_print_file_name_EQ)) {
18647330f729Sjoerg llvm::outs() << GetFilePath(A->getValue(), TC) << "\n";
18657330f729Sjoerg return false;
18667330f729Sjoerg }
18677330f729Sjoerg
18687330f729Sjoerg if (Arg *A = C.getArgs().getLastArg(options::OPT_print_prog_name_EQ)) {
18697330f729Sjoerg StringRef ProgName = A->getValue();
18707330f729Sjoerg
18717330f729Sjoerg // Null program name cannot have a path.
18727330f729Sjoerg if (! ProgName.empty())
18737330f729Sjoerg llvm::outs() << GetProgramPath(ProgName, TC);
18747330f729Sjoerg
18757330f729Sjoerg llvm::outs() << "\n";
18767330f729Sjoerg return false;
18777330f729Sjoerg }
18787330f729Sjoerg
18797330f729Sjoerg if (Arg *A = C.getArgs().getLastArg(options::OPT_autocomplete)) {
18807330f729Sjoerg StringRef PassedFlags = A->getValue();
18817330f729Sjoerg HandleAutocompletions(PassedFlags);
18827330f729Sjoerg return false;
18837330f729Sjoerg }
18847330f729Sjoerg
18857330f729Sjoerg if (C.getArgs().hasArg(options::OPT_print_libgcc_file_name)) {
18867330f729Sjoerg ToolChain::RuntimeLibType RLT = TC.GetRuntimeLibType(C.getArgs());
18877330f729Sjoerg const llvm::Triple Triple(TC.ComputeEffectiveClangTriple(C.getArgs()));
18887330f729Sjoerg RegisterEffectiveTriple TripleRAII(TC, Triple);
18897330f729Sjoerg switch (RLT) {
18907330f729Sjoerg case ToolChain::RLT_CompilerRT:
18917330f729Sjoerg llvm::outs() << TC.getCompilerRT(C.getArgs(), "builtins") << "\n";
18927330f729Sjoerg break;
18937330f729Sjoerg case ToolChain::RLT_Libgcc:
18947330f729Sjoerg llvm::outs() << GetFilePath("libgcc.a", TC) << "\n";
18957330f729Sjoerg break;
18967330f729Sjoerg }
18977330f729Sjoerg return false;
18987330f729Sjoerg }
18997330f729Sjoerg
19007330f729Sjoerg if (C.getArgs().hasArg(options::OPT_print_multi_lib)) {
19017330f729Sjoerg for (const Multilib &Multilib : TC.getMultilibs())
19027330f729Sjoerg llvm::outs() << Multilib << "\n";
19037330f729Sjoerg return false;
19047330f729Sjoerg }
19057330f729Sjoerg
19067330f729Sjoerg if (C.getArgs().hasArg(options::OPT_print_multi_directory)) {
19077330f729Sjoerg const Multilib &Multilib = TC.getMultilib();
19087330f729Sjoerg if (Multilib.gccSuffix().empty())
19097330f729Sjoerg llvm::outs() << ".\n";
19107330f729Sjoerg else {
19117330f729Sjoerg StringRef Suffix(Multilib.gccSuffix());
19127330f729Sjoerg assert(Suffix.front() == '/');
19137330f729Sjoerg llvm::outs() << Suffix.substr(1) << "\n";
19147330f729Sjoerg }
19157330f729Sjoerg return false;
19167330f729Sjoerg }
19177330f729Sjoerg
19187330f729Sjoerg if (C.getArgs().hasArg(options::OPT_print_target_triple)) {
19197330f729Sjoerg llvm::outs() << TC.getTripleString() << "\n";
19207330f729Sjoerg return false;
19217330f729Sjoerg }
19227330f729Sjoerg
19237330f729Sjoerg if (C.getArgs().hasArg(options::OPT_print_effective_triple)) {
19247330f729Sjoerg const llvm::Triple Triple(TC.ComputeEffectiveClangTriple(C.getArgs()));
19257330f729Sjoerg llvm::outs() << Triple.getTriple() << "\n";
19267330f729Sjoerg return false;
19277330f729Sjoerg }
19287330f729Sjoerg
1929*e038c9c4Sjoerg if (C.getArgs().hasArg(options::OPT_print_multiarch)) {
1930*e038c9c4Sjoerg llvm::outs() << TC.getMultiarchTriple(*this, TC.getTriple(), SysRoot)
1931*e038c9c4Sjoerg << "\n";
1932*e038c9c4Sjoerg return false;
1933*e038c9c4Sjoerg }
1934*e038c9c4Sjoerg
1935*e038c9c4Sjoerg if (C.getArgs().hasArg(options::OPT_print_targets)) {
1936*e038c9c4Sjoerg llvm::TargetRegistry::printRegisteredTargetsForVersion(llvm::outs());
1937*e038c9c4Sjoerg return false;
1938*e038c9c4Sjoerg }
1939*e038c9c4Sjoerg
19407330f729Sjoerg return true;
19417330f729Sjoerg }
19427330f729Sjoerg
19437330f729Sjoerg enum {
19447330f729Sjoerg TopLevelAction = 0,
19457330f729Sjoerg HeadSibAction = 1,
19467330f729Sjoerg OtherSibAction = 2,
19477330f729Sjoerg };
19487330f729Sjoerg
19497330f729Sjoerg // Display an action graph human-readably. Action A is the "sink" node
19507330f729Sjoerg // and latest-occuring action. Traversal is in pre-order, visiting the
19517330f729Sjoerg // inputs to each action before printing the action itself.
PrintActions1(const Compilation & C,Action * A,std::map<Action *,unsigned> & Ids,Twine Indent={},int Kind=TopLevelAction)19527330f729Sjoerg static unsigned PrintActions1(const Compilation &C, Action *A,
19537330f729Sjoerg std::map<Action *, unsigned> &Ids,
19547330f729Sjoerg Twine Indent = {}, int Kind = TopLevelAction) {
19557330f729Sjoerg if (Ids.count(A)) // A was already visited.
19567330f729Sjoerg return Ids[A];
19577330f729Sjoerg
19587330f729Sjoerg std::string str;
19597330f729Sjoerg llvm::raw_string_ostream os(str);
19607330f729Sjoerg
__anon51bf6f8c0702(int K) 19617330f729Sjoerg auto getSibIndent = [](int K) -> Twine {
19627330f729Sjoerg return (K == HeadSibAction) ? " " : (K == OtherSibAction) ? "| " : "";
19637330f729Sjoerg };
19647330f729Sjoerg
19657330f729Sjoerg Twine SibIndent = Indent + getSibIndent(Kind);
19667330f729Sjoerg int SibKind = HeadSibAction;
19677330f729Sjoerg os << Action::getClassName(A->getKind()) << ", ";
19687330f729Sjoerg if (InputAction *IA = dyn_cast<InputAction>(A)) {
19697330f729Sjoerg os << "\"" << IA->getInputArg().getValue() << "\"";
19707330f729Sjoerg } else if (BindArchAction *BIA = dyn_cast<BindArchAction>(A)) {
19717330f729Sjoerg os << '"' << BIA->getArchName() << '"' << ", {"
19727330f729Sjoerg << PrintActions1(C, *BIA->input_begin(), Ids, SibIndent, SibKind) << "}";
19737330f729Sjoerg } else if (OffloadAction *OA = dyn_cast<OffloadAction>(A)) {
19747330f729Sjoerg bool IsFirst = true;
19757330f729Sjoerg OA->doOnEachDependence(
__anon51bf6f8c0802(Action *A, const ToolChain *TC, const char *BoundArch) 19767330f729Sjoerg [&](Action *A, const ToolChain *TC, const char *BoundArch) {
1977*e038c9c4Sjoerg assert(TC && "Unknown host toolchain");
19787330f729Sjoerg // E.g. for two CUDA device dependences whose bound arch is sm_20 and
19797330f729Sjoerg // sm_35 this will generate:
19807330f729Sjoerg // "cuda-device" (nvptx64-nvidia-cuda:sm_20) {#ID}, "cuda-device"
19817330f729Sjoerg // (nvptx64-nvidia-cuda:sm_35) {#ID}
19827330f729Sjoerg if (!IsFirst)
19837330f729Sjoerg os << ", ";
19847330f729Sjoerg os << '"';
19857330f729Sjoerg os << A->getOffloadingKindPrefix();
19867330f729Sjoerg os << " (";
19877330f729Sjoerg os << TC->getTriple().normalize();
19887330f729Sjoerg if (BoundArch)
19897330f729Sjoerg os << ":" << BoundArch;
19907330f729Sjoerg os << ")";
19917330f729Sjoerg os << '"';
19927330f729Sjoerg os << " {" << PrintActions1(C, A, Ids, SibIndent, SibKind) << "}";
19937330f729Sjoerg IsFirst = false;
19947330f729Sjoerg SibKind = OtherSibAction;
19957330f729Sjoerg });
19967330f729Sjoerg } else {
19977330f729Sjoerg const ActionList *AL = &A->getInputs();
19987330f729Sjoerg
19997330f729Sjoerg if (AL->size()) {
20007330f729Sjoerg const char *Prefix = "{";
20017330f729Sjoerg for (Action *PreRequisite : *AL) {
20027330f729Sjoerg os << Prefix << PrintActions1(C, PreRequisite, Ids, SibIndent, SibKind);
20037330f729Sjoerg Prefix = ", ";
20047330f729Sjoerg SibKind = OtherSibAction;
20057330f729Sjoerg }
20067330f729Sjoerg os << "}";
20077330f729Sjoerg } else
20087330f729Sjoerg os << "{}";
20097330f729Sjoerg }
20107330f729Sjoerg
20117330f729Sjoerg // Append offload info for all options other than the offloading action
20127330f729Sjoerg // itself (e.g. (cuda-device, sm_20) or (cuda-host)).
20137330f729Sjoerg std::string offload_str;
20147330f729Sjoerg llvm::raw_string_ostream offload_os(offload_str);
20157330f729Sjoerg if (!isa<OffloadAction>(A)) {
20167330f729Sjoerg auto S = A->getOffloadingKindPrefix();
20177330f729Sjoerg if (!S.empty()) {
20187330f729Sjoerg offload_os << ", (" << S;
20197330f729Sjoerg if (A->getOffloadingArch())
20207330f729Sjoerg offload_os << ", " << A->getOffloadingArch();
20217330f729Sjoerg offload_os << ")";
20227330f729Sjoerg }
20237330f729Sjoerg }
20247330f729Sjoerg
__anon51bf6f8c0902(int K) 20257330f729Sjoerg auto getSelfIndent = [](int K) -> Twine {
20267330f729Sjoerg return (K == HeadSibAction) ? "+- " : (K == OtherSibAction) ? "|- " : "";
20277330f729Sjoerg };
20287330f729Sjoerg
20297330f729Sjoerg unsigned Id = Ids.size();
20307330f729Sjoerg Ids[A] = Id;
20317330f729Sjoerg llvm::errs() << Indent + getSelfIndent(Kind) << Id << ": " << os.str() << ", "
20327330f729Sjoerg << types::getTypeName(A->getType()) << offload_os.str() << "\n";
20337330f729Sjoerg
20347330f729Sjoerg return Id;
20357330f729Sjoerg }
20367330f729Sjoerg
20377330f729Sjoerg // Print the action graphs in a compilation C.
20387330f729Sjoerg // For example "clang -c file1.c file2.c" is composed of two subgraphs.
PrintActions(const Compilation & C) const20397330f729Sjoerg void Driver::PrintActions(const Compilation &C) const {
20407330f729Sjoerg std::map<Action *, unsigned> Ids;
20417330f729Sjoerg for (Action *A : C.getActions())
20427330f729Sjoerg PrintActions1(C, A, Ids);
20437330f729Sjoerg }
20447330f729Sjoerg
20457330f729Sjoerg /// Check whether the given input tree contains any compilation or
20467330f729Sjoerg /// assembly actions.
ContainsCompileOrAssembleAction(const Action * A)20477330f729Sjoerg static bool ContainsCompileOrAssembleAction(const Action *A) {
20487330f729Sjoerg if (isa<CompileJobAction>(A) || isa<BackendJobAction>(A) ||
20497330f729Sjoerg isa<AssembleJobAction>(A))
20507330f729Sjoerg return true;
20517330f729Sjoerg
20527330f729Sjoerg for (const Action *Input : A->inputs())
20537330f729Sjoerg if (ContainsCompileOrAssembleAction(Input))
20547330f729Sjoerg return true;
20557330f729Sjoerg
20567330f729Sjoerg return false;
20577330f729Sjoerg }
20587330f729Sjoerg
BuildUniversalActions(Compilation & C,const ToolChain & TC,const InputList & BAInputs) const20597330f729Sjoerg void Driver::BuildUniversalActions(Compilation &C, const ToolChain &TC,
20607330f729Sjoerg const InputList &BAInputs) const {
20617330f729Sjoerg DerivedArgList &Args = C.getArgs();
20627330f729Sjoerg ActionList &Actions = C.getActions();
20637330f729Sjoerg llvm::PrettyStackTraceString CrashInfo("Building universal build actions");
20647330f729Sjoerg // Collect the list of architectures. Duplicates are allowed, but should only
20657330f729Sjoerg // be handled once (in the order seen).
20667330f729Sjoerg llvm::StringSet<> ArchNames;
20677330f729Sjoerg SmallVector<const char *, 4> Archs;
20687330f729Sjoerg for (Arg *A : Args) {
20697330f729Sjoerg if (A->getOption().matches(options::OPT_arch)) {
20707330f729Sjoerg // Validate the option here; we don't save the type here because its
20717330f729Sjoerg // particular spelling may participate in other driver choices.
20727330f729Sjoerg llvm::Triple::ArchType Arch =
20737330f729Sjoerg tools::darwin::getArchTypeForMachOArchName(A->getValue());
20747330f729Sjoerg if (Arch == llvm::Triple::UnknownArch) {
20757330f729Sjoerg Diag(clang::diag::err_drv_invalid_arch_name) << A->getAsString(Args);
20767330f729Sjoerg continue;
20777330f729Sjoerg }
20787330f729Sjoerg
20797330f729Sjoerg A->claim();
20807330f729Sjoerg if (ArchNames.insert(A->getValue()).second)
20817330f729Sjoerg Archs.push_back(A->getValue());
20827330f729Sjoerg }
20837330f729Sjoerg }
20847330f729Sjoerg
20857330f729Sjoerg // When there is no explicit arch for this platform, make sure we still bind
20867330f729Sjoerg // the architecture (to the default) so that -Xarch_ is handled correctly.
20877330f729Sjoerg if (!Archs.size())
20887330f729Sjoerg Archs.push_back(Args.MakeArgString(TC.getDefaultUniversalArchName()));
20897330f729Sjoerg
20907330f729Sjoerg ActionList SingleActions;
20917330f729Sjoerg BuildActions(C, Args, BAInputs, SingleActions);
20927330f729Sjoerg
20937330f729Sjoerg // Add in arch bindings for every top level action, as well as lipo and
20947330f729Sjoerg // dsymutil steps if needed.
20957330f729Sjoerg for (Action* Act : SingleActions) {
20967330f729Sjoerg // Make sure we can lipo this kind of output. If not (and it is an actual
20977330f729Sjoerg // output) then we disallow, since we can't create an output file with the
20987330f729Sjoerg // right name without overwriting it. We could remove this oddity by just
20997330f729Sjoerg // changing the output names to include the arch, which would also fix
21007330f729Sjoerg // -save-temps. Compatibility wins for now.
21017330f729Sjoerg
21027330f729Sjoerg if (Archs.size() > 1 && !types::canLipoType(Act->getType()))
21037330f729Sjoerg Diag(clang::diag::err_drv_invalid_output_with_multiple_archs)
21047330f729Sjoerg << types::getTypeName(Act->getType());
21057330f729Sjoerg
21067330f729Sjoerg ActionList Inputs;
21077330f729Sjoerg for (unsigned i = 0, e = Archs.size(); i != e; ++i)
21087330f729Sjoerg Inputs.push_back(C.MakeAction<BindArchAction>(Act, Archs[i]));
21097330f729Sjoerg
21107330f729Sjoerg // Lipo if necessary, we do it this way because we need to set the arch flag
21117330f729Sjoerg // so that -Xarch_ gets overwritten.
21127330f729Sjoerg if (Inputs.size() == 1 || Act->getType() == types::TY_Nothing)
21137330f729Sjoerg Actions.append(Inputs.begin(), Inputs.end());
21147330f729Sjoerg else
21157330f729Sjoerg Actions.push_back(C.MakeAction<LipoJobAction>(Inputs, Act->getType()));
21167330f729Sjoerg
21177330f729Sjoerg // Handle debug info queries.
21187330f729Sjoerg Arg *A = Args.getLastArg(options::OPT_g_Group);
2119*e038c9c4Sjoerg bool enablesDebugInfo = A && !A->getOption().matches(options::OPT_g0) &&
2120*e038c9c4Sjoerg !A->getOption().matches(options::OPT_gstabs);
2121*e038c9c4Sjoerg if ((enablesDebugInfo || willEmitRemarks(Args)) &&
21227330f729Sjoerg ContainsCompileOrAssembleAction(Actions.back())) {
21237330f729Sjoerg
21247330f729Sjoerg // Add a 'dsymutil' step if necessary, when debug info is enabled and we
21257330f729Sjoerg // have a compile input. We need to run 'dsymutil' ourselves in such cases
21267330f729Sjoerg // because the debug info will refer to a temporary object file which
21277330f729Sjoerg // will be removed at the end of the compilation process.
21287330f729Sjoerg if (Act->getType() == types::TY_Image) {
21297330f729Sjoerg ActionList Inputs;
21307330f729Sjoerg Inputs.push_back(Actions.back());
21317330f729Sjoerg Actions.pop_back();
21327330f729Sjoerg Actions.push_back(
21337330f729Sjoerg C.MakeAction<DsymutilJobAction>(Inputs, types::TY_dSYM));
21347330f729Sjoerg }
21357330f729Sjoerg
21367330f729Sjoerg // Verify the debug info output.
21377330f729Sjoerg if (Args.hasArg(options::OPT_verify_debug_info)) {
21387330f729Sjoerg Action* LastAction = Actions.back();
21397330f729Sjoerg Actions.pop_back();
21407330f729Sjoerg Actions.push_back(C.MakeAction<VerifyDebugInfoJobAction>(
21417330f729Sjoerg LastAction, types::TY_Nothing));
21427330f729Sjoerg }
21437330f729Sjoerg }
21447330f729Sjoerg }
21457330f729Sjoerg }
21467330f729Sjoerg
DiagnoseInputExistence(const DerivedArgList & Args,StringRef Value,types::ID Ty,bool TypoCorrect) const21477330f729Sjoerg bool Driver::DiagnoseInputExistence(const DerivedArgList &Args, StringRef Value,
21487330f729Sjoerg types::ID Ty, bool TypoCorrect) const {
21497330f729Sjoerg if (!getCheckInputsExist())
21507330f729Sjoerg return true;
21517330f729Sjoerg
21527330f729Sjoerg // stdin always exists.
21537330f729Sjoerg if (Value == "-")
21547330f729Sjoerg return true;
21557330f729Sjoerg
21567330f729Sjoerg if (getVFS().exists(Value))
21577330f729Sjoerg return true;
21587330f729Sjoerg
21597330f729Sjoerg if (IsCLMode()) {
21607330f729Sjoerg if (!llvm::sys::path::is_absolute(Twine(Value)) &&
2161*e038c9c4Sjoerg llvm::sys::Process::FindInEnvPath("LIB", Value, ';'))
21627330f729Sjoerg return true;
21637330f729Sjoerg
21647330f729Sjoerg if (Args.hasArg(options::OPT__SLASH_link) && Ty == types::TY_Object) {
21657330f729Sjoerg // Arguments to the /link flag might cause the linker to search for object
21667330f729Sjoerg // and library files in paths we don't know about. Don't error in such
21677330f729Sjoerg // cases.
21687330f729Sjoerg return true;
21697330f729Sjoerg }
21707330f729Sjoerg }
21717330f729Sjoerg
21727330f729Sjoerg if (TypoCorrect) {
21737330f729Sjoerg // Check if the filename is a typo for an option flag. OptTable thinks
21747330f729Sjoerg // that all args that are not known options and that start with / are
21757330f729Sjoerg // filenames, but e.g. `/diagnostic:caret` is more likely a typo for
21767330f729Sjoerg // the option `/diagnostics:caret` than a reference to a file in the root
21777330f729Sjoerg // directory.
21787330f729Sjoerg unsigned IncludedFlagsBitmask;
21797330f729Sjoerg unsigned ExcludedFlagsBitmask;
21807330f729Sjoerg std::tie(IncludedFlagsBitmask, ExcludedFlagsBitmask) =
21817330f729Sjoerg getIncludeExcludeOptionFlagMasks(IsCLMode());
21827330f729Sjoerg std::string Nearest;
21837330f729Sjoerg if (getOpts().findNearest(Value, Nearest, IncludedFlagsBitmask,
21847330f729Sjoerg ExcludedFlagsBitmask) <= 1) {
21857330f729Sjoerg Diag(clang::diag::err_drv_no_such_file_with_suggestion)
21867330f729Sjoerg << Value << Nearest;
21877330f729Sjoerg return false;
21887330f729Sjoerg }
21897330f729Sjoerg }
21907330f729Sjoerg
21917330f729Sjoerg Diag(clang::diag::err_drv_no_such_file) << Value;
21927330f729Sjoerg return false;
21937330f729Sjoerg }
21947330f729Sjoerg
21957330f729Sjoerg // Construct a the list of inputs and their types.
BuildInputs(const ToolChain & TC,DerivedArgList & Args,InputList & Inputs) const21967330f729Sjoerg void Driver::BuildInputs(const ToolChain &TC, DerivedArgList &Args,
21977330f729Sjoerg InputList &Inputs) const {
21987330f729Sjoerg const llvm::opt::OptTable &Opts = getOpts();
21997330f729Sjoerg // Track the current user specified (-x) input. We also explicitly track the
22007330f729Sjoerg // argument used to set the type; we only want to claim the type when we
22017330f729Sjoerg // actually use it, so we warn about unused -x arguments.
22027330f729Sjoerg types::ID InputType = types::TY_Nothing;
22037330f729Sjoerg Arg *InputTypeArg = nullptr;
22047330f729Sjoerg
22057330f729Sjoerg // The last /TC or /TP option sets the input type to C or C++ globally.
22067330f729Sjoerg if (Arg *TCTP = Args.getLastArgNoClaim(options::OPT__SLASH_TC,
22077330f729Sjoerg options::OPT__SLASH_TP)) {
22087330f729Sjoerg InputTypeArg = TCTP;
22097330f729Sjoerg InputType = TCTP->getOption().matches(options::OPT__SLASH_TC)
22107330f729Sjoerg ? types::TY_C
22117330f729Sjoerg : types::TY_CXX;
22127330f729Sjoerg
22137330f729Sjoerg Arg *Previous = nullptr;
22147330f729Sjoerg bool ShowNote = false;
22157330f729Sjoerg for (Arg *A :
22167330f729Sjoerg Args.filtered(options::OPT__SLASH_TC, options::OPT__SLASH_TP)) {
22177330f729Sjoerg if (Previous) {
22187330f729Sjoerg Diag(clang::diag::warn_drv_overriding_flag_option)
22197330f729Sjoerg << Previous->getSpelling() << A->getSpelling();
22207330f729Sjoerg ShowNote = true;
22217330f729Sjoerg }
22227330f729Sjoerg Previous = A;
22237330f729Sjoerg }
22247330f729Sjoerg if (ShowNote)
22257330f729Sjoerg Diag(clang::diag::note_drv_t_option_is_global);
22267330f729Sjoerg
22277330f729Sjoerg // No driver mode exposes -x and /TC or /TP; we don't support mixing them.
22287330f729Sjoerg assert(!Args.hasArg(options::OPT_x) && "-x and /TC or /TP is not allowed");
22297330f729Sjoerg }
22307330f729Sjoerg
22317330f729Sjoerg for (Arg *A : Args) {
22327330f729Sjoerg if (A->getOption().getKind() == Option::InputClass) {
22337330f729Sjoerg const char *Value = A->getValue();
22347330f729Sjoerg types::ID Ty = types::TY_INVALID;
22357330f729Sjoerg
22367330f729Sjoerg // Infer the input type if necessary.
22377330f729Sjoerg if (InputType == types::TY_Nothing) {
22387330f729Sjoerg // If there was an explicit arg for this, claim it.
22397330f729Sjoerg if (InputTypeArg)
22407330f729Sjoerg InputTypeArg->claim();
22417330f729Sjoerg
22427330f729Sjoerg // stdin must be handled specially.
22437330f729Sjoerg if (memcmp(Value, "-", 2) == 0) {
2244*e038c9c4Sjoerg if (IsFlangMode()) {
2245*e038c9c4Sjoerg Ty = types::TY_Fortran;
2246*e038c9c4Sjoerg } else {
2247*e038c9c4Sjoerg // If running with -E, treat as a C input (this changes the
2248*e038c9c4Sjoerg // builtin macros, for example). This may be overridden by -ObjC
2249*e038c9c4Sjoerg // below.
22507330f729Sjoerg //
22517330f729Sjoerg // Otherwise emit an error but still use a valid type to avoid
22527330f729Sjoerg // spurious errors (e.g., no inputs).
22537330f729Sjoerg if (!Args.hasArgNoClaim(options::OPT_E) && !CCCIsCPP())
22547330f729Sjoerg Diag(IsCLMode() ? clang::diag::err_drv_unknown_stdin_type_clang_cl
22557330f729Sjoerg : clang::diag::err_drv_unknown_stdin_type);
22567330f729Sjoerg Ty = types::TY_C;
2257*e038c9c4Sjoerg }
22587330f729Sjoerg } else {
22597330f729Sjoerg // Otherwise lookup by extension.
22607330f729Sjoerg // Fallback is C if invoked as C preprocessor, C++ if invoked with
22617330f729Sjoerg // clang-cl /E, or Object otherwise.
22627330f729Sjoerg // We use a host hook here because Darwin at least has its own
22637330f729Sjoerg // idea of what .s is.
22647330f729Sjoerg if (const char *Ext = strrchr(Value, '.'))
22657330f729Sjoerg Ty = TC.LookupTypeForExtension(Ext + 1);
22667330f729Sjoerg
22677330f729Sjoerg if (Ty == types::TY_INVALID) {
22687330f729Sjoerg if (CCCIsCPP())
22697330f729Sjoerg Ty = types::TY_C;
22707330f729Sjoerg else if (IsCLMode() && Args.hasArgNoClaim(options::OPT_E))
22717330f729Sjoerg Ty = types::TY_CXX;
22727330f729Sjoerg else
22737330f729Sjoerg Ty = types::TY_Object;
22747330f729Sjoerg }
22757330f729Sjoerg
22767330f729Sjoerg // If the driver is invoked as C++ compiler (like clang++ or c++) it
22777330f729Sjoerg // should autodetect some input files as C++ for g++ compatibility.
22787330f729Sjoerg if (CCCIsCXX()) {
22797330f729Sjoerg types::ID OldTy = Ty;
22807330f729Sjoerg Ty = types::lookupCXXTypeForCType(Ty);
22817330f729Sjoerg
22827330f729Sjoerg if (Ty != OldTy)
22837330f729Sjoerg Diag(clang::diag::warn_drv_treating_input_as_cxx)
22847330f729Sjoerg << getTypeName(OldTy) << getTypeName(Ty);
22857330f729Sjoerg }
22867330f729Sjoerg
22877330f729Sjoerg // If running with -fthinlto-index=, extensions that normally identify
22887330f729Sjoerg // native object files actually identify LLVM bitcode files.
22897330f729Sjoerg if (Args.hasArgNoClaim(options::OPT_fthinlto_index_EQ) &&
22907330f729Sjoerg Ty == types::TY_Object)
22917330f729Sjoerg Ty = types::TY_LLVM_BC;
22927330f729Sjoerg }
22937330f729Sjoerg
22947330f729Sjoerg // -ObjC and -ObjC++ override the default language, but only for "source
22957330f729Sjoerg // files". We just treat everything that isn't a linker input as a
22967330f729Sjoerg // source file.
22977330f729Sjoerg //
22987330f729Sjoerg // FIXME: Clean this up if we move the phase sequence into the type.
22997330f729Sjoerg if (Ty != types::TY_Object) {
23007330f729Sjoerg if (Args.hasArg(options::OPT_ObjC))
23017330f729Sjoerg Ty = types::TY_ObjC;
23027330f729Sjoerg else if (Args.hasArg(options::OPT_ObjCXX))
23037330f729Sjoerg Ty = types::TY_ObjCXX;
23047330f729Sjoerg }
23057330f729Sjoerg } else {
23067330f729Sjoerg assert(InputTypeArg && "InputType set w/o InputTypeArg");
23077330f729Sjoerg if (!InputTypeArg->getOption().matches(options::OPT_x)) {
23087330f729Sjoerg // If emulating cl.exe, make sure that /TC and /TP don't affect input
23097330f729Sjoerg // object files.
23107330f729Sjoerg const char *Ext = strrchr(Value, '.');
23117330f729Sjoerg if (Ext && TC.LookupTypeForExtension(Ext + 1) == types::TY_Object)
23127330f729Sjoerg Ty = types::TY_Object;
23137330f729Sjoerg }
23147330f729Sjoerg if (Ty == types::TY_INVALID) {
23157330f729Sjoerg Ty = InputType;
23167330f729Sjoerg InputTypeArg->claim();
23177330f729Sjoerg }
23187330f729Sjoerg }
23197330f729Sjoerg
23207330f729Sjoerg if (DiagnoseInputExistence(Args, Value, Ty, /*TypoCorrect=*/true))
23217330f729Sjoerg Inputs.push_back(std::make_pair(Ty, A));
23227330f729Sjoerg
23237330f729Sjoerg } else if (A->getOption().matches(options::OPT__SLASH_Tc)) {
23247330f729Sjoerg StringRef Value = A->getValue();
23257330f729Sjoerg if (DiagnoseInputExistence(Args, Value, types::TY_C,
23267330f729Sjoerg /*TypoCorrect=*/false)) {
23277330f729Sjoerg Arg *InputArg = MakeInputArg(Args, Opts, A->getValue());
23287330f729Sjoerg Inputs.push_back(std::make_pair(types::TY_C, InputArg));
23297330f729Sjoerg }
23307330f729Sjoerg A->claim();
23317330f729Sjoerg } else if (A->getOption().matches(options::OPT__SLASH_Tp)) {
23327330f729Sjoerg StringRef Value = A->getValue();
23337330f729Sjoerg if (DiagnoseInputExistence(Args, Value, types::TY_CXX,
23347330f729Sjoerg /*TypoCorrect=*/false)) {
23357330f729Sjoerg Arg *InputArg = MakeInputArg(Args, Opts, A->getValue());
23367330f729Sjoerg Inputs.push_back(std::make_pair(types::TY_CXX, InputArg));
23377330f729Sjoerg }
23387330f729Sjoerg A->claim();
23397330f729Sjoerg } else if (A->getOption().hasFlag(options::LinkerInput)) {
23407330f729Sjoerg // Just treat as object type, we could make a special type for this if
23417330f729Sjoerg // necessary.
23427330f729Sjoerg Inputs.push_back(std::make_pair(types::TY_Object, A));
23437330f729Sjoerg
23447330f729Sjoerg } else if (A->getOption().matches(options::OPT_x)) {
23457330f729Sjoerg InputTypeArg = A;
23467330f729Sjoerg InputType = types::lookupTypeForTypeSpecifier(A->getValue());
23477330f729Sjoerg A->claim();
23487330f729Sjoerg
23497330f729Sjoerg // Follow gcc behavior and treat as linker input for invalid -x
23507330f729Sjoerg // options. Its not clear why we shouldn't just revert to unknown; but
23517330f729Sjoerg // this isn't very important, we might as well be bug compatible.
23527330f729Sjoerg if (!InputType) {
23537330f729Sjoerg Diag(clang::diag::err_drv_unknown_language) << A->getValue();
23547330f729Sjoerg InputType = types::TY_Object;
23557330f729Sjoerg }
23567330f729Sjoerg } else if (A->getOption().getID() == options::OPT_U) {
23577330f729Sjoerg assert(A->getNumValues() == 1 && "The /U option has one value.");
23587330f729Sjoerg StringRef Val = A->getValue(0);
23597330f729Sjoerg if (Val.find_first_of("/\\") != StringRef::npos) {
23607330f729Sjoerg // Warn about e.g. "/Users/me/myfile.c".
23617330f729Sjoerg Diag(diag::warn_slash_u_filename) << Val;
23627330f729Sjoerg Diag(diag::note_use_dashdash);
23637330f729Sjoerg }
23647330f729Sjoerg }
23657330f729Sjoerg }
23667330f729Sjoerg if (CCCIsCPP() && Inputs.empty()) {
23677330f729Sjoerg // If called as standalone preprocessor, stdin is processed
23687330f729Sjoerg // if no other input is present.
23697330f729Sjoerg Arg *A = MakeInputArg(Args, Opts, "-");
23707330f729Sjoerg Inputs.push_back(std::make_pair(types::TY_C, A));
23717330f729Sjoerg }
23727330f729Sjoerg }
23737330f729Sjoerg
23747330f729Sjoerg namespace {
23757330f729Sjoerg /// Provides a convenient interface for different programming models to generate
23767330f729Sjoerg /// the required device actions.
23777330f729Sjoerg class OffloadingActionBuilder final {
23787330f729Sjoerg /// Flag used to trace errors in the builder.
23797330f729Sjoerg bool IsValid = false;
23807330f729Sjoerg
23817330f729Sjoerg /// The compilation that is using this builder.
23827330f729Sjoerg Compilation &C;
23837330f729Sjoerg
23847330f729Sjoerg /// Map between an input argument and the offload kinds used to process it.
23857330f729Sjoerg std::map<const Arg *, unsigned> InputArgToOffloadKindMap;
23867330f729Sjoerg
23877330f729Sjoerg /// Builder interface. It doesn't build anything or keep any state.
23887330f729Sjoerg class DeviceActionBuilder {
23897330f729Sjoerg public:
23907330f729Sjoerg typedef const llvm::SmallVectorImpl<phases::ID> PhasesTy;
23917330f729Sjoerg
23927330f729Sjoerg enum ActionBuilderReturnCode {
23937330f729Sjoerg // The builder acted successfully on the current action.
23947330f729Sjoerg ABRT_Success,
23957330f729Sjoerg // The builder didn't have to act on the current action.
23967330f729Sjoerg ABRT_Inactive,
23977330f729Sjoerg // The builder was successful and requested the host action to not be
23987330f729Sjoerg // generated.
23997330f729Sjoerg ABRT_Ignore_Host,
24007330f729Sjoerg };
24017330f729Sjoerg
24027330f729Sjoerg protected:
24037330f729Sjoerg /// Compilation associated with this builder.
24047330f729Sjoerg Compilation &C;
24057330f729Sjoerg
24067330f729Sjoerg /// Tool chains associated with this builder. The same programming
24077330f729Sjoerg /// model may have associated one or more tool chains.
24087330f729Sjoerg SmallVector<const ToolChain *, 2> ToolChains;
24097330f729Sjoerg
24107330f729Sjoerg /// The derived arguments associated with this builder.
24117330f729Sjoerg DerivedArgList &Args;
24127330f729Sjoerg
24137330f729Sjoerg /// The inputs associated with this builder.
24147330f729Sjoerg const Driver::InputList &Inputs;
24157330f729Sjoerg
24167330f729Sjoerg /// The associated offload kind.
24177330f729Sjoerg Action::OffloadKind AssociatedOffloadKind = Action::OFK_None;
24187330f729Sjoerg
24197330f729Sjoerg public:
DeviceActionBuilder(Compilation & C,DerivedArgList & Args,const Driver::InputList & Inputs,Action::OffloadKind AssociatedOffloadKind)24207330f729Sjoerg DeviceActionBuilder(Compilation &C, DerivedArgList &Args,
24217330f729Sjoerg const Driver::InputList &Inputs,
24227330f729Sjoerg Action::OffloadKind AssociatedOffloadKind)
24237330f729Sjoerg : C(C), Args(Args), Inputs(Inputs),
24247330f729Sjoerg AssociatedOffloadKind(AssociatedOffloadKind) {}
~DeviceActionBuilder()24257330f729Sjoerg virtual ~DeviceActionBuilder() {}
24267330f729Sjoerg
24277330f729Sjoerg /// Fill up the array \a DA with all the device dependences that should be
24287330f729Sjoerg /// added to the provided host action \a HostAction. By default it is
24297330f729Sjoerg /// inactive.
24307330f729Sjoerg virtual ActionBuilderReturnCode
getDeviceDependences(OffloadAction::DeviceDependences & DA,phases::ID CurPhase,phases::ID FinalPhase,PhasesTy & Phases)24317330f729Sjoerg getDeviceDependences(OffloadAction::DeviceDependences &DA,
24327330f729Sjoerg phases::ID CurPhase, phases::ID FinalPhase,
24337330f729Sjoerg PhasesTy &Phases) {
24347330f729Sjoerg return ABRT_Inactive;
24357330f729Sjoerg }
24367330f729Sjoerg
24377330f729Sjoerg /// Update the state to include the provided host action \a HostAction as a
24387330f729Sjoerg /// dependency of the current device action. By default it is inactive.
addDeviceDepences(Action * HostAction)24397330f729Sjoerg virtual ActionBuilderReturnCode addDeviceDepences(Action *HostAction) {
24407330f729Sjoerg return ABRT_Inactive;
24417330f729Sjoerg }
24427330f729Sjoerg
24437330f729Sjoerg /// Append top level actions generated by the builder.
appendTopLevelActions(ActionList & AL)24447330f729Sjoerg virtual void appendTopLevelActions(ActionList &AL) {}
24457330f729Sjoerg
2446*e038c9c4Sjoerg /// Append linker device actions generated by the builder.
appendLinkDeviceActions(ActionList & AL)2447*e038c9c4Sjoerg virtual void appendLinkDeviceActions(ActionList &AL) {}
2448*e038c9c4Sjoerg
2449*e038c9c4Sjoerg /// Append linker host action generated by the builder.
appendLinkHostActions(ActionList & AL)2450*e038c9c4Sjoerg virtual Action* appendLinkHostActions(ActionList &AL) { return nullptr; }
24517330f729Sjoerg
24527330f729Sjoerg /// Append linker actions generated by the builder.
appendLinkDependences(OffloadAction::DeviceDependences & DA)24537330f729Sjoerg virtual void appendLinkDependences(OffloadAction::DeviceDependences &DA) {}
24547330f729Sjoerg
24557330f729Sjoerg /// Initialize the builder. Return true if any initialization errors are
24567330f729Sjoerg /// found.
initialize()24577330f729Sjoerg virtual bool initialize() { return false; }
24587330f729Sjoerg
24597330f729Sjoerg /// Return true if the builder can use bundling/unbundling.
canUseBundlerUnbundler() const24607330f729Sjoerg virtual bool canUseBundlerUnbundler() const { return false; }
24617330f729Sjoerg
24627330f729Sjoerg /// Return true if this builder is valid. We have a valid builder if we have
24637330f729Sjoerg /// associated device tool chains.
isValid()24647330f729Sjoerg bool isValid() { return !ToolChains.empty(); }
24657330f729Sjoerg
24667330f729Sjoerg /// Return the associated offload kind.
getAssociatedOffloadKind()24677330f729Sjoerg Action::OffloadKind getAssociatedOffloadKind() {
24687330f729Sjoerg return AssociatedOffloadKind;
24697330f729Sjoerg }
24707330f729Sjoerg };
24717330f729Sjoerg
24727330f729Sjoerg /// Base class for CUDA/HIP action builder. It injects device code in
24737330f729Sjoerg /// the host backend action.
24747330f729Sjoerg class CudaActionBuilderBase : public DeviceActionBuilder {
24757330f729Sjoerg protected:
24767330f729Sjoerg /// Flags to signal if the user requested host-only or device-only
24777330f729Sjoerg /// compilation.
24787330f729Sjoerg bool CompileHostOnly = false;
24797330f729Sjoerg bool CompileDeviceOnly = false;
24807330f729Sjoerg bool EmitLLVM = false;
24817330f729Sjoerg bool EmitAsm = false;
24827330f729Sjoerg
2483*e038c9c4Sjoerg /// ID to identify each device compilation. For CUDA it is simply the
2484*e038c9c4Sjoerg /// GPU arch string. For HIP it is either the GPU arch string or GPU
2485*e038c9c4Sjoerg /// arch string plus feature strings delimited by a plus sign, e.g.
2486*e038c9c4Sjoerg /// gfx906+xnack.
2487*e038c9c4Sjoerg struct TargetID {
2488*e038c9c4Sjoerg /// Target ID string which is persistent throughout the compilation.
2489*e038c9c4Sjoerg const char *ID;
TargetID__anon51bf6f8c0a11::OffloadingActionBuilder::CudaActionBuilderBase::TargetID2490*e038c9c4Sjoerg TargetID(CudaArch Arch) { ID = CudaArchToString(Arch); }
TargetID__anon51bf6f8c0a11::OffloadingActionBuilder::CudaActionBuilderBase::TargetID2491*e038c9c4Sjoerg TargetID(const char *ID) : ID(ID) {}
operator const char*__anon51bf6f8c0a11::OffloadingActionBuilder::CudaActionBuilderBase::TargetID2492*e038c9c4Sjoerg operator const char *() { return ID; }
operator StringRef__anon51bf6f8c0a11::OffloadingActionBuilder::CudaActionBuilderBase::TargetID2493*e038c9c4Sjoerg operator StringRef() { return StringRef(ID); }
2494*e038c9c4Sjoerg };
24957330f729Sjoerg /// List of GPU architectures to use in this compilation.
2496*e038c9c4Sjoerg SmallVector<TargetID, 4> GpuArchList;
24977330f729Sjoerg
24987330f729Sjoerg /// The CUDA actions for the current input.
24997330f729Sjoerg ActionList CudaDeviceActions;
25007330f729Sjoerg
25017330f729Sjoerg /// The CUDA fat binary if it was generated for the current input.
25027330f729Sjoerg Action *CudaFatBinary = nullptr;
25037330f729Sjoerg
25047330f729Sjoerg /// Flag that is set to true if this builder acted on the current input.
25057330f729Sjoerg bool IsActive = false;
25067330f729Sjoerg
25077330f729Sjoerg /// Flag for -fgpu-rdc.
25087330f729Sjoerg bool Relocatable = false;
25097330f729Sjoerg
25107330f729Sjoerg /// Default GPU architecture if there's no one specified.
25117330f729Sjoerg CudaArch DefaultCudaArch = CudaArch::UNKNOWN;
25127330f729Sjoerg
2513*e038c9c4Sjoerg /// Method to generate compilation unit ID specified by option
2514*e038c9c4Sjoerg /// '-fuse-cuid='.
2515*e038c9c4Sjoerg enum UseCUIDKind { CUID_Hash, CUID_Random, CUID_None, CUID_Invalid };
2516*e038c9c4Sjoerg UseCUIDKind UseCUID = CUID_Hash;
2517*e038c9c4Sjoerg
2518*e038c9c4Sjoerg /// Compilation unit ID specified by option '-cuid='.
2519*e038c9c4Sjoerg StringRef FixedCUID;
2520*e038c9c4Sjoerg
25217330f729Sjoerg public:
CudaActionBuilderBase(Compilation & C,DerivedArgList & Args,const Driver::InputList & Inputs,Action::OffloadKind OFKind)25227330f729Sjoerg CudaActionBuilderBase(Compilation &C, DerivedArgList &Args,
25237330f729Sjoerg const Driver::InputList &Inputs,
25247330f729Sjoerg Action::OffloadKind OFKind)
25257330f729Sjoerg : DeviceActionBuilder(C, Args, Inputs, OFKind) {}
25267330f729Sjoerg
addDeviceDepences(Action * HostAction)25277330f729Sjoerg ActionBuilderReturnCode addDeviceDepences(Action *HostAction) override {
25287330f729Sjoerg // While generating code for CUDA, we only depend on the host input action
25297330f729Sjoerg // to trigger the creation of all the CUDA device actions.
25307330f729Sjoerg
25317330f729Sjoerg // If we are dealing with an input action, replicate it for each GPU
25327330f729Sjoerg // architecture. If we are in host-only mode we return 'success' so that
25337330f729Sjoerg // the host uses the CUDA offload kind.
25347330f729Sjoerg if (auto *IA = dyn_cast<InputAction>(HostAction)) {
25357330f729Sjoerg assert(!GpuArchList.empty() &&
25367330f729Sjoerg "We should have at least one GPU architecture.");
25377330f729Sjoerg
25387330f729Sjoerg // If the host input is not CUDA or HIP, we don't need to bother about
25397330f729Sjoerg // this input.
2540*e038c9c4Sjoerg if (!(IA->getType() == types::TY_CUDA ||
2541*e038c9c4Sjoerg IA->getType() == types::TY_HIP ||
2542*e038c9c4Sjoerg IA->getType() == types::TY_PP_HIP)) {
25437330f729Sjoerg // The builder will ignore this input.
25447330f729Sjoerg IsActive = false;
25457330f729Sjoerg return ABRT_Inactive;
25467330f729Sjoerg }
25477330f729Sjoerg
25487330f729Sjoerg // Set the flag to true, so that the builder acts on the current input.
25497330f729Sjoerg IsActive = true;
25507330f729Sjoerg
25517330f729Sjoerg if (CompileHostOnly)
25527330f729Sjoerg return ABRT_Success;
25537330f729Sjoerg
25547330f729Sjoerg // Replicate inputs for each GPU architecture.
25557330f729Sjoerg auto Ty = IA->getType() == types::TY_HIP ? types::TY_HIP_DEVICE
25567330f729Sjoerg : types::TY_CUDA_DEVICE;
2557*e038c9c4Sjoerg std::string CUID = FixedCUID.str();
2558*e038c9c4Sjoerg if (CUID.empty()) {
2559*e038c9c4Sjoerg if (UseCUID == CUID_Random)
2560*e038c9c4Sjoerg CUID = llvm::utohexstr(llvm::sys::Process::GetRandomNumber(),
2561*e038c9c4Sjoerg /*LowerCase=*/true);
2562*e038c9c4Sjoerg else if (UseCUID == CUID_Hash) {
2563*e038c9c4Sjoerg llvm::MD5 Hasher;
2564*e038c9c4Sjoerg llvm::MD5::MD5Result Hash;
2565*e038c9c4Sjoerg SmallString<256> RealPath;
2566*e038c9c4Sjoerg llvm::sys::fs::real_path(IA->getInputArg().getValue(), RealPath,
2567*e038c9c4Sjoerg /*expand_tilde=*/true);
2568*e038c9c4Sjoerg Hasher.update(RealPath);
2569*e038c9c4Sjoerg for (auto *A : Args) {
2570*e038c9c4Sjoerg if (A->getOption().matches(options::OPT_INPUT))
2571*e038c9c4Sjoerg continue;
2572*e038c9c4Sjoerg Hasher.update(A->getAsString(Args));
2573*e038c9c4Sjoerg }
2574*e038c9c4Sjoerg Hasher.final(Hash);
2575*e038c9c4Sjoerg CUID = llvm::utohexstr(Hash.low(), /*LowerCase=*/true);
2576*e038c9c4Sjoerg }
2577*e038c9c4Sjoerg }
2578*e038c9c4Sjoerg IA->setId(CUID);
2579*e038c9c4Sjoerg
25807330f729Sjoerg for (unsigned I = 0, E = GpuArchList.size(); I != E; ++I) {
25817330f729Sjoerg CudaDeviceActions.push_back(
2582*e038c9c4Sjoerg C.MakeAction<InputAction>(IA->getInputArg(), Ty, IA->getId()));
25837330f729Sjoerg }
25847330f729Sjoerg
25857330f729Sjoerg return ABRT_Success;
25867330f729Sjoerg }
25877330f729Sjoerg
25887330f729Sjoerg // If this is an unbundling action use it as is for each CUDA toolchain.
25897330f729Sjoerg if (auto *UA = dyn_cast<OffloadUnbundlingJobAction>(HostAction)) {
25907330f729Sjoerg
25917330f729Sjoerg // If -fgpu-rdc is disabled, should not unbundle since there is no
25927330f729Sjoerg // device code to link.
2593*e038c9c4Sjoerg if (UA->getType() == types::TY_Object && !Relocatable)
25947330f729Sjoerg return ABRT_Inactive;
25957330f729Sjoerg
25967330f729Sjoerg CudaDeviceActions.clear();
25977330f729Sjoerg auto *IA = cast<InputAction>(UA->getInputs().back());
25987330f729Sjoerg std::string FileName = IA->getInputArg().getAsString(Args);
25997330f729Sjoerg // Check if the type of the file is the same as the action. Do not
26007330f729Sjoerg // unbundle it if it is not. Do not unbundle .so files, for example,
26017330f729Sjoerg // which are not object files.
26027330f729Sjoerg if (IA->getType() == types::TY_Object &&
26037330f729Sjoerg (!llvm::sys::path::has_extension(FileName) ||
26047330f729Sjoerg types::lookupTypeForExtension(
26057330f729Sjoerg llvm::sys::path::extension(FileName).drop_front()) !=
26067330f729Sjoerg types::TY_Object))
26077330f729Sjoerg return ABRT_Inactive;
26087330f729Sjoerg
26097330f729Sjoerg for (auto Arch : GpuArchList) {
26107330f729Sjoerg CudaDeviceActions.push_back(UA);
2611*e038c9c4Sjoerg UA->registerDependentActionInfo(ToolChains[0], Arch,
26127330f729Sjoerg AssociatedOffloadKind);
26137330f729Sjoerg }
26147330f729Sjoerg return ABRT_Success;
26157330f729Sjoerg }
26167330f729Sjoerg
26177330f729Sjoerg return IsActive ? ABRT_Success : ABRT_Inactive;
26187330f729Sjoerg }
26197330f729Sjoerg
appendTopLevelActions(ActionList & AL)26207330f729Sjoerg void appendTopLevelActions(ActionList &AL) override {
26217330f729Sjoerg // Utility to append actions to the top level list.
2622*e038c9c4Sjoerg auto AddTopLevel = [&](Action *A, TargetID TargetID) {
26237330f729Sjoerg OffloadAction::DeviceDependences Dep;
2624*e038c9c4Sjoerg Dep.add(*A, *ToolChains.front(), TargetID, AssociatedOffloadKind);
26257330f729Sjoerg AL.push_back(C.MakeAction<OffloadAction>(Dep, A->getType()));
26267330f729Sjoerg };
26277330f729Sjoerg
26287330f729Sjoerg // If we have a fat binary, add it to the list.
26297330f729Sjoerg if (CudaFatBinary) {
2630*e038c9c4Sjoerg AddTopLevel(CudaFatBinary, CudaArch::UNUSED);
26317330f729Sjoerg CudaDeviceActions.clear();
26327330f729Sjoerg CudaFatBinary = nullptr;
26337330f729Sjoerg return;
26347330f729Sjoerg }
26357330f729Sjoerg
26367330f729Sjoerg if (CudaDeviceActions.empty())
26377330f729Sjoerg return;
26387330f729Sjoerg
26397330f729Sjoerg // If we have CUDA actions at this point, that's because we have a have
26407330f729Sjoerg // partial compilation, so we should have an action for each GPU
26417330f729Sjoerg // architecture.
26427330f729Sjoerg assert(CudaDeviceActions.size() == GpuArchList.size() &&
26437330f729Sjoerg "Expecting one action per GPU architecture.");
26447330f729Sjoerg assert(ToolChains.size() == 1 &&
26457330f729Sjoerg "Expecting to have a sing CUDA toolchain.");
26467330f729Sjoerg for (unsigned I = 0, E = GpuArchList.size(); I != E; ++I)
26477330f729Sjoerg AddTopLevel(CudaDeviceActions[I], GpuArchList[I]);
26487330f729Sjoerg
26497330f729Sjoerg CudaDeviceActions.clear();
26507330f729Sjoerg }
26517330f729Sjoerg
2652*e038c9c4Sjoerg /// Get canonicalized offload arch option. \returns empty StringRef if the
2653*e038c9c4Sjoerg /// option is invalid.
2654*e038c9c4Sjoerg virtual StringRef getCanonicalOffloadArch(StringRef Arch) = 0;
2655*e038c9c4Sjoerg
2656*e038c9c4Sjoerg virtual llvm::Optional<std::pair<llvm::StringRef, llvm::StringRef>>
2657*e038c9c4Sjoerg getConflictOffloadArchCombination(const std::set<StringRef> &GpuArchs) = 0;
2658*e038c9c4Sjoerg
initialize()26597330f729Sjoerg bool initialize() override {
26607330f729Sjoerg assert(AssociatedOffloadKind == Action::OFK_Cuda ||
26617330f729Sjoerg AssociatedOffloadKind == Action::OFK_HIP);
26627330f729Sjoerg
26637330f729Sjoerg // We don't need to support CUDA.
26647330f729Sjoerg if (AssociatedOffloadKind == Action::OFK_Cuda &&
26657330f729Sjoerg !C.hasOffloadToolChain<Action::OFK_Cuda>())
26667330f729Sjoerg return false;
26677330f729Sjoerg
26687330f729Sjoerg // We don't need to support HIP.
26697330f729Sjoerg if (AssociatedOffloadKind == Action::OFK_HIP &&
26707330f729Sjoerg !C.hasOffloadToolChain<Action::OFK_HIP>())
26717330f729Sjoerg return false;
26727330f729Sjoerg
26737330f729Sjoerg Relocatable = Args.hasFlag(options::OPT_fgpu_rdc,
26747330f729Sjoerg options::OPT_fno_gpu_rdc, /*Default=*/false);
26757330f729Sjoerg
26767330f729Sjoerg const ToolChain *HostTC = C.getSingleOffloadToolChain<Action::OFK_Host>();
26777330f729Sjoerg assert(HostTC && "No toolchain for host compilation.");
26787330f729Sjoerg if (HostTC->getTriple().isNVPTX() ||
26797330f729Sjoerg HostTC->getTriple().getArch() == llvm::Triple::amdgcn) {
26807330f729Sjoerg // We do not support targeting NVPTX/AMDGCN for host compilation. Throw
26817330f729Sjoerg // an error and abort pipeline construction early so we don't trip
26827330f729Sjoerg // asserts that assume device-side compilation.
26837330f729Sjoerg C.getDriver().Diag(diag::err_drv_cuda_host_arch)
26847330f729Sjoerg << HostTC->getTriple().getArchName();
26857330f729Sjoerg return true;
26867330f729Sjoerg }
26877330f729Sjoerg
26887330f729Sjoerg ToolChains.push_back(
26897330f729Sjoerg AssociatedOffloadKind == Action::OFK_Cuda
26907330f729Sjoerg ? C.getSingleOffloadToolChain<Action::OFK_Cuda>()
26917330f729Sjoerg : C.getSingleOffloadToolChain<Action::OFK_HIP>());
26927330f729Sjoerg
26937330f729Sjoerg Arg *PartialCompilationArg = Args.getLastArg(
26947330f729Sjoerg options::OPT_cuda_host_only, options::OPT_cuda_device_only,
26957330f729Sjoerg options::OPT_cuda_compile_host_device);
26967330f729Sjoerg CompileHostOnly = PartialCompilationArg &&
26977330f729Sjoerg PartialCompilationArg->getOption().matches(
26987330f729Sjoerg options::OPT_cuda_host_only);
26997330f729Sjoerg CompileDeviceOnly = PartialCompilationArg &&
27007330f729Sjoerg PartialCompilationArg->getOption().matches(
27017330f729Sjoerg options::OPT_cuda_device_only);
27027330f729Sjoerg EmitLLVM = Args.getLastArg(options::OPT_emit_llvm);
27037330f729Sjoerg EmitAsm = Args.getLastArg(options::OPT_S);
2704*e038c9c4Sjoerg FixedCUID = Args.getLastArgValue(options::OPT_cuid_EQ);
2705*e038c9c4Sjoerg if (Arg *A = Args.getLastArg(options::OPT_fuse_cuid_EQ)) {
2706*e038c9c4Sjoerg StringRef UseCUIDStr = A->getValue();
2707*e038c9c4Sjoerg UseCUID = llvm::StringSwitch<UseCUIDKind>(UseCUIDStr)
2708*e038c9c4Sjoerg .Case("hash", CUID_Hash)
2709*e038c9c4Sjoerg .Case("random", CUID_Random)
2710*e038c9c4Sjoerg .Case("none", CUID_None)
2711*e038c9c4Sjoerg .Default(CUID_Invalid);
2712*e038c9c4Sjoerg if (UseCUID == CUID_Invalid) {
2713*e038c9c4Sjoerg C.getDriver().Diag(diag::err_drv_invalid_value)
2714*e038c9c4Sjoerg << A->getAsString(Args) << UseCUIDStr;
2715*e038c9c4Sjoerg C.setContainsError();
2716*e038c9c4Sjoerg return true;
2717*e038c9c4Sjoerg }
2718*e038c9c4Sjoerg }
27197330f729Sjoerg
27207330f729Sjoerg // Collect all cuda_gpu_arch parameters, removing duplicates.
2721*e038c9c4Sjoerg std::set<StringRef> GpuArchs;
27227330f729Sjoerg bool Error = false;
27237330f729Sjoerg for (Arg *A : Args) {
2724*e038c9c4Sjoerg if (!(A->getOption().matches(options::OPT_offload_arch_EQ) ||
2725*e038c9c4Sjoerg A->getOption().matches(options::OPT_no_offload_arch_EQ)))
27267330f729Sjoerg continue;
27277330f729Sjoerg A->claim();
27287330f729Sjoerg
2729*e038c9c4Sjoerg StringRef ArchStr = A->getValue();
2730*e038c9c4Sjoerg if (A->getOption().matches(options::OPT_no_offload_arch_EQ) &&
27317330f729Sjoerg ArchStr == "all") {
27327330f729Sjoerg GpuArchs.clear();
27337330f729Sjoerg continue;
27347330f729Sjoerg }
2735*e038c9c4Sjoerg ArchStr = getCanonicalOffloadArch(ArchStr);
2736*e038c9c4Sjoerg if (ArchStr.empty()) {
27377330f729Sjoerg Error = true;
2738*e038c9c4Sjoerg } else if (A->getOption().matches(options::OPT_offload_arch_EQ))
2739*e038c9c4Sjoerg GpuArchs.insert(ArchStr);
2740*e038c9c4Sjoerg else if (A->getOption().matches(options::OPT_no_offload_arch_EQ))
2741*e038c9c4Sjoerg GpuArchs.erase(ArchStr);
27427330f729Sjoerg else
27437330f729Sjoerg llvm_unreachable("Unexpected option.");
27447330f729Sjoerg }
27457330f729Sjoerg
2746*e038c9c4Sjoerg auto &&ConflictingArchs = getConflictOffloadArchCombination(GpuArchs);
2747*e038c9c4Sjoerg if (ConflictingArchs) {
2748*e038c9c4Sjoerg C.getDriver().Diag(clang::diag::err_drv_bad_offload_arch_combo)
2749*e038c9c4Sjoerg << ConflictingArchs.getValue().first
2750*e038c9c4Sjoerg << ConflictingArchs.getValue().second;
2751*e038c9c4Sjoerg C.setContainsError();
2752*e038c9c4Sjoerg return true;
2753*e038c9c4Sjoerg }
2754*e038c9c4Sjoerg
27557330f729Sjoerg // Collect list of GPUs remaining in the set.
2756*e038c9c4Sjoerg for (auto Arch : GpuArchs)
2757*e038c9c4Sjoerg GpuArchList.push_back(Arch.data());
27587330f729Sjoerg
27597330f729Sjoerg // Default to sm_20 which is the lowest common denominator for
27607330f729Sjoerg // supported GPUs. sm_20 code should work correctly, if
27617330f729Sjoerg // suboptimally, on all newer GPUs.
27627330f729Sjoerg if (GpuArchList.empty())
27637330f729Sjoerg GpuArchList.push_back(DefaultCudaArch);
27647330f729Sjoerg
27657330f729Sjoerg return Error;
27667330f729Sjoerg }
27677330f729Sjoerg };
27687330f729Sjoerg
27697330f729Sjoerg /// \brief CUDA action builder. It injects device code in the host backend
27707330f729Sjoerg /// action.
27717330f729Sjoerg class CudaActionBuilder final : public CudaActionBuilderBase {
27727330f729Sjoerg public:
CudaActionBuilder(Compilation & C,DerivedArgList & Args,const Driver::InputList & Inputs)27737330f729Sjoerg CudaActionBuilder(Compilation &C, DerivedArgList &Args,
27747330f729Sjoerg const Driver::InputList &Inputs)
27757330f729Sjoerg : CudaActionBuilderBase(C, Args, Inputs, Action::OFK_Cuda) {
27767330f729Sjoerg DefaultCudaArch = CudaArch::SM_20;
27777330f729Sjoerg }
27787330f729Sjoerg
getCanonicalOffloadArch(StringRef ArchStr)2779*e038c9c4Sjoerg StringRef getCanonicalOffloadArch(StringRef ArchStr) override {
2780*e038c9c4Sjoerg CudaArch Arch = StringToCudaArch(ArchStr);
2781*e038c9c4Sjoerg if (Arch == CudaArch::UNKNOWN) {
2782*e038c9c4Sjoerg C.getDriver().Diag(clang::diag::err_drv_cuda_bad_gpu_arch) << ArchStr;
2783*e038c9c4Sjoerg return StringRef();
2784*e038c9c4Sjoerg }
2785*e038c9c4Sjoerg return CudaArchToString(Arch);
2786*e038c9c4Sjoerg }
2787*e038c9c4Sjoerg
2788*e038c9c4Sjoerg llvm::Optional<std::pair<llvm::StringRef, llvm::StringRef>>
getConflictOffloadArchCombination(const std::set<StringRef> & GpuArchs)2789*e038c9c4Sjoerg getConflictOffloadArchCombination(
2790*e038c9c4Sjoerg const std::set<StringRef> &GpuArchs) override {
2791*e038c9c4Sjoerg return llvm::None;
2792*e038c9c4Sjoerg }
2793*e038c9c4Sjoerg
27947330f729Sjoerg ActionBuilderReturnCode
getDeviceDependences(OffloadAction::DeviceDependences & DA,phases::ID CurPhase,phases::ID FinalPhase,PhasesTy & Phases)27957330f729Sjoerg getDeviceDependences(OffloadAction::DeviceDependences &DA,
27967330f729Sjoerg phases::ID CurPhase, phases::ID FinalPhase,
27977330f729Sjoerg PhasesTy &Phases) override {
27987330f729Sjoerg if (!IsActive)
27997330f729Sjoerg return ABRT_Inactive;
28007330f729Sjoerg
28017330f729Sjoerg // If we don't have more CUDA actions, we don't have any dependences to
28027330f729Sjoerg // create for the host.
28037330f729Sjoerg if (CudaDeviceActions.empty())
28047330f729Sjoerg return ABRT_Success;
28057330f729Sjoerg
28067330f729Sjoerg assert(CudaDeviceActions.size() == GpuArchList.size() &&
28077330f729Sjoerg "Expecting one action per GPU architecture.");
28087330f729Sjoerg assert(!CompileHostOnly &&
28097330f729Sjoerg "Not expecting CUDA actions in host-only compilation.");
28107330f729Sjoerg
28117330f729Sjoerg // If we are generating code for the device or we are in a backend phase,
28127330f729Sjoerg // we attempt to generate the fat binary. We compile each arch to ptx and
28137330f729Sjoerg // assemble to cubin, then feed the cubin *and* the ptx into a device
28147330f729Sjoerg // "link" action, which uses fatbinary to combine these cubins into one
28157330f729Sjoerg // fatbin. The fatbin is then an input to the host action if not in
28167330f729Sjoerg // device-only mode.
28177330f729Sjoerg if (CompileDeviceOnly || CurPhase == phases::Backend) {
28187330f729Sjoerg ActionList DeviceActions;
28197330f729Sjoerg for (unsigned I = 0, E = GpuArchList.size(); I != E; ++I) {
28207330f729Sjoerg // Produce the device action from the current phase up to the assemble
28217330f729Sjoerg // phase.
28227330f729Sjoerg for (auto Ph : Phases) {
28237330f729Sjoerg // Skip the phases that were already dealt with.
28247330f729Sjoerg if (Ph < CurPhase)
28257330f729Sjoerg continue;
28267330f729Sjoerg // We have to be consistent with the host final phase.
28277330f729Sjoerg if (Ph > FinalPhase)
28287330f729Sjoerg break;
28297330f729Sjoerg
28307330f729Sjoerg CudaDeviceActions[I] = C.getDriver().ConstructPhaseAction(
28317330f729Sjoerg C, Args, Ph, CudaDeviceActions[I], Action::OFK_Cuda);
28327330f729Sjoerg
28337330f729Sjoerg if (Ph == phases::Assemble)
28347330f729Sjoerg break;
28357330f729Sjoerg }
28367330f729Sjoerg
28377330f729Sjoerg // If we didn't reach the assemble phase, we can't generate the fat
28387330f729Sjoerg // binary. We don't need to generate the fat binary if we are not in
28397330f729Sjoerg // device-only mode.
28407330f729Sjoerg if (!isa<AssembleJobAction>(CudaDeviceActions[I]) ||
28417330f729Sjoerg CompileDeviceOnly)
28427330f729Sjoerg continue;
28437330f729Sjoerg
28447330f729Sjoerg Action *AssembleAction = CudaDeviceActions[I];
28457330f729Sjoerg assert(AssembleAction->getType() == types::TY_Object);
28467330f729Sjoerg assert(AssembleAction->getInputs().size() == 1);
28477330f729Sjoerg
28487330f729Sjoerg Action *BackendAction = AssembleAction->getInputs()[0];
28497330f729Sjoerg assert(BackendAction->getType() == types::TY_PP_Asm);
28507330f729Sjoerg
28517330f729Sjoerg for (auto &A : {AssembleAction, BackendAction}) {
28527330f729Sjoerg OffloadAction::DeviceDependences DDep;
2853*e038c9c4Sjoerg DDep.add(*A, *ToolChains.front(), GpuArchList[I], Action::OFK_Cuda);
28547330f729Sjoerg DeviceActions.push_back(
28557330f729Sjoerg C.MakeAction<OffloadAction>(DDep, A->getType()));
28567330f729Sjoerg }
28577330f729Sjoerg }
28587330f729Sjoerg
28597330f729Sjoerg // We generate the fat binary if we have device input actions.
28607330f729Sjoerg if (!DeviceActions.empty()) {
28617330f729Sjoerg CudaFatBinary =
28627330f729Sjoerg C.MakeAction<LinkJobAction>(DeviceActions, types::TY_CUDA_FATBIN);
28637330f729Sjoerg
28647330f729Sjoerg if (!CompileDeviceOnly) {
28657330f729Sjoerg DA.add(*CudaFatBinary, *ToolChains.front(), /*BoundArch=*/nullptr,
28667330f729Sjoerg Action::OFK_Cuda);
28677330f729Sjoerg // Clear the fat binary, it is already a dependence to an host
28687330f729Sjoerg // action.
28697330f729Sjoerg CudaFatBinary = nullptr;
28707330f729Sjoerg }
28717330f729Sjoerg
28727330f729Sjoerg // Remove the CUDA actions as they are already connected to an host
28737330f729Sjoerg // action or fat binary.
28747330f729Sjoerg CudaDeviceActions.clear();
28757330f729Sjoerg }
28767330f729Sjoerg
28777330f729Sjoerg // We avoid creating host action in device-only mode.
28787330f729Sjoerg return CompileDeviceOnly ? ABRT_Ignore_Host : ABRT_Success;
28797330f729Sjoerg } else if (CurPhase > phases::Backend) {
28807330f729Sjoerg // If we are past the backend phase and still have a device action, we
28817330f729Sjoerg // don't have to do anything as this action is already a device
28827330f729Sjoerg // top-level action.
28837330f729Sjoerg return ABRT_Success;
28847330f729Sjoerg }
28857330f729Sjoerg
28867330f729Sjoerg assert(CurPhase < phases::Backend && "Generating single CUDA "
28877330f729Sjoerg "instructions should only occur "
28887330f729Sjoerg "before the backend phase!");
28897330f729Sjoerg
28907330f729Sjoerg // By default, we produce an action for each device arch.
28917330f729Sjoerg for (Action *&A : CudaDeviceActions)
28927330f729Sjoerg A = C.getDriver().ConstructPhaseAction(C, Args, CurPhase, A);
28937330f729Sjoerg
28947330f729Sjoerg return ABRT_Success;
28957330f729Sjoerg }
28967330f729Sjoerg };
28977330f729Sjoerg /// \brief HIP action builder. It injects device code in the host backend
28987330f729Sjoerg /// action.
28997330f729Sjoerg class HIPActionBuilder final : public CudaActionBuilderBase {
29007330f729Sjoerg /// The linker inputs obtained for each device arch.
29017330f729Sjoerg SmallVector<ActionList, 8> DeviceLinkerInputs;
2902*e038c9c4Sjoerg bool GPUSanitize;
29037330f729Sjoerg
29047330f729Sjoerg public:
HIPActionBuilder(Compilation & C,DerivedArgList & Args,const Driver::InputList & Inputs)29057330f729Sjoerg HIPActionBuilder(Compilation &C, DerivedArgList &Args,
29067330f729Sjoerg const Driver::InputList &Inputs)
29077330f729Sjoerg : CudaActionBuilderBase(C, Args, Inputs, Action::OFK_HIP) {
29087330f729Sjoerg DefaultCudaArch = CudaArch::GFX803;
2909*e038c9c4Sjoerg GPUSanitize = Args.hasFlag(options::OPT_fgpu_sanitize,
2910*e038c9c4Sjoerg options::OPT_fno_gpu_sanitize, false);
29117330f729Sjoerg }
29127330f729Sjoerg
canUseBundlerUnbundler() const29137330f729Sjoerg bool canUseBundlerUnbundler() const override { return true; }
29147330f729Sjoerg
getCanonicalOffloadArch(StringRef IdStr)2915*e038c9c4Sjoerg StringRef getCanonicalOffloadArch(StringRef IdStr) override {
2916*e038c9c4Sjoerg llvm::StringMap<bool> Features;
2917*e038c9c4Sjoerg auto ArchStr =
2918*e038c9c4Sjoerg parseTargetID(getHIPOffloadTargetTriple(), IdStr, &Features);
2919*e038c9c4Sjoerg if (!ArchStr) {
2920*e038c9c4Sjoerg C.getDriver().Diag(clang::diag::err_drv_bad_target_id) << IdStr;
2921*e038c9c4Sjoerg C.setContainsError();
2922*e038c9c4Sjoerg return StringRef();
2923*e038c9c4Sjoerg }
2924*e038c9c4Sjoerg auto CanId = getCanonicalTargetID(ArchStr.getValue(), Features);
2925*e038c9c4Sjoerg return Args.MakeArgStringRef(CanId);
2926*e038c9c4Sjoerg };
2927*e038c9c4Sjoerg
2928*e038c9c4Sjoerg llvm::Optional<std::pair<llvm::StringRef, llvm::StringRef>>
getConflictOffloadArchCombination(const std::set<StringRef> & GpuArchs)2929*e038c9c4Sjoerg getConflictOffloadArchCombination(
2930*e038c9c4Sjoerg const std::set<StringRef> &GpuArchs) override {
2931*e038c9c4Sjoerg return getConflictTargetIDCombination(GpuArchs);
2932*e038c9c4Sjoerg }
2933*e038c9c4Sjoerg
29347330f729Sjoerg ActionBuilderReturnCode
getDeviceDependences(OffloadAction::DeviceDependences & DA,phases::ID CurPhase,phases::ID FinalPhase,PhasesTy & Phases)29357330f729Sjoerg getDeviceDependences(OffloadAction::DeviceDependences &DA,
29367330f729Sjoerg phases::ID CurPhase, phases::ID FinalPhase,
29377330f729Sjoerg PhasesTy &Phases) override {
29387330f729Sjoerg // amdgcn does not support linking of object files, therefore we skip
29397330f729Sjoerg // backend and assemble phases to output LLVM IR. Except for generating
29407330f729Sjoerg // non-relocatable device coee, where we generate fat binary for device
29417330f729Sjoerg // code and pass to host in Backend phase.
2942*e038c9c4Sjoerg if (CudaDeviceActions.empty())
29437330f729Sjoerg return ABRT_Success;
29447330f729Sjoerg
29457330f729Sjoerg assert(((CurPhase == phases::Link && Relocatable) ||
29467330f729Sjoerg CudaDeviceActions.size() == GpuArchList.size()) &&
29477330f729Sjoerg "Expecting one action per GPU architecture.");
29487330f729Sjoerg assert(!CompileHostOnly &&
29497330f729Sjoerg "Not expecting CUDA actions in host-only compilation.");
29507330f729Sjoerg
29517330f729Sjoerg if (!Relocatable && CurPhase == phases::Backend && !EmitLLVM &&
29527330f729Sjoerg !EmitAsm) {
29537330f729Sjoerg // If we are in backend phase, we attempt to generate the fat binary.
29547330f729Sjoerg // We compile each arch to IR and use a link action to generate code
29557330f729Sjoerg // object containing ISA. Then we use a special "link" action to create
29567330f729Sjoerg // a fat binary containing all the code objects for different GPU's.
29577330f729Sjoerg // The fat binary is then an input to the host action.
29587330f729Sjoerg for (unsigned I = 0, E = GpuArchList.size(); I != E; ++I) {
2959*e038c9c4Sjoerg if (GPUSanitize || C.getDriver().isUsingLTO(/*IsOffload=*/true)) {
2960*e038c9c4Sjoerg // When GPU sanitizer is enabled, since we need to link in the
2961*e038c9c4Sjoerg // the sanitizer runtime library after the sanitize pass, we have
2962*e038c9c4Sjoerg // to skip the backend and assemble phases and use lld to link
2963*e038c9c4Sjoerg // the bitcode. The same happens if users request to use LTO
2964*e038c9c4Sjoerg // explicitly.
29657330f729Sjoerg ActionList AL;
29667330f729Sjoerg AL.push_back(CudaDeviceActions[I]);
2967*e038c9c4Sjoerg // Create a link action to link device IR with device library
2968*e038c9c4Sjoerg // and generate ISA.
29697330f729Sjoerg CudaDeviceActions[I] =
29707330f729Sjoerg C.MakeAction<LinkJobAction>(AL, types::TY_Image);
2971*e038c9c4Sjoerg } else {
2972*e038c9c4Sjoerg // When GPU sanitizer is not enabled, we follow the conventional
2973*e038c9c4Sjoerg // compiler phases, including backend and assemble phases.
2974*e038c9c4Sjoerg ActionList AL;
2975*e038c9c4Sjoerg auto BackendAction = C.getDriver().ConstructPhaseAction(
2976*e038c9c4Sjoerg C, Args, phases::Backend, CudaDeviceActions[I],
2977*e038c9c4Sjoerg AssociatedOffloadKind);
2978*e038c9c4Sjoerg auto AssembleAction = C.getDriver().ConstructPhaseAction(
2979*e038c9c4Sjoerg C, Args, phases::Assemble, BackendAction,
2980*e038c9c4Sjoerg AssociatedOffloadKind);
2981*e038c9c4Sjoerg AL.push_back(AssembleAction);
2982*e038c9c4Sjoerg // Create a link action to link device IR with device library
2983*e038c9c4Sjoerg // and generate ISA.
2984*e038c9c4Sjoerg CudaDeviceActions[I] =
2985*e038c9c4Sjoerg C.MakeAction<LinkJobAction>(AL, types::TY_Image);
2986*e038c9c4Sjoerg }
29877330f729Sjoerg
29887330f729Sjoerg // OffloadingActionBuilder propagates device arch until an offload
29897330f729Sjoerg // action. Since the next action for creating fatbin does
29907330f729Sjoerg // not have device arch, whereas the above link action and its input
29917330f729Sjoerg // have device arch, an offload action is needed to stop the null
29927330f729Sjoerg // device arch of the next action being propagated to the above link
29937330f729Sjoerg // action.
29947330f729Sjoerg OffloadAction::DeviceDependences DDep;
2995*e038c9c4Sjoerg DDep.add(*CudaDeviceActions[I], *ToolChains.front(), GpuArchList[I],
2996*e038c9c4Sjoerg AssociatedOffloadKind);
29977330f729Sjoerg CudaDeviceActions[I] = C.MakeAction<OffloadAction>(
29987330f729Sjoerg DDep, CudaDeviceActions[I]->getType());
29997330f729Sjoerg }
30007330f729Sjoerg // Create HIP fat binary with a special "link" action.
30017330f729Sjoerg CudaFatBinary =
30027330f729Sjoerg C.MakeAction<LinkJobAction>(CudaDeviceActions,
30037330f729Sjoerg types::TY_HIP_FATBIN);
30047330f729Sjoerg
30057330f729Sjoerg if (!CompileDeviceOnly) {
30067330f729Sjoerg DA.add(*CudaFatBinary, *ToolChains.front(), /*BoundArch=*/nullptr,
30077330f729Sjoerg AssociatedOffloadKind);
30087330f729Sjoerg // Clear the fat binary, it is already a dependence to an host
30097330f729Sjoerg // action.
30107330f729Sjoerg CudaFatBinary = nullptr;
30117330f729Sjoerg }
30127330f729Sjoerg
30137330f729Sjoerg // Remove the CUDA actions as they are already connected to an host
30147330f729Sjoerg // action or fat binary.
30157330f729Sjoerg CudaDeviceActions.clear();
30167330f729Sjoerg
30177330f729Sjoerg return CompileDeviceOnly ? ABRT_Ignore_Host : ABRT_Success;
30187330f729Sjoerg } else if (CurPhase == phases::Link) {
30197330f729Sjoerg // Save CudaDeviceActions to DeviceLinkerInputs for each GPU subarch.
30207330f729Sjoerg // This happens to each device action originated from each input file.
30217330f729Sjoerg // Later on, device actions in DeviceLinkerInputs are used to create
30227330f729Sjoerg // device link actions in appendLinkDependences and the created device
30237330f729Sjoerg // link actions are passed to the offload action as device dependence.
30247330f729Sjoerg DeviceLinkerInputs.resize(CudaDeviceActions.size());
30257330f729Sjoerg auto LI = DeviceLinkerInputs.begin();
30267330f729Sjoerg for (auto *A : CudaDeviceActions) {
30277330f729Sjoerg LI->push_back(A);
30287330f729Sjoerg ++LI;
30297330f729Sjoerg }
30307330f729Sjoerg
30317330f729Sjoerg // We will pass the device action as a host dependence, so we don't
30327330f729Sjoerg // need to do anything else with them.
30337330f729Sjoerg CudaDeviceActions.clear();
30347330f729Sjoerg return ABRT_Success;
30357330f729Sjoerg }
30367330f729Sjoerg
30377330f729Sjoerg // By default, we produce an action for each device arch.
30387330f729Sjoerg for (Action *&A : CudaDeviceActions)
30397330f729Sjoerg A = C.getDriver().ConstructPhaseAction(C, Args, CurPhase, A,
30407330f729Sjoerg AssociatedOffloadKind);
30417330f729Sjoerg
30427330f729Sjoerg return (CompileDeviceOnly && CurPhase == FinalPhase) ? ABRT_Ignore_Host
30437330f729Sjoerg : ABRT_Success;
30447330f729Sjoerg }
30457330f729Sjoerg
appendLinkDeviceActions(ActionList & AL)3046*e038c9c4Sjoerg void appendLinkDeviceActions(ActionList &AL) override {
3047*e038c9c4Sjoerg if (DeviceLinkerInputs.size() == 0)
3048*e038c9c4Sjoerg return;
3049*e038c9c4Sjoerg
3050*e038c9c4Sjoerg assert(DeviceLinkerInputs.size() == GpuArchList.size() &&
3051*e038c9c4Sjoerg "Linker inputs and GPU arch list sizes do not match.");
3052*e038c9c4Sjoerg
30537330f729Sjoerg // Append a new link action for each device.
30547330f729Sjoerg unsigned I = 0;
30557330f729Sjoerg for (auto &LI : DeviceLinkerInputs) {
3056*e038c9c4Sjoerg // Each entry in DeviceLinkerInputs corresponds to a GPU arch.
30577330f729Sjoerg auto *DeviceLinkAction =
30587330f729Sjoerg C.MakeAction<LinkJobAction>(LI, types::TY_Image);
3059*e038c9c4Sjoerg // Linking all inputs for the current GPU arch.
3060*e038c9c4Sjoerg // LI contains all the inputs for the linker.
3061*e038c9c4Sjoerg OffloadAction::DeviceDependences DeviceLinkDeps;
3062*e038c9c4Sjoerg DeviceLinkDeps.add(*DeviceLinkAction, *ToolChains[0],
3063*e038c9c4Sjoerg GpuArchList[I], AssociatedOffloadKind);
3064*e038c9c4Sjoerg AL.push_back(C.MakeAction<OffloadAction>(DeviceLinkDeps,
3065*e038c9c4Sjoerg DeviceLinkAction->getType()));
30667330f729Sjoerg ++I;
30677330f729Sjoerg }
3068*e038c9c4Sjoerg DeviceLinkerInputs.clear();
3069*e038c9c4Sjoerg
3070*e038c9c4Sjoerg // Create a host object from all the device images by embedding them
3071*e038c9c4Sjoerg // in a fat binary.
3072*e038c9c4Sjoerg OffloadAction::DeviceDependences DDeps;
3073*e038c9c4Sjoerg auto *TopDeviceLinkAction =
3074*e038c9c4Sjoerg C.MakeAction<LinkJobAction>(AL, types::TY_Object);
3075*e038c9c4Sjoerg DDeps.add(*TopDeviceLinkAction, *ToolChains[0],
3076*e038c9c4Sjoerg nullptr, AssociatedOffloadKind);
3077*e038c9c4Sjoerg
3078*e038c9c4Sjoerg // Offload the host object to the host linker.
3079*e038c9c4Sjoerg AL.push_back(C.MakeAction<OffloadAction>(DDeps, TopDeviceLinkAction->getType()));
30807330f729Sjoerg }
3081*e038c9c4Sjoerg
appendLinkHostActions(ActionList & AL)3082*e038c9c4Sjoerg Action* appendLinkHostActions(ActionList &AL) override { return AL.back(); }
3083*e038c9c4Sjoerg
appendLinkDependences(OffloadAction::DeviceDependences & DA)3084*e038c9c4Sjoerg void appendLinkDependences(OffloadAction::DeviceDependences &DA) override {}
30857330f729Sjoerg };
30867330f729Sjoerg
30877330f729Sjoerg /// OpenMP action builder. The host bitcode is passed to the device frontend
30887330f729Sjoerg /// and all the device linked images are passed to the host link phase.
30897330f729Sjoerg class OpenMPActionBuilder final : public DeviceActionBuilder {
30907330f729Sjoerg /// The OpenMP actions for the current input.
30917330f729Sjoerg ActionList OpenMPDeviceActions;
30927330f729Sjoerg
30937330f729Sjoerg /// The linker inputs obtained for each toolchain.
30947330f729Sjoerg SmallVector<ActionList, 8> DeviceLinkerInputs;
30957330f729Sjoerg
30967330f729Sjoerg public:
OpenMPActionBuilder(Compilation & C,DerivedArgList & Args,const Driver::InputList & Inputs)30977330f729Sjoerg OpenMPActionBuilder(Compilation &C, DerivedArgList &Args,
30987330f729Sjoerg const Driver::InputList &Inputs)
30997330f729Sjoerg : DeviceActionBuilder(C, Args, Inputs, Action::OFK_OpenMP) {}
31007330f729Sjoerg
31017330f729Sjoerg ActionBuilderReturnCode
getDeviceDependences(OffloadAction::DeviceDependences & DA,phases::ID CurPhase,phases::ID FinalPhase,PhasesTy & Phases)31027330f729Sjoerg getDeviceDependences(OffloadAction::DeviceDependences &DA,
31037330f729Sjoerg phases::ID CurPhase, phases::ID FinalPhase,
31047330f729Sjoerg PhasesTy &Phases) override {
31057330f729Sjoerg if (OpenMPDeviceActions.empty())
31067330f729Sjoerg return ABRT_Inactive;
31077330f729Sjoerg
31087330f729Sjoerg // We should always have an action for each input.
31097330f729Sjoerg assert(OpenMPDeviceActions.size() == ToolChains.size() &&
31107330f729Sjoerg "Number of OpenMP actions and toolchains do not match.");
31117330f729Sjoerg
31127330f729Sjoerg // The host only depends on device action in the linking phase, when all
31137330f729Sjoerg // the device images have to be embedded in the host image.
31147330f729Sjoerg if (CurPhase == phases::Link) {
31157330f729Sjoerg assert(ToolChains.size() == DeviceLinkerInputs.size() &&
31167330f729Sjoerg "Toolchains and linker inputs sizes do not match.");
31177330f729Sjoerg auto LI = DeviceLinkerInputs.begin();
31187330f729Sjoerg for (auto *A : OpenMPDeviceActions) {
31197330f729Sjoerg LI->push_back(A);
31207330f729Sjoerg ++LI;
31217330f729Sjoerg }
31227330f729Sjoerg
31237330f729Sjoerg // We passed the device action as a host dependence, so we don't need to
31247330f729Sjoerg // do anything else with them.
31257330f729Sjoerg OpenMPDeviceActions.clear();
31267330f729Sjoerg return ABRT_Success;
31277330f729Sjoerg }
31287330f729Sjoerg
31297330f729Sjoerg // By default, we produce an action for each device arch.
31307330f729Sjoerg for (Action *&A : OpenMPDeviceActions)
31317330f729Sjoerg A = C.getDriver().ConstructPhaseAction(C, Args, CurPhase, A);
31327330f729Sjoerg
31337330f729Sjoerg return ABRT_Success;
31347330f729Sjoerg }
31357330f729Sjoerg
addDeviceDepences(Action * HostAction)31367330f729Sjoerg ActionBuilderReturnCode addDeviceDepences(Action *HostAction) override {
31377330f729Sjoerg
31387330f729Sjoerg // If this is an input action replicate it for each OpenMP toolchain.
31397330f729Sjoerg if (auto *IA = dyn_cast<InputAction>(HostAction)) {
31407330f729Sjoerg OpenMPDeviceActions.clear();
31417330f729Sjoerg for (unsigned I = 0; I < ToolChains.size(); ++I)
31427330f729Sjoerg OpenMPDeviceActions.push_back(
31437330f729Sjoerg C.MakeAction<InputAction>(IA->getInputArg(), IA->getType()));
31447330f729Sjoerg return ABRT_Success;
31457330f729Sjoerg }
31467330f729Sjoerg
31477330f729Sjoerg // If this is an unbundling action use it as is for each OpenMP toolchain.
31487330f729Sjoerg if (auto *UA = dyn_cast<OffloadUnbundlingJobAction>(HostAction)) {
31497330f729Sjoerg OpenMPDeviceActions.clear();
31507330f729Sjoerg auto *IA = cast<InputAction>(UA->getInputs().back());
31517330f729Sjoerg std::string FileName = IA->getInputArg().getAsString(Args);
31527330f729Sjoerg // Check if the type of the file is the same as the action. Do not
31537330f729Sjoerg // unbundle it if it is not. Do not unbundle .so files, for example,
31547330f729Sjoerg // which are not object files.
31557330f729Sjoerg if (IA->getType() == types::TY_Object &&
31567330f729Sjoerg (!llvm::sys::path::has_extension(FileName) ||
31577330f729Sjoerg types::lookupTypeForExtension(
31587330f729Sjoerg llvm::sys::path::extension(FileName).drop_front()) !=
31597330f729Sjoerg types::TY_Object))
31607330f729Sjoerg return ABRT_Inactive;
31617330f729Sjoerg for (unsigned I = 0; I < ToolChains.size(); ++I) {
31627330f729Sjoerg OpenMPDeviceActions.push_back(UA);
31637330f729Sjoerg UA->registerDependentActionInfo(
31647330f729Sjoerg ToolChains[I], /*BoundArch=*/StringRef(), Action::OFK_OpenMP);
31657330f729Sjoerg }
31667330f729Sjoerg return ABRT_Success;
31677330f729Sjoerg }
31687330f729Sjoerg
31697330f729Sjoerg // When generating code for OpenMP we use the host compile phase result as
31707330f729Sjoerg // a dependence to the device compile phase so that it can learn what
31717330f729Sjoerg // declarations should be emitted. However, this is not the only use for
31727330f729Sjoerg // the host action, so we prevent it from being collapsed.
31737330f729Sjoerg if (isa<CompileJobAction>(HostAction)) {
31747330f729Sjoerg HostAction->setCannotBeCollapsedWithNextDependentAction();
31757330f729Sjoerg assert(ToolChains.size() == OpenMPDeviceActions.size() &&
31767330f729Sjoerg "Toolchains and device action sizes do not match.");
31777330f729Sjoerg OffloadAction::HostDependence HDep(
31787330f729Sjoerg *HostAction, *C.getSingleOffloadToolChain<Action::OFK_Host>(),
31797330f729Sjoerg /*BoundArch=*/nullptr, Action::OFK_OpenMP);
31807330f729Sjoerg auto TC = ToolChains.begin();
31817330f729Sjoerg for (Action *&A : OpenMPDeviceActions) {
31827330f729Sjoerg assert(isa<CompileJobAction>(A));
31837330f729Sjoerg OffloadAction::DeviceDependences DDep;
31847330f729Sjoerg DDep.add(*A, **TC, /*BoundArch=*/nullptr, Action::OFK_OpenMP);
31857330f729Sjoerg A = C.MakeAction<OffloadAction>(HDep, DDep);
31867330f729Sjoerg ++TC;
31877330f729Sjoerg }
31887330f729Sjoerg }
31897330f729Sjoerg return ABRT_Success;
31907330f729Sjoerg }
31917330f729Sjoerg
appendTopLevelActions(ActionList & AL)31927330f729Sjoerg void appendTopLevelActions(ActionList &AL) override {
31937330f729Sjoerg if (OpenMPDeviceActions.empty())
31947330f729Sjoerg return;
31957330f729Sjoerg
31967330f729Sjoerg // We should always have an action for each input.
31977330f729Sjoerg assert(OpenMPDeviceActions.size() == ToolChains.size() &&
31987330f729Sjoerg "Number of OpenMP actions and toolchains do not match.");
31997330f729Sjoerg
32007330f729Sjoerg // Append all device actions followed by the proper offload action.
32017330f729Sjoerg auto TI = ToolChains.begin();
32027330f729Sjoerg for (auto *A : OpenMPDeviceActions) {
32037330f729Sjoerg OffloadAction::DeviceDependences Dep;
32047330f729Sjoerg Dep.add(*A, **TI, /*BoundArch=*/nullptr, Action::OFK_OpenMP);
32057330f729Sjoerg AL.push_back(C.MakeAction<OffloadAction>(Dep, A->getType()));
32067330f729Sjoerg ++TI;
32077330f729Sjoerg }
32087330f729Sjoerg // We no longer need the action stored in this builder.
32097330f729Sjoerg OpenMPDeviceActions.clear();
32107330f729Sjoerg }
32117330f729Sjoerg
appendLinkDeviceActions(ActionList & AL)3212*e038c9c4Sjoerg void appendLinkDeviceActions(ActionList &AL) override {
32137330f729Sjoerg assert(ToolChains.size() == DeviceLinkerInputs.size() &&
32147330f729Sjoerg "Toolchains and linker inputs sizes do not match.");
32157330f729Sjoerg
32167330f729Sjoerg // Append a new link action for each device.
32177330f729Sjoerg auto TC = ToolChains.begin();
32187330f729Sjoerg for (auto &LI : DeviceLinkerInputs) {
32197330f729Sjoerg auto *DeviceLinkAction =
32207330f729Sjoerg C.MakeAction<LinkJobAction>(LI, types::TY_Image);
32217330f729Sjoerg OffloadAction::DeviceDependences DeviceLinkDeps;
32227330f729Sjoerg DeviceLinkDeps.add(*DeviceLinkAction, **TC, /*BoundArch=*/nullptr,
32237330f729Sjoerg Action::OFK_OpenMP);
32247330f729Sjoerg AL.push_back(C.MakeAction<OffloadAction>(DeviceLinkDeps,
32257330f729Sjoerg DeviceLinkAction->getType()));
32267330f729Sjoerg ++TC;
32277330f729Sjoerg }
32287330f729Sjoerg DeviceLinkerInputs.clear();
32297330f729Sjoerg }
32307330f729Sjoerg
appendLinkHostActions(ActionList & AL)3231*e038c9c4Sjoerg Action* appendLinkHostActions(ActionList &AL) override {
3232*e038c9c4Sjoerg // Create wrapper bitcode from the result of device link actions and compile
3233*e038c9c4Sjoerg // it to an object which will be added to the host link command.
3234*e038c9c4Sjoerg auto *BC = C.MakeAction<OffloadWrapperJobAction>(AL, types::TY_LLVM_BC);
3235*e038c9c4Sjoerg auto *ASM = C.MakeAction<BackendJobAction>(BC, types::TY_PP_Asm);
3236*e038c9c4Sjoerg return C.MakeAction<AssembleJobAction>(ASM, types::TY_Object);
3237*e038c9c4Sjoerg }
3238*e038c9c4Sjoerg
appendLinkDependences(OffloadAction::DeviceDependences & DA)32397330f729Sjoerg void appendLinkDependences(OffloadAction::DeviceDependences &DA) override {}
32407330f729Sjoerg
initialize()32417330f729Sjoerg bool initialize() override {
32427330f729Sjoerg // Get the OpenMP toolchains. If we don't get any, the action builder will
32437330f729Sjoerg // know there is nothing to do related to OpenMP offloading.
32447330f729Sjoerg auto OpenMPTCRange = C.getOffloadToolChains<Action::OFK_OpenMP>();
32457330f729Sjoerg for (auto TI = OpenMPTCRange.first, TE = OpenMPTCRange.second; TI != TE;
32467330f729Sjoerg ++TI)
32477330f729Sjoerg ToolChains.push_back(TI->second);
32487330f729Sjoerg
32497330f729Sjoerg DeviceLinkerInputs.resize(ToolChains.size());
32507330f729Sjoerg return false;
32517330f729Sjoerg }
32527330f729Sjoerg
canUseBundlerUnbundler() const32537330f729Sjoerg bool canUseBundlerUnbundler() const override {
32547330f729Sjoerg // OpenMP should use bundled files whenever possible.
32557330f729Sjoerg return true;
32567330f729Sjoerg }
32577330f729Sjoerg };
32587330f729Sjoerg
32597330f729Sjoerg ///
32607330f729Sjoerg /// TODO: Add the implementation for other specialized builders here.
32617330f729Sjoerg ///
32627330f729Sjoerg
32637330f729Sjoerg /// Specialized builders being used by this offloading action builder.
32647330f729Sjoerg SmallVector<DeviceActionBuilder *, 4> SpecializedBuilders;
32657330f729Sjoerg
32667330f729Sjoerg /// Flag set to true if all valid builders allow file bundling/unbundling.
32677330f729Sjoerg bool CanUseBundler;
32687330f729Sjoerg
32697330f729Sjoerg public:
OffloadingActionBuilder(Compilation & C,DerivedArgList & Args,const Driver::InputList & Inputs)32707330f729Sjoerg OffloadingActionBuilder(Compilation &C, DerivedArgList &Args,
32717330f729Sjoerg const Driver::InputList &Inputs)
32727330f729Sjoerg : C(C) {
32737330f729Sjoerg // Create a specialized builder for each device toolchain.
32747330f729Sjoerg
32757330f729Sjoerg IsValid = true;
32767330f729Sjoerg
32777330f729Sjoerg // Create a specialized builder for CUDA.
32787330f729Sjoerg SpecializedBuilders.push_back(new CudaActionBuilder(C, Args, Inputs));
32797330f729Sjoerg
32807330f729Sjoerg // Create a specialized builder for HIP.
32817330f729Sjoerg SpecializedBuilders.push_back(new HIPActionBuilder(C, Args, Inputs));
32827330f729Sjoerg
32837330f729Sjoerg // Create a specialized builder for OpenMP.
32847330f729Sjoerg SpecializedBuilders.push_back(new OpenMPActionBuilder(C, Args, Inputs));
32857330f729Sjoerg
32867330f729Sjoerg //
32877330f729Sjoerg // TODO: Build other specialized builders here.
32887330f729Sjoerg //
32897330f729Sjoerg
32907330f729Sjoerg // Initialize all the builders, keeping track of errors. If all valid
32917330f729Sjoerg // builders agree that we can use bundling, set the flag to true.
32927330f729Sjoerg unsigned ValidBuilders = 0u;
32937330f729Sjoerg unsigned ValidBuildersSupportingBundling = 0u;
32947330f729Sjoerg for (auto *SB : SpecializedBuilders) {
32957330f729Sjoerg IsValid = IsValid && !SB->initialize();
32967330f729Sjoerg
32977330f729Sjoerg // Update the counters if the builder is valid.
32987330f729Sjoerg if (SB->isValid()) {
32997330f729Sjoerg ++ValidBuilders;
33007330f729Sjoerg if (SB->canUseBundlerUnbundler())
33017330f729Sjoerg ++ValidBuildersSupportingBundling;
33027330f729Sjoerg }
33037330f729Sjoerg }
33047330f729Sjoerg CanUseBundler =
33057330f729Sjoerg ValidBuilders && ValidBuilders == ValidBuildersSupportingBundling;
33067330f729Sjoerg }
33077330f729Sjoerg
~OffloadingActionBuilder()33087330f729Sjoerg ~OffloadingActionBuilder() {
33097330f729Sjoerg for (auto *SB : SpecializedBuilders)
33107330f729Sjoerg delete SB;
33117330f729Sjoerg }
33127330f729Sjoerg
33137330f729Sjoerg /// Generate an action that adds device dependences (if any) to a host action.
33147330f729Sjoerg /// If no device dependence actions exist, just return the host action \a
33157330f729Sjoerg /// HostAction. If an error is found or if no builder requires the host action
33167330f729Sjoerg /// to be generated, return nullptr.
33177330f729Sjoerg Action *
addDeviceDependencesToHostAction(Action * HostAction,const Arg * InputArg,phases::ID CurPhase,phases::ID FinalPhase,DeviceActionBuilder::PhasesTy & Phases)33187330f729Sjoerg addDeviceDependencesToHostAction(Action *HostAction, const Arg *InputArg,
33197330f729Sjoerg phases::ID CurPhase, phases::ID FinalPhase,
33207330f729Sjoerg DeviceActionBuilder::PhasesTy &Phases) {
33217330f729Sjoerg if (!IsValid)
33227330f729Sjoerg return nullptr;
33237330f729Sjoerg
33247330f729Sjoerg if (SpecializedBuilders.empty())
33257330f729Sjoerg return HostAction;
33267330f729Sjoerg
33277330f729Sjoerg assert(HostAction && "Invalid host action!");
33287330f729Sjoerg
33297330f729Sjoerg OffloadAction::DeviceDependences DDeps;
33307330f729Sjoerg // Check if all the programming models agree we should not emit the host
33317330f729Sjoerg // action. Also, keep track of the offloading kinds employed.
33327330f729Sjoerg auto &OffloadKind = InputArgToOffloadKindMap[InputArg];
33337330f729Sjoerg unsigned InactiveBuilders = 0u;
33347330f729Sjoerg unsigned IgnoringBuilders = 0u;
33357330f729Sjoerg for (auto *SB : SpecializedBuilders) {
33367330f729Sjoerg if (!SB->isValid()) {
33377330f729Sjoerg ++InactiveBuilders;
33387330f729Sjoerg continue;
33397330f729Sjoerg }
33407330f729Sjoerg
33417330f729Sjoerg auto RetCode =
33427330f729Sjoerg SB->getDeviceDependences(DDeps, CurPhase, FinalPhase, Phases);
33437330f729Sjoerg
33447330f729Sjoerg // If the builder explicitly says the host action should be ignored,
33457330f729Sjoerg // we need to increment the variable that tracks the builders that request
33467330f729Sjoerg // the host object to be ignored.
33477330f729Sjoerg if (RetCode == DeviceActionBuilder::ABRT_Ignore_Host)
33487330f729Sjoerg ++IgnoringBuilders;
33497330f729Sjoerg
33507330f729Sjoerg // Unless the builder was inactive for this action, we have to record the
33517330f729Sjoerg // offload kind because the host will have to use it.
33527330f729Sjoerg if (RetCode != DeviceActionBuilder::ABRT_Inactive)
33537330f729Sjoerg OffloadKind |= SB->getAssociatedOffloadKind();
33547330f729Sjoerg }
33557330f729Sjoerg
33567330f729Sjoerg // If all builders agree that the host object should be ignored, just return
33577330f729Sjoerg // nullptr.
33587330f729Sjoerg if (IgnoringBuilders &&
33597330f729Sjoerg SpecializedBuilders.size() == (InactiveBuilders + IgnoringBuilders))
33607330f729Sjoerg return nullptr;
33617330f729Sjoerg
33627330f729Sjoerg if (DDeps.getActions().empty())
33637330f729Sjoerg return HostAction;
33647330f729Sjoerg
33657330f729Sjoerg // We have dependences we need to bundle together. We use an offload action
33667330f729Sjoerg // for that.
33677330f729Sjoerg OffloadAction::HostDependence HDep(
33687330f729Sjoerg *HostAction, *C.getSingleOffloadToolChain<Action::OFK_Host>(),
33697330f729Sjoerg /*BoundArch=*/nullptr, DDeps);
33707330f729Sjoerg return C.MakeAction<OffloadAction>(HDep, DDeps);
33717330f729Sjoerg }
33727330f729Sjoerg
33737330f729Sjoerg /// Generate an action that adds a host dependence to a device action. The
33747330f729Sjoerg /// results will be kept in this action builder. Return true if an error was
33757330f729Sjoerg /// found.
addHostDependenceToDeviceActions(Action * & HostAction,const Arg * InputArg)33767330f729Sjoerg bool addHostDependenceToDeviceActions(Action *&HostAction,
33777330f729Sjoerg const Arg *InputArg) {
33787330f729Sjoerg if (!IsValid)
33797330f729Sjoerg return true;
33807330f729Sjoerg
33817330f729Sjoerg // If we are supporting bundling/unbundling and the current action is an
33827330f729Sjoerg // input action of non-source file, we replace the host action by the
33837330f729Sjoerg // unbundling action. The bundler tool has the logic to detect if an input
33847330f729Sjoerg // is a bundle or not and if the input is not a bundle it assumes it is a
33857330f729Sjoerg // host file. Therefore it is safe to create an unbundling action even if
33867330f729Sjoerg // the input is not a bundle.
33877330f729Sjoerg if (CanUseBundler && isa<InputAction>(HostAction) &&
33887330f729Sjoerg InputArg->getOption().getKind() == llvm::opt::Option::InputClass &&
3389*e038c9c4Sjoerg (!types::isSrcFile(HostAction->getType()) ||
3390*e038c9c4Sjoerg HostAction->getType() == types::TY_PP_HIP)) {
33917330f729Sjoerg auto UnbundlingHostAction =
33927330f729Sjoerg C.MakeAction<OffloadUnbundlingJobAction>(HostAction);
33937330f729Sjoerg UnbundlingHostAction->registerDependentActionInfo(
33947330f729Sjoerg C.getSingleOffloadToolChain<Action::OFK_Host>(),
33957330f729Sjoerg /*BoundArch=*/StringRef(), Action::OFK_Host);
33967330f729Sjoerg HostAction = UnbundlingHostAction;
33977330f729Sjoerg }
33987330f729Sjoerg
33997330f729Sjoerg assert(HostAction && "Invalid host action!");
34007330f729Sjoerg
34017330f729Sjoerg // Register the offload kinds that are used.
34027330f729Sjoerg auto &OffloadKind = InputArgToOffloadKindMap[InputArg];
34037330f729Sjoerg for (auto *SB : SpecializedBuilders) {
34047330f729Sjoerg if (!SB->isValid())
34057330f729Sjoerg continue;
34067330f729Sjoerg
34077330f729Sjoerg auto RetCode = SB->addDeviceDepences(HostAction);
34087330f729Sjoerg
34097330f729Sjoerg // Host dependences for device actions are not compatible with that same
34107330f729Sjoerg // action being ignored.
34117330f729Sjoerg assert(RetCode != DeviceActionBuilder::ABRT_Ignore_Host &&
34127330f729Sjoerg "Host dependence not expected to be ignored.!");
34137330f729Sjoerg
34147330f729Sjoerg // Unless the builder was inactive for this action, we have to record the
34157330f729Sjoerg // offload kind because the host will have to use it.
34167330f729Sjoerg if (RetCode != DeviceActionBuilder::ABRT_Inactive)
34177330f729Sjoerg OffloadKind |= SB->getAssociatedOffloadKind();
34187330f729Sjoerg }
34197330f729Sjoerg
34207330f729Sjoerg // Do not use unbundler if the Host does not depend on device action.
34217330f729Sjoerg if (OffloadKind == Action::OFK_None && CanUseBundler)
34227330f729Sjoerg if (auto *UA = dyn_cast<OffloadUnbundlingJobAction>(HostAction))
34237330f729Sjoerg HostAction = UA->getInputs().back();
34247330f729Sjoerg
34257330f729Sjoerg return false;
34267330f729Sjoerg }
34277330f729Sjoerg
34287330f729Sjoerg /// Add the offloading top level actions to the provided action list. This
34297330f729Sjoerg /// function can replace the host action by a bundling action if the
34307330f729Sjoerg /// programming models allow it.
appendTopLevelActions(ActionList & AL,Action * HostAction,const Arg * InputArg)34317330f729Sjoerg bool appendTopLevelActions(ActionList &AL, Action *HostAction,
34327330f729Sjoerg const Arg *InputArg) {
34337330f729Sjoerg // Get the device actions to be appended.
34347330f729Sjoerg ActionList OffloadAL;
34357330f729Sjoerg for (auto *SB : SpecializedBuilders) {
34367330f729Sjoerg if (!SB->isValid())
34377330f729Sjoerg continue;
34387330f729Sjoerg SB->appendTopLevelActions(OffloadAL);
34397330f729Sjoerg }
34407330f729Sjoerg
34417330f729Sjoerg // If we can use the bundler, replace the host action by the bundling one in
34427330f729Sjoerg // the resulting list. Otherwise, just append the device actions. For
34437330f729Sjoerg // device only compilation, HostAction is a null pointer, therefore only do
34447330f729Sjoerg // this when HostAction is not a null pointer.
34457330f729Sjoerg if (CanUseBundler && HostAction &&
34467330f729Sjoerg HostAction->getType() != types::TY_Nothing && !OffloadAL.empty()) {
34477330f729Sjoerg // Add the host action to the list in order to create the bundling action.
34487330f729Sjoerg OffloadAL.push_back(HostAction);
34497330f729Sjoerg
34507330f729Sjoerg // We expect that the host action was just appended to the action list
34517330f729Sjoerg // before this method was called.
34527330f729Sjoerg assert(HostAction == AL.back() && "Host action not in the list??");
34537330f729Sjoerg HostAction = C.MakeAction<OffloadBundlingJobAction>(OffloadAL);
34547330f729Sjoerg AL.back() = HostAction;
34557330f729Sjoerg } else
34567330f729Sjoerg AL.append(OffloadAL.begin(), OffloadAL.end());
34577330f729Sjoerg
34587330f729Sjoerg // Propagate to the current host action (if any) the offload information
34597330f729Sjoerg // associated with the current input.
34607330f729Sjoerg if (HostAction)
34617330f729Sjoerg HostAction->propagateHostOffloadInfo(InputArgToOffloadKindMap[InputArg],
34627330f729Sjoerg /*BoundArch=*/nullptr);
34637330f729Sjoerg return false;
34647330f729Sjoerg }
34657330f729Sjoerg
makeHostLinkAction()34667330f729Sjoerg Action* makeHostLinkAction() {
34677330f729Sjoerg // Build a list of device linking actions.
34687330f729Sjoerg ActionList DeviceAL;
34697330f729Sjoerg for (DeviceActionBuilder *SB : SpecializedBuilders) {
34707330f729Sjoerg if (!SB->isValid())
34717330f729Sjoerg continue;
3472*e038c9c4Sjoerg SB->appendLinkDeviceActions(DeviceAL);
34737330f729Sjoerg }
34747330f729Sjoerg
34757330f729Sjoerg if (DeviceAL.empty())
34767330f729Sjoerg return nullptr;
34777330f729Sjoerg
3478*e038c9c4Sjoerg // Let builders add host linking actions.
3479*e038c9c4Sjoerg Action* HA = nullptr;
3480*e038c9c4Sjoerg for (DeviceActionBuilder *SB : SpecializedBuilders) {
3481*e038c9c4Sjoerg if (!SB->isValid())
3482*e038c9c4Sjoerg continue;
3483*e038c9c4Sjoerg HA = SB->appendLinkHostActions(DeviceAL);
3484*e038c9c4Sjoerg }
3485*e038c9c4Sjoerg return HA;
34867330f729Sjoerg }
34877330f729Sjoerg
34887330f729Sjoerg /// Processes the host linker action. This currently consists of replacing it
34897330f729Sjoerg /// with an offload action if there are device link objects and propagate to
34907330f729Sjoerg /// the host action all the offload kinds used in the current compilation. The
34917330f729Sjoerg /// resulting action is returned.
processHostLinkAction(Action * HostAction)34927330f729Sjoerg Action *processHostLinkAction(Action *HostAction) {
34937330f729Sjoerg // Add all the dependences from the device linking actions.
34947330f729Sjoerg OffloadAction::DeviceDependences DDeps;
34957330f729Sjoerg for (auto *SB : SpecializedBuilders) {
34967330f729Sjoerg if (!SB->isValid())
34977330f729Sjoerg continue;
34987330f729Sjoerg
34997330f729Sjoerg SB->appendLinkDependences(DDeps);
35007330f729Sjoerg }
35017330f729Sjoerg
35027330f729Sjoerg // Calculate all the offload kinds used in the current compilation.
35037330f729Sjoerg unsigned ActiveOffloadKinds = 0u;
35047330f729Sjoerg for (auto &I : InputArgToOffloadKindMap)
35057330f729Sjoerg ActiveOffloadKinds |= I.second;
35067330f729Sjoerg
35077330f729Sjoerg // If we don't have device dependencies, we don't have to create an offload
35087330f729Sjoerg // action.
35097330f729Sjoerg if (DDeps.getActions().empty()) {
35107330f729Sjoerg // Propagate all the active kinds to host action. Given that it is a link
35117330f729Sjoerg // action it is assumed to depend on all actions generated so far.
35127330f729Sjoerg HostAction->propagateHostOffloadInfo(ActiveOffloadKinds,
35137330f729Sjoerg /*BoundArch=*/nullptr);
35147330f729Sjoerg return HostAction;
35157330f729Sjoerg }
35167330f729Sjoerg
35177330f729Sjoerg // Create the offload action with all dependences. When an offload action
35187330f729Sjoerg // is created the kinds are propagated to the host action, so we don't have
35197330f729Sjoerg // to do that explicitly here.
35207330f729Sjoerg OffloadAction::HostDependence HDep(
35217330f729Sjoerg *HostAction, *C.getSingleOffloadToolChain<Action::OFK_Host>(),
35227330f729Sjoerg /*BoundArch*/ nullptr, ActiveOffloadKinds);
35237330f729Sjoerg return C.MakeAction<OffloadAction>(HDep, DDeps);
35247330f729Sjoerg }
35257330f729Sjoerg };
35267330f729Sjoerg } // anonymous namespace.
35277330f729Sjoerg
handleArguments(Compilation & C,DerivedArgList & Args,const InputList & Inputs,ActionList & Actions) const35287330f729Sjoerg void Driver::handleArguments(Compilation &C, DerivedArgList &Args,
35297330f729Sjoerg const InputList &Inputs,
35307330f729Sjoerg ActionList &Actions) const {
35317330f729Sjoerg
35327330f729Sjoerg // Ignore /Yc/Yu if both /Yc and /Yu passed but with different filenames.
35337330f729Sjoerg Arg *YcArg = Args.getLastArg(options::OPT__SLASH_Yc);
35347330f729Sjoerg Arg *YuArg = Args.getLastArg(options::OPT__SLASH_Yu);
35357330f729Sjoerg if (YcArg && YuArg && strcmp(YcArg->getValue(), YuArg->getValue()) != 0) {
35367330f729Sjoerg Diag(clang::diag::warn_drv_ycyu_different_arg_clang_cl);
35377330f729Sjoerg Args.eraseArg(options::OPT__SLASH_Yc);
35387330f729Sjoerg Args.eraseArg(options::OPT__SLASH_Yu);
35397330f729Sjoerg YcArg = YuArg = nullptr;
35407330f729Sjoerg }
35417330f729Sjoerg if (YcArg && Inputs.size() > 1) {
35427330f729Sjoerg Diag(clang::diag::warn_drv_yc_multiple_inputs_clang_cl);
35437330f729Sjoerg Args.eraseArg(options::OPT__SLASH_Yc);
35447330f729Sjoerg YcArg = nullptr;
35457330f729Sjoerg }
35467330f729Sjoerg
35477330f729Sjoerg Arg *FinalPhaseArg;
35487330f729Sjoerg phases::ID FinalPhase = getFinalPhase(Args, &FinalPhaseArg);
35497330f729Sjoerg
35507330f729Sjoerg if (FinalPhase == phases::Link) {
35517330f729Sjoerg if (Args.hasArg(options::OPT_emit_llvm))
35527330f729Sjoerg Diag(clang::diag::err_drv_emit_llvm_link);
35537330f729Sjoerg if (IsCLMode() && LTOMode != LTOK_None &&
35547330f729Sjoerg !Args.getLastArgValue(options::OPT_fuse_ld_EQ).equals_lower("lld"))
35557330f729Sjoerg Diag(clang::diag::err_drv_lto_without_lld);
35567330f729Sjoerg }
35577330f729Sjoerg
35587330f729Sjoerg if (FinalPhase == phases::Preprocess || Args.hasArg(options::OPT__SLASH_Y_)) {
35597330f729Sjoerg // If only preprocessing or /Y- is used, all pch handling is disabled.
35607330f729Sjoerg // Rather than check for it everywhere, just remove clang-cl pch-related
35617330f729Sjoerg // flags here.
35627330f729Sjoerg Args.eraseArg(options::OPT__SLASH_Fp);
35637330f729Sjoerg Args.eraseArg(options::OPT__SLASH_Yc);
35647330f729Sjoerg Args.eraseArg(options::OPT__SLASH_Yu);
35657330f729Sjoerg YcArg = YuArg = nullptr;
35667330f729Sjoerg }
35677330f729Sjoerg
35687330f729Sjoerg unsigned LastPLSize = 0;
35697330f729Sjoerg for (auto &I : Inputs) {
35707330f729Sjoerg types::ID InputType = I.first;
35717330f729Sjoerg const Arg *InputArg = I.second;
35727330f729Sjoerg
3573*e038c9c4Sjoerg auto PL = types::getCompilationPhases(InputType);
35747330f729Sjoerg LastPLSize = PL.size();
35757330f729Sjoerg
35767330f729Sjoerg // If the first step comes after the final phase we are doing as part of
35777330f729Sjoerg // this compilation, warn the user about it.
35787330f729Sjoerg phases::ID InitialPhase = PL[0];
35797330f729Sjoerg if (InitialPhase > FinalPhase) {
35807330f729Sjoerg if (InputArg->isClaimed())
35817330f729Sjoerg continue;
35827330f729Sjoerg
35837330f729Sjoerg // Claim here to avoid the more general unused warning.
35847330f729Sjoerg InputArg->claim();
35857330f729Sjoerg
35867330f729Sjoerg // Suppress all unused style warnings with -Qunused-arguments
35877330f729Sjoerg if (Args.hasArg(options::OPT_Qunused_arguments))
35887330f729Sjoerg continue;
35897330f729Sjoerg
35907330f729Sjoerg // Special case when final phase determined by binary name, rather than
35917330f729Sjoerg // by a command-line argument with a corresponding Arg.
35927330f729Sjoerg if (CCCIsCPP())
35937330f729Sjoerg Diag(clang::diag::warn_drv_input_file_unused_by_cpp)
35947330f729Sjoerg << InputArg->getAsString(Args) << getPhaseName(InitialPhase);
35957330f729Sjoerg // Special case '-E' warning on a previously preprocessed file to make
35967330f729Sjoerg // more sense.
35977330f729Sjoerg else if (InitialPhase == phases::Compile &&
35987330f729Sjoerg (Args.getLastArg(options::OPT__SLASH_EP,
35997330f729Sjoerg options::OPT__SLASH_P) ||
36007330f729Sjoerg Args.getLastArg(options::OPT_E) ||
36017330f729Sjoerg Args.getLastArg(options::OPT_M, options::OPT_MM)) &&
36027330f729Sjoerg getPreprocessedType(InputType) == types::TY_INVALID)
36037330f729Sjoerg Diag(clang::diag::warn_drv_preprocessed_input_file_unused)
36047330f729Sjoerg << InputArg->getAsString(Args) << !!FinalPhaseArg
36057330f729Sjoerg << (FinalPhaseArg ? FinalPhaseArg->getOption().getName() : "");
36067330f729Sjoerg else
36077330f729Sjoerg Diag(clang::diag::warn_drv_input_file_unused)
36087330f729Sjoerg << InputArg->getAsString(Args) << getPhaseName(InitialPhase)
36097330f729Sjoerg << !!FinalPhaseArg
36107330f729Sjoerg << (FinalPhaseArg ? FinalPhaseArg->getOption().getName() : "");
36117330f729Sjoerg continue;
36127330f729Sjoerg }
36137330f729Sjoerg
36147330f729Sjoerg if (YcArg) {
36157330f729Sjoerg // Add a separate precompile phase for the compile phase.
36167330f729Sjoerg if (FinalPhase >= phases::Compile) {
36177330f729Sjoerg const types::ID HeaderType = lookupHeaderTypeForSourceType(InputType);
36187330f729Sjoerg // Build the pipeline for the pch file.
36197330f729Sjoerg Action *ClangClPch = C.MakeAction<InputAction>(*InputArg, HeaderType);
3620*e038c9c4Sjoerg for (phases::ID Phase : types::getCompilationPhases(HeaderType))
36217330f729Sjoerg ClangClPch = ConstructPhaseAction(C, Args, Phase, ClangClPch);
36227330f729Sjoerg assert(ClangClPch);
36237330f729Sjoerg Actions.push_back(ClangClPch);
36247330f729Sjoerg // The driver currently exits after the first failed command. This
36257330f729Sjoerg // relies on that behavior, to make sure if the pch generation fails,
36267330f729Sjoerg // the main compilation won't run.
36277330f729Sjoerg // FIXME: If the main compilation fails, the PCH generation should
36287330f729Sjoerg // probably not be considered successful either.
36297330f729Sjoerg }
36307330f729Sjoerg }
36317330f729Sjoerg }
36327330f729Sjoerg
36337330f729Sjoerg // If we are linking, claim any options which are obviously only used for
36347330f729Sjoerg // compilation.
36357330f729Sjoerg // FIXME: Understand why the last Phase List length is used here.
36367330f729Sjoerg if (FinalPhase == phases::Link && LastPLSize == 1) {
36377330f729Sjoerg Args.ClaimAllArgs(options::OPT_CompileOnly_Group);
36387330f729Sjoerg Args.ClaimAllArgs(options::OPT_cl_compile_Group);
36397330f729Sjoerg }
36407330f729Sjoerg }
36417330f729Sjoerg
BuildActions(Compilation & C,DerivedArgList & Args,const InputList & Inputs,ActionList & Actions) const36427330f729Sjoerg void Driver::BuildActions(Compilation &C, DerivedArgList &Args,
36437330f729Sjoerg const InputList &Inputs, ActionList &Actions) const {
36447330f729Sjoerg llvm::PrettyStackTraceString CrashInfo("Building compilation actions");
36457330f729Sjoerg
36467330f729Sjoerg if (!SuppressMissingInputWarning && Inputs.empty()) {
36477330f729Sjoerg Diag(clang::diag::err_drv_no_input_files);
36487330f729Sjoerg return;
36497330f729Sjoerg }
36507330f729Sjoerg
36517330f729Sjoerg // Reject -Z* at the top level, these options should never have been exposed
36527330f729Sjoerg // by gcc.
36537330f729Sjoerg if (Arg *A = Args.getLastArg(options::OPT_Z_Joined))
36547330f729Sjoerg Diag(clang::diag::err_drv_use_of_Z_option) << A->getAsString(Args);
36557330f729Sjoerg
36567330f729Sjoerg // Diagnose misuse of /Fo.
36577330f729Sjoerg if (Arg *A = Args.getLastArg(options::OPT__SLASH_Fo)) {
36587330f729Sjoerg StringRef V = A->getValue();
36597330f729Sjoerg if (Inputs.size() > 1 && !V.empty() &&
36607330f729Sjoerg !llvm::sys::path::is_separator(V.back())) {
36617330f729Sjoerg // Check whether /Fo tries to name an output file for multiple inputs.
36627330f729Sjoerg Diag(clang::diag::err_drv_out_file_argument_with_multiple_sources)
36637330f729Sjoerg << A->getSpelling() << V;
36647330f729Sjoerg Args.eraseArg(options::OPT__SLASH_Fo);
36657330f729Sjoerg }
36667330f729Sjoerg }
36677330f729Sjoerg
36687330f729Sjoerg // Diagnose misuse of /Fa.
36697330f729Sjoerg if (Arg *A = Args.getLastArg(options::OPT__SLASH_Fa)) {
36707330f729Sjoerg StringRef V = A->getValue();
36717330f729Sjoerg if (Inputs.size() > 1 && !V.empty() &&
36727330f729Sjoerg !llvm::sys::path::is_separator(V.back())) {
36737330f729Sjoerg // Check whether /Fa tries to name an asm file for multiple inputs.
36747330f729Sjoerg Diag(clang::diag::err_drv_out_file_argument_with_multiple_sources)
36757330f729Sjoerg << A->getSpelling() << V;
36767330f729Sjoerg Args.eraseArg(options::OPT__SLASH_Fa);
36777330f729Sjoerg }
36787330f729Sjoerg }
36797330f729Sjoerg
36807330f729Sjoerg // Diagnose misuse of /o.
36817330f729Sjoerg if (Arg *A = Args.getLastArg(options::OPT__SLASH_o)) {
36827330f729Sjoerg if (A->getValue()[0] == '\0') {
36837330f729Sjoerg // It has to have a value.
36847330f729Sjoerg Diag(clang::diag::err_drv_missing_argument) << A->getSpelling() << 1;
36857330f729Sjoerg Args.eraseArg(options::OPT__SLASH_o);
36867330f729Sjoerg }
36877330f729Sjoerg }
36887330f729Sjoerg
36897330f729Sjoerg handleArguments(C, Args, Inputs, Actions);
36907330f729Sjoerg
36917330f729Sjoerg // Builder to be used to build offloading actions.
36927330f729Sjoerg OffloadingActionBuilder OffloadBuilder(C, Args, Inputs);
36937330f729Sjoerg
36947330f729Sjoerg // Construct the actions to perform.
36957330f729Sjoerg HeaderModulePrecompileJobAction *HeaderModuleAction = nullptr;
36967330f729Sjoerg ActionList LinkerInputs;
36977330f729Sjoerg ActionList MergerInputs;
36987330f729Sjoerg
36997330f729Sjoerg for (auto &I : Inputs) {
37007330f729Sjoerg types::ID InputType = I.first;
37017330f729Sjoerg const Arg *InputArg = I.second;
37027330f729Sjoerg
3703*e038c9c4Sjoerg auto PL = types::getCompilationPhases(*this, Args, InputType);
37047330f729Sjoerg if (PL.empty())
37057330f729Sjoerg continue;
37067330f729Sjoerg
3707*e038c9c4Sjoerg auto FullPL = types::getCompilationPhases(InputType);
37087330f729Sjoerg
37097330f729Sjoerg // Build the pipeline for this file.
37107330f729Sjoerg Action *Current = C.MakeAction<InputAction>(*InputArg, InputType);
37117330f729Sjoerg
37127330f729Sjoerg // Use the current host action in any of the offloading actions, if
37137330f729Sjoerg // required.
37147330f729Sjoerg if (OffloadBuilder.addHostDependenceToDeviceActions(Current, InputArg))
37157330f729Sjoerg break;
37167330f729Sjoerg
37177330f729Sjoerg for (phases::ID Phase : PL) {
37187330f729Sjoerg
37197330f729Sjoerg // Add any offload action the host action depends on.
37207330f729Sjoerg Current = OffloadBuilder.addDeviceDependencesToHostAction(
37217330f729Sjoerg Current, InputArg, Phase, PL.back(), FullPL);
37227330f729Sjoerg if (!Current)
37237330f729Sjoerg break;
37247330f729Sjoerg
37257330f729Sjoerg // Queue linker inputs.
37267330f729Sjoerg if (Phase == phases::Link) {
37277330f729Sjoerg assert(Phase == PL.back() && "linking must be final compilation step.");
37287330f729Sjoerg LinkerInputs.push_back(Current);
37297330f729Sjoerg Current = nullptr;
37307330f729Sjoerg break;
37317330f729Sjoerg }
37327330f729Sjoerg
37337330f729Sjoerg // TODO: Consider removing this because the merged may not end up being
37347330f729Sjoerg // the final Phase in the pipeline. Perhaps the merged could just merge
37357330f729Sjoerg // and then pass an artifact of some sort to the Link Phase.
37367330f729Sjoerg // Queue merger inputs.
37377330f729Sjoerg if (Phase == phases::IfsMerge) {
37387330f729Sjoerg assert(Phase == PL.back() && "merging must be final compilation step.");
37397330f729Sjoerg MergerInputs.push_back(Current);
37407330f729Sjoerg Current = nullptr;
37417330f729Sjoerg break;
37427330f729Sjoerg }
37437330f729Sjoerg
37447330f729Sjoerg // Each precompiled header file after a module file action is a module
37457330f729Sjoerg // header of that same module file, rather than being compiled to a
37467330f729Sjoerg // separate PCH.
37477330f729Sjoerg if (Phase == phases::Precompile && HeaderModuleAction &&
37487330f729Sjoerg getPrecompiledType(InputType) == types::TY_PCH) {
37497330f729Sjoerg HeaderModuleAction->addModuleHeaderInput(Current);
37507330f729Sjoerg Current = nullptr;
37517330f729Sjoerg break;
37527330f729Sjoerg }
37537330f729Sjoerg
37547330f729Sjoerg // FIXME: Should we include any prior module file outputs as inputs of
37557330f729Sjoerg // later actions in the same command line?
37567330f729Sjoerg
37577330f729Sjoerg // Otherwise construct the appropriate action.
37587330f729Sjoerg Action *NewCurrent = ConstructPhaseAction(C, Args, Phase, Current);
37597330f729Sjoerg
37607330f729Sjoerg // We didn't create a new action, so we will just move to the next phase.
37617330f729Sjoerg if (NewCurrent == Current)
37627330f729Sjoerg continue;
37637330f729Sjoerg
37647330f729Sjoerg if (auto *HMA = dyn_cast<HeaderModulePrecompileJobAction>(NewCurrent))
37657330f729Sjoerg HeaderModuleAction = HMA;
37667330f729Sjoerg
37677330f729Sjoerg Current = NewCurrent;
37687330f729Sjoerg
37697330f729Sjoerg // Use the current host action in any of the offloading actions, if
37707330f729Sjoerg // required.
37717330f729Sjoerg if (OffloadBuilder.addHostDependenceToDeviceActions(Current, InputArg))
37727330f729Sjoerg break;
37737330f729Sjoerg
37747330f729Sjoerg if (Current->getType() == types::TY_Nothing)
37757330f729Sjoerg break;
37767330f729Sjoerg }
37777330f729Sjoerg
37787330f729Sjoerg // If we ended with something, add to the output list.
37797330f729Sjoerg if (Current)
37807330f729Sjoerg Actions.push_back(Current);
37817330f729Sjoerg
37827330f729Sjoerg // Add any top level actions generated for offloading.
37837330f729Sjoerg OffloadBuilder.appendTopLevelActions(Actions, Current, InputArg);
37847330f729Sjoerg }
37857330f729Sjoerg
37867330f729Sjoerg // Add a link action if necessary.
37877330f729Sjoerg if (!LinkerInputs.empty()) {
37887330f729Sjoerg if (Action *Wrapper = OffloadBuilder.makeHostLinkAction())
37897330f729Sjoerg LinkerInputs.push_back(Wrapper);
3790*e038c9c4Sjoerg Action *LA;
3791*e038c9c4Sjoerg // Check if this Linker Job should emit a static library.
3792*e038c9c4Sjoerg if (ShouldEmitStaticLibrary(Args)) {
3793*e038c9c4Sjoerg LA = C.MakeAction<StaticLibJobAction>(LinkerInputs, types::TY_Image);
3794*e038c9c4Sjoerg } else {
3795*e038c9c4Sjoerg LA = C.MakeAction<LinkJobAction>(LinkerInputs, types::TY_Image);
3796*e038c9c4Sjoerg }
37977330f729Sjoerg LA = OffloadBuilder.processHostLinkAction(LA);
37987330f729Sjoerg Actions.push_back(LA);
37997330f729Sjoerg }
38007330f729Sjoerg
38017330f729Sjoerg // Add an interface stubs merge action if necessary.
38027330f729Sjoerg if (!MergerInputs.empty())
38037330f729Sjoerg Actions.push_back(
38047330f729Sjoerg C.MakeAction<IfsMergeJobAction>(MergerInputs, types::TY_Image));
38057330f729Sjoerg
3806*e038c9c4Sjoerg if (Args.hasArg(options::OPT_emit_interface_stubs)) {
3807*e038c9c4Sjoerg auto PhaseList = types::getCompilationPhases(
3808*e038c9c4Sjoerg types::TY_IFS_CPP,
3809*e038c9c4Sjoerg Args.hasArg(options::OPT_c) ? phases::Compile : phases::LastPhase);
3810*e038c9c4Sjoerg
3811*e038c9c4Sjoerg ActionList MergerInputs;
3812*e038c9c4Sjoerg
3813*e038c9c4Sjoerg for (auto &I : Inputs) {
3814*e038c9c4Sjoerg types::ID InputType = I.first;
3815*e038c9c4Sjoerg const Arg *InputArg = I.second;
3816*e038c9c4Sjoerg
3817*e038c9c4Sjoerg // Currently clang and the llvm assembler do not support generating symbol
3818*e038c9c4Sjoerg // stubs from assembly, so we skip the input on asm files. For ifs files
3819*e038c9c4Sjoerg // we rely on the normal pipeline setup in the pipeline setup code above.
3820*e038c9c4Sjoerg if (InputType == types::TY_IFS || InputType == types::TY_PP_Asm ||
3821*e038c9c4Sjoerg InputType == types::TY_Asm)
3822*e038c9c4Sjoerg continue;
3823*e038c9c4Sjoerg
3824*e038c9c4Sjoerg Action *Current = C.MakeAction<InputAction>(*InputArg, InputType);
3825*e038c9c4Sjoerg
3826*e038c9c4Sjoerg for (auto Phase : PhaseList) {
3827*e038c9c4Sjoerg switch (Phase) {
3828*e038c9c4Sjoerg default:
3829*e038c9c4Sjoerg llvm_unreachable(
3830*e038c9c4Sjoerg "IFS Pipeline can only consist of Compile followed by IfsMerge.");
3831*e038c9c4Sjoerg case phases::Compile: {
3832*e038c9c4Sjoerg // Only IfsMerge (llvm-ifs) can handle .o files by looking for ifs
3833*e038c9c4Sjoerg // files where the .o file is located. The compile action can not
3834*e038c9c4Sjoerg // handle this.
3835*e038c9c4Sjoerg if (InputType == types::TY_Object)
3836*e038c9c4Sjoerg break;
3837*e038c9c4Sjoerg
3838*e038c9c4Sjoerg Current = C.MakeAction<CompileJobAction>(Current, types::TY_IFS_CPP);
3839*e038c9c4Sjoerg break;
3840*e038c9c4Sjoerg }
3841*e038c9c4Sjoerg case phases::IfsMerge: {
3842*e038c9c4Sjoerg assert(Phase == PhaseList.back() &&
3843*e038c9c4Sjoerg "merging must be final compilation step.");
3844*e038c9c4Sjoerg MergerInputs.push_back(Current);
3845*e038c9c4Sjoerg Current = nullptr;
3846*e038c9c4Sjoerg break;
3847*e038c9c4Sjoerg }
3848*e038c9c4Sjoerg }
3849*e038c9c4Sjoerg }
3850*e038c9c4Sjoerg
3851*e038c9c4Sjoerg // If we ended with something, add to the output list.
3852*e038c9c4Sjoerg if (Current)
3853*e038c9c4Sjoerg Actions.push_back(Current);
3854*e038c9c4Sjoerg }
3855*e038c9c4Sjoerg
3856*e038c9c4Sjoerg // Add an interface stubs merge action if necessary.
3857*e038c9c4Sjoerg if (!MergerInputs.empty())
3858*e038c9c4Sjoerg Actions.push_back(
3859*e038c9c4Sjoerg C.MakeAction<IfsMergeJobAction>(MergerInputs, types::TY_Image));
3860*e038c9c4Sjoerg }
3861*e038c9c4Sjoerg
38627330f729Sjoerg // If --print-supported-cpus, -mcpu=? or -mtune=? is specified, build a custom
38637330f729Sjoerg // Compile phase that prints out supported cpu models and quits.
38647330f729Sjoerg if (Arg *A = Args.getLastArg(options::OPT_print_supported_cpus)) {
38657330f729Sjoerg // Use the -mcpu=? flag as the dummy input to cc1.
38667330f729Sjoerg Actions.clear();
38677330f729Sjoerg Action *InputAc = C.MakeAction<InputAction>(*A, types::TY_C);
38687330f729Sjoerg Actions.push_back(
38697330f729Sjoerg C.MakeAction<PrecompileJobAction>(InputAc, types::TY_Nothing));
38707330f729Sjoerg for (auto &I : Inputs)
38717330f729Sjoerg I.second->claim();
38727330f729Sjoerg }
38737330f729Sjoerg
38747330f729Sjoerg // Claim ignored clang-cl options.
38757330f729Sjoerg Args.ClaimAllArgs(options::OPT_cl_ignored_Group);
38767330f729Sjoerg
38777330f729Sjoerg // Claim --cuda-host-only and --cuda-compile-host-device, which may be passed
38787330f729Sjoerg // to non-CUDA compilations and should not trigger warnings there.
38797330f729Sjoerg Args.ClaimAllArgs(options::OPT_cuda_host_only);
38807330f729Sjoerg Args.ClaimAllArgs(options::OPT_cuda_compile_host_device);
38817330f729Sjoerg }
38827330f729Sjoerg
ConstructPhaseAction(Compilation & C,const ArgList & Args,phases::ID Phase,Action * Input,Action::OffloadKind TargetDeviceOffloadKind) const38837330f729Sjoerg Action *Driver::ConstructPhaseAction(
38847330f729Sjoerg Compilation &C, const ArgList &Args, phases::ID Phase, Action *Input,
38857330f729Sjoerg Action::OffloadKind TargetDeviceOffloadKind) const {
38867330f729Sjoerg llvm::PrettyStackTraceString CrashInfo("Constructing phase actions");
38877330f729Sjoerg
38887330f729Sjoerg // Some types skip the assembler phase (e.g., llvm-bc), but we can't
38897330f729Sjoerg // encode this in the steps because the intermediate type depends on
38907330f729Sjoerg // arguments. Just special case here.
38917330f729Sjoerg if (Phase == phases::Assemble && Input->getType() != types::TY_PP_Asm)
38927330f729Sjoerg return Input;
38937330f729Sjoerg
38947330f729Sjoerg // Build the appropriate action.
38957330f729Sjoerg switch (Phase) {
38967330f729Sjoerg case phases::Link:
38977330f729Sjoerg llvm_unreachable("link action invalid here.");
38987330f729Sjoerg case phases::IfsMerge:
38997330f729Sjoerg llvm_unreachable("ifsmerge action invalid here.");
39007330f729Sjoerg case phases::Preprocess: {
39017330f729Sjoerg types::ID OutputTy;
39027330f729Sjoerg // -M and -MM specify the dependency file name by altering the output type,
39037330f729Sjoerg // -if -MD and -MMD are not specified.
39047330f729Sjoerg if (Args.hasArg(options::OPT_M, options::OPT_MM) &&
39057330f729Sjoerg !Args.hasArg(options::OPT_MD, options::OPT_MMD)) {
39067330f729Sjoerg OutputTy = types::TY_Dependencies;
39077330f729Sjoerg } else {
39087330f729Sjoerg OutputTy = Input->getType();
39097330f729Sjoerg if (!Args.hasFlag(options::OPT_frewrite_includes,
39107330f729Sjoerg options::OPT_fno_rewrite_includes, false) &&
39117330f729Sjoerg !Args.hasFlag(options::OPT_frewrite_imports,
39127330f729Sjoerg options::OPT_fno_rewrite_imports, false) &&
39137330f729Sjoerg !CCGenDiagnostics)
39147330f729Sjoerg OutputTy = types::getPreprocessedType(OutputTy);
39157330f729Sjoerg assert(OutputTy != types::TY_INVALID &&
39167330f729Sjoerg "Cannot preprocess this input type!");
39177330f729Sjoerg }
39187330f729Sjoerg return C.MakeAction<PreprocessJobAction>(Input, OutputTy);
39197330f729Sjoerg }
39207330f729Sjoerg case phases::Precompile: {
39217330f729Sjoerg types::ID OutputTy = getPrecompiledType(Input->getType());
39227330f729Sjoerg assert(OutputTy != types::TY_INVALID &&
39237330f729Sjoerg "Cannot precompile this input type!");
39247330f729Sjoerg
39257330f729Sjoerg // If we're given a module name, precompile header file inputs as a
39267330f729Sjoerg // module, not as a precompiled header.
39277330f729Sjoerg const char *ModName = nullptr;
39287330f729Sjoerg if (OutputTy == types::TY_PCH) {
39297330f729Sjoerg if (Arg *A = Args.getLastArg(options::OPT_fmodule_name_EQ))
39307330f729Sjoerg ModName = A->getValue();
39317330f729Sjoerg if (ModName)
39327330f729Sjoerg OutputTy = types::TY_ModuleFile;
39337330f729Sjoerg }
39347330f729Sjoerg
39357330f729Sjoerg if (Args.hasArg(options::OPT_fsyntax_only)) {
39367330f729Sjoerg // Syntax checks should not emit a PCH file
39377330f729Sjoerg OutputTy = types::TY_Nothing;
39387330f729Sjoerg }
39397330f729Sjoerg
39407330f729Sjoerg if (ModName)
39417330f729Sjoerg return C.MakeAction<HeaderModulePrecompileJobAction>(Input, OutputTy,
39427330f729Sjoerg ModName);
39437330f729Sjoerg return C.MakeAction<PrecompileJobAction>(Input, OutputTy);
39447330f729Sjoerg }
39457330f729Sjoerg case phases::Compile: {
39467330f729Sjoerg if (Args.hasArg(options::OPT_fsyntax_only))
39477330f729Sjoerg return C.MakeAction<CompileJobAction>(Input, types::TY_Nothing);
39487330f729Sjoerg if (Args.hasArg(options::OPT_rewrite_objc))
39497330f729Sjoerg return C.MakeAction<CompileJobAction>(Input, types::TY_RewrittenObjC);
39507330f729Sjoerg if (Args.hasArg(options::OPT_rewrite_legacy_objc))
39517330f729Sjoerg return C.MakeAction<CompileJobAction>(Input,
39527330f729Sjoerg types::TY_RewrittenLegacyObjC);
39537330f729Sjoerg if (Args.hasArg(options::OPT__analyze))
39547330f729Sjoerg return C.MakeAction<AnalyzeJobAction>(Input, types::TY_Plist);
39557330f729Sjoerg if (Args.hasArg(options::OPT__migrate))
39567330f729Sjoerg return C.MakeAction<MigrateJobAction>(Input, types::TY_Remap);
39577330f729Sjoerg if (Args.hasArg(options::OPT_emit_ast))
39587330f729Sjoerg return C.MakeAction<CompileJobAction>(Input, types::TY_AST);
39597330f729Sjoerg if (Args.hasArg(options::OPT_module_file_info))
39607330f729Sjoerg return C.MakeAction<CompileJobAction>(Input, types::TY_ModuleFile);
39617330f729Sjoerg if (Args.hasArg(options::OPT_verify_pch))
39627330f729Sjoerg return C.MakeAction<VerifyPCHJobAction>(Input, types::TY_Nothing);
39637330f729Sjoerg return C.MakeAction<CompileJobAction>(Input, types::TY_LLVM_BC);
39647330f729Sjoerg }
39657330f729Sjoerg case phases::Backend: {
39667330f729Sjoerg if (isUsingLTO() && TargetDeviceOffloadKind == Action::OFK_None) {
39677330f729Sjoerg types::ID Output =
39687330f729Sjoerg Args.hasArg(options::OPT_S) ? types::TY_LTO_IR : types::TY_LTO_BC;
39697330f729Sjoerg return C.MakeAction<BackendJobAction>(Input, Output);
39707330f729Sjoerg }
3971*e038c9c4Sjoerg if (Args.hasArg(options::OPT_emit_llvm) ||
3972*e038c9c4Sjoerg (TargetDeviceOffloadKind == Action::OFK_HIP &&
3973*e038c9c4Sjoerg Args.hasFlag(options::OPT_fgpu_rdc, options::OPT_fno_gpu_rdc,
3974*e038c9c4Sjoerg false))) {
39757330f729Sjoerg types::ID Output =
39767330f729Sjoerg Args.hasArg(options::OPT_S) ? types::TY_LLVM_IR : types::TY_LLVM_BC;
39777330f729Sjoerg return C.MakeAction<BackendJobAction>(Input, Output);
39787330f729Sjoerg }
39797330f729Sjoerg return C.MakeAction<BackendJobAction>(Input, types::TY_PP_Asm);
39807330f729Sjoerg }
39817330f729Sjoerg case phases::Assemble:
39827330f729Sjoerg return C.MakeAction<AssembleJobAction>(std::move(Input), types::TY_Object);
39837330f729Sjoerg }
39847330f729Sjoerg
39857330f729Sjoerg llvm_unreachable("invalid phase in ConstructPhaseAction");
39867330f729Sjoerg }
39877330f729Sjoerg
BuildJobs(Compilation & C) const39887330f729Sjoerg void Driver::BuildJobs(Compilation &C) const {
39897330f729Sjoerg llvm::PrettyStackTraceString CrashInfo("Building compilation jobs");
39907330f729Sjoerg
39917330f729Sjoerg Arg *FinalOutput = C.getArgs().getLastArg(options::OPT_o);
39927330f729Sjoerg
39937330f729Sjoerg // It is an error to provide a -o option if we are making multiple output
3994*e038c9c4Sjoerg // files. There are exceptions:
3995*e038c9c4Sjoerg //
3996*e038c9c4Sjoerg // IfsMergeJob: when generating interface stubs enabled we want to be able to
3997*e038c9c4Sjoerg // generate the stub file at the same time that we generate the real
3998*e038c9c4Sjoerg // library/a.out. So when a .o, .so, etc are the output, with clang interface
3999*e038c9c4Sjoerg // stubs there will also be a .ifs and .ifso at the same location.
4000*e038c9c4Sjoerg //
4001*e038c9c4Sjoerg // CompileJob of type TY_IFS_CPP: when generating interface stubs is enabled
4002*e038c9c4Sjoerg // and -c is passed, we still want to be able to generate a .ifs file while
4003*e038c9c4Sjoerg // we are also generating .o files. So we allow more than one output file in
4004*e038c9c4Sjoerg // this case as well.
4005*e038c9c4Sjoerg //
40067330f729Sjoerg if (FinalOutput) {
40077330f729Sjoerg unsigned NumOutputs = 0;
4008*e038c9c4Sjoerg unsigned NumIfsOutputs = 0;
40097330f729Sjoerg for (const Action *A : C.getActions())
4010*e038c9c4Sjoerg if (A->getType() != types::TY_Nothing &&
4011*e038c9c4Sjoerg !(A->getKind() == Action::IfsMergeJobClass ||
4012*e038c9c4Sjoerg (A->getType() == clang::driver::types::TY_IFS_CPP &&
4013*e038c9c4Sjoerg A->getKind() == clang::driver::Action::CompileJobClass &&
4014*e038c9c4Sjoerg 0 == NumIfsOutputs++) ||
4015*e038c9c4Sjoerg (A->getKind() == Action::BindArchClass && A->getInputs().size() &&
4016*e038c9c4Sjoerg A->getInputs().front()->getKind() == Action::IfsMergeJobClass)))
40177330f729Sjoerg ++NumOutputs;
40187330f729Sjoerg
40197330f729Sjoerg if (NumOutputs > 1) {
40207330f729Sjoerg Diag(clang::diag::err_drv_output_argument_with_multiple_files);
40217330f729Sjoerg FinalOutput = nullptr;
40227330f729Sjoerg }
40237330f729Sjoerg }
40247330f729Sjoerg
4025*e038c9c4Sjoerg const llvm::Triple &RawTriple = C.getDefaultToolChain().getTriple();
4026*e038c9c4Sjoerg if (RawTriple.isOSAIX()) {
4027*e038c9c4Sjoerg if (Arg *A = C.getArgs().getLastArg(options::OPT_G))
4028*e038c9c4Sjoerg Diag(diag::err_drv_unsupported_opt_for_target)
4029*e038c9c4Sjoerg << A->getSpelling() << RawTriple.str();
4030*e038c9c4Sjoerg if (LTOMode == LTOK_Thin)
4031*e038c9c4Sjoerg Diag(diag::err_drv_clang_unsupported) << "thinLTO on AIX";
4032*e038c9c4Sjoerg }
4033*e038c9c4Sjoerg
40347330f729Sjoerg // Collect the list of architectures.
40357330f729Sjoerg llvm::StringSet<> ArchNames;
4036*e038c9c4Sjoerg if (RawTriple.isOSBinFormatMachO())
40377330f729Sjoerg for (const Arg *A : C.getArgs())
40387330f729Sjoerg if (A->getOption().matches(options::OPT_arch))
40397330f729Sjoerg ArchNames.insert(A->getValue());
40407330f729Sjoerg
40417330f729Sjoerg // Set of (Action, canonical ToolChain triple) pairs we've built jobs for.
40427330f729Sjoerg std::map<std::pair<const Action *, std::string>, InputInfo> CachedResults;
40437330f729Sjoerg for (Action *A : C.getActions()) {
40447330f729Sjoerg // If we are linking an image for multiple archs then the linker wants
40457330f729Sjoerg // -arch_multiple and -final_output <final image name>. Unfortunately, this
40467330f729Sjoerg // doesn't fit in cleanly because we have to pass this information down.
40477330f729Sjoerg //
40487330f729Sjoerg // FIXME: This is a hack; find a cleaner way to integrate this into the
40497330f729Sjoerg // process.
40507330f729Sjoerg const char *LinkingOutput = nullptr;
40517330f729Sjoerg if (isa<LipoJobAction>(A)) {
40527330f729Sjoerg if (FinalOutput)
40537330f729Sjoerg LinkingOutput = FinalOutput->getValue();
40547330f729Sjoerg else
40557330f729Sjoerg LinkingOutput = getDefaultImageName();
40567330f729Sjoerg }
40577330f729Sjoerg
40587330f729Sjoerg BuildJobsForAction(C, A, &C.getDefaultToolChain(),
40597330f729Sjoerg /*BoundArch*/ StringRef(),
40607330f729Sjoerg /*AtTopLevel*/ true,
40617330f729Sjoerg /*MultipleArchs*/ ArchNames.size() > 1,
40627330f729Sjoerg /*LinkingOutput*/ LinkingOutput, CachedResults,
40637330f729Sjoerg /*TargetDeviceOffloadKind*/ Action::OFK_None);
40647330f729Sjoerg }
40657330f729Sjoerg
4066*e038c9c4Sjoerg // If we have more than one job, then disable integrated-cc1 for now. Do this
4067*e038c9c4Sjoerg // also when we need to report process execution statistics.
4068*e038c9c4Sjoerg if (C.getJobs().size() > 1 || CCPrintProcessStats)
4069*e038c9c4Sjoerg for (auto &J : C.getJobs())
4070*e038c9c4Sjoerg J.InProcess = false;
4071*e038c9c4Sjoerg
4072*e038c9c4Sjoerg if (CCPrintProcessStats) {
4073*e038c9c4Sjoerg C.setPostCallback([=](const Command &Cmd, int Res) {
4074*e038c9c4Sjoerg Optional<llvm::sys::ProcessStatistics> ProcStat =
4075*e038c9c4Sjoerg Cmd.getProcessStatistics();
4076*e038c9c4Sjoerg if (!ProcStat)
4077*e038c9c4Sjoerg return;
4078*e038c9c4Sjoerg
4079*e038c9c4Sjoerg const char *LinkingOutput = nullptr;
4080*e038c9c4Sjoerg if (FinalOutput)
4081*e038c9c4Sjoerg LinkingOutput = FinalOutput->getValue();
4082*e038c9c4Sjoerg else if (!Cmd.getOutputFilenames().empty())
4083*e038c9c4Sjoerg LinkingOutput = Cmd.getOutputFilenames().front().c_str();
4084*e038c9c4Sjoerg else
4085*e038c9c4Sjoerg LinkingOutput = getDefaultImageName();
4086*e038c9c4Sjoerg
4087*e038c9c4Sjoerg if (CCPrintStatReportFilename.empty()) {
4088*e038c9c4Sjoerg using namespace llvm;
4089*e038c9c4Sjoerg // Human readable output.
4090*e038c9c4Sjoerg outs() << sys::path::filename(Cmd.getExecutable()) << ": "
4091*e038c9c4Sjoerg << "output=" << LinkingOutput;
4092*e038c9c4Sjoerg outs() << ", total="
4093*e038c9c4Sjoerg << format("%.3f", ProcStat->TotalTime.count() / 1000.) << " ms"
4094*e038c9c4Sjoerg << ", user="
4095*e038c9c4Sjoerg << format("%.3f", ProcStat->UserTime.count() / 1000.) << " ms"
4096*e038c9c4Sjoerg << ", mem=" << ProcStat->PeakMemory << " Kb\n";
4097*e038c9c4Sjoerg } else {
4098*e038c9c4Sjoerg // CSV format.
4099*e038c9c4Sjoerg std::string Buffer;
4100*e038c9c4Sjoerg llvm::raw_string_ostream Out(Buffer);
4101*e038c9c4Sjoerg llvm::sys::printArg(Out, llvm::sys::path::filename(Cmd.getExecutable()),
4102*e038c9c4Sjoerg /*Quote*/ true);
4103*e038c9c4Sjoerg Out << ',';
4104*e038c9c4Sjoerg llvm::sys::printArg(Out, LinkingOutput, true);
4105*e038c9c4Sjoerg Out << ',' << ProcStat->TotalTime.count() << ','
4106*e038c9c4Sjoerg << ProcStat->UserTime.count() << ',' << ProcStat->PeakMemory
4107*e038c9c4Sjoerg << '\n';
4108*e038c9c4Sjoerg Out.flush();
4109*e038c9c4Sjoerg std::error_code EC;
4110*e038c9c4Sjoerg llvm::raw_fd_ostream OS(CCPrintStatReportFilename.c_str(), EC,
4111*e038c9c4Sjoerg llvm::sys::fs::OF_Append |
4112*e038c9c4Sjoerg llvm::sys::fs::OF_Text);
4113*e038c9c4Sjoerg if (EC)
4114*e038c9c4Sjoerg return;
4115*e038c9c4Sjoerg auto L = OS.lock();
4116*e038c9c4Sjoerg if (!L) {
4117*e038c9c4Sjoerg llvm::errs() << "ERROR: Cannot lock file "
4118*e038c9c4Sjoerg << CCPrintStatReportFilename << ": "
4119*e038c9c4Sjoerg << toString(L.takeError()) << "\n";
4120*e038c9c4Sjoerg return;
4121*e038c9c4Sjoerg }
4122*e038c9c4Sjoerg OS << Buffer;
4123*e038c9c4Sjoerg OS.flush();
4124*e038c9c4Sjoerg }
4125*e038c9c4Sjoerg });
4126*e038c9c4Sjoerg }
4127*e038c9c4Sjoerg
41287330f729Sjoerg // If the user passed -Qunused-arguments or there were errors, don't warn
41297330f729Sjoerg // about any unused arguments.
41307330f729Sjoerg if (Diags.hasErrorOccurred() ||
41317330f729Sjoerg C.getArgs().hasArg(options::OPT_Qunused_arguments))
41327330f729Sjoerg return;
41337330f729Sjoerg
41347330f729Sjoerg // Claim -### here.
41357330f729Sjoerg (void)C.getArgs().hasArg(options::OPT__HASH_HASH_HASH);
41367330f729Sjoerg
41377330f729Sjoerg // Claim --driver-mode, --rsp-quoting, it was handled earlier.
41387330f729Sjoerg (void)C.getArgs().hasArg(options::OPT_driver_mode);
41397330f729Sjoerg (void)C.getArgs().hasArg(options::OPT_rsp_quoting);
41407330f729Sjoerg
41417330f729Sjoerg for (Arg *A : C.getArgs()) {
41427330f729Sjoerg // FIXME: It would be nice to be able to send the argument to the
41437330f729Sjoerg // DiagnosticsEngine, so that extra values, position, and so on could be
41447330f729Sjoerg // printed.
41457330f729Sjoerg if (!A->isClaimed()) {
41467330f729Sjoerg if (A->getOption().hasFlag(options::NoArgumentUnused))
41477330f729Sjoerg continue;
41487330f729Sjoerg
41497330f729Sjoerg // Suppress the warning automatically if this is just a flag, and it is an
41507330f729Sjoerg // instance of an argument we already claimed.
41517330f729Sjoerg const Option &Opt = A->getOption();
41527330f729Sjoerg if (Opt.getKind() == Option::FlagClass) {
41537330f729Sjoerg bool DuplicateClaimed = false;
41547330f729Sjoerg
41557330f729Sjoerg for (const Arg *AA : C.getArgs().filtered(&Opt)) {
41567330f729Sjoerg if (AA->isClaimed()) {
41577330f729Sjoerg DuplicateClaimed = true;
41587330f729Sjoerg break;
41597330f729Sjoerg }
41607330f729Sjoerg }
41617330f729Sjoerg
41627330f729Sjoerg if (DuplicateClaimed)
41637330f729Sjoerg continue;
41647330f729Sjoerg }
41657330f729Sjoerg
41667330f729Sjoerg // In clang-cl, don't mention unknown arguments here since they have
41677330f729Sjoerg // already been warned about.
41687330f729Sjoerg if (!IsCLMode() || !A->getOption().matches(options::OPT_UNKNOWN))
41697330f729Sjoerg Diag(clang::diag::warn_drv_unused_argument)
41707330f729Sjoerg << A->getAsString(C.getArgs());
41717330f729Sjoerg }
41727330f729Sjoerg }
41737330f729Sjoerg }
41747330f729Sjoerg
41757330f729Sjoerg namespace {
41767330f729Sjoerg /// Utility class to control the collapse of dependent actions and select the
41777330f729Sjoerg /// tools accordingly.
41787330f729Sjoerg class ToolSelector final {
41797330f729Sjoerg /// The tool chain this selector refers to.
41807330f729Sjoerg const ToolChain &TC;
41817330f729Sjoerg
41827330f729Sjoerg /// The compilation this selector refers to.
41837330f729Sjoerg const Compilation &C;
41847330f729Sjoerg
41857330f729Sjoerg /// The base action this selector refers to.
41867330f729Sjoerg const JobAction *BaseAction;
41877330f729Sjoerg
41887330f729Sjoerg /// Set to true if the current toolchain refers to host actions.
41897330f729Sjoerg bool IsHostSelector;
41907330f729Sjoerg
41917330f729Sjoerg /// Set to true if save-temps and embed-bitcode functionalities are active.
41927330f729Sjoerg bool SaveTemps;
41937330f729Sjoerg bool EmbedBitcode;
41947330f729Sjoerg
41957330f729Sjoerg /// Get previous dependent action or null if that does not exist. If
41967330f729Sjoerg /// \a CanBeCollapsed is false, that action must be legal to collapse or
41977330f729Sjoerg /// null will be returned.
getPrevDependentAction(const ActionList & Inputs,ActionList & SavedOffloadAction,bool CanBeCollapsed=true)41987330f729Sjoerg const JobAction *getPrevDependentAction(const ActionList &Inputs,
41997330f729Sjoerg ActionList &SavedOffloadAction,
42007330f729Sjoerg bool CanBeCollapsed = true) {
42017330f729Sjoerg // An option can be collapsed only if it has a single input.
42027330f729Sjoerg if (Inputs.size() != 1)
42037330f729Sjoerg return nullptr;
42047330f729Sjoerg
42057330f729Sjoerg Action *CurAction = *Inputs.begin();
42067330f729Sjoerg if (CanBeCollapsed &&
42077330f729Sjoerg !CurAction->isCollapsingWithNextDependentActionLegal())
42087330f729Sjoerg return nullptr;
42097330f729Sjoerg
42107330f729Sjoerg // If the input action is an offload action. Look through it and save any
42117330f729Sjoerg // offload action that can be dropped in the event of a collapse.
42127330f729Sjoerg if (auto *OA = dyn_cast<OffloadAction>(CurAction)) {
42137330f729Sjoerg // If the dependent action is a device action, we will attempt to collapse
42147330f729Sjoerg // only with other device actions. Otherwise, we would do the same but
42157330f729Sjoerg // with host actions only.
42167330f729Sjoerg if (!IsHostSelector) {
42177330f729Sjoerg if (OA->hasSingleDeviceDependence(/*DoNotConsiderHostActions=*/true)) {
42187330f729Sjoerg CurAction =
42197330f729Sjoerg OA->getSingleDeviceDependence(/*DoNotConsiderHostActions=*/true);
42207330f729Sjoerg if (CanBeCollapsed &&
42217330f729Sjoerg !CurAction->isCollapsingWithNextDependentActionLegal())
42227330f729Sjoerg return nullptr;
42237330f729Sjoerg SavedOffloadAction.push_back(OA);
42247330f729Sjoerg return dyn_cast<JobAction>(CurAction);
42257330f729Sjoerg }
42267330f729Sjoerg } else if (OA->hasHostDependence()) {
42277330f729Sjoerg CurAction = OA->getHostDependence();
42287330f729Sjoerg if (CanBeCollapsed &&
42297330f729Sjoerg !CurAction->isCollapsingWithNextDependentActionLegal())
42307330f729Sjoerg return nullptr;
42317330f729Sjoerg SavedOffloadAction.push_back(OA);
42327330f729Sjoerg return dyn_cast<JobAction>(CurAction);
42337330f729Sjoerg }
42347330f729Sjoerg return nullptr;
42357330f729Sjoerg }
42367330f729Sjoerg
42377330f729Sjoerg return dyn_cast<JobAction>(CurAction);
42387330f729Sjoerg }
42397330f729Sjoerg
42407330f729Sjoerg /// Return true if an assemble action can be collapsed.
canCollapseAssembleAction() const42417330f729Sjoerg bool canCollapseAssembleAction() const {
42427330f729Sjoerg return TC.useIntegratedAs() && !SaveTemps &&
42437330f729Sjoerg !C.getArgs().hasArg(options::OPT_via_file_asm) &&
42447330f729Sjoerg !C.getArgs().hasArg(options::OPT__SLASH_FA) &&
42457330f729Sjoerg !C.getArgs().hasArg(options::OPT__SLASH_Fa);
42467330f729Sjoerg }
42477330f729Sjoerg
42487330f729Sjoerg /// Return true if a preprocessor action can be collapsed.
canCollapsePreprocessorAction() const42497330f729Sjoerg bool canCollapsePreprocessorAction() const {
42507330f729Sjoerg return !C.getArgs().hasArg(options::OPT_no_integrated_cpp) &&
42517330f729Sjoerg !C.getArgs().hasArg(options::OPT_traditional_cpp) && !SaveTemps &&
42527330f729Sjoerg !C.getArgs().hasArg(options::OPT_rewrite_objc);
42537330f729Sjoerg }
42547330f729Sjoerg
42557330f729Sjoerg /// Struct that relates an action with the offload actions that would be
42567330f729Sjoerg /// collapsed with it.
42577330f729Sjoerg struct JobActionInfo final {
42587330f729Sjoerg /// The action this info refers to.
42597330f729Sjoerg const JobAction *JA = nullptr;
42607330f729Sjoerg /// The offload actions we need to take care off if this action is
42617330f729Sjoerg /// collapsed.
42627330f729Sjoerg ActionList SavedOffloadAction;
42637330f729Sjoerg };
42647330f729Sjoerg
42657330f729Sjoerg /// Append collapsed offload actions from the give nnumber of elements in the
42667330f729Sjoerg /// action info array.
AppendCollapsedOffloadAction(ActionList & CollapsedOffloadAction,ArrayRef<JobActionInfo> & ActionInfo,unsigned ElementNum)42677330f729Sjoerg static void AppendCollapsedOffloadAction(ActionList &CollapsedOffloadAction,
42687330f729Sjoerg ArrayRef<JobActionInfo> &ActionInfo,
42697330f729Sjoerg unsigned ElementNum) {
42707330f729Sjoerg assert(ElementNum <= ActionInfo.size() && "Invalid number of elements.");
42717330f729Sjoerg for (unsigned I = 0; I < ElementNum; ++I)
42727330f729Sjoerg CollapsedOffloadAction.append(ActionInfo[I].SavedOffloadAction.begin(),
42737330f729Sjoerg ActionInfo[I].SavedOffloadAction.end());
42747330f729Sjoerg }
42757330f729Sjoerg
42767330f729Sjoerg /// Functions that attempt to perform the combining. They detect if that is
42777330f729Sjoerg /// legal, and if so they update the inputs \a Inputs and the offload action
42787330f729Sjoerg /// that were collapsed in \a CollapsedOffloadAction. A tool that deals with
42797330f729Sjoerg /// the combined action is returned. If the combining is not legal or if the
42807330f729Sjoerg /// tool does not exist, null is returned.
42817330f729Sjoerg /// Currently three kinds of collapsing are supported:
42827330f729Sjoerg /// - Assemble + Backend + Compile;
42837330f729Sjoerg /// - Assemble + Backend ;
42847330f729Sjoerg /// - Backend + Compile.
42857330f729Sjoerg const Tool *
combineAssembleBackendCompile(ArrayRef<JobActionInfo> ActionInfo,ActionList & Inputs,ActionList & CollapsedOffloadAction)42867330f729Sjoerg combineAssembleBackendCompile(ArrayRef<JobActionInfo> ActionInfo,
42877330f729Sjoerg ActionList &Inputs,
42887330f729Sjoerg ActionList &CollapsedOffloadAction) {
42897330f729Sjoerg if (ActionInfo.size() < 3 || !canCollapseAssembleAction())
42907330f729Sjoerg return nullptr;
42917330f729Sjoerg auto *AJ = dyn_cast<AssembleJobAction>(ActionInfo[0].JA);
42927330f729Sjoerg auto *BJ = dyn_cast<BackendJobAction>(ActionInfo[1].JA);
42937330f729Sjoerg auto *CJ = dyn_cast<CompileJobAction>(ActionInfo[2].JA);
42947330f729Sjoerg if (!AJ || !BJ || !CJ)
42957330f729Sjoerg return nullptr;
42967330f729Sjoerg
42977330f729Sjoerg // Get compiler tool.
42987330f729Sjoerg const Tool *T = TC.SelectTool(*CJ);
42997330f729Sjoerg if (!T)
43007330f729Sjoerg return nullptr;
43017330f729Sjoerg
43027330f729Sjoerg // When using -fembed-bitcode, it is required to have the same tool (clang)
43037330f729Sjoerg // for both CompilerJA and BackendJA. Otherwise, combine two stages.
43047330f729Sjoerg if (EmbedBitcode) {
43057330f729Sjoerg const Tool *BT = TC.SelectTool(*BJ);
43067330f729Sjoerg if (BT == T)
43077330f729Sjoerg return nullptr;
43087330f729Sjoerg }
43097330f729Sjoerg
43107330f729Sjoerg if (!T->hasIntegratedAssembler())
43117330f729Sjoerg return nullptr;
43127330f729Sjoerg
43137330f729Sjoerg Inputs = CJ->getInputs();
43147330f729Sjoerg AppendCollapsedOffloadAction(CollapsedOffloadAction, ActionInfo,
43157330f729Sjoerg /*NumElements=*/3);
43167330f729Sjoerg return T;
43177330f729Sjoerg }
combineAssembleBackend(ArrayRef<JobActionInfo> ActionInfo,ActionList & Inputs,ActionList & CollapsedOffloadAction)43187330f729Sjoerg const Tool *combineAssembleBackend(ArrayRef<JobActionInfo> ActionInfo,
43197330f729Sjoerg ActionList &Inputs,
43207330f729Sjoerg ActionList &CollapsedOffloadAction) {
43217330f729Sjoerg if (ActionInfo.size() < 2 || !canCollapseAssembleAction())
43227330f729Sjoerg return nullptr;
43237330f729Sjoerg auto *AJ = dyn_cast<AssembleJobAction>(ActionInfo[0].JA);
43247330f729Sjoerg auto *BJ = dyn_cast<BackendJobAction>(ActionInfo[1].JA);
43257330f729Sjoerg if (!AJ || !BJ)
43267330f729Sjoerg return nullptr;
43277330f729Sjoerg
43287330f729Sjoerg // Get backend tool.
43297330f729Sjoerg const Tool *T = TC.SelectTool(*BJ);
43307330f729Sjoerg if (!T)
43317330f729Sjoerg return nullptr;
43327330f729Sjoerg
43337330f729Sjoerg if (!T->hasIntegratedAssembler())
43347330f729Sjoerg return nullptr;
43357330f729Sjoerg
43367330f729Sjoerg Inputs = BJ->getInputs();
43377330f729Sjoerg AppendCollapsedOffloadAction(CollapsedOffloadAction, ActionInfo,
43387330f729Sjoerg /*NumElements=*/2);
43397330f729Sjoerg return T;
43407330f729Sjoerg }
combineBackendCompile(ArrayRef<JobActionInfo> ActionInfo,ActionList & Inputs,ActionList & CollapsedOffloadAction)43417330f729Sjoerg const Tool *combineBackendCompile(ArrayRef<JobActionInfo> ActionInfo,
43427330f729Sjoerg ActionList &Inputs,
43437330f729Sjoerg ActionList &CollapsedOffloadAction) {
43447330f729Sjoerg if (ActionInfo.size() < 2)
43457330f729Sjoerg return nullptr;
43467330f729Sjoerg auto *BJ = dyn_cast<BackendJobAction>(ActionInfo[0].JA);
43477330f729Sjoerg auto *CJ = dyn_cast<CompileJobAction>(ActionInfo[1].JA);
43487330f729Sjoerg if (!BJ || !CJ)
43497330f729Sjoerg return nullptr;
43507330f729Sjoerg
43517330f729Sjoerg // Check if the initial input (to the compile job or its predessor if one
43527330f729Sjoerg // exists) is LLVM bitcode. In that case, no preprocessor step is required
43537330f729Sjoerg // and we can still collapse the compile and backend jobs when we have
43547330f729Sjoerg // -save-temps. I.e. there is no need for a separate compile job just to
43557330f729Sjoerg // emit unoptimized bitcode.
43567330f729Sjoerg bool InputIsBitcode = true;
43577330f729Sjoerg for (size_t i = 1; i < ActionInfo.size(); i++)
43587330f729Sjoerg if (ActionInfo[i].JA->getType() != types::TY_LLVM_BC &&
43597330f729Sjoerg ActionInfo[i].JA->getType() != types::TY_LTO_BC) {
43607330f729Sjoerg InputIsBitcode = false;
43617330f729Sjoerg break;
43627330f729Sjoerg }
43637330f729Sjoerg if (!InputIsBitcode && !canCollapsePreprocessorAction())
43647330f729Sjoerg return nullptr;
43657330f729Sjoerg
43667330f729Sjoerg // Get compiler tool.
43677330f729Sjoerg const Tool *T = TC.SelectTool(*CJ);
43687330f729Sjoerg if (!T)
43697330f729Sjoerg return nullptr;
43707330f729Sjoerg
43717330f729Sjoerg if (T->canEmitIR() && ((SaveTemps && !InputIsBitcode) || EmbedBitcode))
43727330f729Sjoerg return nullptr;
43737330f729Sjoerg
43747330f729Sjoerg Inputs = CJ->getInputs();
43757330f729Sjoerg AppendCollapsedOffloadAction(CollapsedOffloadAction, ActionInfo,
43767330f729Sjoerg /*NumElements=*/2);
43777330f729Sjoerg return T;
43787330f729Sjoerg }
43797330f729Sjoerg
43807330f729Sjoerg /// Updates the inputs if the obtained tool supports combining with
43817330f729Sjoerg /// preprocessor action, and the current input is indeed a preprocessor
43827330f729Sjoerg /// action. If combining results in the collapse of offloading actions, those
43837330f729Sjoerg /// are appended to \a CollapsedOffloadAction.
combineWithPreprocessor(const Tool * T,ActionList & Inputs,ActionList & CollapsedOffloadAction)43847330f729Sjoerg void combineWithPreprocessor(const Tool *T, ActionList &Inputs,
43857330f729Sjoerg ActionList &CollapsedOffloadAction) {
43867330f729Sjoerg if (!T || !canCollapsePreprocessorAction() || !T->hasIntegratedCPP())
43877330f729Sjoerg return;
43887330f729Sjoerg
43897330f729Sjoerg // Attempt to get a preprocessor action dependence.
43907330f729Sjoerg ActionList PreprocessJobOffloadActions;
43917330f729Sjoerg ActionList NewInputs;
43927330f729Sjoerg for (Action *A : Inputs) {
43937330f729Sjoerg auto *PJ = getPrevDependentAction({A}, PreprocessJobOffloadActions);
43947330f729Sjoerg if (!PJ || !isa<PreprocessJobAction>(PJ)) {
43957330f729Sjoerg NewInputs.push_back(A);
43967330f729Sjoerg continue;
43977330f729Sjoerg }
43987330f729Sjoerg
43997330f729Sjoerg // This is legal to combine. Append any offload action we found and add the
44007330f729Sjoerg // current input to preprocessor inputs.
44017330f729Sjoerg CollapsedOffloadAction.append(PreprocessJobOffloadActions.begin(),
44027330f729Sjoerg PreprocessJobOffloadActions.end());
44037330f729Sjoerg NewInputs.append(PJ->input_begin(), PJ->input_end());
44047330f729Sjoerg }
44057330f729Sjoerg Inputs = NewInputs;
44067330f729Sjoerg }
44077330f729Sjoerg
44087330f729Sjoerg public:
ToolSelector(const JobAction * BaseAction,const ToolChain & TC,const Compilation & C,bool SaveTemps,bool EmbedBitcode)44097330f729Sjoerg ToolSelector(const JobAction *BaseAction, const ToolChain &TC,
44107330f729Sjoerg const Compilation &C, bool SaveTemps, bool EmbedBitcode)
44117330f729Sjoerg : TC(TC), C(C), BaseAction(BaseAction), SaveTemps(SaveTemps),
44127330f729Sjoerg EmbedBitcode(EmbedBitcode) {
44137330f729Sjoerg assert(BaseAction && "Invalid base action.");
44147330f729Sjoerg IsHostSelector = BaseAction->getOffloadingDeviceKind() == Action::OFK_None;
44157330f729Sjoerg }
44167330f729Sjoerg
44177330f729Sjoerg /// Check if a chain of actions can be combined and return the tool that can
44187330f729Sjoerg /// handle the combination of actions. The pointer to the current inputs \a
44197330f729Sjoerg /// Inputs and the list of offload actions \a CollapsedOffloadActions
44207330f729Sjoerg /// connected to collapsed actions are updated accordingly. The latter enables
44217330f729Sjoerg /// the caller of the selector to process them afterwards instead of just
44227330f729Sjoerg /// dropping them. If no suitable tool is found, null will be returned.
getTool(ActionList & Inputs,ActionList & CollapsedOffloadAction)44237330f729Sjoerg const Tool *getTool(ActionList &Inputs,
44247330f729Sjoerg ActionList &CollapsedOffloadAction) {
44257330f729Sjoerg //
44267330f729Sjoerg // Get the largest chain of actions that we could combine.
44277330f729Sjoerg //
44287330f729Sjoerg
44297330f729Sjoerg SmallVector<JobActionInfo, 5> ActionChain(1);
44307330f729Sjoerg ActionChain.back().JA = BaseAction;
44317330f729Sjoerg while (ActionChain.back().JA) {
44327330f729Sjoerg const Action *CurAction = ActionChain.back().JA;
44337330f729Sjoerg
44347330f729Sjoerg // Grow the chain by one element.
44357330f729Sjoerg ActionChain.resize(ActionChain.size() + 1);
44367330f729Sjoerg JobActionInfo &AI = ActionChain.back();
44377330f729Sjoerg
44387330f729Sjoerg // Attempt to fill it with the
44397330f729Sjoerg AI.JA =
44407330f729Sjoerg getPrevDependentAction(CurAction->getInputs(), AI.SavedOffloadAction);
44417330f729Sjoerg }
44427330f729Sjoerg
44437330f729Sjoerg // Pop the last action info as it could not be filled.
44447330f729Sjoerg ActionChain.pop_back();
44457330f729Sjoerg
44467330f729Sjoerg //
44477330f729Sjoerg // Attempt to combine actions. If all combining attempts failed, just return
44487330f729Sjoerg // the tool of the provided action. At the end we attempt to combine the
44497330f729Sjoerg // action with any preprocessor action it may depend on.
44507330f729Sjoerg //
44517330f729Sjoerg
44527330f729Sjoerg const Tool *T = combineAssembleBackendCompile(ActionChain, Inputs,
44537330f729Sjoerg CollapsedOffloadAction);
44547330f729Sjoerg if (!T)
44557330f729Sjoerg T = combineAssembleBackend(ActionChain, Inputs, CollapsedOffloadAction);
44567330f729Sjoerg if (!T)
44577330f729Sjoerg T = combineBackendCompile(ActionChain, Inputs, CollapsedOffloadAction);
44587330f729Sjoerg if (!T) {
44597330f729Sjoerg Inputs = BaseAction->getInputs();
44607330f729Sjoerg T = TC.SelectTool(*BaseAction);
44617330f729Sjoerg }
44627330f729Sjoerg
44637330f729Sjoerg combineWithPreprocessor(T, Inputs, CollapsedOffloadAction);
44647330f729Sjoerg return T;
44657330f729Sjoerg }
44667330f729Sjoerg };
44677330f729Sjoerg }
44687330f729Sjoerg
44697330f729Sjoerg /// Return a string that uniquely identifies the result of a job. The bound arch
44707330f729Sjoerg /// is not necessarily represented in the toolchain's triple -- for example,
44717330f729Sjoerg /// armv7 and armv7s both map to the same triple -- so we need both in our map.
44727330f729Sjoerg /// Also, we need to add the offloading device kind, as the same tool chain can
44737330f729Sjoerg /// be used for host and device for some programming models, e.g. OpenMP.
GetTriplePlusArchString(const ToolChain * TC,StringRef BoundArch,Action::OffloadKind OffloadKind)44747330f729Sjoerg static std::string GetTriplePlusArchString(const ToolChain *TC,
44757330f729Sjoerg StringRef BoundArch,
44767330f729Sjoerg Action::OffloadKind OffloadKind) {
44777330f729Sjoerg std::string TriplePlusArch = TC->getTriple().normalize();
44787330f729Sjoerg if (!BoundArch.empty()) {
44797330f729Sjoerg TriplePlusArch += "-";
44807330f729Sjoerg TriplePlusArch += BoundArch;
44817330f729Sjoerg }
44827330f729Sjoerg TriplePlusArch += "-";
44837330f729Sjoerg TriplePlusArch += Action::GetOffloadKindName(OffloadKind);
44847330f729Sjoerg return TriplePlusArch;
44857330f729Sjoerg }
44867330f729Sjoerg
BuildJobsForAction(Compilation & C,const Action * A,const ToolChain * TC,StringRef BoundArch,bool AtTopLevel,bool MultipleArchs,const char * LinkingOutput,std::map<std::pair<const Action *,std::string>,InputInfo> & CachedResults,Action::OffloadKind TargetDeviceOffloadKind) const44877330f729Sjoerg InputInfo Driver::BuildJobsForAction(
44887330f729Sjoerg Compilation &C, const Action *A, const ToolChain *TC, StringRef BoundArch,
44897330f729Sjoerg bool AtTopLevel, bool MultipleArchs, const char *LinkingOutput,
44907330f729Sjoerg std::map<std::pair<const Action *, std::string>, InputInfo> &CachedResults,
44917330f729Sjoerg Action::OffloadKind TargetDeviceOffloadKind) const {
44927330f729Sjoerg std::pair<const Action *, std::string> ActionTC = {
44937330f729Sjoerg A, GetTriplePlusArchString(TC, BoundArch, TargetDeviceOffloadKind)};
44947330f729Sjoerg auto CachedResult = CachedResults.find(ActionTC);
44957330f729Sjoerg if (CachedResult != CachedResults.end()) {
44967330f729Sjoerg return CachedResult->second;
44977330f729Sjoerg }
44987330f729Sjoerg InputInfo Result = BuildJobsForActionNoCache(
44997330f729Sjoerg C, A, TC, BoundArch, AtTopLevel, MultipleArchs, LinkingOutput,
45007330f729Sjoerg CachedResults, TargetDeviceOffloadKind);
45017330f729Sjoerg CachedResults[ActionTC] = Result;
45027330f729Sjoerg return Result;
45037330f729Sjoerg }
45047330f729Sjoerg
BuildJobsForActionNoCache(Compilation & C,const Action * A,const ToolChain * TC,StringRef BoundArch,bool AtTopLevel,bool MultipleArchs,const char * LinkingOutput,std::map<std::pair<const Action *,std::string>,InputInfo> & CachedResults,Action::OffloadKind TargetDeviceOffloadKind) const45057330f729Sjoerg InputInfo Driver::BuildJobsForActionNoCache(
45067330f729Sjoerg Compilation &C, const Action *A, const ToolChain *TC, StringRef BoundArch,
45077330f729Sjoerg bool AtTopLevel, bool MultipleArchs, const char *LinkingOutput,
45087330f729Sjoerg std::map<std::pair<const Action *, std::string>, InputInfo> &CachedResults,
45097330f729Sjoerg Action::OffloadKind TargetDeviceOffloadKind) const {
45107330f729Sjoerg llvm::PrettyStackTraceString CrashInfo("Building compilation jobs");
45117330f729Sjoerg
45127330f729Sjoerg InputInfoList OffloadDependencesInputInfo;
45137330f729Sjoerg bool BuildingForOffloadDevice = TargetDeviceOffloadKind != Action::OFK_None;
45147330f729Sjoerg if (const OffloadAction *OA = dyn_cast<OffloadAction>(A)) {
45157330f729Sjoerg // The 'Darwin' toolchain is initialized only when its arguments are
45167330f729Sjoerg // computed. Get the default arguments for OFK_None to ensure that
45177330f729Sjoerg // initialization is performed before processing the offload action.
45187330f729Sjoerg // FIXME: Remove when darwin's toolchain is initialized during construction.
45197330f729Sjoerg C.getArgsForToolChain(TC, BoundArch, Action::OFK_None);
45207330f729Sjoerg
45217330f729Sjoerg // The offload action is expected to be used in four different situations.
45227330f729Sjoerg //
45237330f729Sjoerg // a) Set a toolchain/architecture/kind for a host action:
45247330f729Sjoerg // Host Action 1 -> OffloadAction -> Host Action 2
45257330f729Sjoerg //
45267330f729Sjoerg // b) Set a toolchain/architecture/kind for a device action;
45277330f729Sjoerg // Device Action 1 -> OffloadAction -> Device Action 2
45287330f729Sjoerg //
45297330f729Sjoerg // c) Specify a device dependence to a host action;
45307330f729Sjoerg // Device Action 1 _
45317330f729Sjoerg // \
45327330f729Sjoerg // Host Action 1 ---> OffloadAction -> Host Action 2
45337330f729Sjoerg //
45347330f729Sjoerg // d) Specify a host dependence to a device action.
45357330f729Sjoerg // Host Action 1 _
45367330f729Sjoerg // \
45377330f729Sjoerg // Device Action 1 ---> OffloadAction -> Device Action 2
45387330f729Sjoerg //
45397330f729Sjoerg // For a) and b), we just return the job generated for the dependence. For
45407330f729Sjoerg // c) and d) we override the current action with the host/device dependence
45417330f729Sjoerg // if the current toolchain is host/device and set the offload dependences
45427330f729Sjoerg // info with the jobs obtained from the device/host dependence(s).
45437330f729Sjoerg
45447330f729Sjoerg // If there is a single device option, just generate the job for it.
45457330f729Sjoerg if (OA->hasSingleDeviceDependence()) {
45467330f729Sjoerg InputInfo DevA;
45477330f729Sjoerg OA->doOnEachDeviceDependence([&](Action *DepA, const ToolChain *DepTC,
45487330f729Sjoerg const char *DepBoundArch) {
45497330f729Sjoerg DevA =
45507330f729Sjoerg BuildJobsForAction(C, DepA, DepTC, DepBoundArch, AtTopLevel,
45517330f729Sjoerg /*MultipleArchs*/ !!DepBoundArch, LinkingOutput,
45527330f729Sjoerg CachedResults, DepA->getOffloadingDeviceKind());
45537330f729Sjoerg });
45547330f729Sjoerg return DevA;
45557330f729Sjoerg }
45567330f729Sjoerg
45577330f729Sjoerg // If 'Action 2' is host, we generate jobs for the device dependences and
45587330f729Sjoerg // override the current action with the host dependence. Otherwise, we
45597330f729Sjoerg // generate the host dependences and override the action with the device
45607330f729Sjoerg // dependence. The dependences can't therefore be a top-level action.
45617330f729Sjoerg OA->doOnEachDependence(
45627330f729Sjoerg /*IsHostDependence=*/BuildingForOffloadDevice,
45637330f729Sjoerg [&](Action *DepA, const ToolChain *DepTC, const char *DepBoundArch) {
45647330f729Sjoerg OffloadDependencesInputInfo.push_back(BuildJobsForAction(
45657330f729Sjoerg C, DepA, DepTC, DepBoundArch, /*AtTopLevel=*/false,
45667330f729Sjoerg /*MultipleArchs*/ !!DepBoundArch, LinkingOutput, CachedResults,
45677330f729Sjoerg DepA->getOffloadingDeviceKind()));
45687330f729Sjoerg });
45697330f729Sjoerg
45707330f729Sjoerg A = BuildingForOffloadDevice
45717330f729Sjoerg ? OA->getSingleDeviceDependence(/*DoNotConsiderHostActions=*/true)
45727330f729Sjoerg : OA->getHostDependence();
45737330f729Sjoerg }
45747330f729Sjoerg
45757330f729Sjoerg if (const InputAction *IA = dyn_cast<InputAction>(A)) {
45767330f729Sjoerg // FIXME: It would be nice to not claim this here; maybe the old scheme of
45777330f729Sjoerg // just using Args was better?
45787330f729Sjoerg const Arg &Input = IA->getInputArg();
45797330f729Sjoerg Input.claim();
45807330f729Sjoerg if (Input.getOption().matches(options::OPT_INPUT)) {
45817330f729Sjoerg const char *Name = Input.getValue();
45827330f729Sjoerg return InputInfo(A, Name, /* _BaseInput = */ Name);
45837330f729Sjoerg }
45847330f729Sjoerg return InputInfo(A, &Input, /* _BaseInput = */ "");
45857330f729Sjoerg }
45867330f729Sjoerg
45877330f729Sjoerg if (const BindArchAction *BAA = dyn_cast<BindArchAction>(A)) {
45887330f729Sjoerg const ToolChain *TC;
45897330f729Sjoerg StringRef ArchName = BAA->getArchName();
45907330f729Sjoerg
45917330f729Sjoerg if (!ArchName.empty())
45927330f729Sjoerg TC = &getToolChain(C.getArgs(),
45937330f729Sjoerg computeTargetTriple(*this, TargetTriple,
45947330f729Sjoerg C.getArgs(), ArchName));
45957330f729Sjoerg else
45967330f729Sjoerg TC = &C.getDefaultToolChain();
45977330f729Sjoerg
45987330f729Sjoerg return BuildJobsForAction(C, *BAA->input_begin(), TC, ArchName, AtTopLevel,
45997330f729Sjoerg MultipleArchs, LinkingOutput, CachedResults,
46007330f729Sjoerg TargetDeviceOffloadKind);
46017330f729Sjoerg }
46027330f729Sjoerg
46037330f729Sjoerg
46047330f729Sjoerg ActionList Inputs = A->getInputs();
46057330f729Sjoerg
46067330f729Sjoerg const JobAction *JA = cast<JobAction>(A);
46077330f729Sjoerg ActionList CollapsedOffloadActions;
46087330f729Sjoerg
46097330f729Sjoerg ToolSelector TS(JA, *TC, C, isSaveTempsEnabled(),
46107330f729Sjoerg embedBitcodeInObject() && !isUsingLTO());
46117330f729Sjoerg const Tool *T = TS.getTool(Inputs, CollapsedOffloadActions);
46127330f729Sjoerg
46137330f729Sjoerg if (!T)
46147330f729Sjoerg return InputInfo();
46157330f729Sjoerg
4616*e038c9c4Sjoerg if (BuildingForOffloadDevice &&
4617*e038c9c4Sjoerg A->getOffloadingDeviceKind() == Action::OFK_OpenMP) {
4618*e038c9c4Sjoerg if (TC->getTriple().isAMDGCN()) {
4619*e038c9c4Sjoerg // AMDGCN treats backend and assemble actions as no-op because
4620*e038c9c4Sjoerg // linker does not support object files.
4621*e038c9c4Sjoerg if (const BackendJobAction *BA = dyn_cast<BackendJobAction>(A)) {
4622*e038c9c4Sjoerg return BuildJobsForAction(C, *BA->input_begin(), TC, BoundArch,
4623*e038c9c4Sjoerg AtTopLevel, MultipleArchs, LinkingOutput,
4624*e038c9c4Sjoerg CachedResults, TargetDeviceOffloadKind);
4625*e038c9c4Sjoerg }
4626*e038c9c4Sjoerg
4627*e038c9c4Sjoerg if (const AssembleJobAction *AA = dyn_cast<AssembleJobAction>(A)) {
4628*e038c9c4Sjoerg return BuildJobsForAction(C, *AA->input_begin(), TC, BoundArch,
4629*e038c9c4Sjoerg AtTopLevel, MultipleArchs, LinkingOutput,
4630*e038c9c4Sjoerg CachedResults, TargetDeviceOffloadKind);
4631*e038c9c4Sjoerg }
4632*e038c9c4Sjoerg }
4633*e038c9c4Sjoerg }
4634*e038c9c4Sjoerg
46357330f729Sjoerg // If we've collapsed action list that contained OffloadAction we
46367330f729Sjoerg // need to build jobs for host/device-side inputs it may have held.
46377330f729Sjoerg for (const auto *OA : CollapsedOffloadActions)
46387330f729Sjoerg cast<OffloadAction>(OA)->doOnEachDependence(
46397330f729Sjoerg /*IsHostDependence=*/BuildingForOffloadDevice,
46407330f729Sjoerg [&](Action *DepA, const ToolChain *DepTC, const char *DepBoundArch) {
46417330f729Sjoerg OffloadDependencesInputInfo.push_back(BuildJobsForAction(
46427330f729Sjoerg C, DepA, DepTC, DepBoundArch, /* AtTopLevel */ false,
46437330f729Sjoerg /*MultipleArchs=*/!!DepBoundArch, LinkingOutput, CachedResults,
46447330f729Sjoerg DepA->getOffloadingDeviceKind()));
46457330f729Sjoerg });
46467330f729Sjoerg
46477330f729Sjoerg // Only use pipes when there is exactly one input.
46487330f729Sjoerg InputInfoList InputInfos;
46497330f729Sjoerg for (const Action *Input : Inputs) {
46507330f729Sjoerg // Treat dsymutil and verify sub-jobs as being at the top-level too, they
46517330f729Sjoerg // shouldn't get temporary output names.
46527330f729Sjoerg // FIXME: Clean this up.
46537330f729Sjoerg bool SubJobAtTopLevel =
46547330f729Sjoerg AtTopLevel && (isa<DsymutilJobAction>(A) || isa<VerifyJobAction>(A));
46557330f729Sjoerg InputInfos.push_back(BuildJobsForAction(
46567330f729Sjoerg C, Input, TC, BoundArch, SubJobAtTopLevel, MultipleArchs, LinkingOutput,
46577330f729Sjoerg CachedResults, A->getOffloadingDeviceKind()));
46587330f729Sjoerg }
46597330f729Sjoerg
46607330f729Sjoerg // Always use the first input as the base input.
46617330f729Sjoerg const char *BaseInput = InputInfos[0].getBaseInput();
46627330f729Sjoerg
46637330f729Sjoerg // ... except dsymutil actions, which use their actual input as the base
46647330f729Sjoerg // input.
46657330f729Sjoerg if (JA->getType() == types::TY_dSYM)
46667330f729Sjoerg BaseInput = InputInfos[0].getFilename();
46677330f729Sjoerg
46687330f729Sjoerg // ... and in header module compilations, which use the module name.
46697330f729Sjoerg if (auto *ModuleJA = dyn_cast<HeaderModulePrecompileJobAction>(JA))
46707330f729Sjoerg BaseInput = ModuleJA->getModuleName();
46717330f729Sjoerg
46727330f729Sjoerg // Append outputs of offload device jobs to the input list
46737330f729Sjoerg if (!OffloadDependencesInputInfo.empty())
46747330f729Sjoerg InputInfos.append(OffloadDependencesInputInfo.begin(),
46757330f729Sjoerg OffloadDependencesInputInfo.end());
46767330f729Sjoerg
46777330f729Sjoerg // Set the effective triple of the toolchain for the duration of this job.
46787330f729Sjoerg llvm::Triple EffectiveTriple;
46797330f729Sjoerg const ToolChain &ToolTC = T->getToolChain();
46807330f729Sjoerg const ArgList &Args =
46817330f729Sjoerg C.getArgsForToolChain(TC, BoundArch, A->getOffloadingDeviceKind());
46827330f729Sjoerg if (InputInfos.size() != 1) {
46837330f729Sjoerg EffectiveTriple = llvm::Triple(ToolTC.ComputeEffectiveClangTriple(Args));
46847330f729Sjoerg } else {
46857330f729Sjoerg // Pass along the input type if it can be unambiguously determined.
46867330f729Sjoerg EffectiveTriple = llvm::Triple(
46877330f729Sjoerg ToolTC.ComputeEffectiveClangTriple(Args, InputInfos[0].getType()));
46887330f729Sjoerg }
46897330f729Sjoerg RegisterEffectiveTriple TripleRAII(ToolTC, EffectiveTriple);
46907330f729Sjoerg
46917330f729Sjoerg // Determine the place to write output to, if any.
46927330f729Sjoerg InputInfo Result;
46937330f729Sjoerg InputInfoList UnbundlingResults;
46947330f729Sjoerg if (auto *UA = dyn_cast<OffloadUnbundlingJobAction>(JA)) {
46957330f729Sjoerg // If we have an unbundling job, we need to create results for all the
46967330f729Sjoerg // outputs. We also update the results cache so that other actions using
46977330f729Sjoerg // this unbundling action can get the right results.
46987330f729Sjoerg for (auto &UI : UA->getDependentActionsInfo()) {
46997330f729Sjoerg assert(UI.DependentOffloadKind != Action::OFK_None &&
47007330f729Sjoerg "Unbundling with no offloading??");
47017330f729Sjoerg
47027330f729Sjoerg // Unbundling actions are never at the top level. When we generate the
47037330f729Sjoerg // offloading prefix, we also do that for the host file because the
47047330f729Sjoerg // unbundling action does not change the type of the output which can
47057330f729Sjoerg // cause a overwrite.
47067330f729Sjoerg std::string OffloadingPrefix = Action::GetOffloadingFileNamePrefix(
47077330f729Sjoerg UI.DependentOffloadKind,
47087330f729Sjoerg UI.DependentToolChain->getTriple().normalize(),
47097330f729Sjoerg /*CreatePrefixForHost=*/true);
47107330f729Sjoerg auto CurI = InputInfo(
47117330f729Sjoerg UA,
47127330f729Sjoerg GetNamedOutputPath(C, *UA, BaseInput, UI.DependentBoundArch,
47137330f729Sjoerg /*AtTopLevel=*/false,
47147330f729Sjoerg MultipleArchs ||
47157330f729Sjoerg UI.DependentOffloadKind == Action::OFK_HIP,
47167330f729Sjoerg OffloadingPrefix),
47177330f729Sjoerg BaseInput);
47187330f729Sjoerg // Save the unbundling result.
47197330f729Sjoerg UnbundlingResults.push_back(CurI);
47207330f729Sjoerg
47217330f729Sjoerg // Get the unique string identifier for this dependence and cache the
47227330f729Sjoerg // result.
47237330f729Sjoerg StringRef Arch;
47247330f729Sjoerg if (TargetDeviceOffloadKind == Action::OFK_HIP) {
47257330f729Sjoerg if (UI.DependentOffloadKind == Action::OFK_Host)
47267330f729Sjoerg Arch = StringRef();
47277330f729Sjoerg else
47287330f729Sjoerg Arch = UI.DependentBoundArch;
47297330f729Sjoerg } else
47307330f729Sjoerg Arch = BoundArch;
47317330f729Sjoerg
47327330f729Sjoerg CachedResults[{A, GetTriplePlusArchString(UI.DependentToolChain, Arch,
47337330f729Sjoerg UI.DependentOffloadKind)}] =
47347330f729Sjoerg CurI;
47357330f729Sjoerg }
47367330f729Sjoerg
47377330f729Sjoerg // Now that we have all the results generated, select the one that should be
47387330f729Sjoerg // returned for the current depending action.
47397330f729Sjoerg std::pair<const Action *, std::string> ActionTC = {
47407330f729Sjoerg A, GetTriplePlusArchString(TC, BoundArch, TargetDeviceOffloadKind)};
47417330f729Sjoerg assert(CachedResults.find(ActionTC) != CachedResults.end() &&
47427330f729Sjoerg "Result does not exist??");
47437330f729Sjoerg Result = CachedResults[ActionTC];
47447330f729Sjoerg } else if (JA->getType() == types::TY_Nothing)
47457330f729Sjoerg Result = InputInfo(A, BaseInput);
47467330f729Sjoerg else {
47477330f729Sjoerg // We only have to generate a prefix for the host if this is not a top-level
47487330f729Sjoerg // action.
47497330f729Sjoerg std::string OffloadingPrefix = Action::GetOffloadingFileNamePrefix(
47507330f729Sjoerg A->getOffloadingDeviceKind(), TC->getTriple().normalize(),
47517330f729Sjoerg /*CreatePrefixForHost=*/!!A->getOffloadingHostActiveKinds() &&
47527330f729Sjoerg !AtTopLevel);
47537330f729Sjoerg if (isa<OffloadWrapperJobAction>(JA)) {
47547330f729Sjoerg if (Arg *FinalOutput = C.getArgs().getLastArg(options::OPT_o))
47557330f729Sjoerg BaseInput = FinalOutput->getValue();
47567330f729Sjoerg else
47577330f729Sjoerg BaseInput = getDefaultImageName();
4758*e038c9c4Sjoerg BaseInput =
4759*e038c9c4Sjoerg C.getArgs().MakeArgString(std::string(BaseInput) + "-wrapper");
47607330f729Sjoerg }
47617330f729Sjoerg Result = InputInfo(A, GetNamedOutputPath(C, *JA, BaseInput, BoundArch,
47627330f729Sjoerg AtTopLevel, MultipleArchs,
47637330f729Sjoerg OffloadingPrefix),
47647330f729Sjoerg BaseInput);
47657330f729Sjoerg }
47667330f729Sjoerg
47677330f729Sjoerg if (CCCPrintBindings && !CCGenDiagnostics) {
47687330f729Sjoerg llvm::errs() << "# \"" << T->getToolChain().getTripleString() << '"'
47697330f729Sjoerg << " - \"" << T->getName() << "\", inputs: [";
47707330f729Sjoerg for (unsigned i = 0, e = InputInfos.size(); i != e; ++i) {
47717330f729Sjoerg llvm::errs() << InputInfos[i].getAsString();
47727330f729Sjoerg if (i + 1 != e)
47737330f729Sjoerg llvm::errs() << ", ";
47747330f729Sjoerg }
47757330f729Sjoerg if (UnbundlingResults.empty())
47767330f729Sjoerg llvm::errs() << "], output: " << Result.getAsString() << "\n";
47777330f729Sjoerg else {
47787330f729Sjoerg llvm::errs() << "], outputs: [";
47797330f729Sjoerg for (unsigned i = 0, e = UnbundlingResults.size(); i != e; ++i) {
47807330f729Sjoerg llvm::errs() << UnbundlingResults[i].getAsString();
47817330f729Sjoerg if (i + 1 != e)
47827330f729Sjoerg llvm::errs() << ", ";
47837330f729Sjoerg }
47847330f729Sjoerg llvm::errs() << "] \n";
47857330f729Sjoerg }
47867330f729Sjoerg } else {
47877330f729Sjoerg if (UnbundlingResults.empty())
47887330f729Sjoerg T->ConstructJob(
47897330f729Sjoerg C, *JA, Result, InputInfos,
47907330f729Sjoerg C.getArgsForToolChain(TC, BoundArch, JA->getOffloadingDeviceKind()),
47917330f729Sjoerg LinkingOutput);
47927330f729Sjoerg else
47937330f729Sjoerg T->ConstructJobMultipleOutputs(
47947330f729Sjoerg C, *JA, UnbundlingResults, InputInfos,
47957330f729Sjoerg C.getArgsForToolChain(TC, BoundArch, JA->getOffloadingDeviceKind()),
47967330f729Sjoerg LinkingOutput);
47977330f729Sjoerg }
47987330f729Sjoerg return Result;
47997330f729Sjoerg }
48007330f729Sjoerg
getDefaultImageName() const48017330f729Sjoerg const char *Driver::getDefaultImageName() const {
48027330f729Sjoerg llvm::Triple Target(llvm::Triple::normalize(TargetTriple));
48037330f729Sjoerg return Target.isOSWindows() ? "a.exe" : "a.out";
48047330f729Sjoerg }
48057330f729Sjoerg
48067330f729Sjoerg /// Create output filename based on ArgValue, which could either be a
48077330f729Sjoerg /// full filename, filename without extension, or a directory. If ArgValue
48087330f729Sjoerg /// does not provide a filename, then use BaseName, and use the extension
48097330f729Sjoerg /// suitable for FileType.
MakeCLOutputFilename(const ArgList & Args,StringRef ArgValue,StringRef BaseName,types::ID FileType)48107330f729Sjoerg static const char *MakeCLOutputFilename(const ArgList &Args, StringRef ArgValue,
48117330f729Sjoerg StringRef BaseName,
48127330f729Sjoerg types::ID FileType) {
48137330f729Sjoerg SmallString<128> Filename = ArgValue;
48147330f729Sjoerg
48157330f729Sjoerg if (ArgValue.empty()) {
48167330f729Sjoerg // If the argument is empty, output to BaseName in the current dir.
48177330f729Sjoerg Filename = BaseName;
48187330f729Sjoerg } else if (llvm::sys::path::is_separator(Filename.back())) {
48197330f729Sjoerg // If the argument is a directory, output to BaseName in that dir.
48207330f729Sjoerg llvm::sys::path::append(Filename, BaseName);
48217330f729Sjoerg }
48227330f729Sjoerg
48237330f729Sjoerg if (!llvm::sys::path::has_extension(ArgValue)) {
48247330f729Sjoerg // If the argument didn't provide an extension, then set it.
48257330f729Sjoerg const char *Extension = types::getTypeTempSuffix(FileType, true);
48267330f729Sjoerg
48277330f729Sjoerg if (FileType == types::TY_Image &&
48287330f729Sjoerg Args.hasArg(options::OPT__SLASH_LD, options::OPT__SLASH_LDd)) {
48297330f729Sjoerg // The output file is a dll.
48307330f729Sjoerg Extension = "dll";
48317330f729Sjoerg }
48327330f729Sjoerg
48337330f729Sjoerg llvm::sys::path::replace_extension(Filename, Extension);
48347330f729Sjoerg }
48357330f729Sjoerg
48367330f729Sjoerg return Args.MakeArgString(Filename.c_str());
48377330f729Sjoerg }
48387330f729Sjoerg
HasPreprocessOutput(const Action & JA)4839*e038c9c4Sjoerg static bool HasPreprocessOutput(const Action &JA) {
4840*e038c9c4Sjoerg if (isa<PreprocessJobAction>(JA))
4841*e038c9c4Sjoerg return true;
4842*e038c9c4Sjoerg if (isa<OffloadAction>(JA) && isa<PreprocessJobAction>(JA.getInputs()[0]))
4843*e038c9c4Sjoerg return true;
4844*e038c9c4Sjoerg if (isa<OffloadBundlingJobAction>(JA) &&
4845*e038c9c4Sjoerg HasPreprocessOutput(*(JA.getInputs()[0])))
4846*e038c9c4Sjoerg return true;
4847*e038c9c4Sjoerg return false;
4848*e038c9c4Sjoerg }
4849*e038c9c4Sjoerg
GetNamedOutputPath(Compilation & C,const JobAction & JA,const char * BaseInput,StringRef OrigBoundArch,bool AtTopLevel,bool MultipleArchs,StringRef OffloadingPrefix) const48507330f729Sjoerg const char *Driver::GetNamedOutputPath(Compilation &C, const JobAction &JA,
48517330f729Sjoerg const char *BaseInput,
4852*e038c9c4Sjoerg StringRef OrigBoundArch, bool AtTopLevel,
48537330f729Sjoerg bool MultipleArchs,
48547330f729Sjoerg StringRef OffloadingPrefix) const {
4855*e038c9c4Sjoerg std::string BoundArch = OrigBoundArch.str();
4856*e038c9c4Sjoerg #if defined(_WIN32)
4857*e038c9c4Sjoerg // BoundArch may contains ':', which is invalid in file names on Windows,
4858*e038c9c4Sjoerg // therefore replace it with '%'.
4859*e038c9c4Sjoerg std::replace(BoundArch.begin(), BoundArch.end(), ':', '@');
4860*e038c9c4Sjoerg #endif
4861*e038c9c4Sjoerg
48627330f729Sjoerg llvm::PrettyStackTraceString CrashInfo("Computing output path");
48637330f729Sjoerg // Output to a user requested destination?
48647330f729Sjoerg if (AtTopLevel && !isa<DsymutilJobAction>(JA) && !isa<VerifyJobAction>(JA)) {
48657330f729Sjoerg if (Arg *FinalOutput = C.getArgs().getLastArg(options::OPT_o))
48667330f729Sjoerg return C.addResultFile(FinalOutput->getValue(), &JA);
48677330f729Sjoerg }
48687330f729Sjoerg
48697330f729Sjoerg // For /P, preprocess to file named after BaseInput.
48707330f729Sjoerg if (C.getArgs().hasArg(options::OPT__SLASH_P)) {
48717330f729Sjoerg assert(AtTopLevel && isa<PreprocessJobAction>(JA));
48727330f729Sjoerg StringRef BaseName = llvm::sys::path::filename(BaseInput);
48737330f729Sjoerg StringRef NameArg;
48747330f729Sjoerg if (Arg *A = C.getArgs().getLastArg(options::OPT__SLASH_Fi))
48757330f729Sjoerg NameArg = A->getValue();
48767330f729Sjoerg return C.addResultFile(
48777330f729Sjoerg MakeCLOutputFilename(C.getArgs(), NameArg, BaseName, types::TY_PP_C),
48787330f729Sjoerg &JA);
48797330f729Sjoerg }
48807330f729Sjoerg
48817330f729Sjoerg // Default to writing to stdout?
4882*e038c9c4Sjoerg if (AtTopLevel && !CCGenDiagnostics && HasPreprocessOutput(JA)) {
48837330f729Sjoerg return "-";
4884*e038c9c4Sjoerg }
48857330f729Sjoerg
48867330f729Sjoerg // Is this the assembly listing for /FA?
48877330f729Sjoerg if (JA.getType() == types::TY_PP_Asm &&
48887330f729Sjoerg (C.getArgs().hasArg(options::OPT__SLASH_FA) ||
48897330f729Sjoerg C.getArgs().hasArg(options::OPT__SLASH_Fa))) {
48907330f729Sjoerg // Use /Fa and the input filename to determine the asm file name.
48917330f729Sjoerg StringRef BaseName = llvm::sys::path::filename(BaseInput);
48927330f729Sjoerg StringRef FaValue = C.getArgs().getLastArgValue(options::OPT__SLASH_Fa);
48937330f729Sjoerg return C.addResultFile(
48947330f729Sjoerg MakeCLOutputFilename(C.getArgs(), FaValue, BaseName, JA.getType()),
48957330f729Sjoerg &JA);
48967330f729Sjoerg }
48977330f729Sjoerg
48987330f729Sjoerg // Output to a temporary file?
48997330f729Sjoerg if ((!AtTopLevel && !isSaveTempsEnabled() &&
49007330f729Sjoerg !C.getArgs().hasArg(options::OPT__SLASH_Fo)) ||
49017330f729Sjoerg CCGenDiagnostics) {
49027330f729Sjoerg StringRef Name = llvm::sys::path::filename(BaseInput);
49037330f729Sjoerg std::pair<StringRef, StringRef> Split = Name.split('.');
49047330f729Sjoerg SmallString<128> TmpName;
49057330f729Sjoerg const char *Suffix = types::getTypeTempSuffix(JA.getType(), IsCLMode());
49067330f729Sjoerg Arg *A = C.getArgs().getLastArg(options::OPT_fcrash_diagnostics_dir);
49077330f729Sjoerg if (CCGenDiagnostics && A) {
49087330f729Sjoerg SmallString<128> CrashDirectory(A->getValue());
49097330f729Sjoerg if (!getVFS().exists(CrashDirectory))
49107330f729Sjoerg llvm::sys::fs::create_directories(CrashDirectory);
49117330f729Sjoerg llvm::sys::path::append(CrashDirectory, Split.first);
49127330f729Sjoerg const char *Middle = Suffix ? "-%%%%%%." : "-%%%%%%";
49137330f729Sjoerg std::error_code EC = llvm::sys::fs::createUniqueFile(
49147330f729Sjoerg CrashDirectory + Middle + Suffix, TmpName);
49157330f729Sjoerg if (EC) {
49167330f729Sjoerg Diag(clang::diag::err_unable_to_make_temp) << EC.message();
49177330f729Sjoerg return "";
49187330f729Sjoerg }
49197330f729Sjoerg } else {
49207330f729Sjoerg TmpName = GetTemporaryPath(Split.first, Suffix);
49217330f729Sjoerg }
49227330f729Sjoerg return C.addTempFile(C.getArgs().MakeArgString(TmpName));
49237330f729Sjoerg }
49247330f729Sjoerg
49257330f729Sjoerg SmallString<128> BasePath(BaseInput);
4926*e038c9c4Sjoerg SmallString<128> ExternalPath("");
49277330f729Sjoerg StringRef BaseName;
49287330f729Sjoerg
49297330f729Sjoerg // Dsymutil actions should use the full path.
4930*e038c9c4Sjoerg if (isa<DsymutilJobAction>(JA) && C.getArgs().hasArg(options::OPT_dsym_dir)) {
4931*e038c9c4Sjoerg ExternalPath += C.getArgs().getLastArg(options::OPT_dsym_dir)->getValue();
4932*e038c9c4Sjoerg // We use posix style here because the tests (specifically
4933*e038c9c4Sjoerg // darwin-dsymutil.c) demonstrate that posix style paths are acceptable
4934*e038c9c4Sjoerg // even on Windows and if we don't then the similar test covering this
4935*e038c9c4Sjoerg // fails.
4936*e038c9c4Sjoerg llvm::sys::path::append(ExternalPath, llvm::sys::path::Style::posix,
4937*e038c9c4Sjoerg llvm::sys::path::filename(BasePath));
4938*e038c9c4Sjoerg BaseName = ExternalPath;
4939*e038c9c4Sjoerg } else if (isa<DsymutilJobAction>(JA) || isa<VerifyJobAction>(JA))
49407330f729Sjoerg BaseName = BasePath;
49417330f729Sjoerg else
49427330f729Sjoerg BaseName = llvm::sys::path::filename(BasePath);
49437330f729Sjoerg
49447330f729Sjoerg // Determine what the derived output name should be.
49457330f729Sjoerg const char *NamedOutput;
49467330f729Sjoerg
49477330f729Sjoerg if ((JA.getType() == types::TY_Object || JA.getType() == types::TY_LTO_BC) &&
49487330f729Sjoerg C.getArgs().hasArg(options::OPT__SLASH_Fo, options::OPT__SLASH_o)) {
49497330f729Sjoerg // The /Fo or /o flag decides the object filename.
49507330f729Sjoerg StringRef Val =
49517330f729Sjoerg C.getArgs()
49527330f729Sjoerg .getLastArg(options::OPT__SLASH_Fo, options::OPT__SLASH_o)
49537330f729Sjoerg ->getValue();
49547330f729Sjoerg NamedOutput =
49557330f729Sjoerg MakeCLOutputFilename(C.getArgs(), Val, BaseName, types::TY_Object);
49567330f729Sjoerg } else if (JA.getType() == types::TY_Image &&
49577330f729Sjoerg C.getArgs().hasArg(options::OPT__SLASH_Fe,
49587330f729Sjoerg options::OPT__SLASH_o)) {
49597330f729Sjoerg // The /Fe or /o flag names the linked file.
49607330f729Sjoerg StringRef Val =
49617330f729Sjoerg C.getArgs()
49627330f729Sjoerg .getLastArg(options::OPT__SLASH_Fe, options::OPT__SLASH_o)
49637330f729Sjoerg ->getValue();
49647330f729Sjoerg NamedOutput =
49657330f729Sjoerg MakeCLOutputFilename(C.getArgs(), Val, BaseName, types::TY_Image);
49667330f729Sjoerg } else if (JA.getType() == types::TY_Image) {
49677330f729Sjoerg if (IsCLMode()) {
49687330f729Sjoerg // clang-cl uses BaseName for the executable name.
49697330f729Sjoerg NamedOutput =
49707330f729Sjoerg MakeCLOutputFilename(C.getArgs(), "", BaseName, types::TY_Image);
49717330f729Sjoerg } else {
49727330f729Sjoerg SmallString<128> Output(getDefaultImageName());
49737330f729Sjoerg // HIP image for device compilation with -fno-gpu-rdc is per compilation
49747330f729Sjoerg // unit.
49757330f729Sjoerg bool IsHIPNoRDC = JA.getOffloadingDeviceKind() == Action::OFK_HIP &&
49767330f729Sjoerg !C.getArgs().hasFlag(options::OPT_fgpu_rdc,
49777330f729Sjoerg options::OPT_fno_gpu_rdc, false);
49787330f729Sjoerg if (IsHIPNoRDC) {
49797330f729Sjoerg Output = BaseName;
49807330f729Sjoerg llvm::sys::path::replace_extension(Output, "");
49817330f729Sjoerg }
49827330f729Sjoerg Output += OffloadingPrefix;
49837330f729Sjoerg if (MultipleArchs && !BoundArch.empty()) {
49847330f729Sjoerg Output += "-";
49857330f729Sjoerg Output.append(BoundArch);
49867330f729Sjoerg }
49877330f729Sjoerg if (IsHIPNoRDC)
49887330f729Sjoerg Output += ".out";
49897330f729Sjoerg NamedOutput = C.getArgs().MakeArgString(Output.c_str());
49907330f729Sjoerg }
49917330f729Sjoerg } else if (JA.getType() == types::TY_PCH && IsCLMode()) {
49927330f729Sjoerg NamedOutput = C.getArgs().MakeArgString(GetClPchPath(C, BaseName));
49937330f729Sjoerg } else {
49947330f729Sjoerg const char *Suffix = types::getTypeTempSuffix(JA.getType(), IsCLMode());
49957330f729Sjoerg assert(Suffix && "All types used for output should have a suffix.");
49967330f729Sjoerg
49977330f729Sjoerg std::string::size_type End = std::string::npos;
49987330f729Sjoerg if (!types::appendSuffixForType(JA.getType()))
49997330f729Sjoerg End = BaseName.rfind('.');
50007330f729Sjoerg SmallString<128> Suffixed(BaseName.substr(0, End));
50017330f729Sjoerg Suffixed += OffloadingPrefix;
50027330f729Sjoerg if (MultipleArchs && !BoundArch.empty()) {
50037330f729Sjoerg Suffixed += "-";
50047330f729Sjoerg Suffixed.append(BoundArch);
50057330f729Sjoerg }
50067330f729Sjoerg // When using both -save-temps and -emit-llvm, use a ".tmp.bc" suffix for
50077330f729Sjoerg // the unoptimized bitcode so that it does not get overwritten by the ".bc"
50087330f729Sjoerg // optimized bitcode output.
5009*e038c9c4Sjoerg auto IsHIPRDCInCompilePhase = [](const JobAction &JA,
5010*e038c9c4Sjoerg const llvm::opt::DerivedArgList &Args) {
5011*e038c9c4Sjoerg // The relocatable compilation in HIP implies -emit-llvm. Similarly, use a
5012*e038c9c4Sjoerg // ".tmp.bc" suffix for the unoptimized bitcode (generated in the compile
5013*e038c9c4Sjoerg // phase.)
5014*e038c9c4Sjoerg return isa<CompileJobAction>(JA) &&
5015*e038c9c4Sjoerg JA.getOffloadingDeviceKind() == Action::OFK_HIP &&
5016*e038c9c4Sjoerg Args.hasFlag(options::OPT_fgpu_rdc, options::OPT_fno_gpu_rdc,
5017*e038c9c4Sjoerg false);
5018*e038c9c4Sjoerg };
5019*e038c9c4Sjoerg if (!AtTopLevel && JA.getType() == types::TY_LLVM_BC &&
5020*e038c9c4Sjoerg (C.getArgs().hasArg(options::OPT_emit_llvm) ||
5021*e038c9c4Sjoerg IsHIPRDCInCompilePhase(JA, C.getArgs())))
50227330f729Sjoerg Suffixed += ".tmp";
50237330f729Sjoerg Suffixed += '.';
50247330f729Sjoerg Suffixed += Suffix;
50257330f729Sjoerg NamedOutput = C.getArgs().MakeArgString(Suffixed.c_str());
50267330f729Sjoerg }
50277330f729Sjoerg
50287330f729Sjoerg // Prepend object file path if -save-temps=obj
50297330f729Sjoerg if (!AtTopLevel && isSaveTempsObj() && C.getArgs().hasArg(options::OPT_o) &&
50307330f729Sjoerg JA.getType() != types::TY_PCH) {
50317330f729Sjoerg Arg *FinalOutput = C.getArgs().getLastArg(options::OPT_o);
50327330f729Sjoerg SmallString<128> TempPath(FinalOutput->getValue());
50337330f729Sjoerg llvm::sys::path::remove_filename(TempPath);
50347330f729Sjoerg StringRef OutputFileName = llvm::sys::path::filename(NamedOutput);
50357330f729Sjoerg llvm::sys::path::append(TempPath, OutputFileName);
50367330f729Sjoerg NamedOutput = C.getArgs().MakeArgString(TempPath.c_str());
50377330f729Sjoerg }
50387330f729Sjoerg
50397330f729Sjoerg // If we're saving temps and the temp file conflicts with the input file,
50407330f729Sjoerg // then avoid overwriting input file.
50417330f729Sjoerg if (!AtTopLevel && isSaveTempsEnabled() && NamedOutput == BaseName) {
50427330f729Sjoerg bool SameFile = false;
50437330f729Sjoerg SmallString<256> Result;
50447330f729Sjoerg llvm::sys::fs::current_path(Result);
50457330f729Sjoerg llvm::sys::path::append(Result, BaseName);
50467330f729Sjoerg llvm::sys::fs::equivalent(BaseInput, Result.c_str(), SameFile);
50477330f729Sjoerg // Must share the same path to conflict.
50487330f729Sjoerg if (SameFile) {
50497330f729Sjoerg StringRef Name = llvm::sys::path::filename(BaseInput);
50507330f729Sjoerg std::pair<StringRef, StringRef> Split = Name.split('.');
50517330f729Sjoerg std::string TmpName = GetTemporaryPath(
50527330f729Sjoerg Split.first, types::getTypeTempSuffix(JA.getType(), IsCLMode()));
50537330f729Sjoerg return C.addTempFile(C.getArgs().MakeArgString(TmpName));
50547330f729Sjoerg }
50557330f729Sjoerg }
50567330f729Sjoerg
50577330f729Sjoerg // As an annoying special case, PCH generation doesn't strip the pathname.
50587330f729Sjoerg if (JA.getType() == types::TY_PCH && !IsCLMode()) {
50597330f729Sjoerg llvm::sys::path::remove_filename(BasePath);
50607330f729Sjoerg if (BasePath.empty())
50617330f729Sjoerg BasePath = NamedOutput;
50627330f729Sjoerg else
50637330f729Sjoerg llvm::sys::path::append(BasePath, NamedOutput);
50647330f729Sjoerg return C.addResultFile(C.getArgs().MakeArgString(BasePath.c_str()), &JA);
50657330f729Sjoerg } else {
50667330f729Sjoerg return C.addResultFile(NamedOutput, &JA);
50677330f729Sjoerg }
50687330f729Sjoerg }
50697330f729Sjoerg
GetFilePath(StringRef Name,const ToolChain & TC) const50707330f729Sjoerg std::string Driver::GetFilePath(StringRef Name, const ToolChain &TC) const {
50717330f729Sjoerg // Search for Name in a list of paths.
50727330f729Sjoerg auto SearchPaths = [&](const llvm::SmallVectorImpl<std::string> &P)
50737330f729Sjoerg -> llvm::Optional<std::string> {
50747330f729Sjoerg // Respect a limited subset of the '-Bprefix' functionality in GCC by
50757330f729Sjoerg // attempting to use this prefix when looking for file paths.
50767330f729Sjoerg for (const auto &Dir : P) {
50777330f729Sjoerg if (Dir.empty())
50787330f729Sjoerg continue;
50797330f729Sjoerg SmallString<128> P(Dir[0] == '=' ? SysRoot + Dir.substr(1) : Dir);
50807330f729Sjoerg llvm::sys::path::append(P, Name);
50817330f729Sjoerg if (llvm::sys::fs::exists(Twine(P)))
5082*e038c9c4Sjoerg return std::string(P);
50837330f729Sjoerg }
50847330f729Sjoerg return None;
50857330f729Sjoerg };
50867330f729Sjoerg
50877330f729Sjoerg if (auto P = SearchPaths(PrefixDirs))
50887330f729Sjoerg return *P;
50897330f729Sjoerg
50907330f729Sjoerg SmallString<128> R(ResourceDir);
50917330f729Sjoerg llvm::sys::path::append(R, Name);
50927330f729Sjoerg if (llvm::sys::fs::exists(Twine(R)))
5093*e038c9c4Sjoerg return std::string(R.str());
50947330f729Sjoerg
50957330f729Sjoerg SmallString<128> P(TC.getCompilerRTPath());
50967330f729Sjoerg llvm::sys::path::append(P, Name);
50977330f729Sjoerg if (llvm::sys::fs::exists(Twine(P)))
5098*e038c9c4Sjoerg return std::string(P.str());
50997330f729Sjoerg
51007330f729Sjoerg SmallString<128> D(Dir);
51017330f729Sjoerg llvm::sys::path::append(D, "..", Name);
51027330f729Sjoerg if (llvm::sys::fs::exists(Twine(D)))
5103*e038c9c4Sjoerg return std::string(D.str());
51047330f729Sjoerg
51057330f729Sjoerg if (auto P = SearchPaths(TC.getLibraryPaths()))
51067330f729Sjoerg return *P;
51077330f729Sjoerg
51087330f729Sjoerg if (auto P = SearchPaths(TC.getFilePaths()))
51097330f729Sjoerg return *P;
51107330f729Sjoerg
5111*e038c9c4Sjoerg return std::string(Name);
51127330f729Sjoerg }
51137330f729Sjoerg
generatePrefixedToolNames(StringRef Tool,const ToolChain & TC,SmallVectorImpl<std::string> & Names) const51147330f729Sjoerg void Driver::generatePrefixedToolNames(
51157330f729Sjoerg StringRef Tool, const ToolChain &TC,
51167330f729Sjoerg SmallVectorImpl<std::string> &Names) const {
51177330f729Sjoerg // FIXME: Needs a better variable than TargetTriple
51187330f729Sjoerg Names.emplace_back((TargetTriple + "-" + Tool).str());
51197330f729Sjoerg Names.emplace_back(Tool);
51207330f729Sjoerg }
51217330f729Sjoerg
ScanDirForExecutable(SmallString<128> & Dir,StringRef Name)5122*e038c9c4Sjoerg static bool ScanDirForExecutable(SmallString<128> &Dir, StringRef Name) {
51237330f729Sjoerg llvm::sys::path::append(Dir, Name);
51247330f729Sjoerg if (llvm::sys::fs::can_execute(Twine(Dir)))
51257330f729Sjoerg return true;
51267330f729Sjoerg llvm::sys::path::remove_filename(Dir);
51277330f729Sjoerg return false;
51287330f729Sjoerg }
51297330f729Sjoerg
GetProgramPath(StringRef Name,const ToolChain & TC) const51307330f729Sjoerg std::string Driver::GetProgramPath(StringRef Name, const ToolChain &TC) const {
51317330f729Sjoerg SmallVector<std::string, 2> TargetSpecificExecutables;
51327330f729Sjoerg generatePrefixedToolNames(Name, TC, TargetSpecificExecutables);
51337330f729Sjoerg
51347330f729Sjoerg // Respect a limited subset of the '-Bprefix' functionality in GCC by
51357330f729Sjoerg // attempting to use this prefix when looking for program paths.
51367330f729Sjoerg for (const auto &PrefixDir : PrefixDirs) {
51377330f729Sjoerg if (llvm::sys::fs::is_directory(PrefixDir)) {
51387330f729Sjoerg SmallString<128> P(PrefixDir);
5139*e038c9c4Sjoerg if (ScanDirForExecutable(P, Name))
5140*e038c9c4Sjoerg return std::string(P.str());
51417330f729Sjoerg } else {
51427330f729Sjoerg SmallString<128> P((PrefixDir + Name).str());
51437330f729Sjoerg if (llvm::sys::fs::can_execute(Twine(P)))
5144*e038c9c4Sjoerg return std::string(P.str());
51457330f729Sjoerg }
51467330f729Sjoerg }
51477330f729Sjoerg
51487330f729Sjoerg const ToolChain::path_list &List = TC.getProgramPaths();
5149*e038c9c4Sjoerg for (const auto &TargetSpecificExecutable : TargetSpecificExecutables) {
5150*e038c9c4Sjoerg // For each possible name of the tool look for it in
5151*e038c9c4Sjoerg // program paths first, then the path.
5152*e038c9c4Sjoerg // Higher priority names will be first, meaning that
5153*e038c9c4Sjoerg // a higher priority name in the path will be found
5154*e038c9c4Sjoerg // instead of a lower priority name in the program path.
5155*e038c9c4Sjoerg // E.g. <triple>-gcc on the path will be found instead
5156*e038c9c4Sjoerg // of gcc in the program path
51577330f729Sjoerg for (const auto &Path : List) {
51587330f729Sjoerg SmallString<128> P(Path);
5159*e038c9c4Sjoerg if (ScanDirForExecutable(P, TargetSpecificExecutable))
5160*e038c9c4Sjoerg return std::string(P.str());
51617330f729Sjoerg }
51627330f729Sjoerg
5163*e038c9c4Sjoerg // Fall back to the path
51647330f729Sjoerg if (llvm::ErrorOr<std::string> P =
51657330f729Sjoerg llvm::sys::findProgramByName(TargetSpecificExecutable))
51667330f729Sjoerg return *P;
5167*e038c9c4Sjoerg }
51687330f729Sjoerg
5169*e038c9c4Sjoerg return std::string(Name);
51707330f729Sjoerg }
51717330f729Sjoerg
GetTemporaryPath(StringRef Prefix,StringRef Suffix) const51727330f729Sjoerg std::string Driver::GetTemporaryPath(StringRef Prefix, StringRef Suffix) const {
51737330f729Sjoerg SmallString<128> Path;
51747330f729Sjoerg std::error_code EC = llvm::sys::fs::createTemporaryFile(Prefix, Suffix, Path);
51757330f729Sjoerg if (EC) {
51767330f729Sjoerg Diag(clang::diag::err_unable_to_make_temp) << EC.message();
51777330f729Sjoerg return "";
51787330f729Sjoerg }
51797330f729Sjoerg
5180*e038c9c4Sjoerg return std::string(Path.str());
51817330f729Sjoerg }
51827330f729Sjoerg
GetTemporaryDirectory(StringRef Prefix) const51837330f729Sjoerg std::string Driver::GetTemporaryDirectory(StringRef Prefix) const {
51847330f729Sjoerg SmallString<128> Path;
51857330f729Sjoerg std::error_code EC = llvm::sys::fs::createUniqueDirectory(Prefix, Path);
51867330f729Sjoerg if (EC) {
51877330f729Sjoerg Diag(clang::diag::err_unable_to_make_temp) << EC.message();
51887330f729Sjoerg return "";
51897330f729Sjoerg }
51907330f729Sjoerg
5191*e038c9c4Sjoerg return std::string(Path.str());
51927330f729Sjoerg }
51937330f729Sjoerg
GetClPchPath(Compilation & C,StringRef BaseName) const51947330f729Sjoerg std::string Driver::GetClPchPath(Compilation &C, StringRef BaseName) const {
51957330f729Sjoerg SmallString<128> Output;
51967330f729Sjoerg if (Arg *FpArg = C.getArgs().getLastArg(options::OPT__SLASH_Fp)) {
51977330f729Sjoerg // FIXME: If anybody needs it, implement this obscure rule:
51987330f729Sjoerg // "If you specify a directory without a file name, the default file name
51997330f729Sjoerg // is VCx0.pch., where x is the major version of Visual C++ in use."
52007330f729Sjoerg Output = FpArg->getValue();
52017330f729Sjoerg
52027330f729Sjoerg // "If you do not specify an extension as part of the path name, an
52037330f729Sjoerg // extension of .pch is assumed. "
52047330f729Sjoerg if (!llvm::sys::path::has_extension(Output))
52057330f729Sjoerg Output += ".pch";
52067330f729Sjoerg } else {
52077330f729Sjoerg if (Arg *YcArg = C.getArgs().getLastArg(options::OPT__SLASH_Yc))
52087330f729Sjoerg Output = YcArg->getValue();
52097330f729Sjoerg if (Output.empty())
52107330f729Sjoerg Output = BaseName;
52117330f729Sjoerg llvm::sys::path::replace_extension(Output, ".pch");
52127330f729Sjoerg }
5213*e038c9c4Sjoerg return std::string(Output.str());
52147330f729Sjoerg }
52157330f729Sjoerg
getToolChain(const ArgList & Args,const llvm::Triple & Target) const52167330f729Sjoerg const ToolChain &Driver::getToolChain(const ArgList &Args,
52177330f729Sjoerg const llvm::Triple &Target) const {
52187330f729Sjoerg
52197330f729Sjoerg auto &TC = ToolChains[Target.str()];
52207330f729Sjoerg if (!TC) {
52217330f729Sjoerg switch (Target.getOS()) {
52227330f729Sjoerg case llvm::Triple::AIX:
52237330f729Sjoerg TC = std::make_unique<toolchains::AIX>(*this, Target, Args);
52247330f729Sjoerg break;
52257330f729Sjoerg case llvm::Triple::Haiku:
52267330f729Sjoerg TC = std::make_unique<toolchains::Haiku>(*this, Target, Args);
52277330f729Sjoerg break;
52287330f729Sjoerg case llvm::Triple::Ananas:
52297330f729Sjoerg TC = std::make_unique<toolchains::Ananas>(*this, Target, Args);
52307330f729Sjoerg break;
52317330f729Sjoerg case llvm::Triple::CloudABI:
52327330f729Sjoerg TC = std::make_unique<toolchains::CloudABI>(*this, Target, Args);
52337330f729Sjoerg break;
52347330f729Sjoerg case llvm::Triple::Darwin:
52357330f729Sjoerg case llvm::Triple::MacOSX:
52367330f729Sjoerg case llvm::Triple::IOS:
52377330f729Sjoerg case llvm::Triple::TvOS:
52387330f729Sjoerg case llvm::Triple::WatchOS:
52397330f729Sjoerg TC = std::make_unique<toolchains::DarwinClang>(*this, Target, Args);
52407330f729Sjoerg break;
52417330f729Sjoerg case llvm::Triple::DragonFly:
52427330f729Sjoerg TC = std::make_unique<toolchains::DragonFly>(*this, Target, Args);
52437330f729Sjoerg break;
52447330f729Sjoerg case llvm::Triple::OpenBSD:
52457330f729Sjoerg TC = std::make_unique<toolchains::OpenBSD>(*this, Target, Args);
52467330f729Sjoerg break;
52477330f729Sjoerg case llvm::Triple::NetBSD:
52487330f729Sjoerg TC = std::make_unique<toolchains::NetBSD>(*this, Target, Args);
52497330f729Sjoerg break;
52507330f729Sjoerg case llvm::Triple::FreeBSD:
52517330f729Sjoerg TC = std::make_unique<toolchains::FreeBSD>(*this, Target, Args);
52527330f729Sjoerg break;
52537330f729Sjoerg case llvm::Triple::Minix:
52547330f729Sjoerg TC = std::make_unique<toolchains::Minix>(*this, Target, Args);
52557330f729Sjoerg break;
52567330f729Sjoerg case llvm::Triple::Linux:
52577330f729Sjoerg case llvm::Triple::ELFIAMCU:
52587330f729Sjoerg if (Target.getArch() == llvm::Triple::hexagon)
52597330f729Sjoerg TC = std::make_unique<toolchains::HexagonToolChain>(*this, Target,
52607330f729Sjoerg Args);
52617330f729Sjoerg else if ((Target.getVendor() == llvm::Triple::MipsTechnologies) &&
52627330f729Sjoerg !Target.hasEnvironment())
52637330f729Sjoerg TC = std::make_unique<toolchains::MipsLLVMToolChain>(*this, Target,
52647330f729Sjoerg Args);
5265*e038c9c4Sjoerg else if (Target.isPPC())
52667330f729Sjoerg TC = std::make_unique<toolchains::PPCLinuxToolChain>(*this, Target,
52677330f729Sjoerg Args);
5268*e038c9c4Sjoerg else if (Target.getArch() == llvm::Triple::ve)
5269*e038c9c4Sjoerg TC = std::make_unique<toolchains::VEToolChain>(*this, Target, Args);
5270*e038c9c4Sjoerg
52717330f729Sjoerg else
52727330f729Sjoerg TC = std::make_unique<toolchains::Linux>(*this, Target, Args);
52737330f729Sjoerg break;
52747330f729Sjoerg case llvm::Triple::NaCl:
52757330f729Sjoerg TC = std::make_unique<toolchains::NaClToolChain>(*this, Target, Args);
52767330f729Sjoerg break;
52777330f729Sjoerg case llvm::Triple::Fuchsia:
52787330f729Sjoerg TC = std::make_unique<toolchains::Fuchsia>(*this, Target, Args);
52797330f729Sjoerg break;
52807330f729Sjoerg case llvm::Triple::Solaris:
52817330f729Sjoerg TC = std::make_unique<toolchains::Solaris>(*this, Target, Args);
52827330f729Sjoerg break;
52837330f729Sjoerg case llvm::Triple::AMDHSA:
5284*e038c9c4Sjoerg TC = std::make_unique<toolchains::ROCMToolChain>(*this, Target, Args);
5285*e038c9c4Sjoerg break;
52867330f729Sjoerg case llvm::Triple::AMDPAL:
52877330f729Sjoerg case llvm::Triple::Mesa3D:
52887330f729Sjoerg TC = std::make_unique<toolchains::AMDGPUToolChain>(*this, Target, Args);
52897330f729Sjoerg break;
52907330f729Sjoerg case llvm::Triple::Win32:
52917330f729Sjoerg switch (Target.getEnvironment()) {
52927330f729Sjoerg default:
52937330f729Sjoerg if (Target.isOSBinFormatELF())
52947330f729Sjoerg TC = std::make_unique<toolchains::Generic_ELF>(*this, Target, Args);
52957330f729Sjoerg else if (Target.isOSBinFormatMachO())
52967330f729Sjoerg TC = std::make_unique<toolchains::MachO>(*this, Target, Args);
52977330f729Sjoerg else
52987330f729Sjoerg TC = std::make_unique<toolchains::Generic_GCC>(*this, Target, Args);
52997330f729Sjoerg break;
53007330f729Sjoerg case llvm::Triple::GNU:
53017330f729Sjoerg TC = std::make_unique<toolchains::MinGW>(*this, Target, Args);
53027330f729Sjoerg break;
53037330f729Sjoerg case llvm::Triple::Itanium:
53047330f729Sjoerg TC = std::make_unique<toolchains::CrossWindowsToolChain>(*this, Target,
53057330f729Sjoerg Args);
53067330f729Sjoerg break;
53077330f729Sjoerg case llvm::Triple::MSVC:
53087330f729Sjoerg case llvm::Triple::UnknownEnvironment:
53097330f729Sjoerg if (Args.getLastArgValue(options::OPT_fuse_ld_EQ)
53107330f729Sjoerg .startswith_lower("bfd"))
53117330f729Sjoerg TC = std::make_unique<toolchains::CrossWindowsToolChain>(
53127330f729Sjoerg *this, Target, Args);
53137330f729Sjoerg else
53147330f729Sjoerg TC =
53157330f729Sjoerg std::make_unique<toolchains::MSVCToolChain>(*this, Target, Args);
53167330f729Sjoerg break;
53177330f729Sjoerg }
53187330f729Sjoerg break;
53197330f729Sjoerg case llvm::Triple::PS4:
53207330f729Sjoerg TC = std::make_unique<toolchains::PS4CPU>(*this, Target, Args);
53217330f729Sjoerg break;
53227330f729Sjoerg case llvm::Triple::Contiki:
53237330f729Sjoerg TC = std::make_unique<toolchains::Contiki>(*this, Target, Args);
53247330f729Sjoerg break;
53257330f729Sjoerg case llvm::Triple::Hurd:
53267330f729Sjoerg TC = std::make_unique<toolchains::Hurd>(*this, Target, Args);
53277330f729Sjoerg break;
5328*e038c9c4Sjoerg case llvm::Triple::ZOS:
5329*e038c9c4Sjoerg TC = std::make_unique<toolchains::ZOS>(*this, Target, Args);
5330*e038c9c4Sjoerg break;
53317330f729Sjoerg default:
53327330f729Sjoerg // Of these targets, Hexagon is the only one that might have
53337330f729Sjoerg // an OS of Linux, in which case it got handled above already.
53347330f729Sjoerg switch (Target.getArch()) {
53357330f729Sjoerg case llvm::Triple::tce:
53367330f729Sjoerg TC = std::make_unique<toolchains::TCEToolChain>(*this, Target, Args);
53377330f729Sjoerg break;
53387330f729Sjoerg case llvm::Triple::tcele:
53397330f729Sjoerg TC = std::make_unique<toolchains::TCELEToolChain>(*this, Target, Args);
53407330f729Sjoerg break;
53417330f729Sjoerg case llvm::Triple::hexagon:
53427330f729Sjoerg TC = std::make_unique<toolchains::HexagonToolChain>(*this, Target,
53437330f729Sjoerg Args);
53447330f729Sjoerg break;
53457330f729Sjoerg case llvm::Triple::lanai:
53467330f729Sjoerg TC = std::make_unique<toolchains::LanaiToolChain>(*this, Target, Args);
53477330f729Sjoerg break;
53487330f729Sjoerg case llvm::Triple::xcore:
53497330f729Sjoerg TC = std::make_unique<toolchains::XCoreToolChain>(*this, Target, Args);
53507330f729Sjoerg break;
53517330f729Sjoerg case llvm::Triple::wasm32:
53527330f729Sjoerg case llvm::Triple::wasm64:
53537330f729Sjoerg TC = std::make_unique<toolchains::WebAssembly>(*this, Target, Args);
53547330f729Sjoerg break;
53557330f729Sjoerg case llvm::Triple::avr:
53567330f729Sjoerg TC = std::make_unique<toolchains::AVRToolChain>(*this, Target, Args);
53577330f729Sjoerg break;
53587330f729Sjoerg case llvm::Triple::msp430:
53597330f729Sjoerg TC =
53607330f729Sjoerg std::make_unique<toolchains::MSP430ToolChain>(*this, Target, Args);
53617330f729Sjoerg break;
53627330f729Sjoerg case llvm::Triple::riscv32:
53637330f729Sjoerg case llvm::Triple::riscv64:
5364*e038c9c4Sjoerg if (toolchains::RISCVToolChain::hasGCCToolchain(*this, Args))
5365*e038c9c4Sjoerg TC =
5366*e038c9c4Sjoerg std::make_unique<toolchains::RISCVToolChain>(*this, Target, Args);
5367*e038c9c4Sjoerg else
5368*e038c9c4Sjoerg TC = std::make_unique<toolchains::BareMetal>(*this, Target, Args);
5369*e038c9c4Sjoerg break;
5370*e038c9c4Sjoerg case llvm::Triple::ve:
5371*e038c9c4Sjoerg TC = std::make_unique<toolchains::VEToolChain>(*this, Target, Args);
53727330f729Sjoerg break;
53737330f729Sjoerg default:
53747330f729Sjoerg if (Target.getVendor() == llvm::Triple::Myriad)
53757330f729Sjoerg TC = std::make_unique<toolchains::MyriadToolChain>(*this, Target,
53767330f729Sjoerg Args);
53777330f729Sjoerg else if (toolchains::BareMetal::handlesTarget(Target))
53787330f729Sjoerg TC = std::make_unique<toolchains::BareMetal>(*this, Target, Args);
53797330f729Sjoerg else if (Target.isOSBinFormatELF())
53807330f729Sjoerg TC = std::make_unique<toolchains::Generic_ELF>(*this, Target, Args);
53817330f729Sjoerg else if (Target.isOSBinFormatMachO())
53827330f729Sjoerg TC = std::make_unique<toolchains::MachO>(*this, Target, Args);
53837330f729Sjoerg else
53847330f729Sjoerg TC = std::make_unique<toolchains::Generic_GCC>(*this, Target, Args);
53857330f729Sjoerg }
53867330f729Sjoerg }
53877330f729Sjoerg }
53887330f729Sjoerg
53897330f729Sjoerg // Intentionally omitted from the switch above: llvm::Triple::CUDA. CUDA
53907330f729Sjoerg // compiles always need two toolchains, the CUDA toolchain and the host
53917330f729Sjoerg // toolchain. So the only valid way to create a CUDA toolchain is via
53927330f729Sjoerg // CreateOffloadingDeviceToolChains.
53937330f729Sjoerg
53947330f729Sjoerg return *TC;
53957330f729Sjoerg }
53967330f729Sjoerg
ShouldUseClangCompiler(const JobAction & JA) const53977330f729Sjoerg bool Driver::ShouldUseClangCompiler(const JobAction &JA) const {
53987330f729Sjoerg // Say "no" if there is not exactly one input of a type clang understands.
53997330f729Sjoerg if (JA.size() != 1 ||
54007330f729Sjoerg !types::isAcceptedByClang((*JA.input_begin())->getType()))
54017330f729Sjoerg return false;
54027330f729Sjoerg
54037330f729Sjoerg // And say "no" if this is not a kind of action clang understands.
54047330f729Sjoerg if (!isa<PreprocessJobAction>(JA) && !isa<PrecompileJobAction>(JA) &&
54057330f729Sjoerg !isa<CompileJobAction>(JA) && !isa<BackendJobAction>(JA))
54067330f729Sjoerg return false;
54077330f729Sjoerg
54087330f729Sjoerg return true;
54097330f729Sjoerg }
54107330f729Sjoerg
ShouldUseFlangCompiler(const JobAction & JA) const5411*e038c9c4Sjoerg bool Driver::ShouldUseFlangCompiler(const JobAction &JA) const {
5412*e038c9c4Sjoerg // Say "no" if there is not exactly one input of a type flang understands.
5413*e038c9c4Sjoerg if (JA.size() != 1 ||
5414*e038c9c4Sjoerg !types::isFortran((*JA.input_begin())->getType()))
5415*e038c9c4Sjoerg return false;
5416*e038c9c4Sjoerg
5417*e038c9c4Sjoerg // And say "no" if this is not a kind of action flang understands.
5418*e038c9c4Sjoerg if (!isa<PreprocessJobAction>(JA) && !isa<CompileJobAction>(JA) && !isa<BackendJobAction>(JA))
5419*e038c9c4Sjoerg return false;
5420*e038c9c4Sjoerg
5421*e038c9c4Sjoerg return true;
5422*e038c9c4Sjoerg }
5423*e038c9c4Sjoerg
ShouldEmitStaticLibrary(const ArgList & Args) const5424*e038c9c4Sjoerg bool Driver::ShouldEmitStaticLibrary(const ArgList &Args) const {
5425*e038c9c4Sjoerg // Only emit static library if the flag is set explicitly.
5426*e038c9c4Sjoerg if (Args.hasArg(options::OPT_emit_static_lib))
5427*e038c9c4Sjoerg return true;
5428*e038c9c4Sjoerg return false;
5429*e038c9c4Sjoerg }
5430*e038c9c4Sjoerg
54317330f729Sjoerg /// GetReleaseVersion - Parse (([0-9]+)(.([0-9]+)(.([0-9]+)?))?)? and return the
54327330f729Sjoerg /// grouped values as integers. Numbers which are not provided are set to 0.
54337330f729Sjoerg ///
54347330f729Sjoerg /// \return True if the entire string was parsed (9.2), or all groups were
54357330f729Sjoerg /// parsed (10.3.5extrastuff).
GetReleaseVersion(StringRef Str,unsigned & Major,unsigned & Minor,unsigned & Micro,bool & HadExtra)54367330f729Sjoerg bool Driver::GetReleaseVersion(StringRef Str, unsigned &Major, unsigned &Minor,
54377330f729Sjoerg unsigned &Micro, bool &HadExtra) {
54387330f729Sjoerg HadExtra = false;
54397330f729Sjoerg
54407330f729Sjoerg Major = Minor = Micro = 0;
54417330f729Sjoerg if (Str.empty())
54427330f729Sjoerg return false;
54437330f729Sjoerg
54447330f729Sjoerg if (Str.consumeInteger(10, Major))
54457330f729Sjoerg return false;
54467330f729Sjoerg if (Str.empty())
54477330f729Sjoerg return true;
54487330f729Sjoerg if (Str[0] != '.')
54497330f729Sjoerg return false;
54507330f729Sjoerg
54517330f729Sjoerg Str = Str.drop_front(1);
54527330f729Sjoerg
54537330f729Sjoerg if (Str.consumeInteger(10, Minor))
54547330f729Sjoerg return false;
54557330f729Sjoerg if (Str.empty())
54567330f729Sjoerg return true;
54577330f729Sjoerg if (Str[0] != '.')
54587330f729Sjoerg return false;
54597330f729Sjoerg Str = Str.drop_front(1);
54607330f729Sjoerg
54617330f729Sjoerg if (Str.consumeInteger(10, Micro))
54627330f729Sjoerg return false;
54637330f729Sjoerg if (!Str.empty())
54647330f729Sjoerg HadExtra = true;
54657330f729Sjoerg return true;
54667330f729Sjoerg }
54677330f729Sjoerg
54687330f729Sjoerg /// Parse digits from a string \p Str and fulfill \p Digits with
54697330f729Sjoerg /// the parsed numbers. This method assumes that the max number of
54707330f729Sjoerg /// digits to look for is equal to Digits.size().
54717330f729Sjoerg ///
54727330f729Sjoerg /// \return True if the entire string was parsed and there are
54737330f729Sjoerg /// no extra characters remaining at the end.
GetReleaseVersion(StringRef Str,MutableArrayRef<unsigned> Digits)54747330f729Sjoerg bool Driver::GetReleaseVersion(StringRef Str,
54757330f729Sjoerg MutableArrayRef<unsigned> Digits) {
54767330f729Sjoerg if (Str.empty())
54777330f729Sjoerg return false;
54787330f729Sjoerg
54797330f729Sjoerg unsigned CurDigit = 0;
54807330f729Sjoerg while (CurDigit < Digits.size()) {
54817330f729Sjoerg unsigned Digit;
54827330f729Sjoerg if (Str.consumeInteger(10, Digit))
54837330f729Sjoerg return false;
54847330f729Sjoerg Digits[CurDigit] = Digit;
54857330f729Sjoerg if (Str.empty())
54867330f729Sjoerg return true;
54877330f729Sjoerg if (Str[0] != '.')
54887330f729Sjoerg return false;
54897330f729Sjoerg Str = Str.drop_front(1);
54907330f729Sjoerg CurDigit++;
54917330f729Sjoerg }
54927330f729Sjoerg
54937330f729Sjoerg // More digits than requested, bail out...
54947330f729Sjoerg return false;
54957330f729Sjoerg }
54967330f729Sjoerg
54977330f729Sjoerg std::pair<unsigned, unsigned>
getIncludeExcludeOptionFlagMasks(bool IsClCompatMode) const54987330f729Sjoerg Driver::getIncludeExcludeOptionFlagMasks(bool IsClCompatMode) const {
54997330f729Sjoerg unsigned IncludedFlagsBitmask = 0;
55007330f729Sjoerg unsigned ExcludedFlagsBitmask = options::NoDriverOption;
55017330f729Sjoerg
55027330f729Sjoerg if (IsClCompatMode) {
55037330f729Sjoerg // Include CL and Core options.
55047330f729Sjoerg IncludedFlagsBitmask |= options::CLOption;
55057330f729Sjoerg IncludedFlagsBitmask |= options::CoreOption;
55067330f729Sjoerg } else {
55077330f729Sjoerg ExcludedFlagsBitmask |= options::CLOption;
55087330f729Sjoerg }
55097330f729Sjoerg
55107330f729Sjoerg return std::make_pair(IncludedFlagsBitmask, ExcludedFlagsBitmask);
55117330f729Sjoerg }
55127330f729Sjoerg
isOptimizationLevelFast(const ArgList & Args)55137330f729Sjoerg bool clang::driver::isOptimizationLevelFast(const ArgList &Args) {
55147330f729Sjoerg return Args.hasFlag(options::OPT_Ofast, options::OPT_O_Group, false);
55157330f729Sjoerg }
5516*e038c9c4Sjoerg
willEmitRemarks(const ArgList & Args)5517*e038c9c4Sjoerg bool clang::driver::willEmitRemarks(const ArgList &Args) {
5518*e038c9c4Sjoerg // -fsave-optimization-record enables it.
5519*e038c9c4Sjoerg if (Args.hasFlag(options::OPT_fsave_optimization_record,
5520*e038c9c4Sjoerg options::OPT_fno_save_optimization_record, false))
5521*e038c9c4Sjoerg return true;
5522*e038c9c4Sjoerg
5523*e038c9c4Sjoerg // -fsave-optimization-record=<format> enables it as well.
5524*e038c9c4Sjoerg if (Args.hasFlag(options::OPT_fsave_optimization_record_EQ,
5525*e038c9c4Sjoerg options::OPT_fno_save_optimization_record, false))
5526*e038c9c4Sjoerg return true;
5527*e038c9c4Sjoerg
5528*e038c9c4Sjoerg // -foptimization-record-file alone enables it too.
5529*e038c9c4Sjoerg if (Args.hasFlag(options::OPT_foptimization_record_file_EQ,
5530*e038c9c4Sjoerg options::OPT_fno_save_optimization_record, false))
5531*e038c9c4Sjoerg return true;
5532*e038c9c4Sjoerg
5533*e038c9c4Sjoerg // -foptimization-record-passes alone enables it too.
5534*e038c9c4Sjoerg if (Args.hasFlag(options::OPT_foptimization_record_passes_EQ,
5535*e038c9c4Sjoerg options::OPT_fno_save_optimization_record, false))
5536*e038c9c4Sjoerg return true;
5537*e038c9c4Sjoerg return false;
5538*e038c9c4Sjoerg }
5539