Path: blob/main/contrib/llvm-project/clang/lib/Driver/Driver.cpp
35234 views
//===--- Driver.cpp - Clang GCC Compatible Driver -------------------------===//1//2// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.3// See https://llvm.org/LICENSE.txt for license information.4// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception5//6//===----------------------------------------------------------------------===//78#include "clang/Driver/Driver.h"9#include "ToolChains/AIX.h"10#include "ToolChains/AMDGPU.h"11#include "ToolChains/AMDGPUOpenMP.h"12#include "ToolChains/AVR.h"13#include "ToolChains/Arch/RISCV.h"14#include "ToolChains/BareMetal.h"15#include "ToolChains/CSKYToolChain.h"16#include "ToolChains/Clang.h"17#include "ToolChains/CrossWindows.h"18#include "ToolChains/Cuda.h"19#include "ToolChains/Darwin.h"20#include "ToolChains/DragonFly.h"21#include "ToolChains/FreeBSD.h"22#include "ToolChains/Fuchsia.h"23#include "ToolChains/Gnu.h"24#include "ToolChains/HIPAMD.h"25#include "ToolChains/HIPSPV.h"26#include "ToolChains/HLSL.h"27#include "ToolChains/Haiku.h"28#include "ToolChains/Hexagon.h"29#include "ToolChains/Hurd.h"30#include "ToolChains/Lanai.h"31#include "ToolChains/Linux.h"32#include "ToolChains/MSP430.h"33#include "ToolChains/MSVC.h"34#include "ToolChains/MinGW.h"35#include "ToolChains/MipsLinux.h"36#include "ToolChains/NaCl.h"37#include "ToolChains/NetBSD.h"38#include "ToolChains/OHOS.h"39#include "ToolChains/OpenBSD.h"40#include "ToolChains/PPCFreeBSD.h"41#include "ToolChains/PPCLinux.h"42#include "ToolChains/PS4CPU.h"43#include "ToolChains/RISCVToolchain.h"44#include "ToolChains/SPIRV.h"45#include "ToolChains/Solaris.h"46#include "ToolChains/TCE.h"47#include "ToolChains/VEToolchain.h"48#include "ToolChains/WebAssembly.h"49#include "ToolChains/XCore.h"50#include "ToolChains/ZOS.h"51#include "clang/Basic/DiagnosticDriver.h"52#include "clang/Basic/TargetID.h"53#include "clang/Basic/Version.h"54#include "clang/Config/config.h"55#include "clang/Driver/Action.h"56#include "clang/Driver/Compilation.h"57#include "clang/Driver/DriverDiagnostic.h"58#include "clang/Driver/InputInfo.h"59#include "clang/Driver/Job.h"60#include "clang/Driver/Options.h"61#include "clang/Driver/Phases.h"62#include "clang/Driver/SanitizerArgs.h"63#include "clang/Driver/Tool.h"64#include "clang/Driver/ToolChain.h"65#include "clang/Driver/Types.h"66#include "llvm/ADT/ArrayRef.h"67#include "llvm/ADT/STLExtras.h"68#include "llvm/ADT/StringExtras.h"69#include "llvm/ADT/StringRef.h"70#include "llvm/ADT/StringSet.h"71#include "llvm/ADT/StringSwitch.h"72#include "llvm/Config/llvm-config.h"73#include "llvm/MC/TargetRegistry.h"74#include "llvm/Option/Arg.h"75#include "llvm/Option/ArgList.h"76#include "llvm/Option/OptSpecifier.h"77#include "llvm/Option/OptTable.h"78#include "llvm/Option/Option.h"79#include "llvm/Support/CommandLine.h"80#include "llvm/Support/ErrorHandling.h"81#include "llvm/Support/ExitCodes.h"82#include "llvm/Support/FileSystem.h"83#include "llvm/Support/FormatVariadic.h"84#include "llvm/Support/MD5.h"85#include "llvm/Support/Path.h"86#include "llvm/Support/PrettyStackTrace.h"87#include "llvm/Support/Process.h"88#include "llvm/Support/Program.h"89#include "llvm/Support/Regex.h"90#include "llvm/Support/StringSaver.h"91#include "llvm/Support/VirtualFileSystem.h"92#include "llvm/Support/raw_ostream.h"93#include "llvm/TargetParser/Host.h"94#include "llvm/TargetParser/RISCVISAInfo.h"95#include <cstdlib> // ::getenv96#include <map>97#include <memory>98#include <optional>99#include <set>100#include <utility>101#if LLVM_ON_UNIX102#include <unistd.h> // getpid103#endif104105using namespace clang::driver;106using namespace clang;107using namespace llvm::opt;108109static std::optional<llvm::Triple> getOffloadTargetTriple(const Driver &D,110const ArgList &Args) {111auto OffloadTargets = Args.getAllArgValues(options::OPT_offload_EQ);112// Offload compilation flow does not support multiple targets for now. We113// need the HIPActionBuilder (and possibly the CudaActionBuilder{,Base}too)114// to support multiple tool chains first.115switch (OffloadTargets.size()) {116default:117D.Diag(diag::err_drv_only_one_offload_target_supported);118return std::nullopt;119case 0:120D.Diag(diag::err_drv_invalid_or_unsupported_offload_target) << "";121return std::nullopt;122case 1:123break;124}125return llvm::Triple(OffloadTargets[0]);126}127128static std::optional<llvm::Triple>129getNVIDIAOffloadTargetTriple(const Driver &D, const ArgList &Args,130const llvm::Triple &HostTriple) {131if (!Args.hasArg(options::OPT_offload_EQ)) {132return llvm::Triple(HostTriple.isArch64Bit() ? "nvptx64-nvidia-cuda"133: "nvptx-nvidia-cuda");134}135auto TT = getOffloadTargetTriple(D, Args);136if (TT && (TT->getArch() == llvm::Triple::spirv32 ||137TT->getArch() == llvm::Triple::spirv64)) {138if (Args.hasArg(options::OPT_emit_llvm))139return TT;140D.Diag(diag::err_drv_cuda_offload_only_emit_bc);141return std::nullopt;142}143D.Diag(diag::err_drv_invalid_or_unsupported_offload_target) << TT->str();144return std::nullopt;145}146static std::optional<llvm::Triple>147getHIPOffloadTargetTriple(const Driver &D, const ArgList &Args) {148if (!Args.hasArg(options::OPT_offload_EQ)) {149auto OffloadArchs = Args.getAllArgValues(options::OPT_offload_arch_EQ);150if (llvm::find(OffloadArchs, "amdgcnspirv") != OffloadArchs.cend()) {151if (OffloadArchs.size() == 1)152return llvm::Triple("spirv64-amd-amdhsa");153// Mixing specific & SPIR-V compilation is not supported for now.154D.Diag(diag::err_drv_only_one_offload_target_supported);155return std::nullopt;156}157return llvm::Triple("amdgcn-amd-amdhsa"); // Default HIP triple.158}159auto TT = getOffloadTargetTriple(D, Args);160if (!TT)161return std::nullopt;162if (TT->getArch() == llvm::Triple::amdgcn &&163TT->getVendor() == llvm::Triple::AMD &&164TT->getOS() == llvm::Triple::AMDHSA)165return TT;166if (TT->getArch() == llvm::Triple::spirv64)167return TT;168D.Diag(diag::err_drv_invalid_or_unsupported_offload_target) << TT->str();169return std::nullopt;170}171172// static173std::string Driver::GetResourcesPath(StringRef BinaryPath,174StringRef CustomResourceDir) {175// Since the resource directory is embedded in the module hash, it's important176// that all places that need it call this function, so that they get the177// exact same string ("a/../b/" and "b/" get different hashes, for example).178179// Dir is bin/ or lib/, depending on where BinaryPath is.180std::string Dir = std::string(llvm::sys::path::parent_path(BinaryPath));181182SmallString<128> P(Dir);183if (CustomResourceDir != "") {184llvm::sys::path::append(P, CustomResourceDir);185} else {186// On Windows, libclang.dll is in bin/.187// On non-Windows, libclang.so/.dylib is in lib/.188// With a static-library build of libclang, LibClangPath will contain the189// path of the embedding binary, which for LLVM binaries will be in bin/.190// ../lib gets us to lib/ in both cases.191P = llvm::sys::path::parent_path(Dir);192// This search path is also created in the COFF driver of lld, so any193// changes here also needs to happen in lld/COFF/Driver.cpp194llvm::sys::path::append(P, CLANG_INSTALL_LIBDIR_BASENAME, "clang",195CLANG_VERSION_MAJOR_STRING);196}197198return std::string(P);199}200201Driver::Driver(StringRef ClangExecutable, StringRef TargetTriple,202DiagnosticsEngine &Diags, std::string Title,203IntrusiveRefCntPtr<llvm::vfs::FileSystem> VFS)204: Diags(Diags), VFS(std::move(VFS)), Mode(GCCMode),205SaveTemps(SaveTempsNone), BitcodeEmbed(EmbedNone),206Offload(OffloadHostDevice), CXX20HeaderType(HeaderMode_None),207ModulesModeCXX20(false), LTOMode(LTOK_None),208ClangExecutable(ClangExecutable), SysRoot(DEFAULT_SYSROOT),209DriverTitle(Title), CCCPrintBindings(false), CCPrintOptions(false),210CCLogDiagnostics(false), CCGenDiagnostics(false),211CCPrintProcessStats(false), CCPrintInternalStats(false),212TargetTriple(TargetTriple), Saver(Alloc), PrependArg(nullptr),213CheckInputsExist(true), ProbePrecompiled(true),214SuppressMissingInputWarning(false) {215// Provide a sane fallback if no VFS is specified.216if (!this->VFS)217this->VFS = llvm::vfs::getRealFileSystem();218219Name = std::string(llvm::sys::path::filename(ClangExecutable));220Dir = std::string(llvm::sys::path::parent_path(ClangExecutable));221222if ((!SysRoot.empty()) && llvm::sys::path::is_relative(SysRoot)) {223// Prepend InstalledDir if SysRoot is relative224SmallString<128> P(Dir);225llvm::sys::path::append(P, SysRoot);226SysRoot = std::string(P);227}228229#if defined(CLANG_CONFIG_FILE_SYSTEM_DIR)230SystemConfigDir = CLANG_CONFIG_FILE_SYSTEM_DIR;231#endif232#if defined(CLANG_CONFIG_FILE_USER_DIR)233{234SmallString<128> P;235llvm::sys::fs::expand_tilde(CLANG_CONFIG_FILE_USER_DIR, P);236UserConfigDir = static_cast<std::string>(P);237}238#endif239240// Compute the path to the resource directory.241ResourceDir = GetResourcesPath(ClangExecutable, CLANG_RESOURCE_DIR);242}243244void Driver::setDriverMode(StringRef Value) {245static StringRef OptName =246getOpts().getOption(options::OPT_driver_mode).getPrefixedName();247if (auto M = llvm::StringSwitch<std::optional<DriverMode>>(Value)248.Case("gcc", GCCMode)249.Case("g++", GXXMode)250.Case("cpp", CPPMode)251.Case("cl", CLMode)252.Case("flang", FlangMode)253.Case("dxc", DXCMode)254.Default(std::nullopt))255Mode = *M;256else257Diag(diag::err_drv_unsupported_option_argument) << OptName << Value;258}259260InputArgList Driver::ParseArgStrings(ArrayRef<const char *> ArgStrings,261bool UseDriverMode, bool &ContainsError) {262llvm::PrettyStackTraceString CrashInfo("Command line argument parsing");263ContainsError = false;264265llvm::opt::Visibility VisibilityMask = getOptionVisibilityMask(UseDriverMode);266unsigned MissingArgIndex, MissingArgCount;267InputArgList Args = getOpts().ParseArgs(ArgStrings, MissingArgIndex,268MissingArgCount, VisibilityMask);269270// Check for missing argument error.271if (MissingArgCount) {272Diag(diag::err_drv_missing_argument)273<< Args.getArgString(MissingArgIndex) << MissingArgCount;274ContainsError |=275Diags.getDiagnosticLevel(diag::err_drv_missing_argument,276SourceLocation()) > DiagnosticsEngine::Warning;277}278279// Check for unsupported options.280for (const Arg *A : Args) {281if (A->getOption().hasFlag(options::Unsupported)) {282Diag(diag::err_drv_unsupported_opt) << A->getAsString(Args);283ContainsError |= Diags.getDiagnosticLevel(diag::err_drv_unsupported_opt,284SourceLocation()) >285DiagnosticsEngine::Warning;286continue;287}288289// Warn about -mcpu= without an argument.290if (A->getOption().matches(options::OPT_mcpu_EQ) && A->containsValue("")) {291Diag(diag::warn_drv_empty_joined_argument) << A->getAsString(Args);292ContainsError |= Diags.getDiagnosticLevel(293diag::warn_drv_empty_joined_argument,294SourceLocation()) > DiagnosticsEngine::Warning;295}296}297298for (const Arg *A : Args.filtered(options::OPT_UNKNOWN)) {299unsigned DiagID;300auto ArgString = A->getAsString(Args);301std::string Nearest;302if (getOpts().findNearest(ArgString, Nearest, VisibilityMask) > 1) {303if (!IsCLMode() &&304getOpts().findExact(ArgString, Nearest,305llvm::opt::Visibility(options::CC1Option))) {306DiagID = diag::err_drv_unknown_argument_with_suggestion;307Diags.Report(DiagID) << ArgString << "-Xclang " + Nearest;308} else {309DiagID = IsCLMode() ? diag::warn_drv_unknown_argument_clang_cl310: diag::err_drv_unknown_argument;311Diags.Report(DiagID) << ArgString;312}313} else {314DiagID = IsCLMode()315? diag::warn_drv_unknown_argument_clang_cl_with_suggestion316: diag::err_drv_unknown_argument_with_suggestion;317Diags.Report(DiagID) << ArgString << Nearest;318}319ContainsError |= Diags.getDiagnosticLevel(DiagID, SourceLocation()) >320DiagnosticsEngine::Warning;321}322323for (const Arg *A : Args.filtered(options::OPT_o)) {324if (ArgStrings[A->getIndex()] == A->getSpelling())325continue;326327// Warn on joined arguments that are similar to a long argument.328std::string ArgString = ArgStrings[A->getIndex()];329std::string Nearest;330if (getOpts().findExact("-" + ArgString, Nearest, VisibilityMask))331Diags.Report(diag::warn_drv_potentially_misspelled_joined_argument)332<< A->getAsString(Args) << Nearest;333}334335return Args;336}337338// Determine which compilation mode we are in. We look for options which339// affect the phase, starting with the earliest phases, and record which340// option we used to determine the final phase.341phases::ID Driver::getFinalPhase(const DerivedArgList &DAL,342Arg **FinalPhaseArg) const {343Arg *PhaseArg = nullptr;344phases::ID FinalPhase;345346// -{E,EP,P,M,MM} only run the preprocessor.347if (CCCIsCPP() || (PhaseArg = DAL.getLastArg(options::OPT_E)) ||348(PhaseArg = DAL.getLastArg(options::OPT__SLASH_EP)) ||349(PhaseArg = DAL.getLastArg(options::OPT_M, options::OPT_MM)) ||350(PhaseArg = DAL.getLastArg(options::OPT__SLASH_P)) ||351CCGenDiagnostics) {352FinalPhase = phases::Preprocess;353354// --precompile only runs up to precompilation.355// Options that cause the output of C++20 compiled module interfaces or356// header units have the same effect.357} else if ((PhaseArg = DAL.getLastArg(options::OPT__precompile)) ||358(PhaseArg = DAL.getLastArg(options::OPT_extract_api)) ||359(PhaseArg = DAL.getLastArg(options::OPT_fmodule_header,360options::OPT_fmodule_header_EQ))) {361FinalPhase = phases::Precompile;362// -{fsyntax-only,-analyze,emit-ast} only run up to the compiler.363} else if ((PhaseArg = DAL.getLastArg(options::OPT_fsyntax_only)) ||364(PhaseArg = DAL.getLastArg(options::OPT_print_supported_cpus)) ||365(PhaseArg = DAL.getLastArg(options::OPT_print_enabled_extensions)) ||366(PhaseArg = DAL.getLastArg(options::OPT_module_file_info)) ||367(PhaseArg = DAL.getLastArg(options::OPT_verify_pch)) ||368(PhaseArg = DAL.getLastArg(options::OPT_rewrite_objc)) ||369(PhaseArg = DAL.getLastArg(options::OPT_rewrite_legacy_objc)) ||370(PhaseArg = DAL.getLastArg(options::OPT__migrate)) ||371(PhaseArg = DAL.getLastArg(options::OPT__analyze)) ||372(PhaseArg = DAL.getLastArg(options::OPT_emit_cir)) ||373(PhaseArg = DAL.getLastArg(options::OPT_emit_ast))) {374FinalPhase = phases::Compile;375376// -S only runs up to the backend.377} else if ((PhaseArg = DAL.getLastArg(options::OPT_S))) {378FinalPhase = phases::Backend;379380// -c compilation only runs up to the assembler.381} else if ((PhaseArg = DAL.getLastArg(options::OPT_c))) {382FinalPhase = phases::Assemble;383384} else if ((PhaseArg = DAL.getLastArg(options::OPT_emit_interface_stubs))) {385FinalPhase = phases::IfsMerge;386387// Otherwise do everything.388} else389FinalPhase = phases::Link;390391if (FinalPhaseArg)392*FinalPhaseArg = PhaseArg;393394return FinalPhase;395}396397static Arg *MakeInputArg(DerivedArgList &Args, const OptTable &Opts,398StringRef Value, bool Claim = true) {399Arg *A = new Arg(Opts.getOption(options::OPT_INPUT), Value,400Args.getBaseArgs().MakeIndex(Value), Value.data());401Args.AddSynthesizedArg(A);402if (Claim)403A->claim();404return A;405}406407DerivedArgList *Driver::TranslateInputArgs(const InputArgList &Args) const {408const llvm::opt::OptTable &Opts = getOpts();409DerivedArgList *DAL = new DerivedArgList(Args);410411bool HasNostdlib = Args.hasArg(options::OPT_nostdlib);412bool HasNostdlibxx = Args.hasArg(options::OPT_nostdlibxx);413bool HasNodefaultlib = Args.hasArg(options::OPT_nodefaultlibs);414bool IgnoreUnused = false;415for (Arg *A : Args) {416if (IgnoreUnused)417A->claim();418419if (A->getOption().matches(options::OPT_start_no_unused_arguments)) {420IgnoreUnused = true;421continue;422}423if (A->getOption().matches(options::OPT_end_no_unused_arguments)) {424IgnoreUnused = false;425continue;426}427428// Unfortunately, we have to parse some forwarding options (-Xassembler,429// -Xlinker, -Xpreprocessor) because we either integrate their functionality430// (assembler and preprocessor), or bypass a previous driver ('collect2').431432// Rewrite linker options, to replace --no-demangle with a custom internal433// option.434if ((A->getOption().matches(options::OPT_Wl_COMMA) ||435A->getOption().matches(options::OPT_Xlinker)) &&436A->containsValue("--no-demangle")) {437// Add the rewritten no-demangle argument.438DAL->AddFlagArg(A, Opts.getOption(options::OPT_Z_Xlinker__no_demangle));439440// Add the remaining values as Xlinker arguments.441for (StringRef Val : A->getValues())442if (Val != "--no-demangle")443DAL->AddSeparateArg(A, Opts.getOption(options::OPT_Xlinker), Val);444445continue;446}447448// Rewrite preprocessor options, to replace -Wp,-MD,FOO which is used by449// some build systems. We don't try to be complete here because we don't450// care to encourage this usage model.451if (A->getOption().matches(options::OPT_Wp_COMMA) &&452(A->getValue(0) == StringRef("-MD") ||453A->getValue(0) == StringRef("-MMD"))) {454// Rewrite to -MD/-MMD along with -MF.455if (A->getValue(0) == StringRef("-MD"))456DAL->AddFlagArg(A, Opts.getOption(options::OPT_MD));457else458DAL->AddFlagArg(A, Opts.getOption(options::OPT_MMD));459if (A->getNumValues() == 2)460DAL->AddSeparateArg(A, Opts.getOption(options::OPT_MF), A->getValue(1));461continue;462}463464// Rewrite reserved library names.465if (A->getOption().matches(options::OPT_l)) {466StringRef Value = A->getValue();467468// Rewrite unless -nostdlib is present.469if (!HasNostdlib && !HasNodefaultlib && !HasNostdlibxx &&470Value == "stdc++") {471DAL->AddFlagArg(A, Opts.getOption(options::OPT_Z_reserved_lib_stdcxx));472continue;473}474475// Rewrite unconditionally.476if (Value == "cc_kext") {477DAL->AddFlagArg(A, Opts.getOption(options::OPT_Z_reserved_lib_cckext));478continue;479}480}481482// Pick up inputs via the -- option.483if (A->getOption().matches(options::OPT__DASH_DASH)) {484A->claim();485for (StringRef Val : A->getValues())486DAL->append(MakeInputArg(*DAL, Opts, Val, false));487continue;488}489490DAL->append(A);491}492493// DXC mode quits before assembly if an output object file isn't specified.494if (IsDXCMode() && !Args.hasArg(options::OPT_dxc_Fo))495DAL->AddFlagArg(nullptr, Opts.getOption(options::OPT_S));496497// Enforce -static if -miamcu is present.498if (Args.hasFlag(options::OPT_miamcu, options::OPT_mno_iamcu, false))499DAL->AddFlagArg(nullptr, Opts.getOption(options::OPT_static));500501// Add a default value of -mlinker-version=, if one was given and the user502// didn't specify one.503#if defined(HOST_LINK_VERSION)504if (!Args.hasArg(options::OPT_mlinker_version_EQ) &&505strlen(HOST_LINK_VERSION) > 0) {506DAL->AddJoinedArg(0, Opts.getOption(options::OPT_mlinker_version_EQ),507HOST_LINK_VERSION);508DAL->getLastArg(options::OPT_mlinker_version_EQ)->claim();509}510#endif511512return DAL;513}514515/// Compute target triple from args.516///517/// This routine provides the logic to compute a target triple from various518/// args passed to the driver and the default triple string.519static llvm::Triple computeTargetTriple(const Driver &D,520StringRef TargetTriple,521const ArgList &Args,522StringRef DarwinArchName = "") {523// FIXME: Already done in Compilation *Driver::BuildCompilation524if (const Arg *A = Args.getLastArg(options::OPT_target))525TargetTriple = A->getValue();526527llvm::Triple Target(llvm::Triple::normalize(TargetTriple));528529// GNU/Hurd's triples should have been -hurd-gnu*, but were historically made530// -gnu* only, and we can not change this, so we have to detect that case as531// being the Hurd OS.532if (TargetTriple.contains("-unknown-gnu") || TargetTriple.contains("-pc-gnu"))533Target.setOSName("hurd");534535// Handle Apple-specific options available here.536if (Target.isOSBinFormatMachO()) {537// If an explicit Darwin arch name is given, that trumps all.538if (!DarwinArchName.empty()) {539tools::darwin::setTripleTypeForMachOArchName(Target, DarwinArchName,540Args);541return Target;542}543544// Handle the Darwin '-arch' flag.545if (Arg *A = Args.getLastArg(options::OPT_arch)) {546StringRef ArchName = A->getValue();547tools::darwin::setTripleTypeForMachOArchName(Target, ArchName, Args);548}549}550551// Handle pseudo-target flags '-mlittle-endian'/'-EL' and552// '-mbig-endian'/'-EB'.553if (Arg *A = Args.getLastArgNoClaim(options::OPT_mlittle_endian,554options::OPT_mbig_endian)) {555llvm::Triple T = A->getOption().matches(options::OPT_mlittle_endian)556? Target.getLittleEndianArchVariant()557: Target.getBigEndianArchVariant();558if (T.getArch() != llvm::Triple::UnknownArch) {559Target = std::move(T);560Args.claimAllArgs(options::OPT_mlittle_endian, options::OPT_mbig_endian);561}562}563564// Skip further flag support on OSes which don't support '-m32' or '-m64'.565if (Target.getArch() == llvm::Triple::tce)566return Target;567568// On AIX, the env OBJECT_MODE may affect the resulting arch variant.569if (Target.isOSAIX()) {570if (std::optional<std::string> ObjectModeValue =571llvm::sys::Process::GetEnv("OBJECT_MODE")) {572StringRef ObjectMode = *ObjectModeValue;573llvm::Triple::ArchType AT = llvm::Triple::UnknownArch;574575if (ObjectMode == "64") {576AT = Target.get64BitArchVariant().getArch();577} else if (ObjectMode == "32") {578AT = Target.get32BitArchVariant().getArch();579} else {580D.Diag(diag::err_drv_invalid_object_mode) << ObjectMode;581}582583if (AT != llvm::Triple::UnknownArch && AT != Target.getArch())584Target.setArch(AT);585}586}587588// The `-maix[32|64]` flags are only valid for AIX targets.589if (Arg *A = Args.getLastArgNoClaim(options::OPT_maix32, options::OPT_maix64);590A && !Target.isOSAIX())591D.Diag(diag::err_drv_unsupported_opt_for_target)592<< A->getAsString(Args) << Target.str();593594// Handle pseudo-target flags '-m64', '-mx32', '-m32' and '-m16'.595Arg *A = Args.getLastArg(options::OPT_m64, options::OPT_mx32,596options::OPT_m32, options::OPT_m16,597options::OPT_maix32, options::OPT_maix64);598if (A) {599llvm::Triple::ArchType AT = llvm::Triple::UnknownArch;600601if (A->getOption().matches(options::OPT_m64) ||602A->getOption().matches(options::OPT_maix64)) {603AT = Target.get64BitArchVariant().getArch();604if (Target.getEnvironment() == llvm::Triple::GNUX32 ||605Target.getEnvironment() == llvm::Triple::GNUT64)606Target.setEnvironment(llvm::Triple::GNU);607else if (Target.getEnvironment() == llvm::Triple::MuslX32)608Target.setEnvironment(llvm::Triple::Musl);609} else if (A->getOption().matches(options::OPT_mx32) &&610Target.get64BitArchVariant().getArch() == llvm::Triple::x86_64) {611AT = llvm::Triple::x86_64;612if (Target.getEnvironment() == llvm::Triple::Musl)613Target.setEnvironment(llvm::Triple::MuslX32);614else615Target.setEnvironment(llvm::Triple::GNUX32);616} else if (A->getOption().matches(options::OPT_m32) ||617A->getOption().matches(options::OPT_maix32)) {618AT = Target.get32BitArchVariant().getArch();619if (Target.getEnvironment() == llvm::Triple::GNUX32)620Target.setEnvironment(llvm::Triple::GNU);621else if (Target.getEnvironment() == llvm::Triple::MuslX32)622Target.setEnvironment(llvm::Triple::Musl);623} else if (A->getOption().matches(options::OPT_m16) &&624Target.get32BitArchVariant().getArch() == llvm::Triple::x86) {625AT = llvm::Triple::x86;626Target.setEnvironment(llvm::Triple::CODE16);627}628629if (AT != llvm::Triple::UnknownArch && AT != Target.getArch()) {630Target.setArch(AT);631if (Target.isWindowsGNUEnvironment())632toolchains::MinGW::fixTripleArch(D, Target, Args);633}634}635636// Handle -miamcu flag.637if (Args.hasFlag(options::OPT_miamcu, options::OPT_mno_iamcu, false)) {638if (Target.get32BitArchVariant().getArch() != llvm::Triple::x86)639D.Diag(diag::err_drv_unsupported_opt_for_target) << "-miamcu"640<< Target.str();641642if (A && !A->getOption().matches(options::OPT_m32))643D.Diag(diag::err_drv_argument_not_allowed_with)644<< "-miamcu" << A->getBaseArg().getAsString(Args);645646Target.setArch(llvm::Triple::x86);647Target.setArchName("i586");648Target.setEnvironment(llvm::Triple::UnknownEnvironment);649Target.setEnvironmentName("");650Target.setOS(llvm::Triple::ELFIAMCU);651Target.setVendor(llvm::Triple::UnknownVendor);652Target.setVendorName("intel");653}654655// If target is MIPS adjust the target triple656// accordingly to provided ABI name.657if (Target.isMIPS()) {658if ((A = Args.getLastArg(options::OPT_mabi_EQ))) {659StringRef ABIName = A->getValue();660if (ABIName == "32") {661Target = Target.get32BitArchVariant();662if (Target.getEnvironment() == llvm::Triple::GNUABI64 ||663Target.getEnvironment() == llvm::Triple::GNUABIN32)664Target.setEnvironment(llvm::Triple::GNU);665} else if (ABIName == "n32") {666Target = Target.get64BitArchVariant();667if (Target.getEnvironment() == llvm::Triple::GNU ||668Target.getEnvironment() == llvm::Triple::GNUT64 ||669Target.getEnvironment() == llvm::Triple::GNUABI64)670Target.setEnvironment(llvm::Triple::GNUABIN32);671} else if (ABIName == "64") {672Target = Target.get64BitArchVariant();673if (Target.getEnvironment() == llvm::Triple::GNU ||674Target.getEnvironment() == llvm::Triple::GNUT64 ||675Target.getEnvironment() == llvm::Triple::GNUABIN32)676Target.setEnvironment(llvm::Triple::GNUABI64);677}678}679}680681// If target is RISC-V adjust the target triple according to682// provided architecture name683if (Target.isRISCV()) {684if (Args.hasArg(options::OPT_march_EQ) ||685Args.hasArg(options::OPT_mcpu_EQ)) {686std::string ArchName = tools::riscv::getRISCVArch(Args, Target);687auto ISAInfo = llvm::RISCVISAInfo::parseArchString(688ArchName, /*EnableExperimentalExtensions=*/true);689if (!llvm::errorToBool(ISAInfo.takeError())) {690unsigned XLen = (*ISAInfo)->getXLen();691if (XLen == 32)692Target.setArch(llvm::Triple::riscv32);693else if (XLen == 64)694Target.setArch(llvm::Triple::riscv64);695}696}697}698699return Target;700}701702// Parse the LTO options and record the type of LTO compilation703// based on which -f(no-)?lto(=.*)? or -f(no-)?offload-lto(=.*)?704// option occurs last.705static driver::LTOKind parseLTOMode(Driver &D, const llvm::opt::ArgList &Args,706OptSpecifier OptEq, OptSpecifier OptNeg) {707if (!Args.hasFlag(OptEq, OptNeg, false))708return LTOK_None;709710const Arg *A = Args.getLastArg(OptEq);711StringRef LTOName = A->getValue();712713driver::LTOKind LTOMode = llvm::StringSwitch<LTOKind>(LTOName)714.Case("full", LTOK_Full)715.Case("thin", LTOK_Thin)716.Default(LTOK_Unknown);717718if (LTOMode == LTOK_Unknown) {719D.Diag(diag::err_drv_unsupported_option_argument)720<< A->getSpelling() << A->getValue();721return LTOK_None;722}723return LTOMode;724}725726// Parse the LTO options.727void Driver::setLTOMode(const llvm::opt::ArgList &Args) {728LTOMode =729parseLTOMode(*this, Args, options::OPT_flto_EQ, options::OPT_fno_lto);730731OffloadLTOMode = parseLTOMode(*this, Args, options::OPT_foffload_lto_EQ,732options::OPT_fno_offload_lto);733734// Try to enable `-foffload-lto=full` if `-fopenmp-target-jit` is on.735if (Args.hasFlag(options::OPT_fopenmp_target_jit,736options::OPT_fno_openmp_target_jit, false)) {737if (Arg *A = Args.getLastArg(options::OPT_foffload_lto_EQ,738options::OPT_fno_offload_lto))739if (OffloadLTOMode != LTOK_Full)740Diag(diag::err_drv_incompatible_options)741<< A->getSpelling() << "-fopenmp-target-jit";742OffloadLTOMode = LTOK_Full;743}744}745746/// Compute the desired OpenMP runtime from the flags provided.747Driver::OpenMPRuntimeKind Driver::getOpenMPRuntime(const ArgList &Args) const {748StringRef RuntimeName(CLANG_DEFAULT_OPENMP_RUNTIME);749750const Arg *A = Args.getLastArg(options::OPT_fopenmp_EQ);751if (A)752RuntimeName = A->getValue();753754auto RT = llvm::StringSwitch<OpenMPRuntimeKind>(RuntimeName)755.Case("libomp", OMPRT_OMP)756.Case("libgomp", OMPRT_GOMP)757.Case("libiomp5", OMPRT_IOMP5)758.Default(OMPRT_Unknown);759760if (RT == OMPRT_Unknown) {761if (A)762Diag(diag::err_drv_unsupported_option_argument)763<< A->getSpelling() << A->getValue();764else765// FIXME: We could use a nicer diagnostic here.766Diag(diag::err_drv_unsupported_opt) << "-fopenmp";767}768769return RT;770}771772void Driver::CreateOffloadingDeviceToolChains(Compilation &C,773InputList &Inputs) {774775//776// CUDA/HIP777//778// We need to generate a CUDA/HIP toolchain if any of the inputs has a CUDA779// or HIP type. However, mixed CUDA/HIP compilation is not supported.780bool IsCuda =781llvm::any_of(Inputs, [](std::pair<types::ID, const llvm::opt::Arg *> &I) {782return types::isCuda(I.first);783});784bool IsHIP =785llvm::any_of(Inputs,786[](std::pair<types::ID, const llvm::opt::Arg *> &I) {787return types::isHIP(I.first);788}) ||789C.getInputArgs().hasArg(options::OPT_hip_link) ||790C.getInputArgs().hasArg(options::OPT_hipstdpar);791if (IsCuda && IsHIP) {792Diag(clang::diag::err_drv_mix_cuda_hip);793return;794}795if (IsCuda) {796const ToolChain *HostTC = C.getSingleOffloadToolChain<Action::OFK_Host>();797const llvm::Triple &HostTriple = HostTC->getTriple();798auto OFK = Action::OFK_Cuda;799auto CudaTriple =800getNVIDIAOffloadTargetTriple(*this, C.getInputArgs(), HostTriple);801if (!CudaTriple)802return;803// Use the CUDA and host triples as the key into the ToolChains map,804// because the device toolchain we create depends on both.805auto &CudaTC = ToolChains[CudaTriple->str() + "/" + HostTriple.str()];806if (!CudaTC) {807CudaTC = std::make_unique<toolchains::CudaToolChain>(808*this, *CudaTriple, *HostTC, C.getInputArgs());809810// Emit a warning if the detected CUDA version is too new.811CudaInstallationDetector &CudaInstallation =812static_cast<toolchains::CudaToolChain &>(*CudaTC).CudaInstallation;813if (CudaInstallation.isValid())814CudaInstallation.WarnIfUnsupportedVersion();815}816C.addOffloadDeviceToolChain(CudaTC.get(), OFK);817} else if (IsHIP) {818if (auto *OMPTargetArg =819C.getInputArgs().getLastArg(options::OPT_fopenmp_targets_EQ)) {820Diag(clang::diag::err_drv_unsupported_opt_for_language_mode)821<< OMPTargetArg->getSpelling() << "HIP";822return;823}824const ToolChain *HostTC = C.getSingleOffloadToolChain<Action::OFK_Host>();825auto OFK = Action::OFK_HIP;826auto HIPTriple = getHIPOffloadTargetTriple(*this, C.getInputArgs());827if (!HIPTriple)828return;829auto *HIPTC = &getOffloadingDeviceToolChain(C.getInputArgs(), *HIPTriple,830*HostTC, OFK);831assert(HIPTC && "Could not create offloading device tool chain.");832C.addOffloadDeviceToolChain(HIPTC, OFK);833}834835//836// OpenMP837//838// We need to generate an OpenMP toolchain if the user specified targets with839// the -fopenmp-targets option or used --offload-arch with OpenMP enabled.840bool IsOpenMPOffloading =841C.getInputArgs().hasFlag(options::OPT_fopenmp, options::OPT_fopenmp_EQ,842options::OPT_fno_openmp, false) &&843(C.getInputArgs().hasArg(options::OPT_fopenmp_targets_EQ) ||844C.getInputArgs().hasArg(options::OPT_offload_arch_EQ));845if (IsOpenMPOffloading) {846// We expect that -fopenmp-targets is always used in conjunction with the847// option -fopenmp specifying a valid runtime with offloading support, i.e.848// libomp or libiomp.849OpenMPRuntimeKind RuntimeKind = getOpenMPRuntime(C.getInputArgs());850if (RuntimeKind != OMPRT_OMP && RuntimeKind != OMPRT_IOMP5) {851Diag(clang::diag::err_drv_expecting_fopenmp_with_fopenmp_targets);852return;853}854855llvm::StringMap<llvm::DenseSet<StringRef>> DerivedArchs;856llvm::StringMap<StringRef> FoundNormalizedTriples;857std::multiset<StringRef> OpenMPTriples;858859// If the user specified -fopenmp-targets= we create a toolchain for each860// valid triple. Otherwise, if only --offload-arch= was specified we instead861// attempt to derive the appropriate toolchains from the arguments.862if (Arg *OpenMPTargets =863C.getInputArgs().getLastArg(options::OPT_fopenmp_targets_EQ)) {864if (OpenMPTargets && !OpenMPTargets->getNumValues()) {865Diag(clang::diag::warn_drv_empty_joined_argument)866<< OpenMPTargets->getAsString(C.getInputArgs());867return;868}869for (StringRef T : OpenMPTargets->getValues())870OpenMPTriples.insert(T);871} else if (C.getInputArgs().hasArg(options::OPT_offload_arch_EQ) &&872!IsHIP && !IsCuda) {873const ToolChain *HostTC = C.getSingleOffloadToolChain<Action::OFK_Host>();874auto AMDTriple = getHIPOffloadTargetTriple(*this, C.getInputArgs());875auto NVPTXTriple = getNVIDIAOffloadTargetTriple(*this, C.getInputArgs(),876HostTC->getTriple());877878// Attempt to deduce the offloading triple from the set of architectures.879// We can only correctly deduce NVPTX / AMDGPU triples currently. We need880// to temporarily create these toolchains so that we can access tools for881// inferring architectures.882llvm::DenseSet<StringRef> Archs;883if (NVPTXTriple) {884auto TempTC = std::make_unique<toolchains::CudaToolChain>(885*this, *NVPTXTriple, *HostTC, C.getInputArgs());886for (StringRef Arch : getOffloadArchs(887C, C.getArgs(), Action::OFK_OpenMP, &*TempTC, true))888Archs.insert(Arch);889}890if (AMDTriple) {891auto TempTC = std::make_unique<toolchains::AMDGPUOpenMPToolChain>(892*this, *AMDTriple, *HostTC, C.getInputArgs());893for (StringRef Arch : getOffloadArchs(894C, C.getArgs(), Action::OFK_OpenMP, &*TempTC, true))895Archs.insert(Arch);896}897if (!AMDTriple && !NVPTXTriple) {898for (StringRef Arch :899getOffloadArchs(C, C.getArgs(), Action::OFK_OpenMP, nullptr, true))900Archs.insert(Arch);901}902903for (StringRef Arch : Archs) {904if (NVPTXTriple && IsNVIDIAOffloadArch(StringToOffloadArch(905getProcessorFromTargetID(*NVPTXTriple, Arch)))) {906DerivedArchs[NVPTXTriple->getTriple()].insert(Arch);907} else if (AMDTriple &&908IsAMDOffloadArch(StringToOffloadArch(909getProcessorFromTargetID(*AMDTriple, Arch)))) {910DerivedArchs[AMDTriple->getTriple()].insert(Arch);911} else {912Diag(clang::diag::err_drv_failed_to_deduce_target_from_arch) << Arch;913return;914}915}916917// If the set is empty then we failed to find a native architecture.918if (Archs.empty()) {919Diag(clang::diag::err_drv_failed_to_deduce_target_from_arch)920<< "native";921return;922}923924for (const auto &TripleAndArchs : DerivedArchs)925OpenMPTriples.insert(TripleAndArchs.first());926}927928for (StringRef Val : OpenMPTriples) {929llvm::Triple TT(ToolChain::getOpenMPTriple(Val));930std::string NormalizedName = TT.normalize();931932// Make sure we don't have a duplicate triple.933auto Duplicate = FoundNormalizedTriples.find(NormalizedName);934if (Duplicate != FoundNormalizedTriples.end()) {935Diag(clang::diag::warn_drv_omp_offload_target_duplicate)936<< Val << Duplicate->second;937continue;938}939940// Store the current triple so that we can check for duplicates in the941// following iterations.942FoundNormalizedTriples[NormalizedName] = Val;943944// If the specified target is invalid, emit a diagnostic.945if (TT.getArch() == llvm::Triple::UnknownArch)946Diag(clang::diag::err_drv_invalid_omp_target) << Val;947else {948const ToolChain *TC;949// Device toolchains have to be selected differently. They pair host950// and device in their implementation.951if (TT.isNVPTX() || TT.isAMDGCN()) {952const ToolChain *HostTC =953C.getSingleOffloadToolChain<Action::OFK_Host>();954assert(HostTC && "Host toolchain should be always defined.");955auto &DeviceTC =956ToolChains[TT.str() + "/" + HostTC->getTriple().normalize()];957if (!DeviceTC) {958if (TT.isNVPTX())959DeviceTC = std::make_unique<toolchains::CudaToolChain>(960*this, TT, *HostTC, C.getInputArgs());961else if (TT.isAMDGCN())962DeviceTC = std::make_unique<toolchains::AMDGPUOpenMPToolChain>(963*this, TT, *HostTC, C.getInputArgs());964else965assert(DeviceTC && "Device toolchain not defined.");966}967968TC = DeviceTC.get();969} else970TC = &getToolChain(C.getInputArgs(), TT);971C.addOffloadDeviceToolChain(TC, Action::OFK_OpenMP);972if (DerivedArchs.contains(TT.getTriple()))973KnownArchs[TC] = DerivedArchs[TT.getTriple()];974}975}976} else if (C.getInputArgs().hasArg(options::OPT_fopenmp_targets_EQ)) {977Diag(clang::diag::err_drv_expecting_fopenmp_with_fopenmp_targets);978return;979}980981//982// TODO: Add support for other offloading programming models here.983//984}985986static void appendOneArg(InputArgList &Args, const Arg *Opt,987const Arg *BaseArg) {988// The args for config files or /clang: flags belong to different InputArgList989// objects than Args. This copies an Arg from one of those other InputArgLists990// to the ownership of Args.991unsigned Index = Args.MakeIndex(Opt->getSpelling());992Arg *Copy = new llvm::opt::Arg(Opt->getOption(), Args.getArgString(Index),993Index, BaseArg);994Copy->getValues() = Opt->getValues();995if (Opt->isClaimed())996Copy->claim();997Copy->setOwnsValues(Opt->getOwnsValues());998Opt->setOwnsValues(false);999Args.append(Copy);1000}10011002bool Driver::readConfigFile(StringRef FileName,1003llvm::cl::ExpansionContext &ExpCtx) {1004// Try opening the given file.1005auto Status = getVFS().status(FileName);1006if (!Status) {1007Diag(diag::err_drv_cannot_open_config_file)1008<< FileName << Status.getError().message();1009return true;1010}1011if (Status->getType() != llvm::sys::fs::file_type::regular_file) {1012Diag(diag::err_drv_cannot_open_config_file)1013<< FileName << "not a regular file";1014return true;1015}10161017// Try reading the given file.1018SmallVector<const char *, 32> NewCfgArgs;1019if (llvm::Error Err = ExpCtx.readConfigFile(FileName, NewCfgArgs)) {1020Diag(diag::err_drv_cannot_read_config_file)1021<< FileName << toString(std::move(Err));1022return true;1023}10241025// Read options from config file.1026llvm::SmallString<128> CfgFileName(FileName);1027llvm::sys::path::native(CfgFileName);1028bool ContainErrors;1029std::unique_ptr<InputArgList> NewOptions = std::make_unique<InputArgList>(1030ParseArgStrings(NewCfgArgs, /*UseDriverMode=*/true, ContainErrors));1031if (ContainErrors)1032return true;10331034// Claim all arguments that come from a configuration file so that the driver1035// does not warn on any that is unused.1036for (Arg *A : *NewOptions)1037A->claim();10381039if (!CfgOptions)1040CfgOptions = std::move(NewOptions);1041else {1042// If this is a subsequent config file, append options to the previous one.1043for (auto *Opt : *NewOptions) {1044const Arg *BaseArg = &Opt->getBaseArg();1045if (BaseArg == Opt)1046BaseArg = nullptr;1047appendOneArg(*CfgOptions, Opt, BaseArg);1048}1049}1050ConfigFiles.push_back(std::string(CfgFileName));1051return false;1052}10531054bool Driver::loadConfigFiles() {1055llvm::cl::ExpansionContext ExpCtx(Saver.getAllocator(),1056llvm::cl::tokenizeConfigFile);1057ExpCtx.setVFS(&getVFS());10581059// Process options that change search path for config files.1060if (CLOptions) {1061if (CLOptions->hasArg(options::OPT_config_system_dir_EQ)) {1062SmallString<128> CfgDir;1063CfgDir.append(1064CLOptions->getLastArgValue(options::OPT_config_system_dir_EQ));1065if (CfgDir.empty() || getVFS().makeAbsolute(CfgDir))1066SystemConfigDir.clear();1067else1068SystemConfigDir = static_cast<std::string>(CfgDir);1069}1070if (CLOptions->hasArg(options::OPT_config_user_dir_EQ)) {1071SmallString<128> CfgDir;1072llvm::sys::fs::expand_tilde(1073CLOptions->getLastArgValue(options::OPT_config_user_dir_EQ), CfgDir);1074if (CfgDir.empty() || getVFS().makeAbsolute(CfgDir))1075UserConfigDir.clear();1076else1077UserConfigDir = static_cast<std::string>(CfgDir);1078}1079}10801081// Prepare list of directories where config file is searched for.1082StringRef CfgFileSearchDirs[] = {UserConfigDir, SystemConfigDir, Dir};1083ExpCtx.setSearchDirs(CfgFileSearchDirs);10841085// First try to load configuration from the default files, return on error.1086if (loadDefaultConfigFiles(ExpCtx))1087return true;10881089// Then load configuration files specified explicitly.1090SmallString<128> CfgFilePath;1091if (CLOptions) {1092for (auto CfgFileName : CLOptions->getAllArgValues(options::OPT_config)) {1093// If argument contains directory separator, treat it as a path to1094// configuration file.1095if (llvm::sys::path::has_parent_path(CfgFileName)) {1096CfgFilePath.assign(CfgFileName);1097if (llvm::sys::path::is_relative(CfgFilePath)) {1098if (getVFS().makeAbsolute(CfgFilePath)) {1099Diag(diag::err_drv_cannot_open_config_file)1100<< CfgFilePath << "cannot get absolute path";1101return true;1102}1103}1104} else if (!ExpCtx.findConfigFile(CfgFileName, CfgFilePath)) {1105// Report an error that the config file could not be found.1106Diag(diag::err_drv_config_file_not_found) << CfgFileName;1107for (const StringRef &SearchDir : CfgFileSearchDirs)1108if (!SearchDir.empty())1109Diag(diag::note_drv_config_file_searched_in) << SearchDir;1110return true;1111}11121113// Try to read the config file, return on error.1114if (readConfigFile(CfgFilePath, ExpCtx))1115return true;1116}1117}11181119// No error occurred.1120return false;1121}11221123bool Driver::loadDefaultConfigFiles(llvm::cl::ExpansionContext &ExpCtx) {1124// Disable default config if CLANG_NO_DEFAULT_CONFIG is set to a non-empty1125// value.1126if (const char *NoConfigEnv = ::getenv("CLANG_NO_DEFAULT_CONFIG")) {1127if (*NoConfigEnv)1128return false;1129}1130if (CLOptions && CLOptions->hasArg(options::OPT_no_default_config))1131return false;11321133std::string RealMode = getExecutableForDriverMode(Mode);1134std::string Triple;11351136// If name prefix is present, no --target= override was passed via CLOptions1137// and the name prefix is not a valid triple, force it for backwards1138// compatibility.1139if (!ClangNameParts.TargetPrefix.empty() &&1140computeTargetTriple(*this, "/invalid/", *CLOptions).str() ==1141"/invalid/") {1142llvm::Triple PrefixTriple{ClangNameParts.TargetPrefix};1143if (PrefixTriple.getArch() == llvm::Triple::UnknownArch ||1144PrefixTriple.isOSUnknown())1145Triple = PrefixTriple.str();1146}11471148// Otherwise, use the real triple as used by the driver.1149if (Triple.empty()) {1150llvm::Triple RealTriple =1151computeTargetTriple(*this, TargetTriple, *CLOptions);1152Triple = RealTriple.str();1153assert(!Triple.empty());1154}11551156// Search for config files in the following order:1157// 1. <triple>-<mode>.cfg using real driver mode1158// (e.g. i386-pc-linux-gnu-clang++.cfg).1159// 2. <triple>-<mode>.cfg using executable suffix1160// (e.g. i386-pc-linux-gnu-clang-g++.cfg for *clang-g++).1161// 3. <triple>.cfg + <mode>.cfg using real driver mode1162// (e.g. i386-pc-linux-gnu.cfg + clang++.cfg).1163// 4. <triple>.cfg + <mode>.cfg using executable suffix1164// (e.g. i386-pc-linux-gnu.cfg + clang-g++.cfg for *clang-g++).11651166// Try loading <triple>-<mode>.cfg, and return if we find a match.1167SmallString<128> CfgFilePath;1168std::string CfgFileName = Triple + '-' + RealMode + ".cfg";1169if (ExpCtx.findConfigFile(CfgFileName, CfgFilePath))1170return readConfigFile(CfgFilePath, ExpCtx);11711172bool TryModeSuffix = !ClangNameParts.ModeSuffix.empty() &&1173ClangNameParts.ModeSuffix != RealMode;1174if (TryModeSuffix) {1175CfgFileName = Triple + '-' + ClangNameParts.ModeSuffix + ".cfg";1176if (ExpCtx.findConfigFile(CfgFileName, CfgFilePath))1177return readConfigFile(CfgFilePath, ExpCtx);1178}11791180// Try loading <mode>.cfg, and return if loading failed. If a matching file1181// was not found, still proceed on to try <triple>.cfg.1182CfgFileName = RealMode + ".cfg";1183if (ExpCtx.findConfigFile(CfgFileName, CfgFilePath)) {1184if (readConfigFile(CfgFilePath, ExpCtx))1185return true;1186} else if (TryModeSuffix) {1187CfgFileName = ClangNameParts.ModeSuffix + ".cfg";1188if (ExpCtx.findConfigFile(CfgFileName, CfgFilePath) &&1189readConfigFile(CfgFilePath, ExpCtx))1190return true;1191}11921193// Try loading <triple>.cfg and return if we find a match.1194CfgFileName = Triple + ".cfg";1195if (ExpCtx.findConfigFile(CfgFileName, CfgFilePath))1196return readConfigFile(CfgFilePath, ExpCtx);11971198// If we were unable to find a config file deduced from executable name,1199// that is not an error.1200return false;1201}12021203Compilation *Driver::BuildCompilation(ArrayRef<const char *> ArgList) {1204llvm::PrettyStackTraceString CrashInfo("Compilation construction");12051206// FIXME: Handle environment options which affect driver behavior, somewhere1207// (client?). GCC_EXEC_PREFIX, LPATH, CC_PRINT_OPTIONS.12081209// We look for the driver mode option early, because the mode can affect1210// how other options are parsed.12111212auto DriverMode = getDriverMode(ClangExecutable, ArgList.slice(1));1213if (!DriverMode.empty())1214setDriverMode(DriverMode);12151216// FIXME: What are we going to do with -V and -b?12171218// Arguments specified in command line.1219bool ContainsError;1220CLOptions = std::make_unique<InputArgList>(1221ParseArgStrings(ArgList.slice(1), /*UseDriverMode=*/true, ContainsError));12221223// Try parsing configuration file.1224if (!ContainsError)1225ContainsError = loadConfigFiles();1226bool HasConfigFile = !ContainsError && (CfgOptions.get() != nullptr);12271228// All arguments, from both config file and command line.1229InputArgList Args = std::move(HasConfigFile ? std::move(*CfgOptions)1230: std::move(*CLOptions));12311232if (HasConfigFile)1233for (auto *Opt : *CLOptions) {1234if (Opt->getOption().matches(options::OPT_config))1235continue;1236const Arg *BaseArg = &Opt->getBaseArg();1237if (BaseArg == Opt)1238BaseArg = nullptr;1239appendOneArg(Args, Opt, BaseArg);1240}12411242// In CL mode, look for any pass-through arguments1243if (IsCLMode() && !ContainsError) {1244SmallVector<const char *, 16> CLModePassThroughArgList;1245for (const auto *A : Args.filtered(options::OPT__SLASH_clang)) {1246A->claim();1247CLModePassThroughArgList.push_back(A->getValue());1248}12491250if (!CLModePassThroughArgList.empty()) {1251// Parse any pass through args using default clang processing rather1252// than clang-cl processing.1253auto CLModePassThroughOptions = std::make_unique<InputArgList>(1254ParseArgStrings(CLModePassThroughArgList, /*UseDriverMode=*/false,1255ContainsError));12561257if (!ContainsError)1258for (auto *Opt : *CLModePassThroughOptions) {1259appendOneArg(Args, Opt, nullptr);1260}1261}1262}12631264// Check for working directory option before accessing any files1265if (Arg *WD = Args.getLastArg(options::OPT_working_directory))1266if (VFS->setCurrentWorkingDirectory(WD->getValue()))1267Diag(diag::err_drv_unable_to_set_working_directory) << WD->getValue();12681269// Check for missing include directories.1270if (!Diags.isIgnored(diag::warn_missing_include_dirs, SourceLocation())) {1271for (auto IncludeDir : Args.getAllArgValues(options::OPT_I_Group)) {1272if (!VFS->exists(IncludeDir))1273Diag(diag::warn_missing_include_dirs) << IncludeDir;1274}1275}12761277// FIXME: This stuff needs to go into the Compilation, not the driver.1278bool CCCPrintPhases;12791280// -canonical-prefixes, -no-canonical-prefixes are used very early in main.1281Args.ClaimAllArgs(options::OPT_canonical_prefixes);1282Args.ClaimAllArgs(options::OPT_no_canonical_prefixes);12831284// f(no-)integated-cc1 is also used very early in main.1285Args.ClaimAllArgs(options::OPT_fintegrated_cc1);1286Args.ClaimAllArgs(options::OPT_fno_integrated_cc1);12871288// Ignore -pipe.1289Args.ClaimAllArgs(options::OPT_pipe);12901291// Extract -ccc args.1292//1293// FIXME: We need to figure out where this behavior should live. Most of it1294// should be outside in the client; the parts that aren't should have proper1295// options, either by introducing new ones or by overloading gcc ones like -V1296// or -b.1297CCCPrintPhases = Args.hasArg(options::OPT_ccc_print_phases);1298CCCPrintBindings = Args.hasArg(options::OPT_ccc_print_bindings);1299if (const Arg *A = Args.getLastArg(options::OPT_ccc_gcc_name))1300CCCGenericGCCName = A->getValue();13011302// Process -fproc-stat-report options.1303if (const Arg *A = Args.getLastArg(options::OPT_fproc_stat_report_EQ)) {1304CCPrintProcessStats = true;1305CCPrintStatReportFilename = A->getValue();1306}1307if (Args.hasArg(options::OPT_fproc_stat_report))1308CCPrintProcessStats = true;13091310// FIXME: TargetTriple is used by the target-prefixed calls to as/ld1311// and getToolChain is const.1312if (IsCLMode()) {1313// clang-cl targets MSVC-style Win32.1314llvm::Triple T(TargetTriple);1315T.setOS(llvm::Triple::Win32);1316T.setVendor(llvm::Triple::PC);1317T.setEnvironment(llvm::Triple::MSVC);1318T.setObjectFormat(llvm::Triple::COFF);1319if (Args.hasArg(options::OPT__SLASH_arm64EC))1320T.setArch(llvm::Triple::aarch64, llvm::Triple::AArch64SubArch_arm64ec);1321TargetTriple = T.str();1322} else if (IsDXCMode()) {1323// Build TargetTriple from target_profile option for clang-dxc.1324if (const Arg *A = Args.getLastArg(options::OPT_target_profile)) {1325StringRef TargetProfile = A->getValue();1326if (auto Triple =1327toolchains::HLSLToolChain::parseTargetProfile(TargetProfile))1328TargetTriple = *Triple;1329else1330Diag(diag::err_drv_invalid_directx_shader_module) << TargetProfile;13311332A->claim();13331334if (Args.hasArg(options::OPT_spirv)) {1335llvm::Triple T(TargetTriple);1336T.setArch(llvm::Triple::spirv);1337T.setOS(llvm::Triple::Vulkan);13381339// Set specific Vulkan version if applicable.1340if (const Arg *A = Args.getLastArg(options::OPT_fspv_target_env_EQ)) {1341const llvm::StringSet<> ValidValues = {"vulkan1.2", "vulkan1.3"};1342if (ValidValues.contains(A->getValue())) {1343T.setOSName(A->getValue());1344} else {1345Diag(diag::err_drv_invalid_value)1346<< A->getAsString(Args) << A->getValue();1347}1348A->claim();1349}13501351TargetTriple = T.str();1352}1353} else {1354Diag(diag::err_drv_dxc_missing_target_profile);1355}1356}13571358if (const Arg *A = Args.getLastArg(options::OPT_target))1359TargetTriple = A->getValue();1360if (const Arg *A = Args.getLastArg(options::OPT_ccc_install_dir))1361Dir = Dir = A->getValue();1362for (const Arg *A : Args.filtered(options::OPT_B)) {1363A->claim();1364PrefixDirs.push_back(A->getValue(0));1365}1366if (std::optional<std::string> CompilerPathValue =1367llvm::sys::Process::GetEnv("COMPILER_PATH")) {1368StringRef CompilerPath = *CompilerPathValue;1369while (!CompilerPath.empty()) {1370std::pair<StringRef, StringRef> Split =1371CompilerPath.split(llvm::sys::EnvPathSeparator);1372PrefixDirs.push_back(std::string(Split.first));1373CompilerPath = Split.second;1374}1375}1376if (const Arg *A = Args.getLastArg(options::OPT__sysroot_EQ))1377SysRoot = A->getValue();1378if (const Arg *A = Args.getLastArg(options::OPT__dyld_prefix_EQ))1379DyldPrefix = A->getValue();13801381if (const Arg *A = Args.getLastArg(options::OPT_resource_dir))1382ResourceDir = A->getValue();13831384if (const Arg *A = Args.getLastArg(options::OPT_save_temps_EQ)) {1385SaveTemps = llvm::StringSwitch<SaveTempsMode>(A->getValue())1386.Case("cwd", SaveTempsCwd)1387.Case("obj", SaveTempsObj)1388.Default(SaveTempsCwd);1389}13901391if (const Arg *A = Args.getLastArg(options::OPT_offload_host_only,1392options::OPT_offload_device_only,1393options::OPT_offload_host_device)) {1394if (A->getOption().matches(options::OPT_offload_host_only))1395Offload = OffloadHost;1396else if (A->getOption().matches(options::OPT_offload_device_only))1397Offload = OffloadDevice;1398else1399Offload = OffloadHostDevice;1400}14011402setLTOMode(Args);14031404// Process -fembed-bitcode= flags.1405if (Arg *A = Args.getLastArg(options::OPT_fembed_bitcode_EQ)) {1406StringRef Name = A->getValue();1407unsigned Model = llvm::StringSwitch<unsigned>(Name)1408.Case("off", EmbedNone)1409.Case("all", EmbedBitcode)1410.Case("bitcode", EmbedBitcode)1411.Case("marker", EmbedMarker)1412.Default(~0U);1413if (Model == ~0U) {1414Diags.Report(diag::err_drv_invalid_value) << A->getAsString(Args)1415<< Name;1416} else1417BitcodeEmbed = static_cast<BitcodeEmbedMode>(Model);1418}14191420// Remove existing compilation database so that each job can append to it.1421if (Arg *A = Args.getLastArg(options::OPT_MJ))1422llvm::sys::fs::remove(A->getValue());14231424// Setting up the jobs for some precompile cases depends on whether we are1425// treating them as PCH, implicit modules or C++20 ones.1426// TODO: inferring the mode like this seems fragile (it meets the objective1427// of not requiring anything new for operation, however).1428const Arg *Std = Args.getLastArg(options::OPT_std_EQ);1429ModulesModeCXX20 =1430!Args.hasArg(options::OPT_fmodules) && Std &&1431(Std->containsValue("c++20") || Std->containsValue("c++2a") ||1432Std->containsValue("c++23") || Std->containsValue("c++2b") ||1433Std->containsValue("c++26") || Std->containsValue("c++2c") ||1434Std->containsValue("c++latest"));14351436// Process -fmodule-header{=} flags.1437if (Arg *A = Args.getLastArg(options::OPT_fmodule_header_EQ,1438options::OPT_fmodule_header)) {1439// These flags force C++20 handling of headers.1440ModulesModeCXX20 = true;1441if (A->getOption().matches(options::OPT_fmodule_header))1442CXX20HeaderType = HeaderMode_Default;1443else {1444StringRef ArgName = A->getValue();1445unsigned Kind = llvm::StringSwitch<unsigned>(ArgName)1446.Case("user", HeaderMode_User)1447.Case("system", HeaderMode_System)1448.Default(~0U);1449if (Kind == ~0U) {1450Diags.Report(diag::err_drv_invalid_value)1451<< A->getAsString(Args) << ArgName;1452} else1453CXX20HeaderType = static_cast<ModuleHeaderMode>(Kind);1454}1455}14561457std::unique_ptr<llvm::opt::InputArgList> UArgs =1458std::make_unique<InputArgList>(std::move(Args));14591460// Perform the default argument translations.1461DerivedArgList *TranslatedArgs = TranslateInputArgs(*UArgs);14621463// Owned by the host.1464const ToolChain &TC = getToolChain(1465*UArgs, computeTargetTriple(*this, TargetTriple, *UArgs));14661467// Check if the environment version is valid except wasm case.1468llvm::Triple Triple = TC.getTriple();1469if (!Triple.isWasm()) {1470StringRef TripleVersionName = Triple.getEnvironmentVersionString();1471StringRef TripleObjectFormat =1472Triple.getObjectFormatTypeName(Triple.getObjectFormat());1473if (Triple.getEnvironmentVersion().empty() && TripleVersionName != "" &&1474TripleVersionName != TripleObjectFormat) {1475Diags.Report(diag::err_drv_triple_version_invalid)1476<< TripleVersionName << TC.getTripleString();1477ContainsError = true;1478}1479}14801481// Report warning when arm64EC option is overridden by specified target1482if ((TC.getTriple().getArch() != llvm::Triple::aarch64 ||1483TC.getTriple().getSubArch() != llvm::Triple::AArch64SubArch_arm64ec) &&1484UArgs->hasArg(options::OPT__SLASH_arm64EC)) {1485getDiags().Report(clang::diag::warn_target_override_arm64ec)1486<< TC.getTriple().str();1487}14881489// A common user mistake is specifying a target of aarch64-none-eabi or1490// arm-none-elf whereas the correct names are aarch64-none-elf &1491// arm-none-eabi. Detect these cases and issue a warning.1492if (TC.getTriple().getOS() == llvm::Triple::UnknownOS &&1493TC.getTriple().getVendor() == llvm::Triple::UnknownVendor) {1494switch (TC.getTriple().getArch()) {1495case llvm::Triple::arm:1496case llvm::Triple::armeb:1497case llvm::Triple::thumb:1498case llvm::Triple::thumbeb:1499if (TC.getTriple().getEnvironmentName() == "elf") {1500Diag(diag::warn_target_unrecognized_env)1501<< TargetTriple1502<< (TC.getTriple().getArchName().str() + "-none-eabi");1503}1504break;1505case llvm::Triple::aarch64:1506case llvm::Triple::aarch64_be:1507case llvm::Triple::aarch64_32:1508if (TC.getTriple().getEnvironmentName().starts_with("eabi")) {1509Diag(diag::warn_target_unrecognized_env)1510<< TargetTriple1511<< (TC.getTriple().getArchName().str() + "-none-elf");1512}1513break;1514default:1515break;1516}1517}15181519// The compilation takes ownership of Args.1520Compilation *C = new Compilation(*this, TC, UArgs.release(), TranslatedArgs,1521ContainsError);15221523if (!HandleImmediateArgs(*C))1524return C;15251526// Construct the list of inputs.1527InputList Inputs;1528BuildInputs(C->getDefaultToolChain(), *TranslatedArgs, Inputs);15291530// Populate the tool chains for the offloading devices, if any.1531CreateOffloadingDeviceToolChains(*C, Inputs);15321533// Construct the list of abstract actions to perform for this compilation. On1534// MachO targets this uses the driver-driver and universal actions.1535if (TC.getTriple().isOSBinFormatMachO())1536BuildUniversalActions(*C, C->getDefaultToolChain(), Inputs);1537else1538BuildActions(*C, C->getArgs(), Inputs, C->getActions());15391540if (CCCPrintPhases) {1541PrintActions(*C);1542return C;1543}15441545BuildJobs(*C);15461547return C;1548}15491550static void printArgList(raw_ostream &OS, const llvm::opt::ArgList &Args) {1551llvm::opt::ArgStringList ASL;1552for (const auto *A : Args) {1553// Use user's original spelling of flags. For example, use1554// `/source-charset:utf-8` instead of `-finput-charset=utf-8` if the user1555// wrote the former.1556while (A->getAlias())1557A = A->getAlias();1558A->render(Args, ASL);1559}15601561for (auto I = ASL.begin(), E = ASL.end(); I != E; ++I) {1562if (I != ASL.begin())1563OS << ' ';1564llvm::sys::printArg(OS, *I, true);1565}1566OS << '\n';1567}15681569bool Driver::getCrashDiagnosticFile(StringRef ReproCrashFilename,1570SmallString<128> &CrashDiagDir) {1571using namespace llvm::sys;1572assert(llvm::Triple(llvm::sys::getProcessTriple()).isOSDarwin() &&1573"Only knows about .crash files on Darwin");15741575// The .crash file can be found on at ~/Library/Logs/DiagnosticReports/1576// (or /Library/Logs/DiagnosticReports for root) and has the filename pattern1577// clang-<VERSION>_<YYYY-MM-DD-HHMMSS>_<hostname>.crash.1578path::home_directory(CrashDiagDir);1579if (CrashDiagDir.starts_with("/var/root"))1580CrashDiagDir = "/";1581path::append(CrashDiagDir, "Library/Logs/DiagnosticReports");1582int PID =1583#if LLVM_ON_UNIX1584getpid();1585#else15860;1587#endif1588std::error_code EC;1589fs::file_status FileStatus;1590TimePoint<> LastAccessTime;1591SmallString<128> CrashFilePath;1592// Lookup the .crash files and get the one generated by a subprocess spawned1593// by this driver invocation.1594for (fs::directory_iterator File(CrashDiagDir, EC), FileEnd;1595File != FileEnd && !EC; File.increment(EC)) {1596StringRef FileName = path::filename(File->path());1597if (!FileName.starts_with(Name))1598continue;1599if (fs::status(File->path(), FileStatus))1600continue;1601llvm::ErrorOr<std::unique_ptr<llvm::MemoryBuffer>> CrashFile =1602llvm::MemoryBuffer::getFile(File->path());1603if (!CrashFile)1604continue;1605// The first line should start with "Process:", otherwise this isn't a real1606// .crash file.1607StringRef Data = CrashFile.get()->getBuffer();1608if (!Data.starts_with("Process:"))1609continue;1610// Parse parent process pid line, e.g: "Parent Process: clang-4.0 [79141]"1611size_t ParentProcPos = Data.find("Parent Process:");1612if (ParentProcPos == StringRef::npos)1613continue;1614size_t LineEnd = Data.find_first_of("\n", ParentProcPos);1615if (LineEnd == StringRef::npos)1616continue;1617StringRef ParentProcess = Data.slice(ParentProcPos+15, LineEnd).trim();1618int OpenBracket = -1, CloseBracket = -1;1619for (size_t i = 0, e = ParentProcess.size(); i < e; ++i) {1620if (ParentProcess[i] == '[')1621OpenBracket = i;1622if (ParentProcess[i] == ']')1623CloseBracket = i;1624}1625// Extract the parent process PID from the .crash file and check whether1626// it matches this driver invocation pid.1627int CrashPID;1628if (OpenBracket < 0 || CloseBracket < 0 ||1629ParentProcess.slice(OpenBracket + 1, CloseBracket)1630.getAsInteger(10, CrashPID) || CrashPID != PID) {1631continue;1632}16331634// Found a .crash file matching the driver pid. To avoid getting an older1635// and misleading crash file, continue looking for the most recent.1636// FIXME: the driver can dispatch multiple cc1 invocations, leading to1637// multiple crashes poiting to the same parent process. Since the driver1638// does not collect pid information for the dispatched invocation there's1639// currently no way to distinguish among them.1640const auto FileAccessTime = FileStatus.getLastModificationTime();1641if (FileAccessTime > LastAccessTime) {1642CrashFilePath.assign(File->path());1643LastAccessTime = FileAccessTime;1644}1645}16461647// If found, copy it over to the location of other reproducer files.1648if (!CrashFilePath.empty()) {1649EC = fs::copy_file(CrashFilePath, ReproCrashFilename);1650if (EC)1651return false;1652return true;1653}16541655return false;1656}16571658static const char BugReporMsg[] =1659"\n********************\n\n"1660"PLEASE ATTACH THE FOLLOWING FILES TO THE BUG REPORT:\n"1661"Preprocessed source(s) and associated run script(s) are located at:";16621663// When clang crashes, produce diagnostic information including the fully1664// preprocessed source file(s). Request that the developer attach the1665// diagnostic information to a bug report.1666void Driver::generateCompilationDiagnostics(1667Compilation &C, const Command &FailingCommand,1668StringRef AdditionalInformation, CompilationDiagnosticReport *Report) {1669if (C.getArgs().hasArg(options::OPT_fno_crash_diagnostics))1670return;16711672unsigned Level = 1;1673if (Arg *A = C.getArgs().getLastArg(options::OPT_fcrash_diagnostics_EQ)) {1674Level = llvm::StringSwitch<unsigned>(A->getValue())1675.Case("off", 0)1676.Case("compiler", 1)1677.Case("all", 2)1678.Default(1);1679}1680if (!Level)1681return;16821683// Don't try to generate diagnostics for dsymutil jobs.1684if (FailingCommand.getCreator().isDsymutilJob())1685return;16861687bool IsLLD = false;1688ArgStringList SavedTemps;1689if (FailingCommand.getCreator().isLinkJob()) {1690C.getDefaultToolChain().GetLinkerPath(&IsLLD);1691if (!IsLLD || Level < 2)1692return;16931694// If lld crashed, we will re-run the same command with the input it used1695// to have. In that case we should not remove temp files in1696// initCompilationForDiagnostics yet. They will be added back and removed1697// later.1698SavedTemps = std::move(C.getTempFiles());1699assert(!C.getTempFiles().size());1700}17011702// Print the version of the compiler.1703PrintVersion(C, llvm::errs());17041705// Suppress driver output and emit preprocessor output to temp file.1706CCGenDiagnostics = true;17071708// Save the original job command(s).1709Command Cmd = FailingCommand;17101711// Keep track of whether we produce any errors while trying to produce1712// preprocessed sources.1713DiagnosticErrorTrap Trap(Diags);17141715// Suppress tool output.1716C.initCompilationForDiagnostics();17171718// If lld failed, rerun it again with --reproduce.1719if (IsLLD) {1720const char *TmpName = CreateTempFile(C, "linker-crash", "tar");1721Command NewLLDInvocation = Cmd;1722llvm::opt::ArgStringList ArgList = NewLLDInvocation.getArguments();1723StringRef ReproduceOption =1724C.getDefaultToolChain().getTriple().isWindowsMSVCEnvironment()1725? "/reproduce:"1726: "--reproduce=";1727ArgList.push_back(Saver.save(Twine(ReproduceOption) + TmpName).data());1728NewLLDInvocation.replaceArguments(std::move(ArgList));17291730// Redirect stdout/stderr to /dev/null.1731NewLLDInvocation.Execute({std::nullopt, {""}, {""}}, nullptr, nullptr);1732Diag(clang::diag::note_drv_command_failed_diag_msg) << BugReporMsg;1733Diag(clang::diag::note_drv_command_failed_diag_msg) << TmpName;1734Diag(clang::diag::note_drv_command_failed_diag_msg)1735<< "\n\n********************";1736if (Report)1737Report->TemporaryFiles.push_back(TmpName);1738return;1739}17401741// Construct the list of inputs.1742InputList Inputs;1743BuildInputs(C.getDefaultToolChain(), C.getArgs(), Inputs);17441745for (InputList::iterator it = Inputs.begin(), ie = Inputs.end(); it != ie;) {1746bool IgnoreInput = false;17471748// Ignore input from stdin or any inputs that cannot be preprocessed.1749// Check type first as not all linker inputs have a value.1750if (types::getPreprocessedType(it->first) == types::TY_INVALID) {1751IgnoreInput = true;1752} else if (!strcmp(it->second->getValue(), "-")) {1753Diag(clang::diag::note_drv_command_failed_diag_msg)1754<< "Error generating preprocessed source(s) - "1755"ignoring input from stdin.";1756IgnoreInput = true;1757}17581759if (IgnoreInput) {1760it = Inputs.erase(it);1761ie = Inputs.end();1762} else {1763++it;1764}1765}17661767if (Inputs.empty()) {1768Diag(clang::diag::note_drv_command_failed_diag_msg)1769<< "Error generating preprocessed source(s) - "1770"no preprocessable inputs.";1771return;1772}17731774// Don't attempt to generate preprocessed files if multiple -arch options are1775// used, unless they're all duplicates.1776llvm::StringSet<> ArchNames;1777for (const Arg *A : C.getArgs()) {1778if (A->getOption().matches(options::OPT_arch)) {1779StringRef ArchName = A->getValue();1780ArchNames.insert(ArchName);1781}1782}1783if (ArchNames.size() > 1) {1784Diag(clang::diag::note_drv_command_failed_diag_msg)1785<< "Error generating preprocessed source(s) - cannot generate "1786"preprocessed source with multiple -arch options.";1787return;1788}17891790// Construct the list of abstract actions to perform for this compilation. On1791// Darwin OSes this uses the driver-driver and builds universal actions.1792const ToolChain &TC = C.getDefaultToolChain();1793if (TC.getTriple().isOSBinFormatMachO())1794BuildUniversalActions(C, TC, Inputs);1795else1796BuildActions(C, C.getArgs(), Inputs, C.getActions());17971798BuildJobs(C);17991800// If there were errors building the compilation, quit now.1801if (Trap.hasErrorOccurred()) {1802Diag(clang::diag::note_drv_command_failed_diag_msg)1803<< "Error generating preprocessed source(s).";1804return;1805}18061807// Generate preprocessed output.1808SmallVector<std::pair<int, const Command *>, 4> FailingCommands;1809C.ExecuteJobs(C.getJobs(), FailingCommands);18101811// If any of the preprocessing commands failed, clean up and exit.1812if (!FailingCommands.empty()) {1813Diag(clang::diag::note_drv_command_failed_diag_msg)1814<< "Error generating preprocessed source(s).";1815return;1816}18171818const ArgStringList &TempFiles = C.getTempFiles();1819if (TempFiles.empty()) {1820Diag(clang::diag::note_drv_command_failed_diag_msg)1821<< "Error generating preprocessed source(s).";1822return;1823}18241825Diag(clang::diag::note_drv_command_failed_diag_msg) << BugReporMsg;18261827SmallString<128> VFS;1828SmallString<128> ReproCrashFilename;1829for (const char *TempFile : TempFiles) {1830Diag(clang::diag::note_drv_command_failed_diag_msg) << TempFile;1831if (Report)1832Report->TemporaryFiles.push_back(TempFile);1833if (ReproCrashFilename.empty()) {1834ReproCrashFilename = TempFile;1835llvm::sys::path::replace_extension(ReproCrashFilename, ".crash");1836}1837if (StringRef(TempFile).ends_with(".cache")) {1838// In some cases (modules) we'll dump extra data to help with reproducing1839// the crash into a directory next to the output.1840VFS = llvm::sys::path::filename(TempFile);1841llvm::sys::path::append(VFS, "vfs", "vfs.yaml");1842}1843}18441845for (const char *TempFile : SavedTemps)1846C.addTempFile(TempFile);18471848// Assume associated files are based off of the first temporary file.1849CrashReportInfo CrashInfo(TempFiles[0], VFS);18501851llvm::SmallString<128> Script(CrashInfo.Filename);1852llvm::sys::path::replace_extension(Script, "sh");1853std::error_code EC;1854llvm::raw_fd_ostream ScriptOS(Script, EC, llvm::sys::fs::CD_CreateNew,1855llvm::sys::fs::FA_Write,1856llvm::sys::fs::OF_Text);1857if (EC) {1858Diag(clang::diag::note_drv_command_failed_diag_msg)1859<< "Error generating run script: " << Script << " " << EC.message();1860} else {1861ScriptOS << "# Crash reproducer for " << getClangFullVersion() << "\n"1862<< "# Driver args: ";1863printArgList(ScriptOS, C.getInputArgs());1864ScriptOS << "# Original command: ";1865Cmd.Print(ScriptOS, "\n", /*Quote=*/true);1866Cmd.Print(ScriptOS, "\n", /*Quote=*/true, &CrashInfo);1867if (!AdditionalInformation.empty())1868ScriptOS << "\n# Additional information: " << AdditionalInformation1869<< "\n";1870if (Report)1871Report->TemporaryFiles.push_back(std::string(Script));1872Diag(clang::diag::note_drv_command_failed_diag_msg) << Script;1873}18741875// On darwin, provide information about the .crash diagnostic report.1876if (llvm::Triple(llvm::sys::getProcessTriple()).isOSDarwin()) {1877SmallString<128> CrashDiagDir;1878if (getCrashDiagnosticFile(ReproCrashFilename, CrashDiagDir)) {1879Diag(clang::diag::note_drv_command_failed_diag_msg)1880<< ReproCrashFilename.str();1881} else { // Suggest a directory for the user to look for .crash files.1882llvm::sys::path::append(CrashDiagDir, Name);1883CrashDiagDir += "_<YYYY-MM-DD-HHMMSS>_<hostname>.crash";1884Diag(clang::diag::note_drv_command_failed_diag_msg)1885<< "Crash backtrace is located in";1886Diag(clang::diag::note_drv_command_failed_diag_msg)1887<< CrashDiagDir.str();1888Diag(clang::diag::note_drv_command_failed_diag_msg)1889<< "(choose the .crash file that corresponds to your crash)";1890}1891}18921893Diag(clang::diag::note_drv_command_failed_diag_msg)1894<< "\n\n********************";1895}18961897void Driver::setUpResponseFiles(Compilation &C, Command &Cmd) {1898// Since commandLineFitsWithinSystemLimits() may underestimate system's1899// capacity if the tool does not support response files, there is a chance/1900// that things will just work without a response file, so we silently just1901// skip it.1902if (Cmd.getResponseFileSupport().ResponseKind ==1903ResponseFileSupport::RF_None ||1904llvm::sys::commandLineFitsWithinSystemLimits(Cmd.getExecutable(),1905Cmd.getArguments()))1906return;19071908std::string TmpName = GetTemporaryPath("response", "txt");1909Cmd.setResponseFile(C.addTempFile(C.getArgs().MakeArgString(TmpName)));1910}19111912int Driver::ExecuteCompilation(1913Compilation &C,1914SmallVectorImpl<std::pair<int, const Command *>> &FailingCommands) {1915if (C.getArgs().hasArg(options::OPT_fdriver_only)) {1916if (C.getArgs().hasArg(options::OPT_v))1917C.getJobs().Print(llvm::errs(), "\n", true);19181919C.ExecuteJobs(C.getJobs(), FailingCommands, /*LogOnly=*/true);19201921// If there were errors building the compilation, quit now.1922if (!FailingCommands.empty() || Diags.hasErrorOccurred())1923return 1;19241925return 0;1926}19271928// Just print if -### was present.1929if (C.getArgs().hasArg(options::OPT__HASH_HASH_HASH)) {1930C.getJobs().Print(llvm::errs(), "\n", true);1931return Diags.hasErrorOccurred() ? 1 : 0;1932}19331934// If there were errors building the compilation, quit now.1935if (Diags.hasErrorOccurred())1936return 1;19371938// Set up response file names for each command, if necessary.1939for (auto &Job : C.getJobs())1940setUpResponseFiles(C, Job);19411942C.ExecuteJobs(C.getJobs(), FailingCommands);19431944// If the command succeeded, we are done.1945if (FailingCommands.empty())1946return 0;19471948// Otherwise, remove result files and print extra information about abnormal1949// failures.1950int Res = 0;1951for (const auto &CmdPair : FailingCommands) {1952int CommandRes = CmdPair.first;1953const Command *FailingCommand = CmdPair.second;19541955// Remove result files if we're not saving temps.1956if (!isSaveTempsEnabled()) {1957const JobAction *JA = cast<JobAction>(&FailingCommand->getSource());1958C.CleanupFileMap(C.getResultFiles(), JA, true);19591960// Failure result files are valid unless we crashed.1961if (CommandRes < 0)1962C.CleanupFileMap(C.getFailureResultFiles(), JA, true);1963}19641965// llvm/lib/Support/*/Signals.inc will exit with a special return code1966// for SIGPIPE. Do not print diagnostics for this case.1967if (CommandRes == EX_IOERR) {1968Res = CommandRes;1969continue;1970}19711972// Print extra information about abnormal failures, if possible.1973//1974// This is ad-hoc, but we don't want to be excessively noisy. If the result1975// status was 1, assume the command failed normally. In particular, if it1976// was the compiler then assume it gave a reasonable error code. Failures1977// in other tools are less common, and they generally have worse1978// diagnostics, so always print the diagnostic there.1979const Tool &FailingTool = FailingCommand->getCreator();19801981if (!FailingCommand->getCreator().hasGoodDiagnostics() || CommandRes != 1) {1982// FIXME: See FIXME above regarding result code interpretation.1983if (CommandRes < 0)1984Diag(clang::diag::err_drv_command_signalled)1985<< FailingTool.getShortName();1986else1987Diag(clang::diag::err_drv_command_failed)1988<< FailingTool.getShortName() << CommandRes;1989}1990}1991return Res;1992}19931994void Driver::PrintHelp(bool ShowHidden) const {1995llvm::opt::Visibility VisibilityMask = getOptionVisibilityMask();19961997std::string Usage = llvm::formatv("{0} [options] file...", Name).str();1998getOpts().printHelp(llvm::outs(), Usage.c_str(), DriverTitle.c_str(),1999ShowHidden, /*ShowAllAliases=*/false,2000VisibilityMask);2001}20022003void Driver::PrintVersion(const Compilation &C, raw_ostream &OS) const {2004if (IsFlangMode()) {2005OS << getClangToolFullVersion("flang-new") << '\n';2006} else {2007// FIXME: The following handlers should use a callback mechanism, we don't2008// know what the client would like to do.2009OS << getClangFullVersion() << '\n';2010}2011const ToolChain &TC = C.getDefaultToolChain();2012OS << "Target: " << TC.getTripleString() << '\n';20132014// Print the threading model.2015if (Arg *A = C.getArgs().getLastArg(options::OPT_mthread_model)) {2016// Don't print if the ToolChain would have barfed on it already2017if (TC.isThreadModelSupported(A->getValue()))2018OS << "Thread model: " << A->getValue();2019} else2020OS << "Thread model: " << TC.getThreadModel();2021OS << '\n';20222023// Print out the install directory.2024OS << "InstalledDir: " << Dir << '\n';20252026// Print the build config if it's non-default.2027// Intended to help LLVM developers understand the configs of compilers2028// they're investigating.2029if (!llvm::cl::getCompilerBuildConfig().empty())2030llvm::cl::printBuildConfig(OS);20312032// If configuration files were used, print their paths.2033for (auto ConfigFile : ConfigFiles)2034OS << "Configuration file: " << ConfigFile << '\n';2035}20362037/// PrintDiagnosticCategories - Implement the --print-diagnostic-categories2038/// option.2039static void PrintDiagnosticCategories(raw_ostream &OS) {2040// Skip the empty category.2041for (unsigned i = 1, max = DiagnosticIDs::getNumberOfCategories(); i != max;2042++i)2043OS << i << ',' << DiagnosticIDs::getCategoryNameFromID(i) << '\n';2044}20452046void Driver::HandleAutocompletions(StringRef PassedFlags) const {2047if (PassedFlags == "")2048return;2049// Print out all options that start with a given argument. This is used for2050// shell autocompletion.2051std::vector<std::string> SuggestedCompletions;2052std::vector<std::string> Flags;20532054llvm::opt::Visibility VisibilityMask(options::ClangOption);20552056// Make sure that Flang-only options don't pollute the Clang output2057// TODO: Make sure that Clang-only options don't pollute Flang output2058if (IsFlangMode())2059VisibilityMask = llvm::opt::Visibility(options::FlangOption);20602061// Distinguish "--autocomplete=-someflag" and "--autocomplete=-someflag,"2062// because the latter indicates that the user put space before pushing tab2063// which should end up in a file completion.2064const bool HasSpace = PassedFlags.ends_with(",");20652066// Parse PassedFlags by "," as all the command-line flags are passed to this2067// function separated by ","2068StringRef TargetFlags = PassedFlags;2069while (TargetFlags != "") {2070StringRef CurFlag;2071std::tie(CurFlag, TargetFlags) = TargetFlags.split(",");2072Flags.push_back(std::string(CurFlag));2073}20742075// We want to show cc1-only options only when clang is invoked with -cc1 or2076// -Xclang.2077if (llvm::is_contained(Flags, "-Xclang") || llvm::is_contained(Flags, "-cc1"))2078VisibilityMask = llvm::opt::Visibility(options::CC1Option);20792080const llvm::opt::OptTable &Opts = getOpts();2081StringRef Cur;2082Cur = Flags.at(Flags.size() - 1);2083StringRef Prev;2084if (Flags.size() >= 2) {2085Prev = Flags.at(Flags.size() - 2);2086SuggestedCompletions = Opts.suggestValueCompletions(Prev, Cur);2087}20882089if (SuggestedCompletions.empty())2090SuggestedCompletions = Opts.suggestValueCompletions(Cur, "");20912092// If Flags were empty, it means the user typed `clang [tab]` where we should2093// list all possible flags. If there was no value completion and the user2094// pressed tab after a space, we should fall back to a file completion.2095// We're printing a newline to be consistent with what we print at the end of2096// this function.2097if (SuggestedCompletions.empty() && HasSpace && !Flags.empty()) {2098llvm::outs() << '\n';2099return;2100}21012102// When flag ends with '=' and there was no value completion, return empty2103// string and fall back to the file autocompletion.2104if (SuggestedCompletions.empty() && !Cur.ends_with("=")) {2105// If the flag is in the form of "--autocomplete=-foo",2106// we were requested to print out all option names that start with "-foo".2107// For example, "--autocomplete=-fsyn" is expanded to "-fsyntax-only".2108SuggestedCompletions = Opts.findByPrefix(2109Cur, VisibilityMask,2110/*DisableFlags=*/options::Unsupported | options::Ignored);21112112// We have to query the -W flags manually as they're not in the OptTable.2113// TODO: Find a good way to add them to OptTable instead and them remove2114// this code.2115for (StringRef S : DiagnosticIDs::getDiagnosticFlags())2116if (S.starts_with(Cur))2117SuggestedCompletions.push_back(std::string(S));2118}21192120// Sort the autocomplete candidates so that shells print them out in a2121// deterministic order. We could sort in any way, but we chose2122// case-insensitive sorting for consistency with the -help option2123// which prints out options in the case-insensitive alphabetical order.2124llvm::sort(SuggestedCompletions, [](StringRef A, StringRef B) {2125if (int X = A.compare_insensitive(B))2126return X < 0;2127return A.compare(B) > 0;2128});21292130llvm::outs() << llvm::join(SuggestedCompletions, "\n") << '\n';2131}21322133bool Driver::HandleImmediateArgs(Compilation &C) {2134// The order these options are handled in gcc is all over the place, but we2135// don't expect inconsistencies w.r.t. that to matter in practice.21362137if (C.getArgs().hasArg(options::OPT_dumpmachine)) {2138llvm::outs() << C.getDefaultToolChain().getTripleString() << '\n';2139return false;2140}21412142if (C.getArgs().hasArg(options::OPT_dumpversion)) {2143// Since -dumpversion is only implemented for pedantic GCC compatibility, we2144// return an answer which matches our definition of __VERSION__.2145llvm::outs() << CLANG_VERSION_STRING << "\n";2146return false;2147}21482149if (C.getArgs().hasArg(options::OPT__print_diagnostic_categories)) {2150PrintDiagnosticCategories(llvm::outs());2151return false;2152}21532154if (C.getArgs().hasArg(options::OPT_help) ||2155C.getArgs().hasArg(options::OPT__help_hidden)) {2156PrintHelp(C.getArgs().hasArg(options::OPT__help_hidden));2157return false;2158}21592160if (C.getArgs().hasArg(options::OPT__version)) {2161// Follow gcc behavior and use stdout for --version and stderr for -v.2162PrintVersion(C, llvm::outs());2163return false;2164}21652166if (C.getArgs().hasArg(options::OPT_v) ||2167C.getArgs().hasArg(options::OPT__HASH_HASH_HASH) ||2168C.getArgs().hasArg(options::OPT_print_supported_cpus) ||2169C.getArgs().hasArg(options::OPT_print_supported_extensions) ||2170C.getArgs().hasArg(options::OPT_print_enabled_extensions)) {2171PrintVersion(C, llvm::errs());2172SuppressMissingInputWarning = true;2173}21742175if (C.getArgs().hasArg(options::OPT_v)) {2176if (!SystemConfigDir.empty())2177llvm::errs() << "System configuration file directory: "2178<< SystemConfigDir << "\n";2179if (!UserConfigDir.empty())2180llvm::errs() << "User configuration file directory: "2181<< UserConfigDir << "\n";2182}21832184const ToolChain &TC = C.getDefaultToolChain();21852186if (C.getArgs().hasArg(options::OPT_v))2187TC.printVerboseInfo(llvm::errs());21882189if (C.getArgs().hasArg(options::OPT_print_resource_dir)) {2190llvm::outs() << ResourceDir << '\n';2191return false;2192}21932194if (C.getArgs().hasArg(options::OPT_print_search_dirs)) {2195llvm::outs() << "programs: =";2196bool separator = false;2197// Print -B and COMPILER_PATH.2198for (const std::string &Path : PrefixDirs) {2199if (separator)2200llvm::outs() << llvm::sys::EnvPathSeparator;2201llvm::outs() << Path;2202separator = true;2203}2204for (const std::string &Path : TC.getProgramPaths()) {2205if (separator)2206llvm::outs() << llvm::sys::EnvPathSeparator;2207llvm::outs() << Path;2208separator = true;2209}2210llvm::outs() << "\n";2211llvm::outs() << "libraries: =" << ResourceDir;22122213StringRef sysroot = C.getSysRoot();22142215for (const std::string &Path : TC.getFilePaths()) {2216// Always print a separator. ResourceDir was the first item shown.2217llvm::outs() << llvm::sys::EnvPathSeparator;2218// Interpretation of leading '=' is needed only for NetBSD.2219if (Path[0] == '=')2220llvm::outs() << sysroot << Path.substr(1);2221else2222llvm::outs() << Path;2223}2224llvm::outs() << "\n";2225return false;2226}22272228if (C.getArgs().hasArg(options::OPT_print_std_module_manifest_path)) {2229llvm::outs() << GetStdModuleManifestPath(C, C.getDefaultToolChain())2230<< '\n';2231return false;2232}22332234if (C.getArgs().hasArg(options::OPT_print_runtime_dir)) {2235if (std::optional<std::string> RuntimePath = TC.getRuntimePath())2236llvm::outs() << *RuntimePath << '\n';2237else2238llvm::outs() << TC.getCompilerRTPath() << '\n';2239return false;2240}22412242if (C.getArgs().hasArg(options::OPT_print_diagnostic_options)) {2243std::vector<std::string> Flags = DiagnosticIDs::getDiagnosticFlags();2244for (std::size_t I = 0; I != Flags.size(); I += 2)2245llvm::outs() << " " << Flags[I] << "\n " << Flags[I + 1] << "\n\n";2246return false;2247}22482249// FIXME: The following handlers should use a callback mechanism, we don't2250// know what the client would like to do.2251if (Arg *A = C.getArgs().getLastArg(options::OPT_print_file_name_EQ)) {2252llvm::outs() << GetFilePath(A->getValue(), TC) << "\n";2253return false;2254}22552256if (Arg *A = C.getArgs().getLastArg(options::OPT_print_prog_name_EQ)) {2257StringRef ProgName = A->getValue();22582259// Null program name cannot have a path.2260if (! ProgName.empty())2261llvm::outs() << GetProgramPath(ProgName, TC);22622263llvm::outs() << "\n";2264return false;2265}22662267if (Arg *A = C.getArgs().getLastArg(options::OPT_autocomplete)) {2268StringRef PassedFlags = A->getValue();2269HandleAutocompletions(PassedFlags);2270return false;2271}22722273if (C.getArgs().hasArg(options::OPT_print_libgcc_file_name)) {2274ToolChain::RuntimeLibType RLT = TC.GetRuntimeLibType(C.getArgs());2275const llvm::Triple Triple(TC.ComputeEffectiveClangTriple(C.getArgs()));2276// The 'Darwin' toolchain is initialized only when its arguments are2277// computed. Get the default arguments for OFK_None to ensure that2278// initialization is performed before trying to access properties of2279// the toolchain in the functions below.2280// FIXME: Remove when darwin's toolchain is initialized during construction.2281// FIXME: For some more esoteric targets the default toolchain is not the2282// correct one.2283C.getArgsForToolChain(&TC, Triple.getArchName(), Action::OFK_None);2284RegisterEffectiveTriple TripleRAII(TC, Triple);2285switch (RLT) {2286case ToolChain::RLT_CompilerRT:2287llvm::outs() << TC.getCompilerRT(C.getArgs(), "builtins") << "\n";2288break;2289case ToolChain::RLT_Libgcc:2290llvm::outs() << GetFilePath("libgcc.a", TC) << "\n";2291break;2292}2293return false;2294}22952296if (C.getArgs().hasArg(options::OPT_print_multi_lib)) {2297for (const Multilib &Multilib : TC.getMultilibs())2298llvm::outs() << Multilib << "\n";2299return false;2300}23012302if (C.getArgs().hasArg(options::OPT_print_multi_flags)) {2303Multilib::flags_list ArgFlags = TC.getMultilibFlags(C.getArgs());2304llvm::StringSet<> ExpandedFlags = TC.getMultilibs().expandFlags(ArgFlags);2305std::set<llvm::StringRef> SortedFlags;2306for (const auto &FlagEntry : ExpandedFlags)2307SortedFlags.insert(FlagEntry.getKey());2308for (auto Flag : SortedFlags)2309llvm::outs() << Flag << '\n';2310return false;2311}23122313if (C.getArgs().hasArg(options::OPT_print_multi_directory)) {2314for (const Multilib &Multilib : TC.getSelectedMultilibs()) {2315if (Multilib.gccSuffix().empty())2316llvm::outs() << ".\n";2317else {2318StringRef Suffix(Multilib.gccSuffix());2319assert(Suffix.front() == '/');2320llvm::outs() << Suffix.substr(1) << "\n";2321}2322}2323return false;2324}23252326if (C.getArgs().hasArg(options::OPT_print_target_triple)) {2327llvm::outs() << TC.getTripleString() << "\n";2328return false;2329}23302331if (C.getArgs().hasArg(options::OPT_print_effective_triple)) {2332const llvm::Triple Triple(TC.ComputeEffectiveClangTriple(C.getArgs()));2333llvm::outs() << Triple.getTriple() << "\n";2334return false;2335}23362337if (C.getArgs().hasArg(options::OPT_print_targets)) {2338llvm::TargetRegistry::printRegisteredTargetsForVersion(llvm::outs());2339return false;2340}23412342return true;2343}23442345enum {2346TopLevelAction = 0,2347HeadSibAction = 1,2348OtherSibAction = 2,2349};23502351// Display an action graph human-readably. Action A is the "sink" node2352// and latest-occuring action. Traversal is in pre-order, visiting the2353// inputs to each action before printing the action itself.2354static unsigned PrintActions1(const Compilation &C, Action *A,2355std::map<Action *, unsigned> &Ids,2356Twine Indent = {}, int Kind = TopLevelAction) {2357if (Ids.count(A)) // A was already visited.2358return Ids[A];23592360std::string str;2361llvm::raw_string_ostream os(str);23622363auto getSibIndent = [](int K) -> Twine {2364return (K == HeadSibAction) ? " " : (K == OtherSibAction) ? "| " : "";2365};23662367Twine SibIndent = Indent + getSibIndent(Kind);2368int SibKind = HeadSibAction;2369os << Action::getClassName(A->getKind()) << ", ";2370if (InputAction *IA = dyn_cast<InputAction>(A)) {2371os << "\"" << IA->getInputArg().getValue() << "\"";2372} else if (BindArchAction *BIA = dyn_cast<BindArchAction>(A)) {2373os << '"' << BIA->getArchName() << '"' << ", {"2374<< PrintActions1(C, *BIA->input_begin(), Ids, SibIndent, SibKind) << "}";2375} else if (OffloadAction *OA = dyn_cast<OffloadAction>(A)) {2376bool IsFirst = true;2377OA->doOnEachDependence(2378[&](Action *A, const ToolChain *TC, const char *BoundArch) {2379assert(TC && "Unknown host toolchain");2380// E.g. for two CUDA device dependences whose bound arch is sm_20 and2381// sm_35 this will generate:2382// "cuda-device" (nvptx64-nvidia-cuda:sm_20) {#ID}, "cuda-device"2383// (nvptx64-nvidia-cuda:sm_35) {#ID}2384if (!IsFirst)2385os << ", ";2386os << '"';2387os << A->getOffloadingKindPrefix();2388os << " (";2389os << TC->getTriple().normalize();2390if (BoundArch)2391os << ":" << BoundArch;2392os << ")";2393os << '"';2394os << " {" << PrintActions1(C, A, Ids, SibIndent, SibKind) << "}";2395IsFirst = false;2396SibKind = OtherSibAction;2397});2398} else {2399const ActionList *AL = &A->getInputs();24002401if (AL->size()) {2402const char *Prefix = "{";2403for (Action *PreRequisite : *AL) {2404os << Prefix << PrintActions1(C, PreRequisite, Ids, SibIndent, SibKind);2405Prefix = ", ";2406SibKind = OtherSibAction;2407}2408os << "}";2409} else2410os << "{}";2411}24122413// Append offload info for all options other than the offloading action2414// itself (e.g. (cuda-device, sm_20) or (cuda-host)).2415std::string offload_str;2416llvm::raw_string_ostream offload_os(offload_str);2417if (!isa<OffloadAction>(A)) {2418auto S = A->getOffloadingKindPrefix();2419if (!S.empty()) {2420offload_os << ", (" << S;2421if (A->getOffloadingArch())2422offload_os << ", " << A->getOffloadingArch();2423offload_os << ")";2424}2425}24262427auto getSelfIndent = [](int K) -> Twine {2428return (K == HeadSibAction) ? "+- " : (K == OtherSibAction) ? "|- " : "";2429};24302431unsigned Id = Ids.size();2432Ids[A] = Id;2433llvm::errs() << Indent + getSelfIndent(Kind) << Id << ": " << os.str() << ", "2434<< types::getTypeName(A->getType()) << offload_os.str() << "\n";24352436return Id;2437}24382439// Print the action graphs in a compilation C.2440// For example "clang -c file1.c file2.c" is composed of two subgraphs.2441void Driver::PrintActions(const Compilation &C) const {2442std::map<Action *, unsigned> Ids;2443for (Action *A : C.getActions())2444PrintActions1(C, A, Ids);2445}24462447/// Check whether the given input tree contains any compilation or2448/// assembly actions.2449static bool ContainsCompileOrAssembleAction(const Action *A) {2450if (isa<CompileJobAction>(A) || isa<BackendJobAction>(A) ||2451isa<AssembleJobAction>(A))2452return true;24532454return llvm::any_of(A->inputs(), ContainsCompileOrAssembleAction);2455}24562457void Driver::BuildUniversalActions(Compilation &C, const ToolChain &TC,2458const InputList &BAInputs) const {2459DerivedArgList &Args = C.getArgs();2460ActionList &Actions = C.getActions();2461llvm::PrettyStackTraceString CrashInfo("Building universal build actions");2462// Collect the list of architectures. Duplicates are allowed, but should only2463// be handled once (in the order seen).2464llvm::StringSet<> ArchNames;2465SmallVector<const char *, 4> Archs;2466for (Arg *A : Args) {2467if (A->getOption().matches(options::OPT_arch)) {2468// Validate the option here; we don't save the type here because its2469// particular spelling may participate in other driver choices.2470llvm::Triple::ArchType Arch =2471tools::darwin::getArchTypeForMachOArchName(A->getValue());2472if (Arch == llvm::Triple::UnknownArch) {2473Diag(clang::diag::err_drv_invalid_arch_name) << A->getAsString(Args);2474continue;2475}24762477A->claim();2478if (ArchNames.insert(A->getValue()).second)2479Archs.push_back(A->getValue());2480}2481}24822483// When there is no explicit arch for this platform, make sure we still bind2484// the architecture (to the default) so that -Xarch_ is handled correctly.2485if (!Archs.size())2486Archs.push_back(Args.MakeArgString(TC.getDefaultUniversalArchName()));24872488ActionList SingleActions;2489BuildActions(C, Args, BAInputs, SingleActions);24902491// Add in arch bindings for every top level action, as well as lipo and2492// dsymutil steps if needed.2493for (Action* Act : SingleActions) {2494// Make sure we can lipo this kind of output. If not (and it is an actual2495// output) then we disallow, since we can't create an output file with the2496// right name without overwriting it. We could remove this oddity by just2497// changing the output names to include the arch, which would also fix2498// -save-temps. Compatibility wins for now.24992500if (Archs.size() > 1 && !types::canLipoType(Act->getType()))2501Diag(clang::diag::err_drv_invalid_output_with_multiple_archs)2502<< types::getTypeName(Act->getType());25032504ActionList Inputs;2505for (unsigned i = 0, e = Archs.size(); i != e; ++i)2506Inputs.push_back(C.MakeAction<BindArchAction>(Act, Archs[i]));25072508// Lipo if necessary, we do it this way because we need to set the arch flag2509// so that -Xarch_ gets overwritten.2510if (Inputs.size() == 1 || Act->getType() == types::TY_Nothing)2511Actions.append(Inputs.begin(), Inputs.end());2512else2513Actions.push_back(C.MakeAction<LipoJobAction>(Inputs, Act->getType()));25142515// Handle debug info queries.2516Arg *A = Args.getLastArg(options::OPT_g_Group);2517bool enablesDebugInfo = A && !A->getOption().matches(options::OPT_g0) &&2518!A->getOption().matches(options::OPT_gstabs);2519if ((enablesDebugInfo || willEmitRemarks(Args)) &&2520ContainsCompileOrAssembleAction(Actions.back())) {25212522// Add a 'dsymutil' step if necessary, when debug info is enabled and we2523// have a compile input. We need to run 'dsymutil' ourselves in such cases2524// because the debug info will refer to a temporary object file which2525// will be removed at the end of the compilation process.2526if (Act->getType() == types::TY_Image) {2527ActionList Inputs;2528Inputs.push_back(Actions.back());2529Actions.pop_back();2530Actions.push_back(2531C.MakeAction<DsymutilJobAction>(Inputs, types::TY_dSYM));2532}25332534// Verify the debug info output.2535if (Args.hasArg(options::OPT_verify_debug_info)) {2536Action* LastAction = Actions.back();2537Actions.pop_back();2538Actions.push_back(C.MakeAction<VerifyDebugInfoJobAction>(2539LastAction, types::TY_Nothing));2540}2541}2542}2543}25442545bool Driver::DiagnoseInputExistence(const DerivedArgList &Args, StringRef Value,2546types::ID Ty, bool TypoCorrect) const {2547if (!getCheckInputsExist())2548return true;25492550// stdin always exists.2551if (Value == "-")2552return true;25532554// If it's a header to be found in the system or user search path, then defer2555// complaints about its absence until those searches can be done. When we2556// are definitely processing headers for C++20 header units, extend this to2557// allow the user to put "-fmodule-header -xc++-header vector" for example.2558if (Ty == types::TY_CXXSHeader || Ty == types::TY_CXXUHeader ||2559(ModulesModeCXX20 && Ty == types::TY_CXXHeader))2560return true;25612562if (getVFS().exists(Value))2563return true;25642565if (TypoCorrect) {2566// Check if the filename is a typo for an option flag. OptTable thinks2567// that all args that are not known options and that start with / are2568// filenames, but e.g. `/diagnostic:caret` is more likely a typo for2569// the option `/diagnostics:caret` than a reference to a file in the root2570// directory.2571std::string Nearest;2572if (getOpts().findNearest(Value, Nearest, getOptionVisibilityMask()) <= 1) {2573Diag(clang::diag::err_drv_no_such_file_with_suggestion)2574<< Value << Nearest;2575return false;2576}2577}25782579// In CL mode, don't error on apparently non-existent linker inputs, because2580// they can be influenced by linker flags the clang driver might not2581// understand.2582// Examples:2583// - `clang-cl main.cc ole32.lib` in a non-MSVC shell will make the driver2584// module look for an MSVC installation in the registry. (We could ask2585// the MSVCToolChain object if it can find `ole32.lib`, but the logic to2586// look in the registry might move into lld-link in the future so that2587// lld-link invocations in non-MSVC shells just work too.)2588// - `clang-cl ... /link ...` can pass arbitrary flags to the linker,2589// including /libpath:, which is used to find .lib and .obj files.2590// So do not diagnose this on the driver level. Rely on the linker diagnosing2591// it. (If we don't end up invoking the linker, this means we'll emit a2592// "'linker' input unused [-Wunused-command-line-argument]" warning instead2593// of an error.)2594//2595// Only do this skip after the typo correction step above. `/Brepo` is treated2596// as TY_Object, but it's clearly a typo for `/Brepro`. It seems fine to emit2597// an error if we have a flag that's within an edit distance of 1 from a2598// flag. (Users can use `-Wl,` or `/linker` to launder the flag past the2599// driver in the unlikely case they run into this.)2600//2601// Don't do this for inputs that start with a '/', else we'd pass options2602// like /libpath: through to the linker silently.2603//2604// Emitting an error for linker inputs can also cause incorrect diagnostics2605// with the gcc driver. The command2606// clang -fuse-ld=lld -Wl,--chroot,some/dir /file.o2607// will make lld look for some/dir/file.o, while we will diagnose here that2608// `/file.o` does not exist. However, configure scripts check if2609// `clang /GR-` compiles without error to see if the compiler is cl.exe,2610// so we can't downgrade diagnostics for `/GR-` from an error to a warning2611// in cc mode. (We can in cl mode because cl.exe itself only warns on2612// unknown flags.)2613if (IsCLMode() && Ty == types::TY_Object && !Value.starts_with("/"))2614return true;26152616Diag(clang::diag::err_drv_no_such_file) << Value;2617return false;2618}26192620// Get the C++20 Header Unit type corresponding to the input type.2621static types::ID CXXHeaderUnitType(ModuleHeaderMode HM) {2622switch (HM) {2623case HeaderMode_User:2624return types::TY_CXXUHeader;2625case HeaderMode_System:2626return types::TY_CXXSHeader;2627case HeaderMode_Default:2628break;2629case HeaderMode_None:2630llvm_unreachable("should not be called in this case");2631}2632return types::TY_CXXHUHeader;2633}26342635// Construct a the list of inputs and their types.2636void Driver::BuildInputs(const ToolChain &TC, DerivedArgList &Args,2637InputList &Inputs) const {2638const llvm::opt::OptTable &Opts = getOpts();2639// Track the current user specified (-x) input. We also explicitly track the2640// argument used to set the type; we only want to claim the type when we2641// actually use it, so we warn about unused -x arguments.2642types::ID InputType = types::TY_Nothing;2643Arg *InputTypeArg = nullptr;26442645// The last /TC or /TP option sets the input type to C or C++ globally.2646if (Arg *TCTP = Args.getLastArgNoClaim(options::OPT__SLASH_TC,2647options::OPT__SLASH_TP)) {2648InputTypeArg = TCTP;2649InputType = TCTP->getOption().matches(options::OPT__SLASH_TC)2650? types::TY_C2651: types::TY_CXX;26522653Arg *Previous = nullptr;2654bool ShowNote = false;2655for (Arg *A :2656Args.filtered(options::OPT__SLASH_TC, options::OPT__SLASH_TP)) {2657if (Previous) {2658Diag(clang::diag::warn_drv_overriding_option)2659<< Previous->getSpelling() << A->getSpelling();2660ShowNote = true;2661}2662Previous = A;2663}2664if (ShowNote)2665Diag(clang::diag::note_drv_t_option_is_global);2666}26672668// Warn -x after last input file has no effect2669{2670Arg *LastXArg = Args.getLastArgNoClaim(options::OPT_x);2671Arg *LastInputArg = Args.getLastArgNoClaim(options::OPT_INPUT);2672if (LastXArg && LastInputArg &&2673LastInputArg->getIndex() < LastXArg->getIndex())2674Diag(clang::diag::warn_drv_unused_x) << LastXArg->getValue();2675}26762677for (Arg *A : Args) {2678if (A->getOption().getKind() == Option::InputClass) {2679const char *Value = A->getValue();2680types::ID Ty = types::TY_INVALID;26812682// Infer the input type if necessary.2683if (InputType == types::TY_Nothing) {2684// If there was an explicit arg for this, claim it.2685if (InputTypeArg)2686InputTypeArg->claim();26872688// stdin must be handled specially.2689if (memcmp(Value, "-", 2) == 0) {2690if (IsFlangMode()) {2691Ty = types::TY_Fortran;2692} else if (IsDXCMode()) {2693Ty = types::TY_HLSL;2694} else {2695// If running with -E, treat as a C input (this changes the2696// builtin macros, for example). This may be overridden by -ObjC2697// below.2698//2699// Otherwise emit an error but still use a valid type to avoid2700// spurious errors (e.g., no inputs).2701assert(!CCGenDiagnostics && "stdin produces no crash reproducer");2702if (!Args.hasArgNoClaim(options::OPT_E) && !CCCIsCPP())2703Diag(IsCLMode() ? clang::diag::err_drv_unknown_stdin_type_clang_cl2704: clang::diag::err_drv_unknown_stdin_type);2705Ty = types::TY_C;2706}2707} else {2708// Otherwise lookup by extension.2709// Fallback is C if invoked as C preprocessor, C++ if invoked with2710// clang-cl /E, or Object otherwise.2711// We use a host hook here because Darwin at least has its own2712// idea of what .s is.2713if (const char *Ext = strrchr(Value, '.'))2714Ty = TC.LookupTypeForExtension(Ext + 1);27152716if (Ty == types::TY_INVALID) {2717if (IsCLMode() && (Args.hasArgNoClaim(options::OPT_E) || CCGenDiagnostics))2718Ty = types::TY_CXX;2719else if (CCCIsCPP() || CCGenDiagnostics)2720Ty = types::TY_C;2721else2722Ty = types::TY_Object;2723}27242725// If the driver is invoked as C++ compiler (like clang++ or c++) it2726// should autodetect some input files as C++ for g++ compatibility.2727if (CCCIsCXX()) {2728types::ID OldTy = Ty;2729Ty = types::lookupCXXTypeForCType(Ty);27302731// Do not complain about foo.h, when we are known to be processing2732// it as a C++20 header unit.2733if (Ty != OldTy && !(OldTy == types::TY_CHeader && hasHeaderMode()))2734Diag(clang::diag::warn_drv_treating_input_as_cxx)2735<< getTypeName(OldTy) << getTypeName(Ty);2736}27372738// If running with -fthinlto-index=, extensions that normally identify2739// native object files actually identify LLVM bitcode files.2740if (Args.hasArgNoClaim(options::OPT_fthinlto_index_EQ) &&2741Ty == types::TY_Object)2742Ty = types::TY_LLVM_BC;2743}27442745// -ObjC and -ObjC++ override the default language, but only for "source2746// files". We just treat everything that isn't a linker input as a2747// source file.2748//2749// FIXME: Clean this up if we move the phase sequence into the type.2750if (Ty != types::TY_Object) {2751if (Args.hasArg(options::OPT_ObjC))2752Ty = types::TY_ObjC;2753else if (Args.hasArg(options::OPT_ObjCXX))2754Ty = types::TY_ObjCXX;2755}27562757// Disambiguate headers that are meant to be header units from those2758// intended to be PCH. Avoid missing '.h' cases that are counted as2759// C headers by default - we know we are in C++ mode and we do not2760// want to issue a complaint about compiling things in the wrong mode.2761if ((Ty == types::TY_CXXHeader || Ty == types::TY_CHeader) &&2762hasHeaderMode())2763Ty = CXXHeaderUnitType(CXX20HeaderType);2764} else {2765assert(InputTypeArg && "InputType set w/o InputTypeArg");2766if (!InputTypeArg->getOption().matches(options::OPT_x)) {2767// If emulating cl.exe, make sure that /TC and /TP don't affect input2768// object files.2769const char *Ext = strrchr(Value, '.');2770if (Ext && TC.LookupTypeForExtension(Ext + 1) == types::TY_Object)2771Ty = types::TY_Object;2772}2773if (Ty == types::TY_INVALID) {2774Ty = InputType;2775InputTypeArg->claim();2776}2777}27782779if ((Ty == types::TY_C || Ty == types::TY_CXX) &&2780Args.hasArgNoClaim(options::OPT_hipstdpar))2781Ty = types::TY_HIP;27822783if (DiagnoseInputExistence(Args, Value, Ty, /*TypoCorrect=*/true))2784Inputs.push_back(std::make_pair(Ty, A));27852786} else if (A->getOption().matches(options::OPT__SLASH_Tc)) {2787StringRef Value = A->getValue();2788if (DiagnoseInputExistence(Args, Value, types::TY_C,2789/*TypoCorrect=*/false)) {2790Arg *InputArg = MakeInputArg(Args, Opts, A->getValue());2791Inputs.push_back(std::make_pair(types::TY_C, InputArg));2792}2793A->claim();2794} else if (A->getOption().matches(options::OPT__SLASH_Tp)) {2795StringRef Value = A->getValue();2796if (DiagnoseInputExistence(Args, Value, types::TY_CXX,2797/*TypoCorrect=*/false)) {2798Arg *InputArg = MakeInputArg(Args, Opts, A->getValue());2799Inputs.push_back(std::make_pair(types::TY_CXX, InputArg));2800}2801A->claim();2802} else if (A->getOption().hasFlag(options::LinkerInput)) {2803// Just treat as object type, we could make a special type for this if2804// necessary.2805Inputs.push_back(std::make_pair(types::TY_Object, A));28062807} else if (A->getOption().matches(options::OPT_x)) {2808InputTypeArg = A;2809InputType = types::lookupTypeForTypeSpecifier(A->getValue());2810A->claim();28112812// Follow gcc behavior and treat as linker input for invalid -x2813// options. Its not clear why we shouldn't just revert to unknown; but2814// this isn't very important, we might as well be bug compatible.2815if (!InputType) {2816Diag(clang::diag::err_drv_unknown_language) << A->getValue();2817InputType = types::TY_Object;2818}28192820// If the user has put -fmodule-header{,=} then we treat C++ headers as2821// header unit inputs. So we 'promote' -xc++-header appropriately.2822if (InputType == types::TY_CXXHeader && hasHeaderMode())2823InputType = CXXHeaderUnitType(CXX20HeaderType);2824} else if (A->getOption().getID() == options::OPT_U) {2825assert(A->getNumValues() == 1 && "The /U option has one value.");2826StringRef Val = A->getValue(0);2827if (Val.find_first_of("/\\") != StringRef::npos) {2828// Warn about e.g. "/Users/me/myfile.c".2829Diag(diag::warn_slash_u_filename) << Val;2830Diag(diag::note_use_dashdash);2831}2832}2833}2834if (CCCIsCPP() && Inputs.empty()) {2835// If called as standalone preprocessor, stdin is processed2836// if no other input is present.2837Arg *A = MakeInputArg(Args, Opts, "-");2838Inputs.push_back(std::make_pair(types::TY_C, A));2839}2840}28412842namespace {2843/// Provides a convenient interface for different programming models to generate2844/// the required device actions.2845class OffloadingActionBuilder final {2846/// Flag used to trace errors in the builder.2847bool IsValid = false;28482849/// The compilation that is using this builder.2850Compilation &C;28512852/// Map between an input argument and the offload kinds used to process it.2853std::map<const Arg *, unsigned> InputArgToOffloadKindMap;28542855/// Map between a host action and its originating input argument.2856std::map<Action *, const Arg *> HostActionToInputArgMap;28572858/// Builder interface. It doesn't build anything or keep any state.2859class DeviceActionBuilder {2860public:2861typedef const llvm::SmallVectorImpl<phases::ID> PhasesTy;28622863enum ActionBuilderReturnCode {2864// The builder acted successfully on the current action.2865ABRT_Success,2866// The builder didn't have to act on the current action.2867ABRT_Inactive,2868// The builder was successful and requested the host action to not be2869// generated.2870ABRT_Ignore_Host,2871};28722873protected:2874/// Compilation associated with this builder.2875Compilation &C;28762877/// Tool chains associated with this builder. The same programming2878/// model may have associated one or more tool chains.2879SmallVector<const ToolChain *, 2> ToolChains;28802881/// The derived arguments associated with this builder.2882DerivedArgList &Args;28832884/// The inputs associated with this builder.2885const Driver::InputList &Inputs;28862887/// The associated offload kind.2888Action::OffloadKind AssociatedOffloadKind = Action::OFK_None;28892890public:2891DeviceActionBuilder(Compilation &C, DerivedArgList &Args,2892const Driver::InputList &Inputs,2893Action::OffloadKind AssociatedOffloadKind)2894: C(C), Args(Args), Inputs(Inputs),2895AssociatedOffloadKind(AssociatedOffloadKind) {}2896virtual ~DeviceActionBuilder() {}28972898/// Fill up the array \a DA with all the device dependences that should be2899/// added to the provided host action \a HostAction. By default it is2900/// inactive.2901virtual ActionBuilderReturnCode2902getDeviceDependences(OffloadAction::DeviceDependences &DA,2903phases::ID CurPhase, phases::ID FinalPhase,2904PhasesTy &Phases) {2905return ABRT_Inactive;2906}29072908/// Update the state to include the provided host action \a HostAction as a2909/// dependency of the current device action. By default it is inactive.2910virtual ActionBuilderReturnCode addDeviceDependences(Action *HostAction) {2911return ABRT_Inactive;2912}29132914/// Append top level actions generated by the builder.2915virtual void appendTopLevelActions(ActionList &AL) {}29162917/// Append linker device actions generated by the builder.2918virtual void appendLinkDeviceActions(ActionList &AL) {}29192920/// Append linker host action generated by the builder.2921virtual Action* appendLinkHostActions(ActionList &AL) { return nullptr; }29222923/// Append linker actions generated by the builder.2924virtual void appendLinkDependences(OffloadAction::DeviceDependences &DA) {}29252926/// Initialize the builder. Return true if any initialization errors are2927/// found.2928virtual bool initialize() { return false; }29292930/// Return true if the builder can use bundling/unbundling.2931virtual bool canUseBundlerUnbundler() const { return false; }29322933/// Return true if this builder is valid. We have a valid builder if we have2934/// associated device tool chains.2935bool isValid() { return !ToolChains.empty(); }29362937/// Return the associated offload kind.2938Action::OffloadKind getAssociatedOffloadKind() {2939return AssociatedOffloadKind;2940}2941};29422943/// Base class for CUDA/HIP action builder. It injects device code in2944/// the host backend action.2945class CudaActionBuilderBase : public DeviceActionBuilder {2946protected:2947/// Flags to signal if the user requested host-only or device-only2948/// compilation.2949bool CompileHostOnly = false;2950bool CompileDeviceOnly = false;2951bool EmitLLVM = false;2952bool EmitAsm = false;29532954/// ID to identify each device compilation. For CUDA it is simply the2955/// GPU arch string. For HIP it is either the GPU arch string or GPU2956/// arch string plus feature strings delimited by a plus sign, e.g.2957/// gfx906+xnack.2958struct TargetID {2959/// Target ID string which is persistent throughout the compilation.2960const char *ID;2961TargetID(OffloadArch Arch) { ID = OffloadArchToString(Arch); }2962TargetID(const char *ID) : ID(ID) {}2963operator const char *() { return ID; }2964operator StringRef() { return StringRef(ID); }2965};2966/// List of GPU architectures to use in this compilation.2967SmallVector<TargetID, 4> GpuArchList;29682969/// The CUDA actions for the current input.2970ActionList CudaDeviceActions;29712972/// The CUDA fat binary if it was generated for the current input.2973Action *CudaFatBinary = nullptr;29742975/// Flag that is set to true if this builder acted on the current input.2976bool IsActive = false;29772978/// Flag for -fgpu-rdc.2979bool Relocatable = false;29802981/// Default GPU architecture if there's no one specified.2982OffloadArch DefaultOffloadArch = OffloadArch::UNKNOWN;29832984/// Method to generate compilation unit ID specified by option2985/// '-fuse-cuid='.2986enum UseCUIDKind { CUID_Hash, CUID_Random, CUID_None, CUID_Invalid };2987UseCUIDKind UseCUID = CUID_Hash;29882989/// Compilation unit ID specified by option '-cuid='.2990StringRef FixedCUID;29912992public:2993CudaActionBuilderBase(Compilation &C, DerivedArgList &Args,2994const Driver::InputList &Inputs,2995Action::OffloadKind OFKind)2996: DeviceActionBuilder(C, Args, Inputs, OFKind) {29972998CompileDeviceOnly = C.getDriver().offloadDeviceOnly();2999Relocatable = Args.hasFlag(options::OPT_fgpu_rdc,3000options::OPT_fno_gpu_rdc, /*Default=*/false);3001}30023003ActionBuilderReturnCode addDeviceDependences(Action *HostAction) override {3004// While generating code for CUDA, we only depend on the host input action3005// to trigger the creation of all the CUDA device actions.30063007// If we are dealing with an input action, replicate it for each GPU3008// architecture. If we are in host-only mode we return 'success' so that3009// the host uses the CUDA offload kind.3010if (auto *IA = dyn_cast<InputAction>(HostAction)) {3011assert(!GpuArchList.empty() &&3012"We should have at least one GPU architecture.");30133014// If the host input is not CUDA or HIP, we don't need to bother about3015// this input.3016if (!(IA->getType() == types::TY_CUDA ||3017IA->getType() == types::TY_HIP ||3018IA->getType() == types::TY_PP_HIP)) {3019// The builder will ignore this input.3020IsActive = false;3021return ABRT_Inactive;3022}30233024// Set the flag to true, so that the builder acts on the current input.3025IsActive = true;30263027if (CompileHostOnly)3028return ABRT_Success;30293030// Replicate inputs for each GPU architecture.3031auto Ty = IA->getType() == types::TY_HIP ? types::TY_HIP_DEVICE3032: types::TY_CUDA_DEVICE;3033std::string CUID = FixedCUID.str();3034if (CUID.empty()) {3035if (UseCUID == CUID_Random)3036CUID = llvm::utohexstr(llvm::sys::Process::GetRandomNumber(),3037/*LowerCase=*/true);3038else if (UseCUID == CUID_Hash) {3039llvm::MD5 Hasher;3040llvm::MD5::MD5Result Hash;3041SmallString<256> RealPath;3042llvm::sys::fs::real_path(IA->getInputArg().getValue(), RealPath,3043/*expand_tilde=*/true);3044Hasher.update(RealPath);3045for (auto *A : Args) {3046if (A->getOption().matches(options::OPT_INPUT))3047continue;3048Hasher.update(A->getAsString(Args));3049}3050Hasher.final(Hash);3051CUID = llvm::utohexstr(Hash.low(), /*LowerCase=*/true);3052}3053}3054IA->setId(CUID);30553056for (unsigned I = 0, E = GpuArchList.size(); I != E; ++I) {3057CudaDeviceActions.push_back(3058C.MakeAction<InputAction>(IA->getInputArg(), Ty, IA->getId()));3059}30603061return ABRT_Success;3062}30633064// If this is an unbundling action use it as is for each CUDA toolchain.3065if (auto *UA = dyn_cast<OffloadUnbundlingJobAction>(HostAction)) {30663067// If -fgpu-rdc is disabled, should not unbundle since there is no3068// device code to link.3069if (UA->getType() == types::TY_Object && !Relocatable)3070return ABRT_Inactive;30713072CudaDeviceActions.clear();3073auto *IA = cast<InputAction>(UA->getInputs().back());3074std::string FileName = IA->getInputArg().getAsString(Args);3075// Check if the type of the file is the same as the action. Do not3076// unbundle it if it is not. Do not unbundle .so files, for example,3077// which are not object files. Files with extension ".lib" is classified3078// as TY_Object but they are actually archives, therefore should not be3079// unbundled here as objects. They will be handled at other places.3080const StringRef LibFileExt = ".lib";3081if (IA->getType() == types::TY_Object &&3082(!llvm::sys::path::has_extension(FileName) ||3083types::lookupTypeForExtension(3084llvm::sys::path::extension(FileName).drop_front()) !=3085types::TY_Object ||3086llvm::sys::path::extension(FileName) == LibFileExt))3087return ABRT_Inactive;30883089for (auto Arch : GpuArchList) {3090CudaDeviceActions.push_back(UA);3091UA->registerDependentActionInfo(ToolChains[0], Arch,3092AssociatedOffloadKind);3093}3094IsActive = true;3095return ABRT_Success;3096}30973098return IsActive ? ABRT_Success : ABRT_Inactive;3099}31003101void appendTopLevelActions(ActionList &AL) override {3102// Utility to append actions to the top level list.3103auto AddTopLevel = [&](Action *A, TargetID TargetID) {3104OffloadAction::DeviceDependences Dep;3105Dep.add(*A, *ToolChains.front(), TargetID, AssociatedOffloadKind);3106AL.push_back(C.MakeAction<OffloadAction>(Dep, A->getType()));3107};31083109// If we have a fat binary, add it to the list.3110if (CudaFatBinary) {3111AddTopLevel(CudaFatBinary, OffloadArch::UNUSED);3112CudaDeviceActions.clear();3113CudaFatBinary = nullptr;3114return;3115}31163117if (CudaDeviceActions.empty())3118return;31193120// If we have CUDA actions at this point, that's because we have a have3121// partial compilation, so we should have an action for each GPU3122// architecture.3123assert(CudaDeviceActions.size() == GpuArchList.size() &&3124"Expecting one action per GPU architecture.");3125assert(ToolChains.size() == 1 &&3126"Expecting to have a single CUDA toolchain.");3127for (unsigned I = 0, E = GpuArchList.size(); I != E; ++I)3128AddTopLevel(CudaDeviceActions[I], GpuArchList[I]);31293130CudaDeviceActions.clear();3131}31323133/// Get canonicalized offload arch option. \returns empty StringRef if the3134/// option is invalid.3135virtual StringRef getCanonicalOffloadArch(StringRef Arch) = 0;31363137virtual std::optional<std::pair<llvm::StringRef, llvm::StringRef>>3138getConflictOffloadArchCombination(const std::set<StringRef> &GpuArchs) = 0;31393140bool initialize() override {3141assert(AssociatedOffloadKind == Action::OFK_Cuda ||3142AssociatedOffloadKind == Action::OFK_HIP);31433144// We don't need to support CUDA.3145if (AssociatedOffloadKind == Action::OFK_Cuda &&3146!C.hasOffloadToolChain<Action::OFK_Cuda>())3147return false;31483149// We don't need to support HIP.3150if (AssociatedOffloadKind == Action::OFK_HIP &&3151!C.hasOffloadToolChain<Action::OFK_HIP>())3152return false;31533154const ToolChain *HostTC = C.getSingleOffloadToolChain<Action::OFK_Host>();3155assert(HostTC && "No toolchain for host compilation.");3156if (HostTC->getTriple().isNVPTX() ||3157HostTC->getTriple().getArch() == llvm::Triple::amdgcn) {3158// We do not support targeting NVPTX/AMDGCN for host compilation. Throw3159// an error and abort pipeline construction early so we don't trip3160// asserts that assume device-side compilation.3161C.getDriver().Diag(diag::err_drv_cuda_host_arch)3162<< HostTC->getTriple().getArchName();3163return true;3164}31653166ToolChains.push_back(3167AssociatedOffloadKind == Action::OFK_Cuda3168? C.getSingleOffloadToolChain<Action::OFK_Cuda>()3169: C.getSingleOffloadToolChain<Action::OFK_HIP>());31703171CompileHostOnly = C.getDriver().offloadHostOnly();3172EmitLLVM = Args.getLastArg(options::OPT_emit_llvm);3173EmitAsm = Args.getLastArg(options::OPT_S);3174FixedCUID = Args.getLastArgValue(options::OPT_cuid_EQ);3175if (Arg *A = Args.getLastArg(options::OPT_fuse_cuid_EQ)) {3176StringRef UseCUIDStr = A->getValue();3177UseCUID = llvm::StringSwitch<UseCUIDKind>(UseCUIDStr)3178.Case("hash", CUID_Hash)3179.Case("random", CUID_Random)3180.Case("none", CUID_None)3181.Default(CUID_Invalid);3182if (UseCUID == CUID_Invalid) {3183C.getDriver().Diag(diag::err_drv_invalid_value)3184<< A->getAsString(Args) << UseCUIDStr;3185C.setContainsError();3186return true;3187}3188}31893190// --offload and --offload-arch options are mutually exclusive.3191if (Args.hasArgNoClaim(options::OPT_offload_EQ) &&3192Args.hasArgNoClaim(options::OPT_offload_arch_EQ,3193options::OPT_no_offload_arch_EQ)) {3194C.getDriver().Diag(diag::err_opt_not_valid_with_opt) << "--offload-arch"3195<< "--offload";3196}31973198// Collect all offload arch parameters, removing duplicates.3199std::set<StringRef> GpuArchs;3200bool Error = false;3201for (Arg *A : Args) {3202if (!(A->getOption().matches(options::OPT_offload_arch_EQ) ||3203A->getOption().matches(options::OPT_no_offload_arch_EQ)))3204continue;3205A->claim();32063207for (StringRef ArchStr : llvm::split(A->getValue(), ",")) {3208if (A->getOption().matches(options::OPT_no_offload_arch_EQ) &&3209ArchStr == "all") {3210GpuArchs.clear();3211} else if (ArchStr == "native") {3212const ToolChain &TC = *ToolChains.front();3213auto GPUsOrErr = ToolChains.front()->getSystemGPUArchs(Args);3214if (!GPUsOrErr) {3215TC.getDriver().Diag(diag::err_drv_undetermined_gpu_arch)3216<< llvm::Triple::getArchTypeName(TC.getArch())3217<< llvm::toString(GPUsOrErr.takeError()) << "--offload-arch";3218continue;3219}32203221for (auto GPU : *GPUsOrErr) {3222GpuArchs.insert(Args.MakeArgString(GPU));3223}3224} else {3225ArchStr = getCanonicalOffloadArch(ArchStr);3226if (ArchStr.empty()) {3227Error = true;3228} else if (A->getOption().matches(options::OPT_offload_arch_EQ))3229GpuArchs.insert(ArchStr);3230else if (A->getOption().matches(options::OPT_no_offload_arch_EQ))3231GpuArchs.erase(ArchStr);3232else3233llvm_unreachable("Unexpected option.");3234}3235}3236}32373238auto &&ConflictingArchs = getConflictOffloadArchCombination(GpuArchs);3239if (ConflictingArchs) {3240C.getDriver().Diag(clang::diag::err_drv_bad_offload_arch_combo)3241<< ConflictingArchs->first << ConflictingArchs->second;3242C.setContainsError();3243return true;3244}32453246// Collect list of GPUs remaining in the set.3247for (auto Arch : GpuArchs)3248GpuArchList.push_back(Arch.data());32493250// Default to sm_20 which is the lowest common denominator for3251// supported GPUs. sm_20 code should work correctly, if3252// suboptimally, on all newer GPUs.3253if (GpuArchList.empty()) {3254if (ToolChains.front()->getTriple().isSPIRV()) {3255if (ToolChains.front()->getTriple().getVendor() == llvm::Triple::AMD)3256GpuArchList.push_back(OffloadArch::AMDGCNSPIRV);3257else3258GpuArchList.push_back(OffloadArch::Generic);3259} else {3260GpuArchList.push_back(DefaultOffloadArch);3261}3262}32633264return Error;3265}3266};32673268/// \brief CUDA action builder. It injects device code in the host backend3269/// action.3270class CudaActionBuilder final : public CudaActionBuilderBase {3271public:3272CudaActionBuilder(Compilation &C, DerivedArgList &Args,3273const Driver::InputList &Inputs)3274: CudaActionBuilderBase(C, Args, Inputs, Action::OFK_Cuda) {3275DefaultOffloadArch = OffloadArch::CudaDefault;3276}32773278StringRef getCanonicalOffloadArch(StringRef ArchStr) override {3279OffloadArch Arch = StringToOffloadArch(ArchStr);3280if (Arch == OffloadArch::UNKNOWN || !IsNVIDIAOffloadArch(Arch)) {3281C.getDriver().Diag(clang::diag::err_drv_cuda_bad_gpu_arch) << ArchStr;3282return StringRef();3283}3284return OffloadArchToString(Arch);3285}32863287std::optional<std::pair<llvm::StringRef, llvm::StringRef>>3288getConflictOffloadArchCombination(3289const std::set<StringRef> &GpuArchs) override {3290return std::nullopt;3291}32923293ActionBuilderReturnCode3294getDeviceDependences(OffloadAction::DeviceDependences &DA,3295phases::ID CurPhase, phases::ID FinalPhase,3296PhasesTy &Phases) override {3297if (!IsActive)3298return ABRT_Inactive;32993300// If we don't have more CUDA actions, we don't have any dependences to3301// create for the host.3302if (CudaDeviceActions.empty())3303return ABRT_Success;33043305assert(CudaDeviceActions.size() == GpuArchList.size() &&3306"Expecting one action per GPU architecture.");3307assert(!CompileHostOnly &&3308"Not expecting CUDA actions in host-only compilation.");33093310// If we are generating code for the device or we are in a backend phase,3311// we attempt to generate the fat binary. We compile each arch to ptx and3312// assemble to cubin, then feed the cubin *and* the ptx into a device3313// "link" action, which uses fatbinary to combine these cubins into one3314// fatbin. The fatbin is then an input to the host action if not in3315// device-only mode.3316if (CompileDeviceOnly || CurPhase == phases::Backend) {3317ActionList DeviceActions;3318for (unsigned I = 0, E = GpuArchList.size(); I != E; ++I) {3319// Produce the device action from the current phase up to the assemble3320// phase.3321for (auto Ph : Phases) {3322// Skip the phases that were already dealt with.3323if (Ph < CurPhase)3324continue;3325// We have to be consistent with the host final phase.3326if (Ph > FinalPhase)3327break;33283329CudaDeviceActions[I] = C.getDriver().ConstructPhaseAction(3330C, Args, Ph, CudaDeviceActions[I], Action::OFK_Cuda);33313332if (Ph == phases::Assemble)3333break;3334}33353336// If we didn't reach the assemble phase, we can't generate the fat3337// binary. We don't need to generate the fat binary if we are not in3338// device-only mode.3339if (!isa<AssembleJobAction>(CudaDeviceActions[I]) ||3340CompileDeviceOnly)3341continue;33423343Action *AssembleAction = CudaDeviceActions[I];3344assert(AssembleAction->getType() == types::TY_Object);3345assert(AssembleAction->getInputs().size() == 1);33463347Action *BackendAction = AssembleAction->getInputs()[0];3348assert(BackendAction->getType() == types::TY_PP_Asm);33493350for (auto &A : {AssembleAction, BackendAction}) {3351OffloadAction::DeviceDependences DDep;3352DDep.add(*A, *ToolChains.front(), GpuArchList[I], Action::OFK_Cuda);3353DeviceActions.push_back(3354C.MakeAction<OffloadAction>(DDep, A->getType()));3355}3356}33573358// We generate the fat binary if we have device input actions.3359if (!DeviceActions.empty()) {3360CudaFatBinary =3361C.MakeAction<LinkJobAction>(DeviceActions, types::TY_CUDA_FATBIN);33623363if (!CompileDeviceOnly) {3364DA.add(*CudaFatBinary, *ToolChains.front(), /*BoundArch=*/nullptr,3365Action::OFK_Cuda);3366// Clear the fat binary, it is already a dependence to an host3367// action.3368CudaFatBinary = nullptr;3369}33703371// Remove the CUDA actions as they are already connected to an host3372// action or fat binary.3373CudaDeviceActions.clear();3374}33753376// We avoid creating host action in device-only mode.3377return CompileDeviceOnly ? ABRT_Ignore_Host : ABRT_Success;3378} else if (CurPhase > phases::Backend) {3379// If we are past the backend phase and still have a device action, we3380// don't have to do anything as this action is already a device3381// top-level action.3382return ABRT_Success;3383}33843385assert(CurPhase < phases::Backend && "Generating single CUDA "3386"instructions should only occur "3387"before the backend phase!");33883389// By default, we produce an action for each device arch.3390for (Action *&A : CudaDeviceActions)3391A = C.getDriver().ConstructPhaseAction(C, Args, CurPhase, A);33923393return ABRT_Success;3394}3395};3396/// \brief HIP action builder. It injects device code in the host backend3397/// action.3398class HIPActionBuilder final : public CudaActionBuilderBase {3399/// The linker inputs obtained for each device arch.3400SmallVector<ActionList, 8> DeviceLinkerInputs;3401// The default bundling behavior depends on the type of output, therefore3402// BundleOutput needs to be tri-value: None, true, or false.3403// Bundle code objects except --no-gpu-output is specified for device3404// only compilation. Bundle other type of output files only if3405// --gpu-bundle-output is specified for device only compilation.3406std::optional<bool> BundleOutput;3407std::optional<bool> EmitReloc;34083409public:3410HIPActionBuilder(Compilation &C, DerivedArgList &Args,3411const Driver::InputList &Inputs)3412: CudaActionBuilderBase(C, Args, Inputs, Action::OFK_HIP) {34133414DefaultOffloadArch = OffloadArch::HIPDefault;34153416if (Args.hasArg(options::OPT_fhip_emit_relocatable,3417options::OPT_fno_hip_emit_relocatable)) {3418EmitReloc = Args.hasFlag(options::OPT_fhip_emit_relocatable,3419options::OPT_fno_hip_emit_relocatable, false);34203421if (*EmitReloc) {3422if (Relocatable) {3423C.getDriver().Diag(diag::err_opt_not_valid_with_opt)3424<< "-fhip-emit-relocatable"3425<< "-fgpu-rdc";3426}34273428if (!CompileDeviceOnly) {3429C.getDriver().Diag(diag::err_opt_not_valid_without_opt)3430<< "-fhip-emit-relocatable"3431<< "--cuda-device-only";3432}3433}3434}34353436if (Args.hasArg(options::OPT_gpu_bundle_output,3437options::OPT_no_gpu_bundle_output))3438BundleOutput = Args.hasFlag(options::OPT_gpu_bundle_output,3439options::OPT_no_gpu_bundle_output, true) &&3440(!EmitReloc || !*EmitReloc);3441}34423443bool canUseBundlerUnbundler() const override { return true; }34443445StringRef getCanonicalOffloadArch(StringRef IdStr) override {3446llvm::StringMap<bool> Features;3447// getHIPOffloadTargetTriple() is known to return valid value as it has3448// been called successfully in the CreateOffloadingDeviceToolChains().3449auto ArchStr = parseTargetID(3450*getHIPOffloadTargetTriple(C.getDriver(), C.getInputArgs()), IdStr,3451&Features);3452if (!ArchStr) {3453C.getDriver().Diag(clang::diag::err_drv_bad_target_id) << IdStr;3454C.setContainsError();3455return StringRef();3456}3457auto CanId = getCanonicalTargetID(*ArchStr, Features);3458return Args.MakeArgStringRef(CanId);3459};34603461std::optional<std::pair<llvm::StringRef, llvm::StringRef>>3462getConflictOffloadArchCombination(3463const std::set<StringRef> &GpuArchs) override {3464return getConflictTargetIDCombination(GpuArchs);3465}34663467ActionBuilderReturnCode3468getDeviceDependences(OffloadAction::DeviceDependences &DA,3469phases::ID CurPhase, phases::ID FinalPhase,3470PhasesTy &Phases) override {3471if (!IsActive)3472return ABRT_Inactive;34733474// amdgcn does not support linking of object files, therefore we skip3475// backend and assemble phases to output LLVM IR. Except for generating3476// non-relocatable device code, where we generate fat binary for device3477// code and pass to host in Backend phase.3478if (CudaDeviceActions.empty())3479return ABRT_Success;34803481assert(((CurPhase == phases::Link && Relocatable) ||3482CudaDeviceActions.size() == GpuArchList.size()) &&3483"Expecting one action per GPU architecture.");3484assert(!CompileHostOnly &&3485"Not expecting HIP actions in host-only compilation.");34863487bool ShouldLink = !EmitReloc || !*EmitReloc;34883489if (!Relocatable && CurPhase == phases::Backend && !EmitLLVM &&3490!EmitAsm && ShouldLink) {3491// If we are in backend phase, we attempt to generate the fat binary.3492// We compile each arch to IR and use a link action to generate code3493// object containing ISA. Then we use a special "link" action to create3494// a fat binary containing all the code objects for different GPU's.3495// The fat binary is then an input to the host action.3496for (unsigned I = 0, E = GpuArchList.size(); I != E; ++I) {3497if (C.getDriver().isUsingLTO(/*IsOffload=*/true)) {3498// When LTO is enabled, skip the backend and assemble phases and3499// use lld to link the bitcode.3500ActionList AL;3501AL.push_back(CudaDeviceActions[I]);3502// Create a link action to link device IR with device library3503// and generate ISA.3504CudaDeviceActions[I] =3505C.MakeAction<LinkJobAction>(AL, types::TY_Image);3506} else {3507// When LTO is not enabled, we follow the conventional3508// compiler phases, including backend and assemble phases.3509ActionList AL;3510Action *BackendAction = nullptr;3511if (ToolChains.front()->getTriple().isSPIRV()) {3512// Emit LLVM bitcode for SPIR-V targets. SPIR-V device tool chain3513// (HIPSPVToolChain) runs post-link LLVM IR passes.3514types::ID Output = Args.hasArg(options::OPT_S)3515? types::TY_LLVM_IR3516: types::TY_LLVM_BC;3517BackendAction =3518C.MakeAction<BackendJobAction>(CudaDeviceActions[I], Output);3519} else3520BackendAction = C.getDriver().ConstructPhaseAction(3521C, Args, phases::Backend, CudaDeviceActions[I],3522AssociatedOffloadKind);3523auto AssembleAction = C.getDriver().ConstructPhaseAction(3524C, Args, phases::Assemble, BackendAction,3525AssociatedOffloadKind);3526AL.push_back(AssembleAction);3527// Create a link action to link device IR with device library3528// and generate ISA.3529CudaDeviceActions[I] =3530C.MakeAction<LinkJobAction>(AL, types::TY_Image);3531}35323533// OffloadingActionBuilder propagates device arch until an offload3534// action. Since the next action for creating fatbin does3535// not have device arch, whereas the above link action and its input3536// have device arch, an offload action is needed to stop the null3537// device arch of the next action being propagated to the above link3538// action.3539OffloadAction::DeviceDependences DDep;3540DDep.add(*CudaDeviceActions[I], *ToolChains.front(), GpuArchList[I],3541AssociatedOffloadKind);3542CudaDeviceActions[I] = C.MakeAction<OffloadAction>(3543DDep, CudaDeviceActions[I]->getType());3544}35453546if (!CompileDeviceOnly || !BundleOutput || *BundleOutput) {3547// Create HIP fat binary with a special "link" action.3548CudaFatBinary = C.MakeAction<LinkJobAction>(CudaDeviceActions,3549types::TY_HIP_FATBIN);35503551if (!CompileDeviceOnly) {3552DA.add(*CudaFatBinary, *ToolChains.front(), /*BoundArch=*/nullptr,3553AssociatedOffloadKind);3554// Clear the fat binary, it is already a dependence to an host3555// action.3556CudaFatBinary = nullptr;3557}35583559// Remove the CUDA actions as they are already connected to an host3560// action or fat binary.3561CudaDeviceActions.clear();3562}35633564return CompileDeviceOnly ? ABRT_Ignore_Host : ABRT_Success;3565} else if (CurPhase == phases::Link) {3566if (!ShouldLink)3567return ABRT_Success;3568// Save CudaDeviceActions to DeviceLinkerInputs for each GPU subarch.3569// This happens to each device action originated from each input file.3570// Later on, device actions in DeviceLinkerInputs are used to create3571// device link actions in appendLinkDependences and the created device3572// link actions are passed to the offload action as device dependence.3573DeviceLinkerInputs.resize(CudaDeviceActions.size());3574auto LI = DeviceLinkerInputs.begin();3575for (auto *A : CudaDeviceActions) {3576LI->push_back(A);3577++LI;3578}35793580// We will pass the device action as a host dependence, so we don't3581// need to do anything else with them.3582CudaDeviceActions.clear();3583return CompileDeviceOnly ? ABRT_Ignore_Host : ABRT_Success;3584}35853586// By default, we produce an action for each device arch.3587for (Action *&A : CudaDeviceActions)3588A = C.getDriver().ConstructPhaseAction(C, Args, CurPhase, A,3589AssociatedOffloadKind);35903591if (CompileDeviceOnly && CurPhase == FinalPhase && BundleOutput &&3592*BundleOutput) {3593for (unsigned I = 0, E = GpuArchList.size(); I != E; ++I) {3594OffloadAction::DeviceDependences DDep;3595DDep.add(*CudaDeviceActions[I], *ToolChains.front(), GpuArchList[I],3596AssociatedOffloadKind);3597CudaDeviceActions[I] = C.MakeAction<OffloadAction>(3598DDep, CudaDeviceActions[I]->getType());3599}3600CudaFatBinary =3601C.MakeAction<OffloadBundlingJobAction>(CudaDeviceActions);3602CudaDeviceActions.clear();3603}36043605return (CompileDeviceOnly &&3606(CurPhase == FinalPhase ||3607(!ShouldLink && CurPhase == phases::Assemble)))3608? ABRT_Ignore_Host3609: ABRT_Success;3610}36113612void appendLinkDeviceActions(ActionList &AL) override {3613if (DeviceLinkerInputs.size() == 0)3614return;36153616assert(DeviceLinkerInputs.size() == GpuArchList.size() &&3617"Linker inputs and GPU arch list sizes do not match.");36183619ActionList Actions;3620unsigned I = 0;3621// Append a new link action for each device.3622// Each entry in DeviceLinkerInputs corresponds to a GPU arch.3623for (auto &LI : DeviceLinkerInputs) {36243625types::ID Output = Args.hasArg(options::OPT_emit_llvm)3626? types::TY_LLVM_BC3627: types::TY_Image;36283629auto *DeviceLinkAction = C.MakeAction<LinkJobAction>(LI, Output);3630// Linking all inputs for the current GPU arch.3631// LI contains all the inputs for the linker.3632OffloadAction::DeviceDependences DeviceLinkDeps;3633DeviceLinkDeps.add(*DeviceLinkAction, *ToolChains[0],3634GpuArchList[I], AssociatedOffloadKind);3635Actions.push_back(C.MakeAction<OffloadAction>(3636DeviceLinkDeps, DeviceLinkAction->getType()));3637++I;3638}3639DeviceLinkerInputs.clear();36403641// If emitting LLVM, do not generate final host/device compilation action3642if (Args.hasArg(options::OPT_emit_llvm)) {3643AL.append(Actions);3644return;3645}36463647// Create a host object from all the device images by embedding them3648// in a fat binary for mixed host-device compilation. For device-only3649// compilation, creates a fat binary.3650OffloadAction::DeviceDependences DDeps;3651if (!CompileDeviceOnly || !BundleOutput || *BundleOutput) {3652auto *TopDeviceLinkAction = C.MakeAction<LinkJobAction>(3653Actions,3654CompileDeviceOnly ? types::TY_HIP_FATBIN : types::TY_Object);3655DDeps.add(*TopDeviceLinkAction, *ToolChains[0], nullptr,3656AssociatedOffloadKind);3657// Offload the host object to the host linker.3658AL.push_back(3659C.MakeAction<OffloadAction>(DDeps, TopDeviceLinkAction->getType()));3660} else {3661AL.append(Actions);3662}3663}36643665Action* appendLinkHostActions(ActionList &AL) override { return AL.back(); }36663667void appendLinkDependences(OffloadAction::DeviceDependences &DA) override {}3668};36693670///3671/// TODO: Add the implementation for other specialized builders here.3672///36733674/// Specialized builders being used by this offloading action builder.3675SmallVector<DeviceActionBuilder *, 4> SpecializedBuilders;36763677/// Flag set to true if all valid builders allow file bundling/unbundling.3678bool CanUseBundler;36793680public:3681OffloadingActionBuilder(Compilation &C, DerivedArgList &Args,3682const Driver::InputList &Inputs)3683: C(C) {3684// Create a specialized builder for each device toolchain.36853686IsValid = true;36873688// Create a specialized builder for CUDA.3689SpecializedBuilders.push_back(new CudaActionBuilder(C, Args, Inputs));36903691// Create a specialized builder for HIP.3692SpecializedBuilders.push_back(new HIPActionBuilder(C, Args, Inputs));36933694//3695// TODO: Build other specialized builders here.3696//36973698// Initialize all the builders, keeping track of errors. If all valid3699// builders agree that we can use bundling, set the flag to true.3700unsigned ValidBuilders = 0u;3701unsigned ValidBuildersSupportingBundling = 0u;3702for (auto *SB : SpecializedBuilders) {3703IsValid = IsValid && !SB->initialize();37043705// Update the counters if the builder is valid.3706if (SB->isValid()) {3707++ValidBuilders;3708if (SB->canUseBundlerUnbundler())3709++ValidBuildersSupportingBundling;3710}3711}3712CanUseBundler =3713ValidBuilders && ValidBuilders == ValidBuildersSupportingBundling;3714}37153716~OffloadingActionBuilder() {3717for (auto *SB : SpecializedBuilders)3718delete SB;3719}37203721/// Record a host action and its originating input argument.3722void recordHostAction(Action *HostAction, const Arg *InputArg) {3723assert(HostAction && "Invalid host action");3724assert(InputArg && "Invalid input argument");3725auto Loc = HostActionToInputArgMap.find(HostAction);3726if (Loc == HostActionToInputArgMap.end())3727HostActionToInputArgMap[HostAction] = InputArg;3728assert(HostActionToInputArgMap[HostAction] == InputArg &&3729"host action mapped to multiple input arguments");3730}37313732/// Generate an action that adds device dependences (if any) to a host action.3733/// If no device dependence actions exist, just return the host action \a3734/// HostAction. If an error is found or if no builder requires the host action3735/// to be generated, return nullptr.3736Action *3737addDeviceDependencesToHostAction(Action *HostAction, const Arg *InputArg,3738phases::ID CurPhase, phases::ID FinalPhase,3739DeviceActionBuilder::PhasesTy &Phases) {3740if (!IsValid)3741return nullptr;37423743if (SpecializedBuilders.empty())3744return HostAction;37453746assert(HostAction && "Invalid host action!");3747recordHostAction(HostAction, InputArg);37483749OffloadAction::DeviceDependences DDeps;3750// Check if all the programming models agree we should not emit the host3751// action. Also, keep track of the offloading kinds employed.3752auto &OffloadKind = InputArgToOffloadKindMap[InputArg];3753unsigned InactiveBuilders = 0u;3754unsigned IgnoringBuilders = 0u;3755for (auto *SB : SpecializedBuilders) {3756if (!SB->isValid()) {3757++InactiveBuilders;3758continue;3759}3760auto RetCode =3761SB->getDeviceDependences(DDeps, CurPhase, FinalPhase, Phases);37623763// If the builder explicitly says the host action should be ignored,3764// we need to increment the variable that tracks the builders that request3765// the host object to be ignored.3766if (RetCode == DeviceActionBuilder::ABRT_Ignore_Host)3767++IgnoringBuilders;37683769// Unless the builder was inactive for this action, we have to record the3770// offload kind because the host will have to use it.3771if (RetCode != DeviceActionBuilder::ABRT_Inactive)3772OffloadKind |= SB->getAssociatedOffloadKind();3773}37743775// If all builders agree that the host object should be ignored, just return3776// nullptr.3777if (IgnoringBuilders &&3778SpecializedBuilders.size() == (InactiveBuilders + IgnoringBuilders))3779return nullptr;37803781if (DDeps.getActions().empty())3782return HostAction;37833784// We have dependences we need to bundle together. We use an offload action3785// for that.3786OffloadAction::HostDependence HDep(3787*HostAction, *C.getSingleOffloadToolChain<Action::OFK_Host>(),3788/*BoundArch=*/nullptr, DDeps);3789return C.MakeAction<OffloadAction>(HDep, DDeps);3790}37913792/// Generate an action that adds a host dependence to a device action. The3793/// results will be kept in this action builder. Return true if an error was3794/// found.3795bool addHostDependenceToDeviceActions(Action *&HostAction,3796const Arg *InputArg) {3797if (!IsValid)3798return true;37993800recordHostAction(HostAction, InputArg);38013802// If we are supporting bundling/unbundling and the current action is an3803// input action of non-source file, we replace the host action by the3804// unbundling action. The bundler tool has the logic to detect if an input3805// is a bundle or not and if the input is not a bundle it assumes it is a3806// host file. Therefore it is safe to create an unbundling action even if3807// the input is not a bundle.3808if (CanUseBundler && isa<InputAction>(HostAction) &&3809InputArg->getOption().getKind() == llvm::opt::Option::InputClass &&3810(!types::isSrcFile(HostAction->getType()) ||3811HostAction->getType() == types::TY_PP_HIP)) {3812auto UnbundlingHostAction =3813C.MakeAction<OffloadUnbundlingJobAction>(HostAction);3814UnbundlingHostAction->registerDependentActionInfo(3815C.getSingleOffloadToolChain<Action::OFK_Host>(),3816/*BoundArch=*/StringRef(), Action::OFK_Host);3817HostAction = UnbundlingHostAction;3818recordHostAction(HostAction, InputArg);3819}38203821assert(HostAction && "Invalid host action!");38223823// Register the offload kinds that are used.3824auto &OffloadKind = InputArgToOffloadKindMap[InputArg];3825for (auto *SB : SpecializedBuilders) {3826if (!SB->isValid())3827continue;38283829auto RetCode = SB->addDeviceDependences(HostAction);38303831// Host dependences for device actions are not compatible with that same3832// action being ignored.3833assert(RetCode != DeviceActionBuilder::ABRT_Ignore_Host &&3834"Host dependence not expected to be ignored.!");38353836// Unless the builder was inactive for this action, we have to record the3837// offload kind because the host will have to use it.3838if (RetCode != DeviceActionBuilder::ABRT_Inactive)3839OffloadKind |= SB->getAssociatedOffloadKind();3840}38413842// Do not use unbundler if the Host does not depend on device action.3843if (OffloadKind == Action::OFK_None && CanUseBundler)3844if (auto *UA = dyn_cast<OffloadUnbundlingJobAction>(HostAction))3845HostAction = UA->getInputs().back();38463847return false;3848}38493850/// Add the offloading top level actions to the provided action list. This3851/// function can replace the host action by a bundling action if the3852/// programming models allow it.3853bool appendTopLevelActions(ActionList &AL, Action *HostAction,3854const Arg *InputArg) {3855if (HostAction)3856recordHostAction(HostAction, InputArg);38573858// Get the device actions to be appended.3859ActionList OffloadAL;3860for (auto *SB : SpecializedBuilders) {3861if (!SB->isValid())3862continue;3863SB->appendTopLevelActions(OffloadAL);3864}38653866// If we can use the bundler, replace the host action by the bundling one in3867// the resulting list. Otherwise, just append the device actions. For3868// device only compilation, HostAction is a null pointer, therefore only do3869// this when HostAction is not a null pointer.3870if (CanUseBundler && HostAction &&3871HostAction->getType() != types::TY_Nothing && !OffloadAL.empty()) {3872// Add the host action to the list in order to create the bundling action.3873OffloadAL.push_back(HostAction);38743875// We expect that the host action was just appended to the action list3876// before this method was called.3877assert(HostAction == AL.back() && "Host action not in the list??");3878HostAction = C.MakeAction<OffloadBundlingJobAction>(OffloadAL);3879recordHostAction(HostAction, InputArg);3880AL.back() = HostAction;3881} else3882AL.append(OffloadAL.begin(), OffloadAL.end());38833884// Propagate to the current host action (if any) the offload information3885// associated with the current input.3886if (HostAction)3887HostAction->propagateHostOffloadInfo(InputArgToOffloadKindMap[InputArg],3888/*BoundArch=*/nullptr);3889return false;3890}38913892void appendDeviceLinkActions(ActionList &AL) {3893for (DeviceActionBuilder *SB : SpecializedBuilders) {3894if (!SB->isValid())3895continue;3896SB->appendLinkDeviceActions(AL);3897}3898}38993900Action *makeHostLinkAction() {3901// Build a list of device linking actions.3902ActionList DeviceAL;3903appendDeviceLinkActions(DeviceAL);3904if (DeviceAL.empty())3905return nullptr;39063907// Let builders add host linking actions.3908Action* HA = nullptr;3909for (DeviceActionBuilder *SB : SpecializedBuilders) {3910if (!SB->isValid())3911continue;3912HA = SB->appendLinkHostActions(DeviceAL);3913// This created host action has no originating input argument, therefore3914// needs to set its offloading kind directly.3915if (HA)3916HA->propagateHostOffloadInfo(SB->getAssociatedOffloadKind(),3917/*BoundArch=*/nullptr);3918}3919return HA;3920}39213922/// Processes the host linker action. This currently consists of replacing it3923/// with an offload action if there are device link objects and propagate to3924/// the host action all the offload kinds used in the current compilation. The3925/// resulting action is returned.3926Action *processHostLinkAction(Action *HostAction) {3927// Add all the dependences from the device linking actions.3928OffloadAction::DeviceDependences DDeps;3929for (auto *SB : SpecializedBuilders) {3930if (!SB->isValid())3931continue;39323933SB->appendLinkDependences(DDeps);3934}39353936// Calculate all the offload kinds used in the current compilation.3937unsigned ActiveOffloadKinds = 0u;3938for (auto &I : InputArgToOffloadKindMap)3939ActiveOffloadKinds |= I.second;39403941// If we don't have device dependencies, we don't have to create an offload3942// action.3943if (DDeps.getActions().empty()) {3944// Set all the active offloading kinds to the link action. Given that it3945// is a link action it is assumed to depend on all actions generated so3946// far.3947HostAction->setHostOffloadInfo(ActiveOffloadKinds,3948/*BoundArch=*/nullptr);3949// Propagate active offloading kinds for each input to the link action.3950// Each input may have different active offloading kind.3951for (auto *A : HostAction->inputs()) {3952auto ArgLoc = HostActionToInputArgMap.find(A);3953if (ArgLoc == HostActionToInputArgMap.end())3954continue;3955auto OFKLoc = InputArgToOffloadKindMap.find(ArgLoc->second);3956if (OFKLoc == InputArgToOffloadKindMap.end())3957continue;3958A->propagateHostOffloadInfo(OFKLoc->second, /*BoundArch=*/nullptr);3959}3960return HostAction;3961}39623963// Create the offload action with all dependences. When an offload action3964// is created the kinds are propagated to the host action, so we don't have3965// to do that explicitly here.3966OffloadAction::HostDependence HDep(3967*HostAction, *C.getSingleOffloadToolChain<Action::OFK_Host>(),3968/*BoundArch*/ nullptr, ActiveOffloadKinds);3969return C.MakeAction<OffloadAction>(HDep, DDeps);3970}3971};3972} // anonymous namespace.39733974void Driver::handleArguments(Compilation &C, DerivedArgList &Args,3975const InputList &Inputs,3976ActionList &Actions) const {39773978// Ignore /Yc/Yu if both /Yc and /Yu passed but with different filenames.3979Arg *YcArg = Args.getLastArg(options::OPT__SLASH_Yc);3980Arg *YuArg = Args.getLastArg(options::OPT__SLASH_Yu);3981if (YcArg && YuArg && strcmp(YcArg->getValue(), YuArg->getValue()) != 0) {3982Diag(clang::diag::warn_drv_ycyu_different_arg_clang_cl);3983Args.eraseArg(options::OPT__SLASH_Yc);3984Args.eraseArg(options::OPT__SLASH_Yu);3985YcArg = YuArg = nullptr;3986}3987if (YcArg && Inputs.size() > 1) {3988Diag(clang::diag::warn_drv_yc_multiple_inputs_clang_cl);3989Args.eraseArg(options::OPT__SLASH_Yc);3990YcArg = nullptr;3991}39923993Arg *FinalPhaseArg;3994phases::ID FinalPhase = getFinalPhase(Args, &FinalPhaseArg);39953996if (FinalPhase == phases::Link) {3997if (Args.hasArgNoClaim(options::OPT_hipstdpar)) {3998Args.AddFlagArg(nullptr, getOpts().getOption(options::OPT_hip_link));3999Args.AddFlagArg(nullptr,4000getOpts().getOption(options::OPT_frtlib_add_rpath));4001}4002// Emitting LLVM while linking disabled except in HIPAMD Toolchain4003if (Args.hasArg(options::OPT_emit_llvm) && !Args.hasArg(options::OPT_hip_link))4004Diag(clang::diag::err_drv_emit_llvm_link);4005if (IsCLMode() && LTOMode != LTOK_None &&4006!Args.getLastArgValue(options::OPT_fuse_ld_EQ)4007.equals_insensitive("lld"))4008Diag(clang::diag::err_drv_lto_without_lld);40094010// If -dumpdir is not specified, give a default prefix derived from the link4011// output filename. For example, `clang -g -gsplit-dwarf a.c -o x` passes4012// `-dumpdir x-` to cc1. If -o is unspecified, use4013// stem(getDefaultImageName()) (usually stem("a.out") = "a").4014if (!Args.hasArg(options::OPT_dumpdir)) {4015Arg *FinalOutput = Args.getLastArg(options::OPT_o, options::OPT__SLASH_o);4016Arg *Arg = Args.MakeSeparateArg(4017nullptr, getOpts().getOption(options::OPT_dumpdir),4018Args.MakeArgString(4019(FinalOutput ? FinalOutput->getValue()4020: llvm::sys::path::stem(getDefaultImageName())) +4021"-"));4022Arg->claim();4023Args.append(Arg);4024}4025}40264027if (FinalPhase == phases::Preprocess || Args.hasArg(options::OPT__SLASH_Y_)) {4028// If only preprocessing or /Y- is used, all pch handling is disabled.4029// Rather than check for it everywhere, just remove clang-cl pch-related4030// flags here.4031Args.eraseArg(options::OPT__SLASH_Fp);4032Args.eraseArg(options::OPT__SLASH_Yc);4033Args.eraseArg(options::OPT__SLASH_Yu);4034YcArg = YuArg = nullptr;4035}40364037unsigned LastPLSize = 0;4038for (auto &I : Inputs) {4039types::ID InputType = I.first;4040const Arg *InputArg = I.second;40414042auto PL = types::getCompilationPhases(InputType);4043LastPLSize = PL.size();40444045// If the first step comes after the final phase we are doing as part of4046// this compilation, warn the user about it.4047phases::ID InitialPhase = PL[0];4048if (InitialPhase > FinalPhase) {4049if (InputArg->isClaimed())4050continue;40514052// Claim here to avoid the more general unused warning.4053InputArg->claim();40544055// Suppress all unused style warnings with -Qunused-arguments4056if (Args.hasArg(options::OPT_Qunused_arguments))4057continue;40584059// Special case when final phase determined by binary name, rather than4060// by a command-line argument with a corresponding Arg.4061if (CCCIsCPP())4062Diag(clang::diag::warn_drv_input_file_unused_by_cpp)4063<< InputArg->getAsString(Args) << getPhaseName(InitialPhase);4064// Special case '-E' warning on a previously preprocessed file to make4065// more sense.4066else if (InitialPhase == phases::Compile &&4067(Args.getLastArg(options::OPT__SLASH_EP,4068options::OPT__SLASH_P) ||4069Args.getLastArg(options::OPT_E) ||4070Args.getLastArg(options::OPT_M, options::OPT_MM)) &&4071getPreprocessedType(InputType) == types::TY_INVALID)4072Diag(clang::diag::warn_drv_preprocessed_input_file_unused)4073<< InputArg->getAsString(Args) << !!FinalPhaseArg4074<< (FinalPhaseArg ? FinalPhaseArg->getOption().getName() : "");4075else4076Diag(clang::diag::warn_drv_input_file_unused)4077<< InputArg->getAsString(Args) << getPhaseName(InitialPhase)4078<< !!FinalPhaseArg4079<< (FinalPhaseArg ? FinalPhaseArg->getOption().getName() : "");4080continue;4081}40824083if (YcArg) {4084// Add a separate precompile phase for the compile phase.4085if (FinalPhase >= phases::Compile) {4086const types::ID HeaderType = lookupHeaderTypeForSourceType(InputType);4087// Build the pipeline for the pch file.4088Action *ClangClPch = C.MakeAction<InputAction>(*InputArg, HeaderType);4089for (phases::ID Phase : types::getCompilationPhases(HeaderType))4090ClangClPch = ConstructPhaseAction(C, Args, Phase, ClangClPch);4091assert(ClangClPch);4092Actions.push_back(ClangClPch);4093// The driver currently exits after the first failed command. This4094// relies on that behavior, to make sure if the pch generation fails,4095// the main compilation won't run.4096// FIXME: If the main compilation fails, the PCH generation should4097// probably not be considered successful either.4098}4099}4100}41014102// If we are linking, claim any options which are obviously only used for4103// compilation.4104// FIXME: Understand why the last Phase List length is used here.4105if (FinalPhase == phases::Link && LastPLSize == 1) {4106Args.ClaimAllArgs(options::OPT_CompileOnly_Group);4107Args.ClaimAllArgs(options::OPT_cl_compile_Group);4108}4109}41104111void Driver::BuildActions(Compilation &C, DerivedArgList &Args,4112const InputList &Inputs, ActionList &Actions) const {4113llvm::PrettyStackTraceString CrashInfo("Building compilation actions");41144115if (!SuppressMissingInputWarning && Inputs.empty()) {4116Diag(clang::diag::err_drv_no_input_files);4117return;4118}41194120// Diagnose misuse of /Fo.4121if (Arg *A = Args.getLastArg(options::OPT__SLASH_Fo)) {4122StringRef V = A->getValue();4123if (Inputs.size() > 1 && !V.empty() &&4124!llvm::sys::path::is_separator(V.back())) {4125// Check whether /Fo tries to name an output file for multiple inputs.4126Diag(clang::diag::err_drv_out_file_argument_with_multiple_sources)4127<< A->getSpelling() << V;4128Args.eraseArg(options::OPT__SLASH_Fo);4129}4130}41314132// Diagnose misuse of /Fa.4133if (Arg *A = Args.getLastArg(options::OPT__SLASH_Fa)) {4134StringRef V = A->getValue();4135if (Inputs.size() > 1 && !V.empty() &&4136!llvm::sys::path::is_separator(V.back())) {4137// Check whether /Fa tries to name an asm file for multiple inputs.4138Diag(clang::diag::err_drv_out_file_argument_with_multiple_sources)4139<< A->getSpelling() << V;4140Args.eraseArg(options::OPT__SLASH_Fa);4141}4142}41434144// Diagnose misuse of /o.4145if (Arg *A = Args.getLastArg(options::OPT__SLASH_o)) {4146if (A->getValue()[0] == '\0') {4147// It has to have a value.4148Diag(clang::diag::err_drv_missing_argument) << A->getSpelling() << 1;4149Args.eraseArg(options::OPT__SLASH_o);4150}4151}41524153handleArguments(C, Args, Inputs, Actions);41544155bool UseNewOffloadingDriver =4156C.isOffloadingHostKind(Action::OFK_OpenMP) ||4157Args.hasFlag(options::OPT_offload_new_driver,4158options::OPT_no_offload_new_driver, false);41594160// Builder to be used to build offloading actions.4161std::unique_ptr<OffloadingActionBuilder> OffloadBuilder =4162!UseNewOffloadingDriver4163? std::make_unique<OffloadingActionBuilder>(C, Args, Inputs)4164: nullptr;41654166// Construct the actions to perform.4167ExtractAPIJobAction *ExtractAPIAction = nullptr;4168ActionList LinkerInputs;4169ActionList MergerInputs;41704171for (auto &I : Inputs) {4172types::ID InputType = I.first;4173const Arg *InputArg = I.second;41744175auto PL = types::getCompilationPhases(*this, Args, InputType);4176if (PL.empty())4177continue;41784179auto FullPL = types::getCompilationPhases(InputType);41804181// Build the pipeline for this file.4182Action *Current = C.MakeAction<InputAction>(*InputArg, InputType);41834184// Use the current host action in any of the offloading actions, if4185// required.4186if (!UseNewOffloadingDriver)4187if (OffloadBuilder->addHostDependenceToDeviceActions(Current, InputArg))4188break;41894190for (phases::ID Phase : PL) {41914192// Add any offload action the host action depends on.4193if (!UseNewOffloadingDriver)4194Current = OffloadBuilder->addDeviceDependencesToHostAction(4195Current, InputArg, Phase, PL.back(), FullPL);4196if (!Current)4197break;41984199// Queue linker inputs.4200if (Phase == phases::Link) {4201assert(Phase == PL.back() && "linking must be final compilation step.");4202// We don't need to generate additional link commands if emitting AMD4203// bitcode or compiling only for the offload device4204if (!(C.getInputArgs().hasArg(options::OPT_hip_link) &&4205(C.getInputArgs().hasArg(options::OPT_emit_llvm))) &&4206!offloadDeviceOnly())4207LinkerInputs.push_back(Current);4208Current = nullptr;4209break;4210}42114212// TODO: Consider removing this because the merged may not end up being4213// the final Phase in the pipeline. Perhaps the merged could just merge4214// and then pass an artifact of some sort to the Link Phase.4215// Queue merger inputs.4216if (Phase == phases::IfsMerge) {4217assert(Phase == PL.back() && "merging must be final compilation step.");4218MergerInputs.push_back(Current);4219Current = nullptr;4220break;4221}42224223if (Phase == phases::Precompile && ExtractAPIAction) {4224ExtractAPIAction->addHeaderInput(Current);4225Current = nullptr;4226break;4227}42284229// FIXME: Should we include any prior module file outputs as inputs of4230// later actions in the same command line?42314232// Otherwise construct the appropriate action.4233Action *NewCurrent = ConstructPhaseAction(C, Args, Phase, Current);42344235// We didn't create a new action, so we will just move to the next phase.4236if (NewCurrent == Current)4237continue;42384239if (auto *EAA = dyn_cast<ExtractAPIJobAction>(NewCurrent))4240ExtractAPIAction = EAA;42414242Current = NewCurrent;42434244// Try to build the offloading actions and add the result as a dependency4245// to the host.4246if (UseNewOffloadingDriver)4247Current = BuildOffloadingActions(C, Args, I, Current);4248// Use the current host action in any of the offloading actions, if4249// required.4250else if (OffloadBuilder->addHostDependenceToDeviceActions(Current,4251InputArg))4252break;42534254if (Current->getType() == types::TY_Nothing)4255break;4256}42574258// If we ended with something, add to the output list.4259if (Current)4260Actions.push_back(Current);42614262// Add any top level actions generated for offloading.4263if (!UseNewOffloadingDriver)4264OffloadBuilder->appendTopLevelActions(Actions, Current, InputArg);4265else if (Current)4266Current->propagateHostOffloadInfo(C.getActiveOffloadKinds(),4267/*BoundArch=*/nullptr);4268}42694270// Add a link action if necessary.42714272if (LinkerInputs.empty()) {4273Arg *FinalPhaseArg;4274if (getFinalPhase(Args, &FinalPhaseArg) == phases::Link)4275if (!UseNewOffloadingDriver)4276OffloadBuilder->appendDeviceLinkActions(Actions);4277}42784279if (!LinkerInputs.empty()) {4280if (!UseNewOffloadingDriver)4281if (Action *Wrapper = OffloadBuilder->makeHostLinkAction())4282LinkerInputs.push_back(Wrapper);4283Action *LA;4284// Check if this Linker Job should emit a static library.4285if (ShouldEmitStaticLibrary(Args)) {4286LA = C.MakeAction<StaticLibJobAction>(LinkerInputs, types::TY_Image);4287} else if (UseNewOffloadingDriver ||4288Args.hasArg(options::OPT_offload_link)) {4289LA = C.MakeAction<LinkerWrapperJobAction>(LinkerInputs, types::TY_Image);4290LA->propagateHostOffloadInfo(C.getActiveOffloadKinds(),4291/*BoundArch=*/nullptr);4292} else {4293LA = C.MakeAction<LinkJobAction>(LinkerInputs, types::TY_Image);4294}4295if (!UseNewOffloadingDriver)4296LA = OffloadBuilder->processHostLinkAction(LA);4297Actions.push_back(LA);4298}42994300// Add an interface stubs merge action if necessary.4301if (!MergerInputs.empty())4302Actions.push_back(4303C.MakeAction<IfsMergeJobAction>(MergerInputs, types::TY_Image));43044305if (Args.hasArg(options::OPT_emit_interface_stubs)) {4306auto PhaseList = types::getCompilationPhases(4307types::TY_IFS_CPP,4308Args.hasArg(options::OPT_c) ? phases::Compile : phases::IfsMerge);43094310ActionList MergerInputs;43114312for (auto &I : Inputs) {4313types::ID InputType = I.first;4314const Arg *InputArg = I.second;43154316// Currently clang and the llvm assembler do not support generating symbol4317// stubs from assembly, so we skip the input on asm files. For ifs files4318// we rely on the normal pipeline setup in the pipeline setup code above.4319if (InputType == types::TY_IFS || InputType == types::TY_PP_Asm ||4320InputType == types::TY_Asm)4321continue;43224323Action *Current = C.MakeAction<InputAction>(*InputArg, InputType);43244325for (auto Phase : PhaseList) {4326switch (Phase) {4327default:4328llvm_unreachable(4329"IFS Pipeline can only consist of Compile followed by IfsMerge.");4330case phases::Compile: {4331// Only IfsMerge (llvm-ifs) can handle .o files by looking for ifs4332// files where the .o file is located. The compile action can not4333// handle this.4334if (InputType == types::TY_Object)4335break;43364337Current = C.MakeAction<CompileJobAction>(Current, types::TY_IFS_CPP);4338break;4339}4340case phases::IfsMerge: {4341assert(Phase == PhaseList.back() &&4342"merging must be final compilation step.");4343MergerInputs.push_back(Current);4344Current = nullptr;4345break;4346}4347}4348}43494350// If we ended with something, add to the output list.4351if (Current)4352Actions.push_back(Current);4353}43544355// Add an interface stubs merge action if necessary.4356if (!MergerInputs.empty())4357Actions.push_back(4358C.MakeAction<IfsMergeJobAction>(MergerInputs, types::TY_Image));4359}43604361for (auto Opt : {options::OPT_print_supported_cpus,4362options::OPT_print_supported_extensions,4363options::OPT_print_enabled_extensions}) {4364// If --print-supported-cpus, -mcpu=? or -mtune=? is specified, build a4365// custom Compile phase that prints out supported cpu models and quits.4366//4367// If either --print-supported-extensions or --print-enabled-extensions is4368// specified, call the corresponding helper function that prints out the4369// supported/enabled extensions and quits.4370if (Arg *A = Args.getLastArg(Opt)) {4371if (Opt == options::OPT_print_supported_extensions &&4372!C.getDefaultToolChain().getTriple().isRISCV() &&4373!C.getDefaultToolChain().getTriple().isAArch64() &&4374!C.getDefaultToolChain().getTriple().isARM()) {4375C.getDriver().Diag(diag::err_opt_not_valid_on_target)4376<< "--print-supported-extensions";4377return;4378}4379if (Opt == options::OPT_print_enabled_extensions &&4380!C.getDefaultToolChain().getTriple().isRISCV() &&4381!C.getDefaultToolChain().getTriple().isAArch64()) {4382C.getDriver().Diag(diag::err_opt_not_valid_on_target)4383<< "--print-enabled-extensions";4384return;4385}43864387// Use the -mcpu=? flag as the dummy input to cc1.4388Actions.clear();4389Action *InputAc = C.MakeAction<InputAction>(*A, types::TY_C);4390Actions.push_back(4391C.MakeAction<PrecompileJobAction>(InputAc, types::TY_Nothing));4392for (auto &I : Inputs)4393I.second->claim();4394}4395}43964397// Call validator for dxil when -Vd not in Args.4398if (C.getDefaultToolChain().getTriple().isDXIL()) {4399// Only add action when needValidation.4400const auto &TC =4401static_cast<const toolchains::HLSLToolChain &>(C.getDefaultToolChain());4402if (TC.requiresValidation(Args)) {4403Action *LastAction = Actions.back();4404Actions.push_back(C.MakeAction<BinaryAnalyzeJobAction>(4405LastAction, types::TY_DX_CONTAINER));4406}4407}44084409// Claim ignored clang-cl options.4410Args.ClaimAllArgs(options::OPT_cl_ignored_Group);4411}44124413/// Returns the canonical name for the offloading architecture when using a HIP4414/// or CUDA architecture.4415static StringRef getCanonicalArchString(Compilation &C,4416const llvm::opt::DerivedArgList &Args,4417StringRef ArchStr,4418const llvm::Triple &Triple,4419bool SuppressError = false) {4420// Lookup the CUDA / HIP architecture string. Only report an error if we were4421// expecting the triple to be only NVPTX / AMDGPU.4422OffloadArch Arch =4423StringToOffloadArch(getProcessorFromTargetID(Triple, ArchStr));4424if (!SuppressError && Triple.isNVPTX() &&4425(Arch == OffloadArch::UNKNOWN || !IsNVIDIAOffloadArch(Arch))) {4426C.getDriver().Diag(clang::diag::err_drv_offload_bad_gpu_arch)4427<< "CUDA" << ArchStr;4428return StringRef();4429} else if (!SuppressError && Triple.isAMDGPU() &&4430(Arch == OffloadArch::UNKNOWN || !IsAMDOffloadArch(Arch))) {4431C.getDriver().Diag(clang::diag::err_drv_offload_bad_gpu_arch)4432<< "HIP" << ArchStr;4433return StringRef();4434}44354436if (IsNVIDIAOffloadArch(Arch))4437return Args.MakeArgStringRef(OffloadArchToString(Arch));44384439if (IsAMDOffloadArch(Arch)) {4440llvm::StringMap<bool> Features;4441auto HIPTriple = getHIPOffloadTargetTriple(C.getDriver(), C.getInputArgs());4442if (!HIPTriple)4443return StringRef();4444auto Arch = parseTargetID(*HIPTriple, ArchStr, &Features);4445if (!Arch) {4446C.getDriver().Diag(clang::diag::err_drv_bad_target_id) << ArchStr;4447C.setContainsError();4448return StringRef();4449}4450return Args.MakeArgStringRef(getCanonicalTargetID(*Arch, Features));4451}44524453// If the input isn't CUDA or HIP just return the architecture.4454return ArchStr;4455}44564457/// Checks if the set offloading architectures does not conflict. Returns the4458/// incompatible pair if a conflict occurs.4459static std::optional<std::pair<llvm::StringRef, llvm::StringRef>>4460getConflictOffloadArchCombination(const llvm::DenseSet<StringRef> &Archs,4461llvm::Triple Triple) {4462if (!Triple.isAMDGPU())4463return std::nullopt;44644465std::set<StringRef> ArchSet;4466llvm::copy(Archs, std::inserter(ArchSet, ArchSet.begin()));4467return getConflictTargetIDCombination(ArchSet);4468}44694470llvm::DenseSet<StringRef>4471Driver::getOffloadArchs(Compilation &C, const llvm::opt::DerivedArgList &Args,4472Action::OffloadKind Kind, const ToolChain *TC,4473bool SuppressError) const {4474if (!TC)4475TC = &C.getDefaultToolChain();44764477// --offload and --offload-arch options are mutually exclusive.4478if (Args.hasArgNoClaim(options::OPT_offload_EQ) &&4479Args.hasArgNoClaim(options::OPT_offload_arch_EQ,4480options::OPT_no_offload_arch_EQ)) {4481C.getDriver().Diag(diag::err_opt_not_valid_with_opt)4482<< "--offload"4483<< (Args.hasArgNoClaim(options::OPT_offload_arch_EQ)4484? "--offload-arch"4485: "--no-offload-arch");4486}44874488if (KnownArchs.contains(TC))4489return KnownArchs.lookup(TC);44904491llvm::DenseSet<StringRef> Archs;4492for (auto *Arg : Args) {4493// Extract any '--[no-]offload-arch' arguments intended for this toolchain.4494std::unique_ptr<llvm::opt::Arg> ExtractedArg = nullptr;4495if (Arg->getOption().matches(options::OPT_Xopenmp_target_EQ) &&4496ToolChain::getOpenMPTriple(Arg->getValue(0)) == TC->getTriple()) {4497Arg->claim();4498unsigned Index = Args.getBaseArgs().MakeIndex(Arg->getValue(1));4499ExtractedArg = getOpts().ParseOneArg(Args, Index);4500Arg = ExtractedArg.get();4501}45024503// Add or remove the seen architectures in order of appearance. If an4504// invalid architecture is given we simply exit.4505if (Arg->getOption().matches(options::OPT_offload_arch_EQ)) {4506for (StringRef Arch : llvm::split(Arg->getValue(), ",")) {4507if (Arch == "native" || Arch.empty()) {4508auto GPUsOrErr = TC->getSystemGPUArchs(Args);4509if (!GPUsOrErr) {4510if (SuppressError)4511llvm::consumeError(GPUsOrErr.takeError());4512else4513TC->getDriver().Diag(diag::err_drv_undetermined_gpu_arch)4514<< llvm::Triple::getArchTypeName(TC->getArch())4515<< llvm::toString(GPUsOrErr.takeError()) << "--offload-arch";4516continue;4517}45184519for (auto ArchStr : *GPUsOrErr) {4520Archs.insert(4521getCanonicalArchString(C, Args, Args.MakeArgString(ArchStr),4522TC->getTriple(), SuppressError));4523}4524} else {4525StringRef ArchStr = getCanonicalArchString(4526C, Args, Arch, TC->getTriple(), SuppressError);4527if (ArchStr.empty())4528return Archs;4529Archs.insert(ArchStr);4530}4531}4532} else if (Arg->getOption().matches(options::OPT_no_offload_arch_EQ)) {4533for (StringRef Arch : llvm::split(Arg->getValue(), ",")) {4534if (Arch == "all") {4535Archs.clear();4536} else {4537StringRef ArchStr = getCanonicalArchString(4538C, Args, Arch, TC->getTriple(), SuppressError);4539if (ArchStr.empty())4540return Archs;4541Archs.erase(ArchStr);4542}4543}4544}4545}45464547if (auto ConflictingArchs =4548getConflictOffloadArchCombination(Archs, TC->getTriple())) {4549C.getDriver().Diag(clang::diag::err_drv_bad_offload_arch_combo)4550<< ConflictingArchs->first << ConflictingArchs->second;4551C.setContainsError();4552}45534554// Skip filling defaults if we're just querying what is availible.4555if (SuppressError)4556return Archs;45574558if (Archs.empty()) {4559if (Kind == Action::OFK_Cuda)4560Archs.insert(OffloadArchToString(OffloadArch::CudaDefault));4561else if (Kind == Action::OFK_HIP)4562Archs.insert(OffloadArchToString(OffloadArch::HIPDefault));4563else if (Kind == Action::OFK_OpenMP)4564Archs.insert(StringRef());4565} else {4566Args.ClaimAllArgs(options::OPT_offload_arch_EQ);4567Args.ClaimAllArgs(options::OPT_no_offload_arch_EQ);4568}45694570return Archs;4571}45724573Action *Driver::BuildOffloadingActions(Compilation &C,4574llvm::opt::DerivedArgList &Args,4575const InputTy &Input,4576Action *HostAction) const {4577// Don't build offloading actions if explicitly disabled or we do not have a4578// valid source input and compile action to embed it in. If preprocessing only4579// ignore embedding.4580if (offloadHostOnly() || !types::isSrcFile(Input.first) ||4581!(isa<CompileJobAction>(HostAction) ||4582getFinalPhase(Args) == phases::Preprocess))4583return HostAction;45844585ActionList OffloadActions;4586OffloadAction::DeviceDependences DDeps;45874588const Action::OffloadKind OffloadKinds[] = {4589Action::OFK_OpenMP, Action::OFK_Cuda, Action::OFK_HIP};45904591for (Action::OffloadKind Kind : OffloadKinds) {4592SmallVector<const ToolChain *, 2> ToolChains;4593ActionList DeviceActions;45944595auto TCRange = C.getOffloadToolChains(Kind);4596for (auto TI = TCRange.first, TE = TCRange.second; TI != TE; ++TI)4597ToolChains.push_back(TI->second);45984599if (ToolChains.empty())4600continue;46014602types::ID InputType = Input.first;4603const Arg *InputArg = Input.second;46044605// The toolchain can be active for unsupported file types.4606if ((Kind == Action::OFK_Cuda && !types::isCuda(InputType)) ||4607(Kind == Action::OFK_HIP && !types::isHIP(InputType)))4608continue;46094610// Get the product of all bound architectures and toolchains.4611SmallVector<std::pair<const ToolChain *, StringRef>> TCAndArchs;4612for (const ToolChain *TC : ToolChains) {4613llvm::DenseSet<StringRef> Arches = getOffloadArchs(C, Args, Kind, TC);4614SmallVector<StringRef, 0> Sorted(Arches.begin(), Arches.end());4615llvm::sort(Sorted);4616for (StringRef Arch : Sorted)4617TCAndArchs.push_back(std::make_pair(TC, Arch));4618}46194620for (unsigned I = 0, E = TCAndArchs.size(); I != E; ++I)4621DeviceActions.push_back(C.MakeAction<InputAction>(*InputArg, InputType));46224623if (DeviceActions.empty())4624return HostAction;46254626auto PL = types::getCompilationPhases(*this, Args, InputType);46274628for (phases::ID Phase : PL) {4629if (Phase == phases::Link) {4630assert(Phase == PL.back() && "linking must be final compilation step.");4631break;4632}46334634auto TCAndArch = TCAndArchs.begin();4635for (Action *&A : DeviceActions) {4636if (A->getType() == types::TY_Nothing)4637continue;46384639// Propagate the ToolChain so we can use it in ConstructPhaseAction.4640A->propagateDeviceOffloadInfo(Kind, TCAndArch->second.data(),4641TCAndArch->first);4642A = ConstructPhaseAction(C, Args, Phase, A, Kind);46434644if (isa<CompileJobAction>(A) && isa<CompileJobAction>(HostAction) &&4645Kind == Action::OFK_OpenMP &&4646HostAction->getType() != types::TY_Nothing) {4647// OpenMP offloading has a dependency on the host compile action to4648// identify which declarations need to be emitted. This shouldn't be4649// collapsed with any other actions so we can use it in the device.4650HostAction->setCannotBeCollapsedWithNextDependentAction();4651OffloadAction::HostDependence HDep(4652*HostAction, *C.getSingleOffloadToolChain<Action::OFK_Host>(),4653TCAndArch->second.data(), Kind);4654OffloadAction::DeviceDependences DDep;4655DDep.add(*A, *TCAndArch->first, TCAndArch->second.data(), Kind);4656A = C.MakeAction<OffloadAction>(HDep, DDep);4657}46584659++TCAndArch;4660}4661}46624663// Compiling HIP in non-RDC mode requires linking each action individually.4664for (Action *&A : DeviceActions) {4665if ((A->getType() != types::TY_Object &&4666A->getType() != types::TY_LTO_BC) ||4667Kind != Action::OFK_HIP ||4668Args.hasFlag(options::OPT_fgpu_rdc, options::OPT_fno_gpu_rdc, false))4669continue;4670ActionList LinkerInput = {A};4671A = C.MakeAction<LinkJobAction>(LinkerInput, types::TY_Image);4672}46734674auto TCAndArch = TCAndArchs.begin();4675for (Action *A : DeviceActions) {4676DDeps.add(*A, *TCAndArch->first, TCAndArch->second.data(), Kind);4677OffloadAction::DeviceDependences DDep;4678DDep.add(*A, *TCAndArch->first, TCAndArch->second.data(), Kind);46794680// Compiling CUDA in non-RDC mode uses the PTX output if available.4681for (Action *Input : A->getInputs())4682if (Kind == Action::OFK_Cuda && A->getType() == types::TY_Object &&4683!Args.hasFlag(options::OPT_fgpu_rdc, options::OPT_fno_gpu_rdc,4684false))4685DDep.add(*Input, *TCAndArch->first, TCAndArch->second.data(), Kind);4686OffloadActions.push_back(C.MakeAction<OffloadAction>(DDep, A->getType()));46874688++TCAndArch;4689}4690}46914692// HIP code in non-RDC mode will bundle the output if it invoked the linker.4693bool ShouldBundleHIP =4694C.isOffloadingHostKind(Action::OFK_HIP) &&4695Args.hasFlag(options::OPT_gpu_bundle_output,4696options::OPT_no_gpu_bundle_output, true) &&4697!Args.hasFlag(options::OPT_fgpu_rdc, options::OPT_fno_gpu_rdc, false) &&4698!llvm::any_of(OffloadActions,4699[](Action *A) { return A->getType() != types::TY_Image; });47004701// All kinds exit now in device-only mode except for non-RDC mode HIP.4702if (offloadDeviceOnly() && !ShouldBundleHIP)4703return C.MakeAction<OffloadAction>(DDeps, types::TY_Nothing);47044705if (OffloadActions.empty())4706return HostAction;47074708OffloadAction::DeviceDependences DDep;4709if (C.isOffloadingHostKind(Action::OFK_Cuda) &&4710!Args.hasFlag(options::OPT_fgpu_rdc, options::OPT_fno_gpu_rdc, false)) {4711// If we are not in RDC-mode we just emit the final CUDA fatbinary for4712// each translation unit without requiring any linking.4713Action *FatbinAction =4714C.MakeAction<LinkJobAction>(OffloadActions, types::TY_CUDA_FATBIN);4715DDep.add(*FatbinAction, *C.getSingleOffloadToolChain<Action::OFK_Cuda>(),4716nullptr, Action::OFK_Cuda);4717} else if (C.isOffloadingHostKind(Action::OFK_HIP) &&4718!Args.hasFlag(options::OPT_fgpu_rdc, options::OPT_fno_gpu_rdc,4719false)) {4720// If we are not in RDC-mode we just emit the final HIP fatbinary for each4721// translation unit, linking each input individually.4722Action *FatbinAction =4723C.MakeAction<LinkJobAction>(OffloadActions, types::TY_HIP_FATBIN);4724DDep.add(*FatbinAction, *C.getSingleOffloadToolChain<Action::OFK_HIP>(),4725nullptr, Action::OFK_HIP);4726} else {4727// Package all the offloading actions into a single output that can be4728// embedded in the host and linked.4729Action *PackagerAction =4730C.MakeAction<OffloadPackagerJobAction>(OffloadActions, types::TY_Image);4731DDep.add(*PackagerAction, *C.getSingleOffloadToolChain<Action::OFK_Host>(),4732nullptr, C.getActiveOffloadKinds());4733}47344735// HIP wants '--offload-device-only' to create a fatbinary by default.4736if (offloadDeviceOnly())4737return C.MakeAction<OffloadAction>(DDep, types::TY_Nothing);47384739// If we are unable to embed a single device output into the host, we need to4740// add each device output as a host dependency to ensure they are still built.4741bool SingleDeviceOutput = !llvm::any_of(OffloadActions, [](Action *A) {4742return A->getType() == types::TY_Nothing;4743}) && isa<CompileJobAction>(HostAction);4744OffloadAction::HostDependence HDep(4745*HostAction, *C.getSingleOffloadToolChain<Action::OFK_Host>(),4746/*BoundArch=*/nullptr, SingleDeviceOutput ? DDep : DDeps);4747return C.MakeAction<OffloadAction>(HDep, SingleDeviceOutput ? DDep : DDeps);4748}47494750Action *Driver::ConstructPhaseAction(4751Compilation &C, const ArgList &Args, phases::ID Phase, Action *Input,4752Action::OffloadKind TargetDeviceOffloadKind) const {4753llvm::PrettyStackTraceString CrashInfo("Constructing phase actions");47544755// Some types skip the assembler phase (e.g., llvm-bc), but we can't4756// encode this in the steps because the intermediate type depends on4757// arguments. Just special case here.4758if (Phase == phases::Assemble && Input->getType() != types::TY_PP_Asm)4759return Input;47604761// Build the appropriate action.4762switch (Phase) {4763case phases::Link:4764llvm_unreachable("link action invalid here.");4765case phases::IfsMerge:4766llvm_unreachable("ifsmerge action invalid here.");4767case phases::Preprocess: {4768types::ID OutputTy;4769// -M and -MM specify the dependency file name by altering the output type,4770// -if -MD and -MMD are not specified.4771if (Args.hasArg(options::OPT_M, options::OPT_MM) &&4772!Args.hasArg(options::OPT_MD, options::OPT_MMD)) {4773OutputTy = types::TY_Dependencies;4774} else {4775OutputTy = Input->getType();4776// For these cases, the preprocessor is only translating forms, the Output4777// still needs preprocessing.4778if (!Args.hasFlag(options::OPT_frewrite_includes,4779options::OPT_fno_rewrite_includes, false) &&4780!Args.hasFlag(options::OPT_frewrite_imports,4781options::OPT_fno_rewrite_imports, false) &&4782!Args.hasFlag(options::OPT_fdirectives_only,4783options::OPT_fno_directives_only, false) &&4784!CCGenDiagnostics)4785OutputTy = types::getPreprocessedType(OutputTy);4786assert(OutputTy != types::TY_INVALID &&4787"Cannot preprocess this input type!");4788}4789return C.MakeAction<PreprocessJobAction>(Input, OutputTy);4790}4791case phases::Precompile: {4792// API extraction should not generate an actual precompilation action.4793if (Args.hasArg(options::OPT_extract_api))4794return C.MakeAction<ExtractAPIJobAction>(Input, types::TY_API_INFO);47954796// With 'fexperimental-modules-reduced-bmi', we don't want to run the4797// precompile phase unless the user specified '--precompile'. In the case4798// the '--precompile' flag is enabled, we will try to emit the reduced BMI4799// as a by product in GenerateModuleInterfaceAction.4800if (Args.hasArg(options::OPT_modules_reduced_bmi) &&4801!Args.getLastArg(options::OPT__precompile))4802return Input;48034804types::ID OutputTy = getPrecompiledType(Input->getType());4805assert(OutputTy != types::TY_INVALID &&4806"Cannot precompile this input type!");48074808// If we're given a module name, precompile header file inputs as a4809// module, not as a precompiled header.4810const char *ModName = nullptr;4811if (OutputTy == types::TY_PCH) {4812if (Arg *A = Args.getLastArg(options::OPT_fmodule_name_EQ))4813ModName = A->getValue();4814if (ModName)4815OutputTy = types::TY_ModuleFile;4816}48174818if (Args.hasArg(options::OPT_fsyntax_only)) {4819// Syntax checks should not emit a PCH file4820OutputTy = types::TY_Nothing;4821}48224823return C.MakeAction<PrecompileJobAction>(Input, OutputTy);4824}4825case phases::Compile: {4826if (Args.hasArg(options::OPT_fsyntax_only))4827return C.MakeAction<CompileJobAction>(Input, types::TY_Nothing);4828if (Args.hasArg(options::OPT_rewrite_objc))4829return C.MakeAction<CompileJobAction>(Input, types::TY_RewrittenObjC);4830if (Args.hasArg(options::OPT_rewrite_legacy_objc))4831return C.MakeAction<CompileJobAction>(Input,4832types::TY_RewrittenLegacyObjC);4833if (Args.hasArg(options::OPT__analyze))4834return C.MakeAction<AnalyzeJobAction>(Input, types::TY_Plist);4835if (Args.hasArg(options::OPT__migrate))4836return C.MakeAction<MigrateJobAction>(Input, types::TY_Remap);4837if (Args.hasArg(options::OPT_emit_ast))4838return C.MakeAction<CompileJobAction>(Input, types::TY_AST);4839if (Args.hasArg(options::OPT_emit_cir))4840return C.MakeAction<CompileJobAction>(Input, types::TY_CIR);4841if (Args.hasArg(options::OPT_module_file_info))4842return C.MakeAction<CompileJobAction>(Input, types::TY_ModuleFile);4843if (Args.hasArg(options::OPT_verify_pch))4844return C.MakeAction<VerifyPCHJobAction>(Input, types::TY_Nothing);4845if (Args.hasArg(options::OPT_extract_api))4846return C.MakeAction<ExtractAPIJobAction>(Input, types::TY_API_INFO);4847return C.MakeAction<CompileJobAction>(Input, types::TY_LLVM_BC);4848}4849case phases::Backend: {4850if (isUsingLTO() && TargetDeviceOffloadKind == Action::OFK_None) {4851types::ID Output;4852if (Args.hasArg(options::OPT_ffat_lto_objects) &&4853!Args.hasArg(options::OPT_emit_llvm))4854Output = types::TY_PP_Asm;4855else if (Args.hasArg(options::OPT_S))4856Output = types::TY_LTO_IR;4857else4858Output = types::TY_LTO_BC;4859return C.MakeAction<BackendJobAction>(Input, Output);4860}4861if (isUsingLTO(/* IsOffload */ true) &&4862TargetDeviceOffloadKind != Action::OFK_None) {4863types::ID Output =4864Args.hasArg(options::OPT_S) ? types::TY_LTO_IR : types::TY_LTO_BC;4865return C.MakeAction<BackendJobAction>(Input, Output);4866}4867if (Args.hasArg(options::OPT_emit_llvm) ||4868(((Input->getOffloadingToolChain() &&4869Input->getOffloadingToolChain()->getTriple().isAMDGPU()) ||4870TargetDeviceOffloadKind == Action::OFK_HIP) &&4871(Args.hasFlag(options::OPT_fgpu_rdc, options::OPT_fno_gpu_rdc,4872false) ||4873TargetDeviceOffloadKind == Action::OFK_OpenMP))) {4874types::ID Output =4875Args.hasArg(options::OPT_S) &&4876(TargetDeviceOffloadKind == Action::OFK_None ||4877offloadDeviceOnly() ||4878(TargetDeviceOffloadKind == Action::OFK_HIP &&4879!Args.hasFlag(options::OPT_offload_new_driver,4880options::OPT_no_offload_new_driver, false)))4881? types::TY_LLVM_IR4882: types::TY_LLVM_BC;4883return C.MakeAction<BackendJobAction>(Input, Output);4884}4885return C.MakeAction<BackendJobAction>(Input, types::TY_PP_Asm);4886}4887case phases::Assemble:4888return C.MakeAction<AssembleJobAction>(std::move(Input), types::TY_Object);4889}48904891llvm_unreachable("invalid phase in ConstructPhaseAction");4892}48934894void Driver::BuildJobs(Compilation &C) const {4895llvm::PrettyStackTraceString CrashInfo("Building compilation jobs");48964897Arg *FinalOutput = C.getArgs().getLastArg(options::OPT_o);48984899// It is an error to provide a -o option if we are making multiple output4900// files. There are exceptions:4901//4902// IfsMergeJob: when generating interface stubs enabled we want to be able to4903// generate the stub file at the same time that we generate the real4904// library/a.out. So when a .o, .so, etc are the output, with clang interface4905// stubs there will also be a .ifs and .ifso at the same location.4906//4907// CompileJob of type TY_IFS_CPP: when generating interface stubs is enabled4908// and -c is passed, we still want to be able to generate a .ifs file while4909// we are also generating .o files. So we allow more than one output file in4910// this case as well.4911//4912// OffloadClass of type TY_Nothing: device-only output will place many outputs4913// into a single offloading action. We should count all inputs to the action4914// as outputs. Also ignore device-only outputs if we're compiling with4915// -fsyntax-only.4916if (FinalOutput) {4917unsigned NumOutputs = 0;4918unsigned NumIfsOutputs = 0;4919for (const Action *A : C.getActions()) {4920if (A->getType() != types::TY_Nothing &&4921A->getType() != types::TY_DX_CONTAINER &&4922!(A->getKind() == Action::IfsMergeJobClass ||4923(A->getType() == clang::driver::types::TY_IFS_CPP &&4924A->getKind() == clang::driver::Action::CompileJobClass &&49250 == NumIfsOutputs++) ||4926(A->getKind() == Action::BindArchClass && A->getInputs().size() &&4927A->getInputs().front()->getKind() == Action::IfsMergeJobClass)))4928++NumOutputs;4929else if (A->getKind() == Action::OffloadClass &&4930A->getType() == types::TY_Nothing &&4931!C.getArgs().hasArg(options::OPT_fsyntax_only))4932NumOutputs += A->size();4933}49344935if (NumOutputs > 1) {4936Diag(clang::diag::err_drv_output_argument_with_multiple_files);4937FinalOutput = nullptr;4938}4939}49404941const llvm::Triple &RawTriple = C.getDefaultToolChain().getTriple();49424943// Collect the list of architectures.4944llvm::StringSet<> ArchNames;4945if (RawTriple.isOSBinFormatMachO())4946for (const Arg *A : C.getArgs())4947if (A->getOption().matches(options::OPT_arch))4948ArchNames.insert(A->getValue());49494950// Set of (Action, canonical ToolChain triple) pairs we've built jobs for.4951std::map<std::pair<const Action *, std::string>, InputInfoList> CachedResults;4952for (Action *A : C.getActions()) {4953// If we are linking an image for multiple archs then the linker wants4954// -arch_multiple and -final_output <final image name>. Unfortunately, this4955// doesn't fit in cleanly because we have to pass this information down.4956//4957// FIXME: This is a hack; find a cleaner way to integrate this into the4958// process.4959const char *LinkingOutput = nullptr;4960if (isa<LipoJobAction>(A)) {4961if (FinalOutput)4962LinkingOutput = FinalOutput->getValue();4963else4964LinkingOutput = getDefaultImageName();4965}49664967BuildJobsForAction(C, A, &C.getDefaultToolChain(),4968/*BoundArch*/ StringRef(),4969/*AtTopLevel*/ true,4970/*MultipleArchs*/ ArchNames.size() > 1,4971/*LinkingOutput*/ LinkingOutput, CachedResults,4972/*TargetDeviceOffloadKind*/ Action::OFK_None);4973}49744975// If we have more than one job, then disable integrated-cc1 for now. Do this4976// also when we need to report process execution statistics.4977if (C.getJobs().size() > 1 || CCPrintProcessStats)4978for (auto &J : C.getJobs())4979J.InProcess = false;49804981if (CCPrintProcessStats) {4982C.setPostCallback([=](const Command &Cmd, int Res) {4983std::optional<llvm::sys::ProcessStatistics> ProcStat =4984Cmd.getProcessStatistics();4985if (!ProcStat)4986return;49874988const char *LinkingOutput = nullptr;4989if (FinalOutput)4990LinkingOutput = FinalOutput->getValue();4991else if (!Cmd.getOutputFilenames().empty())4992LinkingOutput = Cmd.getOutputFilenames().front().c_str();4993else4994LinkingOutput = getDefaultImageName();49954996if (CCPrintStatReportFilename.empty()) {4997using namespace llvm;4998// Human readable output.4999outs() << sys::path::filename(Cmd.getExecutable()) << ": "5000<< "output=" << LinkingOutput;5001outs() << ", total="5002<< format("%.3f", ProcStat->TotalTime.count() / 1000.) << " ms"5003<< ", user="5004<< format("%.3f", ProcStat->UserTime.count() / 1000.) << " ms"5005<< ", mem=" << ProcStat->PeakMemory << " Kb\n";5006} else {5007// CSV format.5008std::string Buffer;5009llvm::raw_string_ostream Out(Buffer);5010llvm::sys::printArg(Out, llvm::sys::path::filename(Cmd.getExecutable()),5011/*Quote*/ true);5012Out << ',';5013llvm::sys::printArg(Out, LinkingOutput, true);5014Out << ',' << ProcStat->TotalTime.count() << ','5015<< ProcStat->UserTime.count() << ',' << ProcStat->PeakMemory5016<< '\n';5017Out.flush();5018std::error_code EC;5019llvm::raw_fd_ostream OS(CCPrintStatReportFilename, EC,5020llvm::sys::fs::OF_Append |5021llvm::sys::fs::OF_Text);5022if (EC)5023return;5024auto L = OS.lock();5025if (!L) {5026llvm::errs() << "ERROR: Cannot lock file "5027<< CCPrintStatReportFilename << ": "5028<< toString(L.takeError()) << "\n";5029return;5030}5031OS << Buffer;5032OS.flush();5033}5034});5035}50365037// If the user passed -Qunused-arguments or there were errors, don't warn5038// about any unused arguments.5039if (Diags.hasErrorOccurred() ||5040C.getArgs().hasArg(options::OPT_Qunused_arguments))5041return;50425043// Claim -fdriver-only here.5044(void)C.getArgs().hasArg(options::OPT_fdriver_only);5045// Claim -### here.5046(void)C.getArgs().hasArg(options::OPT__HASH_HASH_HASH);50475048// Claim --driver-mode, --rsp-quoting, it was handled earlier.5049(void)C.getArgs().hasArg(options::OPT_driver_mode);5050(void)C.getArgs().hasArg(options::OPT_rsp_quoting);50515052bool HasAssembleJob = llvm::any_of(C.getJobs(), [](auto &J) {5053// Match ClangAs and other derived assemblers of Tool. ClangAs uses a5054// longer ShortName "clang integrated assembler" while other assemblers just5055// use "assembler".5056return strstr(J.getCreator().getShortName(), "assembler");5057});5058for (Arg *A : C.getArgs()) {5059// FIXME: It would be nice to be able to send the argument to the5060// DiagnosticsEngine, so that extra values, position, and so on could be5061// printed.5062if (!A->isClaimed()) {5063if (A->getOption().hasFlag(options::NoArgumentUnused))5064continue;50655066// Suppress the warning automatically if this is just a flag, and it is an5067// instance of an argument we already claimed.5068const Option &Opt = A->getOption();5069if (Opt.getKind() == Option::FlagClass) {5070bool DuplicateClaimed = false;50715072for (const Arg *AA : C.getArgs().filtered(&Opt)) {5073if (AA->isClaimed()) {5074DuplicateClaimed = true;5075break;5076}5077}50785079if (DuplicateClaimed)5080continue;5081}50825083// In clang-cl, don't mention unknown arguments here since they have5084// already been warned about.5085if (!IsCLMode() || !A->getOption().matches(options::OPT_UNKNOWN)) {5086if (A->getOption().hasFlag(options::TargetSpecific) &&5087!A->isIgnoredTargetSpecific() && !HasAssembleJob &&5088// When for example -### or -v is used5089// without a file, target specific options are not5090// consumed/validated.5091// Instead emitting an error emit a warning instead.5092!C.getActions().empty()) {5093Diag(diag::err_drv_unsupported_opt_for_target)5094<< A->getSpelling() << getTargetTriple();5095} else {5096Diag(clang::diag::warn_drv_unused_argument)5097<< A->getAsString(C.getArgs());5098}5099}5100}5101}5102}51035104namespace {5105/// Utility class to control the collapse of dependent actions and select the5106/// tools accordingly.5107class ToolSelector final {5108/// The tool chain this selector refers to.5109const ToolChain &TC;51105111/// The compilation this selector refers to.5112const Compilation &C;51135114/// The base action this selector refers to.5115const JobAction *BaseAction;51165117/// Set to true if the current toolchain refers to host actions.5118bool IsHostSelector;51195120/// Set to true if save-temps and embed-bitcode functionalities are active.5121bool SaveTemps;5122bool EmbedBitcode;51235124/// Get previous dependent action or null if that does not exist. If5125/// \a CanBeCollapsed is false, that action must be legal to collapse or5126/// null will be returned.5127const JobAction *getPrevDependentAction(const ActionList &Inputs,5128ActionList &SavedOffloadAction,5129bool CanBeCollapsed = true) {5130// An option can be collapsed only if it has a single input.5131if (Inputs.size() != 1)5132return nullptr;51335134Action *CurAction = *Inputs.begin();5135if (CanBeCollapsed &&5136!CurAction->isCollapsingWithNextDependentActionLegal())5137return nullptr;51385139// If the input action is an offload action. Look through it and save any5140// offload action that can be dropped in the event of a collapse.5141if (auto *OA = dyn_cast<OffloadAction>(CurAction)) {5142// If the dependent action is a device action, we will attempt to collapse5143// only with other device actions. Otherwise, we would do the same but5144// with host actions only.5145if (!IsHostSelector) {5146if (OA->hasSingleDeviceDependence(/*DoNotConsiderHostActions=*/true)) {5147CurAction =5148OA->getSingleDeviceDependence(/*DoNotConsiderHostActions=*/true);5149if (CanBeCollapsed &&5150!CurAction->isCollapsingWithNextDependentActionLegal())5151return nullptr;5152SavedOffloadAction.push_back(OA);5153return dyn_cast<JobAction>(CurAction);5154}5155} else if (OA->hasHostDependence()) {5156CurAction = OA->getHostDependence();5157if (CanBeCollapsed &&5158!CurAction->isCollapsingWithNextDependentActionLegal())5159return nullptr;5160SavedOffloadAction.push_back(OA);5161return dyn_cast<JobAction>(CurAction);5162}5163return nullptr;5164}51655166return dyn_cast<JobAction>(CurAction);5167}51685169/// Return true if an assemble action can be collapsed.5170bool canCollapseAssembleAction() const {5171return TC.useIntegratedAs() && !SaveTemps &&5172!C.getArgs().hasArg(options::OPT_via_file_asm) &&5173!C.getArgs().hasArg(options::OPT__SLASH_FA) &&5174!C.getArgs().hasArg(options::OPT__SLASH_Fa) &&5175!C.getArgs().hasArg(options::OPT_dxc_Fc);5176}51775178/// Return true if a preprocessor action can be collapsed.5179bool canCollapsePreprocessorAction() const {5180return !C.getArgs().hasArg(options::OPT_no_integrated_cpp) &&5181!C.getArgs().hasArg(options::OPT_traditional_cpp) && !SaveTemps &&5182!C.getArgs().hasArg(options::OPT_rewrite_objc);5183}51845185/// Struct that relates an action with the offload actions that would be5186/// collapsed with it.5187struct JobActionInfo final {5188/// The action this info refers to.5189const JobAction *JA = nullptr;5190/// The offload actions we need to take care off if this action is5191/// collapsed.5192ActionList SavedOffloadAction;5193};51945195/// Append collapsed offload actions from the give nnumber of elements in the5196/// action info array.5197static void AppendCollapsedOffloadAction(ActionList &CollapsedOffloadAction,5198ArrayRef<JobActionInfo> &ActionInfo,5199unsigned ElementNum) {5200assert(ElementNum <= ActionInfo.size() && "Invalid number of elements.");5201for (unsigned I = 0; I < ElementNum; ++I)5202CollapsedOffloadAction.append(ActionInfo[I].SavedOffloadAction.begin(),5203ActionInfo[I].SavedOffloadAction.end());5204}52055206/// Functions that attempt to perform the combining. They detect if that is5207/// legal, and if so they update the inputs \a Inputs and the offload action5208/// that were collapsed in \a CollapsedOffloadAction. A tool that deals with5209/// the combined action is returned. If the combining is not legal or if the5210/// tool does not exist, null is returned.5211/// Currently three kinds of collapsing are supported:5212/// - Assemble + Backend + Compile;5213/// - Assemble + Backend ;5214/// - Backend + Compile.5215const Tool *5216combineAssembleBackendCompile(ArrayRef<JobActionInfo> ActionInfo,5217ActionList &Inputs,5218ActionList &CollapsedOffloadAction) {5219if (ActionInfo.size() < 3 || !canCollapseAssembleAction())5220return nullptr;5221auto *AJ = dyn_cast<AssembleJobAction>(ActionInfo[0].JA);5222auto *BJ = dyn_cast<BackendJobAction>(ActionInfo[1].JA);5223auto *CJ = dyn_cast<CompileJobAction>(ActionInfo[2].JA);5224if (!AJ || !BJ || !CJ)5225return nullptr;52265227// Get compiler tool.5228const Tool *T = TC.SelectTool(*CJ);5229if (!T)5230return nullptr;52315232// Can't collapse if we don't have codegen support unless we are5233// emitting LLVM IR.5234bool OutputIsLLVM = types::isLLVMIR(ActionInfo[0].JA->getType());5235if (!T->hasIntegratedBackend() && !(OutputIsLLVM && T->canEmitIR()))5236return nullptr;52375238// When using -fembed-bitcode, it is required to have the same tool (clang)5239// for both CompilerJA and BackendJA. Otherwise, combine two stages.5240if (EmbedBitcode) {5241const Tool *BT = TC.SelectTool(*BJ);5242if (BT == T)5243return nullptr;5244}52455246if (!T->hasIntegratedAssembler())5247return nullptr;52485249Inputs = CJ->getInputs();5250AppendCollapsedOffloadAction(CollapsedOffloadAction, ActionInfo,5251/*NumElements=*/3);5252return T;5253}5254const Tool *combineAssembleBackend(ArrayRef<JobActionInfo> ActionInfo,5255ActionList &Inputs,5256ActionList &CollapsedOffloadAction) {5257if (ActionInfo.size() < 2 || !canCollapseAssembleAction())5258return nullptr;5259auto *AJ = dyn_cast<AssembleJobAction>(ActionInfo[0].JA);5260auto *BJ = dyn_cast<BackendJobAction>(ActionInfo[1].JA);5261if (!AJ || !BJ)5262return nullptr;52635264// Get backend tool.5265const Tool *T = TC.SelectTool(*BJ);5266if (!T)5267return nullptr;52685269if (!T->hasIntegratedAssembler())5270return nullptr;52715272Inputs = BJ->getInputs();5273AppendCollapsedOffloadAction(CollapsedOffloadAction, ActionInfo,5274/*NumElements=*/2);5275return T;5276}5277const Tool *combineBackendCompile(ArrayRef<JobActionInfo> ActionInfo,5278ActionList &Inputs,5279ActionList &CollapsedOffloadAction) {5280if (ActionInfo.size() < 2)5281return nullptr;5282auto *BJ = dyn_cast<BackendJobAction>(ActionInfo[0].JA);5283auto *CJ = dyn_cast<CompileJobAction>(ActionInfo[1].JA);5284if (!BJ || !CJ)5285return nullptr;52865287// Check if the initial input (to the compile job or its predessor if one5288// exists) is LLVM bitcode. In that case, no preprocessor step is required5289// and we can still collapse the compile and backend jobs when we have5290// -save-temps. I.e. there is no need for a separate compile job just to5291// emit unoptimized bitcode.5292bool InputIsBitcode = true;5293for (size_t i = 1; i < ActionInfo.size(); i++)5294if (ActionInfo[i].JA->getType() != types::TY_LLVM_BC &&5295ActionInfo[i].JA->getType() != types::TY_LTO_BC) {5296InputIsBitcode = false;5297break;5298}5299if (!InputIsBitcode && !canCollapsePreprocessorAction())5300return nullptr;53015302// Get compiler tool.5303const Tool *T = TC.SelectTool(*CJ);5304if (!T)5305return nullptr;53065307// Can't collapse if we don't have codegen support unless we are5308// emitting LLVM IR.5309bool OutputIsLLVM = types::isLLVMIR(ActionInfo[0].JA->getType());5310if (!T->hasIntegratedBackend() && !(OutputIsLLVM && T->canEmitIR()))5311return nullptr;53125313if (T->canEmitIR() && ((SaveTemps && !InputIsBitcode) || EmbedBitcode))5314return nullptr;53155316Inputs = CJ->getInputs();5317AppendCollapsedOffloadAction(CollapsedOffloadAction, ActionInfo,5318/*NumElements=*/2);5319return T;5320}53215322/// Updates the inputs if the obtained tool supports combining with5323/// preprocessor action, and the current input is indeed a preprocessor5324/// action. If combining results in the collapse of offloading actions, those5325/// are appended to \a CollapsedOffloadAction.5326void combineWithPreprocessor(const Tool *T, ActionList &Inputs,5327ActionList &CollapsedOffloadAction) {5328if (!T || !canCollapsePreprocessorAction() || !T->hasIntegratedCPP())5329return;53305331// Attempt to get a preprocessor action dependence.5332ActionList PreprocessJobOffloadActions;5333ActionList NewInputs;5334for (Action *A : Inputs) {5335auto *PJ = getPrevDependentAction({A}, PreprocessJobOffloadActions);5336if (!PJ || !isa<PreprocessJobAction>(PJ)) {5337NewInputs.push_back(A);5338continue;5339}53405341// This is legal to combine. Append any offload action we found and add the5342// current input to preprocessor inputs.5343CollapsedOffloadAction.append(PreprocessJobOffloadActions.begin(),5344PreprocessJobOffloadActions.end());5345NewInputs.append(PJ->input_begin(), PJ->input_end());5346}5347Inputs = NewInputs;5348}53495350public:5351ToolSelector(const JobAction *BaseAction, const ToolChain &TC,5352const Compilation &C, bool SaveTemps, bool EmbedBitcode)5353: TC(TC), C(C), BaseAction(BaseAction), SaveTemps(SaveTemps),5354EmbedBitcode(EmbedBitcode) {5355assert(BaseAction && "Invalid base action.");5356IsHostSelector = BaseAction->getOffloadingDeviceKind() == Action::OFK_None;5357}53585359/// Check if a chain of actions can be combined and return the tool that can5360/// handle the combination of actions. The pointer to the current inputs \a5361/// Inputs and the list of offload actions \a CollapsedOffloadActions5362/// connected to collapsed actions are updated accordingly. The latter enables5363/// the caller of the selector to process them afterwards instead of just5364/// dropping them. If no suitable tool is found, null will be returned.5365const Tool *getTool(ActionList &Inputs,5366ActionList &CollapsedOffloadAction) {5367//5368// Get the largest chain of actions that we could combine.5369//53705371SmallVector<JobActionInfo, 5> ActionChain(1);5372ActionChain.back().JA = BaseAction;5373while (ActionChain.back().JA) {5374const Action *CurAction = ActionChain.back().JA;53755376// Grow the chain by one element.5377ActionChain.resize(ActionChain.size() + 1);5378JobActionInfo &AI = ActionChain.back();53795380// Attempt to fill it with the5381AI.JA =5382getPrevDependentAction(CurAction->getInputs(), AI.SavedOffloadAction);5383}53845385// Pop the last action info as it could not be filled.5386ActionChain.pop_back();53875388//5389// Attempt to combine actions. If all combining attempts failed, just return5390// the tool of the provided action. At the end we attempt to combine the5391// action with any preprocessor action it may depend on.5392//53935394const Tool *T = combineAssembleBackendCompile(ActionChain, Inputs,5395CollapsedOffloadAction);5396if (!T)5397T = combineAssembleBackend(ActionChain, Inputs, CollapsedOffloadAction);5398if (!T)5399T = combineBackendCompile(ActionChain, Inputs, CollapsedOffloadAction);5400if (!T) {5401Inputs = BaseAction->getInputs();5402T = TC.SelectTool(*BaseAction);5403}54045405combineWithPreprocessor(T, Inputs, CollapsedOffloadAction);5406return T;5407}5408};5409}54105411/// Return a string that uniquely identifies the result of a job. The bound arch5412/// is not necessarily represented in the toolchain's triple -- for example,5413/// armv7 and armv7s both map to the same triple -- so we need both in our map.5414/// Also, we need to add the offloading device kind, as the same tool chain can5415/// be used for host and device for some programming models, e.g. OpenMP.5416static std::string GetTriplePlusArchString(const ToolChain *TC,5417StringRef BoundArch,5418Action::OffloadKind OffloadKind) {5419std::string TriplePlusArch = TC->getTriple().normalize();5420if (!BoundArch.empty()) {5421TriplePlusArch += "-";5422TriplePlusArch += BoundArch;5423}5424TriplePlusArch += "-";5425TriplePlusArch += Action::GetOffloadKindName(OffloadKind);5426return TriplePlusArch;5427}54285429InputInfoList Driver::BuildJobsForAction(5430Compilation &C, const Action *A, const ToolChain *TC, StringRef BoundArch,5431bool AtTopLevel, bool MultipleArchs, const char *LinkingOutput,5432std::map<std::pair<const Action *, std::string>, InputInfoList>5433&CachedResults,5434Action::OffloadKind TargetDeviceOffloadKind) const {5435std::pair<const Action *, std::string> ActionTC = {5436A, GetTriplePlusArchString(TC, BoundArch, TargetDeviceOffloadKind)};5437auto CachedResult = CachedResults.find(ActionTC);5438if (CachedResult != CachedResults.end()) {5439return CachedResult->second;5440}5441InputInfoList Result = BuildJobsForActionNoCache(5442C, A, TC, BoundArch, AtTopLevel, MultipleArchs, LinkingOutput,5443CachedResults, TargetDeviceOffloadKind);5444CachedResults[ActionTC] = Result;5445return Result;5446}54475448static void handleTimeTrace(Compilation &C, const ArgList &Args,5449const JobAction *JA, const char *BaseInput,5450const InputInfo &Result) {5451Arg *A =5452Args.getLastArg(options::OPT_ftime_trace, options::OPT_ftime_trace_EQ);5453if (!A)5454return;5455SmallString<128> Path;5456if (A->getOption().matches(options::OPT_ftime_trace_EQ)) {5457Path = A->getValue();5458if (llvm::sys::fs::is_directory(Path)) {5459SmallString<128> Tmp(Result.getFilename());5460llvm::sys::path::replace_extension(Tmp, "json");5461llvm::sys::path::append(Path, llvm::sys::path::filename(Tmp));5462}5463} else {5464if (Arg *DumpDir = Args.getLastArgNoClaim(options::OPT_dumpdir)) {5465// The trace file is ${dumpdir}${basename}.json. Note that dumpdir may not5466// end with a path separator.5467Path = DumpDir->getValue();5468Path += llvm::sys::path::filename(BaseInput);5469} else {5470Path = Result.getFilename();5471}5472llvm::sys::path::replace_extension(Path, "json");5473}5474const char *ResultFile = C.getArgs().MakeArgString(Path);5475C.addTimeTraceFile(ResultFile, JA);5476C.addResultFile(ResultFile, JA);5477}54785479InputInfoList Driver::BuildJobsForActionNoCache(5480Compilation &C, const Action *A, const ToolChain *TC, StringRef BoundArch,5481bool AtTopLevel, bool MultipleArchs, const char *LinkingOutput,5482std::map<std::pair<const Action *, std::string>, InputInfoList>5483&CachedResults,5484Action::OffloadKind TargetDeviceOffloadKind) const {5485llvm::PrettyStackTraceString CrashInfo("Building compilation jobs");54865487InputInfoList OffloadDependencesInputInfo;5488bool BuildingForOffloadDevice = TargetDeviceOffloadKind != Action::OFK_None;5489if (const OffloadAction *OA = dyn_cast<OffloadAction>(A)) {5490// The 'Darwin' toolchain is initialized only when its arguments are5491// computed. Get the default arguments for OFK_None to ensure that5492// initialization is performed before processing the offload action.5493// FIXME: Remove when darwin's toolchain is initialized during construction.5494C.getArgsForToolChain(TC, BoundArch, Action::OFK_None);54955496// The offload action is expected to be used in four different situations.5497//5498// a) Set a toolchain/architecture/kind for a host action:5499// Host Action 1 -> OffloadAction -> Host Action 25500//5501// b) Set a toolchain/architecture/kind for a device action;5502// Device Action 1 -> OffloadAction -> Device Action 25503//5504// c) Specify a device dependence to a host action;5505// Device Action 1 _5506// \5507// Host Action 1 ---> OffloadAction -> Host Action 25508//5509// d) Specify a host dependence to a device action.5510// Host Action 1 _5511// \5512// Device Action 1 ---> OffloadAction -> Device Action 25513//5514// For a) and b), we just return the job generated for the dependences. For5515// c) and d) we override the current action with the host/device dependence5516// if the current toolchain is host/device and set the offload dependences5517// info with the jobs obtained from the device/host dependence(s).55185519// If there is a single device option or has no host action, just generate5520// the job for it.5521if (OA->hasSingleDeviceDependence() || !OA->hasHostDependence()) {5522InputInfoList DevA;5523OA->doOnEachDeviceDependence([&](Action *DepA, const ToolChain *DepTC,5524const char *DepBoundArch) {5525DevA.append(BuildJobsForAction(C, DepA, DepTC, DepBoundArch, AtTopLevel,5526/*MultipleArchs*/ !!DepBoundArch,5527LinkingOutput, CachedResults,5528DepA->getOffloadingDeviceKind()));5529});5530return DevA;5531}55325533// If 'Action 2' is host, we generate jobs for the device dependences and5534// override the current action with the host dependence. Otherwise, we5535// generate the host dependences and override the action with the device5536// dependence. The dependences can't therefore be a top-level action.5537OA->doOnEachDependence(5538/*IsHostDependence=*/BuildingForOffloadDevice,5539[&](Action *DepA, const ToolChain *DepTC, const char *DepBoundArch) {5540OffloadDependencesInputInfo.append(BuildJobsForAction(5541C, DepA, DepTC, DepBoundArch, /*AtTopLevel=*/false,5542/*MultipleArchs*/ !!DepBoundArch, LinkingOutput, CachedResults,5543DepA->getOffloadingDeviceKind()));5544});55455546A = BuildingForOffloadDevice5547? OA->getSingleDeviceDependence(/*DoNotConsiderHostActions=*/true)5548: OA->getHostDependence();55495550// We may have already built this action as a part of the offloading5551// toolchain, return the cached input if so.5552std::pair<const Action *, std::string> ActionTC = {5553OA->getHostDependence(),5554GetTriplePlusArchString(TC, BoundArch, TargetDeviceOffloadKind)};5555if (CachedResults.find(ActionTC) != CachedResults.end()) {5556InputInfoList Inputs = CachedResults[ActionTC];5557Inputs.append(OffloadDependencesInputInfo);5558return Inputs;5559}5560}55615562if (const InputAction *IA = dyn_cast<InputAction>(A)) {5563// FIXME: It would be nice to not claim this here; maybe the old scheme of5564// just using Args was better?5565const Arg &Input = IA->getInputArg();5566Input.claim();5567if (Input.getOption().matches(options::OPT_INPUT)) {5568const char *Name = Input.getValue();5569return {InputInfo(A, Name, /* _BaseInput = */ Name)};5570}5571return {InputInfo(A, &Input, /* _BaseInput = */ "")};5572}55735574if (const BindArchAction *BAA = dyn_cast<BindArchAction>(A)) {5575const ToolChain *TC;5576StringRef ArchName = BAA->getArchName();55775578if (!ArchName.empty())5579TC = &getToolChain(C.getArgs(),5580computeTargetTriple(*this, TargetTriple,5581C.getArgs(), ArchName));5582else5583TC = &C.getDefaultToolChain();55845585return BuildJobsForAction(C, *BAA->input_begin(), TC, ArchName, AtTopLevel,5586MultipleArchs, LinkingOutput, CachedResults,5587TargetDeviceOffloadKind);5588}558955905591ActionList Inputs = A->getInputs();55925593const JobAction *JA = cast<JobAction>(A);5594ActionList CollapsedOffloadActions;55955596ToolSelector TS(JA, *TC, C, isSaveTempsEnabled(),5597embedBitcodeInObject() && !isUsingLTO());5598const Tool *T = TS.getTool(Inputs, CollapsedOffloadActions);55995600if (!T)5601return {InputInfo()};56025603// If we've collapsed action list that contained OffloadAction we5604// need to build jobs for host/device-side inputs it may have held.5605for (const auto *OA : CollapsedOffloadActions)5606cast<OffloadAction>(OA)->doOnEachDependence(5607/*IsHostDependence=*/BuildingForOffloadDevice,5608[&](Action *DepA, const ToolChain *DepTC, const char *DepBoundArch) {5609OffloadDependencesInputInfo.append(BuildJobsForAction(5610C, DepA, DepTC, DepBoundArch, /* AtTopLevel */ false,5611/*MultipleArchs=*/!!DepBoundArch, LinkingOutput, CachedResults,5612DepA->getOffloadingDeviceKind()));5613});56145615// Only use pipes when there is exactly one input.5616InputInfoList InputInfos;5617for (const Action *Input : Inputs) {5618// Treat dsymutil and verify sub-jobs as being at the top-level too, they5619// shouldn't get temporary output names.5620// FIXME: Clean this up.5621bool SubJobAtTopLevel =5622AtTopLevel && (isa<DsymutilJobAction>(A) || isa<VerifyJobAction>(A));5623InputInfos.append(BuildJobsForAction(5624C, Input, TC, BoundArch, SubJobAtTopLevel, MultipleArchs, LinkingOutput,5625CachedResults, A->getOffloadingDeviceKind()));5626}56275628// Always use the first file input as the base input.5629const char *BaseInput = InputInfos[0].getBaseInput();5630for (auto &Info : InputInfos) {5631if (Info.isFilename()) {5632BaseInput = Info.getBaseInput();5633break;5634}5635}56365637// ... except dsymutil actions, which use their actual input as the base5638// input.5639if (JA->getType() == types::TY_dSYM)5640BaseInput = InputInfos[0].getFilename();56415642// Append outputs of offload device jobs to the input list5643if (!OffloadDependencesInputInfo.empty())5644InputInfos.append(OffloadDependencesInputInfo.begin(),5645OffloadDependencesInputInfo.end());56465647// Set the effective triple of the toolchain for the duration of this job.5648llvm::Triple EffectiveTriple;5649const ToolChain &ToolTC = T->getToolChain();5650const ArgList &Args =5651C.getArgsForToolChain(TC, BoundArch, A->getOffloadingDeviceKind());5652if (InputInfos.size() != 1) {5653EffectiveTriple = llvm::Triple(ToolTC.ComputeEffectiveClangTriple(Args));5654} else {5655// Pass along the input type if it can be unambiguously determined.5656EffectiveTriple = llvm::Triple(5657ToolTC.ComputeEffectiveClangTriple(Args, InputInfos[0].getType()));5658}5659RegisterEffectiveTriple TripleRAII(ToolTC, EffectiveTriple);56605661// Determine the place to write output to, if any.5662InputInfo Result;5663InputInfoList UnbundlingResults;5664if (auto *UA = dyn_cast<OffloadUnbundlingJobAction>(JA)) {5665// If we have an unbundling job, we need to create results for all the5666// outputs. We also update the results cache so that other actions using5667// this unbundling action can get the right results.5668for (auto &UI : UA->getDependentActionsInfo()) {5669assert(UI.DependentOffloadKind != Action::OFK_None &&5670"Unbundling with no offloading??");56715672// Unbundling actions are never at the top level. When we generate the5673// offloading prefix, we also do that for the host file because the5674// unbundling action does not change the type of the output which can5675// cause a overwrite.5676std::string OffloadingPrefix = Action::GetOffloadingFileNamePrefix(5677UI.DependentOffloadKind,5678UI.DependentToolChain->getTriple().normalize(),5679/*CreatePrefixForHost=*/true);5680auto CurI = InputInfo(5681UA,5682GetNamedOutputPath(C, *UA, BaseInput, UI.DependentBoundArch,5683/*AtTopLevel=*/false,5684MultipleArchs ||5685UI.DependentOffloadKind == Action::OFK_HIP,5686OffloadingPrefix),5687BaseInput);5688// Save the unbundling result.5689UnbundlingResults.push_back(CurI);56905691// Get the unique string identifier for this dependence and cache the5692// result.5693StringRef Arch;5694if (TargetDeviceOffloadKind == Action::OFK_HIP) {5695if (UI.DependentOffloadKind == Action::OFK_Host)5696Arch = StringRef();5697else5698Arch = UI.DependentBoundArch;5699} else5700Arch = BoundArch;57015702CachedResults[{A, GetTriplePlusArchString(UI.DependentToolChain, Arch,5703UI.DependentOffloadKind)}] = {5704CurI};5705}57065707// Now that we have all the results generated, select the one that should be5708// returned for the current depending action.5709std::pair<const Action *, std::string> ActionTC = {5710A, GetTriplePlusArchString(TC, BoundArch, TargetDeviceOffloadKind)};5711assert(CachedResults.find(ActionTC) != CachedResults.end() &&5712"Result does not exist??");5713Result = CachedResults[ActionTC].front();5714} else if (JA->getType() == types::TY_Nothing)5715Result = {InputInfo(A, BaseInput)};5716else {5717// We only have to generate a prefix for the host if this is not a top-level5718// action.5719std::string OffloadingPrefix = Action::GetOffloadingFileNamePrefix(5720A->getOffloadingDeviceKind(), TC->getTriple().normalize(),5721/*CreatePrefixForHost=*/isa<OffloadPackagerJobAction>(A) ||5722!(A->getOffloadingHostActiveKinds() == Action::OFK_None ||5723AtTopLevel));5724Result = InputInfo(A, GetNamedOutputPath(C, *JA, BaseInput, BoundArch,5725AtTopLevel, MultipleArchs,5726OffloadingPrefix),5727BaseInput);5728if (T->canEmitIR() && OffloadingPrefix.empty())5729handleTimeTrace(C, Args, JA, BaseInput, Result);5730}57315732if (CCCPrintBindings && !CCGenDiagnostics) {5733llvm::errs() << "# \"" << T->getToolChain().getTripleString() << '"'5734<< " - \"" << T->getName() << "\", inputs: [";5735for (unsigned i = 0, e = InputInfos.size(); i != e; ++i) {5736llvm::errs() << InputInfos[i].getAsString();5737if (i + 1 != e)5738llvm::errs() << ", ";5739}5740if (UnbundlingResults.empty())5741llvm::errs() << "], output: " << Result.getAsString() << "\n";5742else {5743llvm::errs() << "], outputs: [";5744for (unsigned i = 0, e = UnbundlingResults.size(); i != e; ++i) {5745llvm::errs() << UnbundlingResults[i].getAsString();5746if (i + 1 != e)5747llvm::errs() << ", ";5748}5749llvm::errs() << "] \n";5750}5751} else {5752if (UnbundlingResults.empty())5753T->ConstructJob(5754C, *JA, Result, InputInfos,5755C.getArgsForToolChain(TC, BoundArch, JA->getOffloadingDeviceKind()),5756LinkingOutput);5757else5758T->ConstructJobMultipleOutputs(5759C, *JA, UnbundlingResults, InputInfos,5760C.getArgsForToolChain(TC, BoundArch, JA->getOffloadingDeviceKind()),5761LinkingOutput);5762}5763return {Result};5764}57655766const char *Driver::getDefaultImageName() const {5767llvm::Triple Target(llvm::Triple::normalize(TargetTriple));5768return Target.isOSWindows() ? "a.exe" : "a.out";5769}57705771/// Create output filename based on ArgValue, which could either be a5772/// full filename, filename without extension, or a directory. If ArgValue5773/// does not provide a filename, then use BaseName, and use the extension5774/// suitable for FileType.5775static const char *MakeCLOutputFilename(const ArgList &Args, StringRef ArgValue,5776StringRef BaseName,5777types::ID FileType) {5778SmallString<128> Filename = ArgValue;57795780if (ArgValue.empty()) {5781// If the argument is empty, output to BaseName in the current dir.5782Filename = BaseName;5783} else if (llvm::sys::path::is_separator(Filename.back())) {5784// If the argument is a directory, output to BaseName in that dir.5785llvm::sys::path::append(Filename, BaseName);5786}57875788if (!llvm::sys::path::has_extension(ArgValue)) {5789// If the argument didn't provide an extension, then set it.5790const char *Extension = types::getTypeTempSuffix(FileType, true);57915792if (FileType == types::TY_Image &&5793Args.hasArg(options::OPT__SLASH_LD, options::OPT__SLASH_LDd)) {5794// The output file is a dll.5795Extension = "dll";5796}57975798llvm::sys::path::replace_extension(Filename, Extension);5799}58005801return Args.MakeArgString(Filename.c_str());5802}58035804static bool HasPreprocessOutput(const Action &JA) {5805if (isa<PreprocessJobAction>(JA))5806return true;5807if (isa<OffloadAction>(JA) && isa<PreprocessJobAction>(JA.getInputs()[0]))5808return true;5809if (isa<OffloadBundlingJobAction>(JA) &&5810HasPreprocessOutput(*(JA.getInputs()[0])))5811return true;5812return false;5813}58145815const char *Driver::CreateTempFile(Compilation &C, StringRef Prefix,5816StringRef Suffix, bool MultipleArchs,5817StringRef BoundArch,5818bool NeedUniqueDirectory) const {5819SmallString<128> TmpName;5820Arg *A = C.getArgs().getLastArg(options::OPT_fcrash_diagnostics_dir);5821std::optional<std::string> CrashDirectory =5822CCGenDiagnostics && A5823? std::string(A->getValue())5824: llvm::sys::Process::GetEnv("CLANG_CRASH_DIAGNOSTICS_DIR");5825if (CrashDirectory) {5826if (!getVFS().exists(*CrashDirectory))5827llvm::sys::fs::create_directories(*CrashDirectory);5828SmallString<128> Path(*CrashDirectory);5829llvm::sys::path::append(Path, Prefix);5830const char *Middle = !Suffix.empty() ? "-%%%%%%." : "-%%%%%%";5831if (std::error_code EC =5832llvm::sys::fs::createUniqueFile(Path + Middle + Suffix, TmpName)) {5833Diag(clang::diag::err_unable_to_make_temp) << EC.message();5834return "";5835}5836} else {5837if (MultipleArchs && !BoundArch.empty()) {5838if (NeedUniqueDirectory) {5839TmpName = GetTemporaryDirectory(Prefix);5840llvm::sys::path::append(TmpName,5841Twine(Prefix) + "-" + BoundArch + "." + Suffix);5842} else {5843TmpName =5844GetTemporaryPath((Twine(Prefix) + "-" + BoundArch).str(), Suffix);5845}58465847} else {5848TmpName = GetTemporaryPath(Prefix, Suffix);5849}5850}5851return C.addTempFile(C.getArgs().MakeArgString(TmpName));5852}58535854// Calculate the output path of the module file when compiling a module unit5855// with the `-fmodule-output` option or `-fmodule-output=` option specified.5856// The behavior is:5857// - If `-fmodule-output=` is specfied, then the module file is5858// writing to the value.5859// - Otherwise if the output object file of the module unit is specified, the5860// output path5861// of the module file should be the same with the output object file except5862// the corresponding suffix. This requires both `-o` and `-c` are specified.5863// - Otherwise, the output path of the module file will be the same with the5864// input with the corresponding suffix.5865static const char *GetModuleOutputPath(Compilation &C, const JobAction &JA,5866const char *BaseInput) {5867assert(isa<PrecompileJobAction>(JA) && JA.getType() == types::TY_ModuleFile &&5868(C.getArgs().hasArg(options::OPT_fmodule_output) ||5869C.getArgs().hasArg(options::OPT_fmodule_output_EQ)));58705871SmallString<256> OutputPath =5872tools::getCXX20NamedModuleOutputPath(C.getArgs(), BaseInput);58735874return C.addResultFile(C.getArgs().MakeArgString(OutputPath.c_str()), &JA);5875}58765877const char *Driver::GetNamedOutputPath(Compilation &C, const JobAction &JA,5878const char *BaseInput,5879StringRef OrigBoundArch, bool AtTopLevel,5880bool MultipleArchs,5881StringRef OffloadingPrefix) const {5882std::string BoundArch = OrigBoundArch.str();5883if (is_style_windows(llvm::sys::path::Style::native)) {5884// BoundArch may contains ':', which is invalid in file names on Windows,5885// therefore replace it with '%'.5886std::replace(BoundArch.begin(), BoundArch.end(), ':', '@');5887}58885889llvm::PrettyStackTraceString CrashInfo("Computing output path");5890// Output to a user requested destination?5891if (AtTopLevel && !isa<DsymutilJobAction>(JA) && !isa<VerifyJobAction>(JA)) {5892if (Arg *FinalOutput = C.getArgs().getLastArg(options::OPT_o))5893return C.addResultFile(FinalOutput->getValue(), &JA);5894}58955896// For /P, preprocess to file named after BaseInput.5897if (C.getArgs().hasArg(options::OPT__SLASH_P)) {5898assert(AtTopLevel && isa<PreprocessJobAction>(JA));5899StringRef BaseName = llvm::sys::path::filename(BaseInput);5900StringRef NameArg;5901if (Arg *A = C.getArgs().getLastArg(options::OPT__SLASH_Fi))5902NameArg = A->getValue();5903return C.addResultFile(5904MakeCLOutputFilename(C.getArgs(), NameArg, BaseName, types::TY_PP_C),5905&JA);5906}59075908// Default to writing to stdout?5909if (AtTopLevel && !CCGenDiagnostics && HasPreprocessOutput(JA)) {5910return "-";5911}59125913if (JA.getType() == types::TY_ModuleFile &&5914C.getArgs().getLastArg(options::OPT_module_file_info)) {5915return "-";5916}59175918if (JA.getType() == types::TY_PP_Asm &&5919C.getArgs().hasArg(options::OPT_dxc_Fc)) {5920StringRef FcValue = C.getArgs().getLastArgValue(options::OPT_dxc_Fc);5921// TODO: Should we use `MakeCLOutputFilename` here? If so, we can probably5922// handle this as part of the SLASH_Fa handling below.5923return C.addResultFile(C.getArgs().MakeArgString(FcValue.str()), &JA);5924}59255926if (JA.getType() == types::TY_Object &&5927C.getArgs().hasArg(options::OPT_dxc_Fo)) {5928StringRef FoValue = C.getArgs().getLastArgValue(options::OPT_dxc_Fo);5929// TODO: Should we use `MakeCLOutputFilename` here? If so, we can probably5930// handle this as part of the SLASH_Fo handling below.5931return C.addResultFile(C.getArgs().MakeArgString(FoValue.str()), &JA);5932}59335934// Is this the assembly listing for /FA?5935if (JA.getType() == types::TY_PP_Asm &&5936(C.getArgs().hasArg(options::OPT__SLASH_FA) ||5937C.getArgs().hasArg(options::OPT__SLASH_Fa))) {5938// Use /Fa and the input filename to determine the asm file name.5939StringRef BaseName = llvm::sys::path::filename(BaseInput);5940StringRef FaValue = C.getArgs().getLastArgValue(options::OPT__SLASH_Fa);5941return C.addResultFile(5942MakeCLOutputFilename(C.getArgs(), FaValue, BaseName, JA.getType()),5943&JA);5944}59455946if (JA.getType() == types::TY_API_INFO &&5947C.getArgs().hasArg(options::OPT_emit_extension_symbol_graphs) &&5948C.getArgs().hasArg(options::OPT_o))5949Diag(clang::diag::err_drv_unexpected_symbol_graph_output)5950<< C.getArgs().getLastArgValue(options::OPT_o);59515952// DXC defaults to standard out when generating assembly. We check this after5953// any DXC flags that might specify a file.5954if (AtTopLevel && JA.getType() == types::TY_PP_Asm && IsDXCMode())5955return "-";59565957bool SpecifiedModuleOutput =5958C.getArgs().hasArg(options::OPT_fmodule_output) ||5959C.getArgs().hasArg(options::OPT_fmodule_output_EQ);5960if (MultipleArchs && SpecifiedModuleOutput)5961Diag(clang::diag::err_drv_module_output_with_multiple_arch);59625963// If we're emitting a module output with the specified option5964// `-fmodule-output`.5965if (!AtTopLevel && isa<PrecompileJobAction>(JA) &&5966JA.getType() == types::TY_ModuleFile && SpecifiedModuleOutput) {5967assert(!C.getArgs().hasArg(options::OPT_modules_reduced_bmi));5968return GetModuleOutputPath(C, JA, BaseInput);5969}59705971// Output to a temporary file?5972if ((!AtTopLevel && !isSaveTempsEnabled() &&5973!C.getArgs().hasArg(options::OPT__SLASH_Fo)) ||5974CCGenDiagnostics) {5975StringRef Name = llvm::sys::path::filename(BaseInput);5976std::pair<StringRef, StringRef> Split = Name.split('.');5977const char *Suffix =5978types::getTypeTempSuffix(JA.getType(), IsCLMode() || IsDXCMode());5979// The non-offloading toolchain on Darwin requires deterministic input5980// file name for binaries to be deterministic, therefore it needs unique5981// directory.5982llvm::Triple Triple(C.getDriver().getTargetTriple());5983bool NeedUniqueDirectory =5984(JA.getOffloadingDeviceKind() == Action::OFK_None ||5985JA.getOffloadingDeviceKind() == Action::OFK_Host) &&5986Triple.isOSDarwin();5987return CreateTempFile(C, Split.first, Suffix, MultipleArchs, BoundArch,5988NeedUniqueDirectory);5989}59905991SmallString<128> BasePath(BaseInput);5992SmallString<128> ExternalPath("");5993StringRef BaseName;59945995// Dsymutil actions should use the full path.5996if (isa<DsymutilJobAction>(JA) && C.getArgs().hasArg(options::OPT_dsym_dir)) {5997ExternalPath += C.getArgs().getLastArg(options::OPT_dsym_dir)->getValue();5998// We use posix style here because the tests (specifically5999// darwin-dsymutil.c) demonstrate that posix style paths are acceptable6000// even on Windows and if we don't then the similar test covering this6001// fails.6002llvm::sys::path::append(ExternalPath, llvm::sys::path::Style::posix,6003llvm::sys::path::filename(BasePath));6004BaseName = ExternalPath;6005} else if (isa<DsymutilJobAction>(JA) || isa<VerifyJobAction>(JA))6006BaseName = BasePath;6007else6008BaseName = llvm::sys::path::filename(BasePath);60096010// Determine what the derived output name should be.6011const char *NamedOutput;60126013if ((JA.getType() == types::TY_Object || JA.getType() == types::TY_LTO_BC) &&6014C.getArgs().hasArg(options::OPT__SLASH_Fo, options::OPT__SLASH_o)) {6015// The /Fo or /o flag decides the object filename.6016StringRef Val =6017C.getArgs()6018.getLastArg(options::OPT__SLASH_Fo, options::OPT__SLASH_o)6019->getValue();6020NamedOutput =6021MakeCLOutputFilename(C.getArgs(), Val, BaseName, types::TY_Object);6022} else if (JA.getType() == types::TY_Image &&6023C.getArgs().hasArg(options::OPT__SLASH_Fe,6024options::OPT__SLASH_o)) {6025// The /Fe or /o flag names the linked file.6026StringRef Val =6027C.getArgs()6028.getLastArg(options::OPT__SLASH_Fe, options::OPT__SLASH_o)6029->getValue();6030NamedOutput =6031MakeCLOutputFilename(C.getArgs(), Val, BaseName, types::TY_Image);6032} else if (JA.getType() == types::TY_Image) {6033if (IsCLMode()) {6034// clang-cl uses BaseName for the executable name.6035NamedOutput =6036MakeCLOutputFilename(C.getArgs(), "", BaseName, types::TY_Image);6037} else {6038SmallString<128> Output(getDefaultImageName());6039// HIP image for device compilation with -fno-gpu-rdc is per compilation6040// unit.6041bool IsHIPNoRDC = JA.getOffloadingDeviceKind() == Action::OFK_HIP &&6042!C.getArgs().hasFlag(options::OPT_fgpu_rdc,6043options::OPT_fno_gpu_rdc, false);6044bool UseOutExtension = IsHIPNoRDC || isa<OffloadPackagerJobAction>(JA);6045if (UseOutExtension) {6046Output = BaseName;6047llvm::sys::path::replace_extension(Output, "");6048}6049Output += OffloadingPrefix;6050if (MultipleArchs && !BoundArch.empty()) {6051Output += "-";6052Output.append(BoundArch);6053}6054if (UseOutExtension)6055Output += ".out";6056NamedOutput = C.getArgs().MakeArgString(Output.c_str());6057}6058} else if (JA.getType() == types::TY_PCH && IsCLMode()) {6059NamedOutput = C.getArgs().MakeArgString(GetClPchPath(C, BaseName));6060} else if ((JA.getType() == types::TY_Plist || JA.getType() == types::TY_AST) &&6061C.getArgs().hasArg(options::OPT__SLASH_o)) {6062StringRef Val =6063C.getArgs()6064.getLastArg(options::OPT__SLASH_o)6065->getValue();6066NamedOutput =6067MakeCLOutputFilename(C.getArgs(), Val, BaseName, types::TY_Object);6068} else {6069const char *Suffix =6070types::getTypeTempSuffix(JA.getType(), IsCLMode() || IsDXCMode());6071assert(Suffix && "All types used for output should have a suffix.");60726073std::string::size_type End = std::string::npos;6074if (!types::appendSuffixForType(JA.getType()))6075End = BaseName.rfind('.');6076SmallString<128> Suffixed(BaseName.substr(0, End));6077Suffixed += OffloadingPrefix;6078if (MultipleArchs && !BoundArch.empty()) {6079Suffixed += "-";6080Suffixed.append(BoundArch);6081}6082// When using both -save-temps and -emit-llvm, use a ".tmp.bc" suffix for6083// the unoptimized bitcode so that it does not get overwritten by the ".bc"6084// optimized bitcode output.6085auto IsAMDRDCInCompilePhase = [](const JobAction &JA,6086const llvm::opt::DerivedArgList &Args) {6087// The relocatable compilation in HIP and OpenMP implies -emit-llvm.6088// Similarly, use a ".tmp.bc" suffix for the unoptimized bitcode6089// (generated in the compile phase.)6090const ToolChain *TC = JA.getOffloadingToolChain();6091return isa<CompileJobAction>(JA) &&6092((JA.getOffloadingDeviceKind() == Action::OFK_HIP &&6093Args.hasFlag(options::OPT_fgpu_rdc, options::OPT_fno_gpu_rdc,6094false)) ||6095(JA.getOffloadingDeviceKind() == Action::OFK_OpenMP && TC &&6096TC->getTriple().isAMDGPU()));6097};6098if (!AtTopLevel && JA.getType() == types::TY_LLVM_BC &&6099(C.getArgs().hasArg(options::OPT_emit_llvm) ||6100IsAMDRDCInCompilePhase(JA, C.getArgs())))6101Suffixed += ".tmp";6102Suffixed += '.';6103Suffixed += Suffix;6104NamedOutput = C.getArgs().MakeArgString(Suffixed.c_str());6105}61066107// Prepend object file path if -save-temps=obj6108if (!AtTopLevel && isSaveTempsObj() && C.getArgs().hasArg(options::OPT_o) &&6109JA.getType() != types::TY_PCH) {6110Arg *FinalOutput = C.getArgs().getLastArg(options::OPT_o);6111SmallString<128> TempPath(FinalOutput->getValue());6112llvm::sys::path::remove_filename(TempPath);6113StringRef OutputFileName = llvm::sys::path::filename(NamedOutput);6114llvm::sys::path::append(TempPath, OutputFileName);6115NamedOutput = C.getArgs().MakeArgString(TempPath.c_str());6116}61176118// If we're saving temps and the temp file conflicts with the input file,6119// then avoid overwriting input file.6120if (!AtTopLevel && isSaveTempsEnabled() && NamedOutput == BaseName) {6121bool SameFile = false;6122SmallString<256> Result;6123llvm::sys::fs::current_path(Result);6124llvm::sys::path::append(Result, BaseName);6125llvm::sys::fs::equivalent(BaseInput, Result.c_str(), SameFile);6126// Must share the same path to conflict.6127if (SameFile) {6128StringRef Name = llvm::sys::path::filename(BaseInput);6129std::pair<StringRef, StringRef> Split = Name.split('.');6130std::string TmpName = GetTemporaryPath(6131Split.first,6132types::getTypeTempSuffix(JA.getType(), IsCLMode() || IsDXCMode()));6133return C.addTempFile(C.getArgs().MakeArgString(TmpName));6134}6135}61366137// As an annoying special case, PCH generation doesn't strip the pathname.6138if (JA.getType() == types::TY_PCH && !IsCLMode()) {6139llvm::sys::path::remove_filename(BasePath);6140if (BasePath.empty())6141BasePath = NamedOutput;6142else6143llvm::sys::path::append(BasePath, NamedOutput);6144return C.addResultFile(C.getArgs().MakeArgString(BasePath.c_str()), &JA);6145}61466147return C.addResultFile(NamedOutput, &JA);6148}61496150std::string Driver::GetFilePath(StringRef Name, const ToolChain &TC) const {6151// Search for Name in a list of paths.6152auto SearchPaths = [&](const llvm::SmallVectorImpl<std::string> &P)6153-> std::optional<std::string> {6154// Respect a limited subset of the '-Bprefix' functionality in GCC by6155// attempting to use this prefix when looking for file paths.6156for (const auto &Dir : P) {6157if (Dir.empty())6158continue;6159SmallString<128> P(Dir[0] == '=' ? SysRoot + Dir.substr(1) : Dir);6160llvm::sys::path::append(P, Name);6161if (llvm::sys::fs::exists(Twine(P)))6162return std::string(P);6163}6164return std::nullopt;6165};61666167if (auto P = SearchPaths(PrefixDirs))6168return *P;61696170SmallString<128> R(ResourceDir);6171llvm::sys::path::append(R, Name);6172if (llvm::sys::fs::exists(Twine(R)))6173return std::string(R);61746175SmallString<128> P(TC.getCompilerRTPath());6176llvm::sys::path::append(P, Name);6177if (llvm::sys::fs::exists(Twine(P)))6178return std::string(P);61796180SmallString<128> D(Dir);6181llvm::sys::path::append(D, "..", Name);6182if (llvm::sys::fs::exists(Twine(D)))6183return std::string(D);61846185if (auto P = SearchPaths(TC.getLibraryPaths()))6186return *P;61876188if (auto P = SearchPaths(TC.getFilePaths()))6189return *P;61906191SmallString<128> R2(ResourceDir);6192llvm::sys::path::append(R2, "..", "..", Name);6193if (llvm::sys::fs::exists(Twine(R2)))6194return std::string(R2);61956196return std::string(Name);6197}61986199void Driver::generatePrefixedToolNames(6200StringRef Tool, const ToolChain &TC,6201SmallVectorImpl<std::string> &Names) const {6202// FIXME: Needs a better variable than TargetTriple6203Names.emplace_back((TargetTriple + "-" + Tool).str());6204Names.emplace_back(Tool);6205}62066207static bool ScanDirForExecutable(SmallString<128> &Dir, StringRef Name) {6208llvm::sys::path::append(Dir, Name);6209if (llvm::sys::fs::can_execute(Twine(Dir)))6210return true;6211llvm::sys::path::remove_filename(Dir);6212return false;6213}62146215std::string Driver::GetProgramPath(StringRef Name, const ToolChain &TC) const {6216SmallVector<std::string, 2> TargetSpecificExecutables;6217generatePrefixedToolNames(Name, TC, TargetSpecificExecutables);62186219// Respect a limited subset of the '-Bprefix' functionality in GCC by6220// attempting to use this prefix when looking for program paths.6221for (const auto &PrefixDir : PrefixDirs) {6222if (llvm::sys::fs::is_directory(PrefixDir)) {6223SmallString<128> P(PrefixDir);6224if (ScanDirForExecutable(P, Name))6225return std::string(P);6226} else {6227SmallString<128> P((PrefixDir + Name).str());6228if (llvm::sys::fs::can_execute(Twine(P)))6229return std::string(P);6230}6231}62326233const ToolChain::path_list &List = TC.getProgramPaths();6234for (const auto &TargetSpecificExecutable : TargetSpecificExecutables) {6235// For each possible name of the tool look for it in6236// program paths first, then the path.6237// Higher priority names will be first, meaning that6238// a higher priority name in the path will be found6239// instead of a lower priority name in the program path.6240// E.g. <triple>-gcc on the path will be found instead6241// of gcc in the program path6242for (const auto &Path : List) {6243SmallString<128> P(Path);6244if (ScanDirForExecutable(P, TargetSpecificExecutable))6245return std::string(P);6246}62476248// Fall back to the path6249if (llvm::ErrorOr<std::string> P =6250llvm::sys::findProgramByName(TargetSpecificExecutable))6251return *P;6252}62536254return std::string(Name);6255}62566257std::string Driver::GetStdModuleManifestPath(const Compilation &C,6258const ToolChain &TC) const {6259std::string error = "<NOT PRESENT>";62606261switch (TC.GetCXXStdlibType(C.getArgs())) {6262case ToolChain::CST_Libcxx: {6263auto evaluate = [&](const char *library) -> std::optional<std::string> {6264std::string lib = GetFilePath(library, TC);62656266// Note when there are multiple flavours of libc++ the module json needs6267// to look at the command-line arguments for the proper json. These6268// flavours do not exist at the moment, but there are plans to provide a6269// variant that is built with sanitizer instrumentation enabled.62706271// For example6272// StringRef modules = [&] {6273// const SanitizerArgs &Sanitize = TC.getSanitizerArgs(C.getArgs());6274// if (Sanitize.needsAsanRt())6275// return "libc++.modules-asan.json";6276// return "libc++.modules.json";6277// }();62786279SmallString<128> path(lib.begin(), lib.end());6280llvm::sys::path::remove_filename(path);6281llvm::sys::path::append(path, "libc++.modules.json");6282if (TC.getVFS().exists(path))6283return static_cast<std::string>(path);62846285return {};6286};62876288if (std::optional<std::string> result = evaluate("libc++.so"); result)6289return *result;62906291return evaluate("libc++.a").value_or(error);6292}62936294case ToolChain::CST_Libstdcxx:6295// libstdc++ does not provide Standard library modules yet.6296return error;6297}62986299return error;6300}63016302std::string Driver::GetTemporaryPath(StringRef Prefix, StringRef Suffix) const {6303SmallString<128> Path;6304std::error_code EC = llvm::sys::fs::createTemporaryFile(Prefix, Suffix, Path);6305if (EC) {6306Diag(clang::diag::err_unable_to_make_temp) << EC.message();6307return "";6308}63096310return std::string(Path);6311}63126313std::string Driver::GetTemporaryDirectory(StringRef Prefix) const {6314SmallString<128> Path;6315std::error_code EC = llvm::sys::fs::createUniqueDirectory(Prefix, Path);6316if (EC) {6317Diag(clang::diag::err_unable_to_make_temp) << EC.message();6318return "";6319}63206321return std::string(Path);6322}63236324std::string Driver::GetClPchPath(Compilation &C, StringRef BaseName) const {6325SmallString<128> Output;6326if (Arg *FpArg = C.getArgs().getLastArg(options::OPT__SLASH_Fp)) {6327// FIXME: If anybody needs it, implement this obscure rule:6328// "If you specify a directory without a file name, the default file name6329// is VCx0.pch., where x is the major version of Visual C++ in use."6330Output = FpArg->getValue();63316332// "If you do not specify an extension as part of the path name, an6333// extension of .pch is assumed. "6334if (!llvm::sys::path::has_extension(Output))6335Output += ".pch";6336} else {6337if (Arg *YcArg = C.getArgs().getLastArg(options::OPT__SLASH_Yc))6338Output = YcArg->getValue();6339if (Output.empty())6340Output = BaseName;6341llvm::sys::path::replace_extension(Output, ".pch");6342}6343return std::string(Output);6344}63456346const ToolChain &Driver::getToolChain(const ArgList &Args,6347const llvm::Triple &Target) const {63486349auto &TC = ToolChains[Target.str()];6350if (!TC) {6351switch (Target.getOS()) {6352case llvm::Triple::AIX:6353TC = std::make_unique<toolchains::AIX>(*this, Target, Args);6354break;6355case llvm::Triple::Haiku:6356TC = std::make_unique<toolchains::Haiku>(*this, Target, Args);6357break;6358case llvm::Triple::Darwin:6359case llvm::Triple::MacOSX:6360case llvm::Triple::IOS:6361case llvm::Triple::TvOS:6362case llvm::Triple::WatchOS:6363case llvm::Triple::XROS:6364case llvm::Triple::DriverKit:6365TC = std::make_unique<toolchains::DarwinClang>(*this, Target, Args);6366break;6367case llvm::Triple::DragonFly:6368TC = std::make_unique<toolchains::DragonFly>(*this, Target, Args);6369break;6370case llvm::Triple::OpenBSD:6371TC = std::make_unique<toolchains::OpenBSD>(*this, Target, Args);6372break;6373case llvm::Triple::NetBSD:6374TC = std::make_unique<toolchains::NetBSD>(*this, Target, Args);6375break;6376case llvm::Triple::FreeBSD:6377if (Target.isPPC())6378TC = std::make_unique<toolchains::PPCFreeBSDToolChain>(*this, Target,6379Args);6380else6381TC = std::make_unique<toolchains::FreeBSD>(*this, Target, Args);6382break;6383case llvm::Triple::Linux:6384case llvm::Triple::ELFIAMCU:6385if (Target.getArch() == llvm::Triple::hexagon)6386TC = std::make_unique<toolchains::HexagonToolChain>(*this, Target,6387Args);6388else if ((Target.getVendor() == llvm::Triple::MipsTechnologies) &&6389!Target.hasEnvironment())6390TC = std::make_unique<toolchains::MipsLLVMToolChain>(*this, Target,6391Args);6392else if (Target.isPPC())6393TC = std::make_unique<toolchains::PPCLinuxToolChain>(*this, Target,6394Args);6395else if (Target.getArch() == llvm::Triple::ve)6396TC = std::make_unique<toolchains::VEToolChain>(*this, Target, Args);6397else if (Target.isOHOSFamily())6398TC = std::make_unique<toolchains::OHOS>(*this, Target, Args);6399else6400TC = std::make_unique<toolchains::Linux>(*this, Target, Args);6401break;6402case llvm::Triple::NaCl:6403TC = std::make_unique<toolchains::NaClToolChain>(*this, Target, Args);6404break;6405case llvm::Triple::Fuchsia:6406TC = std::make_unique<toolchains::Fuchsia>(*this, Target, Args);6407break;6408case llvm::Triple::Solaris:6409TC = std::make_unique<toolchains::Solaris>(*this, Target, Args);6410break;6411case llvm::Triple::CUDA:6412TC = std::make_unique<toolchains::NVPTXToolChain>(*this, Target, Args);6413break;6414case llvm::Triple::AMDHSA:6415TC = std::make_unique<toolchains::ROCMToolChain>(*this, Target, Args);6416break;6417case llvm::Triple::AMDPAL:6418case llvm::Triple::Mesa3D:6419TC = std::make_unique<toolchains::AMDGPUToolChain>(*this, Target, Args);6420break;6421case llvm::Triple::Win32:6422switch (Target.getEnvironment()) {6423default:6424if (Target.isOSBinFormatELF())6425TC = std::make_unique<toolchains::Generic_ELF>(*this, Target, Args);6426else if (Target.isOSBinFormatMachO())6427TC = std::make_unique<toolchains::MachO>(*this, Target, Args);6428else6429TC = std::make_unique<toolchains::Generic_GCC>(*this, Target, Args);6430break;6431case llvm::Triple::GNU:6432TC = std::make_unique<toolchains::MinGW>(*this, Target, Args);6433break;6434case llvm::Triple::Itanium:6435TC = std::make_unique<toolchains::CrossWindowsToolChain>(*this, Target,6436Args);6437break;6438case llvm::Triple::MSVC:6439case llvm::Triple::UnknownEnvironment:6440if (Args.getLastArgValue(options::OPT_fuse_ld_EQ)6441.starts_with_insensitive("bfd"))6442TC = std::make_unique<toolchains::CrossWindowsToolChain>(6443*this, Target, Args);6444else6445TC =6446std::make_unique<toolchains::MSVCToolChain>(*this, Target, Args);6447break;6448}6449break;6450case llvm::Triple::PS4:6451TC = std::make_unique<toolchains::PS4CPU>(*this, Target, Args);6452break;6453case llvm::Triple::PS5:6454TC = std::make_unique<toolchains::PS5CPU>(*this, Target, Args);6455break;6456case llvm::Triple::Hurd:6457TC = std::make_unique<toolchains::Hurd>(*this, Target, Args);6458break;6459case llvm::Triple::LiteOS:6460TC = std::make_unique<toolchains::OHOS>(*this, Target, Args);6461break;6462case llvm::Triple::ZOS:6463TC = std::make_unique<toolchains::ZOS>(*this, Target, Args);6464break;6465case llvm::Triple::ShaderModel:6466TC = std::make_unique<toolchains::HLSLToolChain>(*this, Target, Args);6467break;6468default:6469// Of these targets, Hexagon is the only one that might have6470// an OS of Linux, in which case it got handled above already.6471switch (Target.getArch()) {6472case llvm::Triple::tce:6473TC = std::make_unique<toolchains::TCEToolChain>(*this, Target, Args);6474break;6475case llvm::Triple::tcele:6476TC = std::make_unique<toolchains::TCELEToolChain>(*this, Target, Args);6477break;6478case llvm::Triple::hexagon:6479TC = std::make_unique<toolchains::HexagonToolChain>(*this, Target,6480Args);6481break;6482case llvm::Triple::lanai:6483TC = std::make_unique<toolchains::LanaiToolChain>(*this, Target, Args);6484break;6485case llvm::Triple::xcore:6486TC = std::make_unique<toolchains::XCoreToolChain>(*this, Target, Args);6487break;6488case llvm::Triple::wasm32:6489case llvm::Triple::wasm64:6490TC = std::make_unique<toolchains::WebAssembly>(*this, Target, Args);6491break;6492case llvm::Triple::avr:6493TC = std::make_unique<toolchains::AVRToolChain>(*this, Target, Args);6494break;6495case llvm::Triple::msp430:6496TC =6497std::make_unique<toolchains::MSP430ToolChain>(*this, Target, Args);6498break;6499case llvm::Triple::riscv32:6500case llvm::Triple::riscv64:6501if (toolchains::RISCVToolChain::hasGCCToolchain(*this, Args))6502TC =6503std::make_unique<toolchains::RISCVToolChain>(*this, Target, Args);6504else6505TC = std::make_unique<toolchains::BareMetal>(*this, Target, Args);6506break;6507case llvm::Triple::ve:6508TC = std::make_unique<toolchains::VEToolChain>(*this, Target, Args);6509break;6510case llvm::Triple::spirv32:6511case llvm::Triple::spirv64:6512TC = std::make_unique<toolchains::SPIRVToolChain>(*this, Target, Args);6513break;6514case llvm::Triple::csky:6515TC = std::make_unique<toolchains::CSKYToolChain>(*this, Target, Args);6516break;6517default:6518if (toolchains::BareMetal::handlesTarget(Target))6519TC = std::make_unique<toolchains::BareMetal>(*this, Target, Args);6520else if (Target.isOSBinFormatELF())6521TC = std::make_unique<toolchains::Generic_ELF>(*this, Target, Args);6522else if (Target.isOSBinFormatMachO())6523TC = std::make_unique<toolchains::MachO>(*this, Target, Args);6524else6525TC = std::make_unique<toolchains::Generic_GCC>(*this, Target, Args);6526}6527}6528}65296530return *TC;6531}65326533const ToolChain &Driver::getOffloadingDeviceToolChain(6534const ArgList &Args, const llvm::Triple &Target, const ToolChain &HostTC,6535const Action::OffloadKind &TargetDeviceOffloadKind) const {6536// Use device / host triples as the key into the ToolChains map because the6537// device ToolChain we create depends on both.6538auto &TC = ToolChains[Target.str() + "/" + HostTC.getTriple().str()];6539if (!TC) {6540// Categorized by offload kind > arch rather than OS > arch like6541// the normal getToolChain call, as it seems a reasonable way to categorize6542// things.6543switch (TargetDeviceOffloadKind) {6544case Action::OFK_HIP: {6545if (((Target.getArch() == llvm::Triple::amdgcn ||6546Target.getArch() == llvm::Triple::spirv64) &&6547Target.getVendor() == llvm::Triple::AMD &&6548Target.getOS() == llvm::Triple::AMDHSA) ||6549!Args.hasArgNoClaim(options::OPT_offload_EQ))6550TC = std::make_unique<toolchains::HIPAMDToolChain>(*this, Target,6551HostTC, Args);6552else if (Target.getArch() == llvm::Triple::spirv64 &&6553Target.getVendor() == llvm::Triple::UnknownVendor &&6554Target.getOS() == llvm::Triple::UnknownOS)6555TC = std::make_unique<toolchains::HIPSPVToolChain>(*this, Target,6556HostTC, Args);6557break;6558}6559default:6560break;6561}6562}65636564return *TC;6565}65666567bool Driver::ShouldUseClangCompiler(const JobAction &JA) const {6568// Say "no" if there is not exactly one input of a type clang understands.6569if (JA.size() != 1 ||6570!types::isAcceptedByClang((*JA.input_begin())->getType()))6571return false;65726573// And say "no" if this is not a kind of action clang understands.6574if (!isa<PreprocessJobAction>(JA) && !isa<PrecompileJobAction>(JA) &&6575!isa<CompileJobAction>(JA) && !isa<BackendJobAction>(JA) &&6576!isa<ExtractAPIJobAction>(JA))6577return false;65786579return true;6580}65816582bool Driver::ShouldUseFlangCompiler(const JobAction &JA) const {6583// Say "no" if there is not exactly one input of a type flang understands.6584if (JA.size() != 1 ||6585!types::isAcceptedByFlang((*JA.input_begin())->getType()))6586return false;65876588// And say "no" if this is not a kind of action flang understands.6589if (!isa<PreprocessJobAction>(JA) && !isa<CompileJobAction>(JA) &&6590!isa<BackendJobAction>(JA))6591return false;65926593return true;6594}65956596bool Driver::ShouldEmitStaticLibrary(const ArgList &Args) const {6597// Only emit static library if the flag is set explicitly.6598if (Args.hasArg(options::OPT_emit_static_lib))6599return true;6600return false;6601}66026603/// GetReleaseVersion - Parse (([0-9]+)(.([0-9]+)(.([0-9]+)?))?)? and return the6604/// grouped values as integers. Numbers which are not provided are set to 0.6605///6606/// \return True if the entire string was parsed (9.2), or all groups were6607/// parsed (10.3.5extrastuff).6608bool Driver::GetReleaseVersion(StringRef Str, unsigned &Major, unsigned &Minor,6609unsigned &Micro, bool &HadExtra) {6610HadExtra = false;66116612Major = Minor = Micro = 0;6613if (Str.empty())6614return false;66156616if (Str.consumeInteger(10, Major))6617return false;6618if (Str.empty())6619return true;6620if (!Str.consume_front("."))6621return false;66226623if (Str.consumeInteger(10, Minor))6624return false;6625if (Str.empty())6626return true;6627if (!Str.consume_front("."))6628return false;66296630if (Str.consumeInteger(10, Micro))6631return false;6632if (!Str.empty())6633HadExtra = true;6634return true;6635}66366637/// Parse digits from a string \p Str and fulfill \p Digits with6638/// the parsed numbers. This method assumes that the max number of6639/// digits to look for is equal to Digits.size().6640///6641/// \return True if the entire string was parsed and there are6642/// no extra characters remaining at the end.6643bool Driver::GetReleaseVersion(StringRef Str,6644MutableArrayRef<unsigned> Digits) {6645if (Str.empty())6646return false;66476648unsigned CurDigit = 0;6649while (CurDigit < Digits.size()) {6650unsigned Digit;6651if (Str.consumeInteger(10, Digit))6652return false;6653Digits[CurDigit] = Digit;6654if (Str.empty())6655return true;6656if (!Str.consume_front("."))6657return false;6658CurDigit++;6659}66606661// More digits than requested, bail out...6662return false;6663}66646665llvm::opt::Visibility6666Driver::getOptionVisibilityMask(bool UseDriverMode) const {6667if (!UseDriverMode)6668return llvm::opt::Visibility(options::ClangOption);6669if (IsCLMode())6670return llvm::opt::Visibility(options::CLOption);6671if (IsDXCMode())6672return llvm::opt::Visibility(options::DXCOption);6673if (IsFlangMode()) {6674return llvm::opt::Visibility(options::FlangOption);6675}6676return llvm::opt::Visibility(options::ClangOption);6677}66786679const char *Driver::getExecutableForDriverMode(DriverMode Mode) {6680switch (Mode) {6681case GCCMode:6682return "clang";6683case GXXMode:6684return "clang++";6685case CPPMode:6686return "clang-cpp";6687case CLMode:6688return "clang-cl";6689case FlangMode:6690return "flang";6691case DXCMode:6692return "clang-dxc";6693}66946695llvm_unreachable("Unhandled Mode");6696}66976698bool clang::driver::isOptimizationLevelFast(const ArgList &Args) {6699return Args.hasFlag(options::OPT_Ofast, options::OPT_O_Group, false);6700}67016702bool clang::driver::willEmitRemarks(const ArgList &Args) {6703// -fsave-optimization-record enables it.6704if (Args.hasFlag(options::OPT_fsave_optimization_record,6705options::OPT_fno_save_optimization_record, false))6706return true;67076708// -fsave-optimization-record=<format> enables it as well.6709if (Args.hasFlag(options::OPT_fsave_optimization_record_EQ,6710options::OPT_fno_save_optimization_record, false))6711return true;67126713// -foptimization-record-file alone enables it too.6714if (Args.hasFlag(options::OPT_foptimization_record_file_EQ,6715options::OPT_fno_save_optimization_record, false))6716return true;67176718// -foptimization-record-passes alone enables it too.6719if (Args.hasFlag(options::OPT_foptimization_record_passes_EQ,6720options::OPT_fno_save_optimization_record, false))6721return true;6722return false;6723}67246725llvm::StringRef clang::driver::getDriverMode(StringRef ProgName,6726ArrayRef<const char *> Args) {6727static StringRef OptName =6728getDriverOptTable().getOption(options::OPT_driver_mode).getPrefixedName();6729llvm::StringRef Opt;6730for (StringRef Arg : Args) {6731if (!Arg.starts_with(OptName))6732continue;6733Opt = Arg;6734}6735if (Opt.empty())6736Opt = ToolChain::getTargetAndModeFromProgramName(ProgName).DriverMode;6737return Opt.consume_front(OptName) ? Opt : "";6738}67396740bool driver::IsClangCL(StringRef DriverMode) { return DriverMode == "cl"; }67416742llvm::Error driver::expandResponseFiles(SmallVectorImpl<const char *> &Args,6743bool ClangCLMode,6744llvm::BumpPtrAllocator &Alloc,6745llvm::vfs::FileSystem *FS) {6746// Parse response files using the GNU syntax, unless we're in CL mode. There6747// are two ways to put clang in CL compatibility mode: ProgName is either6748// clang-cl or cl, or --driver-mode=cl is on the command line. The normal6749// command line parsing can't happen until after response file parsing, so we6750// have to manually search for a --driver-mode=cl argument the hard way.6751// Finally, our -cc1 tools don't care which tokenization mode we use because6752// response files written by clang will tokenize the same way in either mode.6753enum { Default, POSIX, Windows } RSPQuoting = Default;6754for (const char *F : Args) {6755if (strcmp(F, "--rsp-quoting=posix") == 0)6756RSPQuoting = POSIX;6757else if (strcmp(F, "--rsp-quoting=windows") == 0)6758RSPQuoting = Windows;6759}67606761// Determines whether we want nullptr markers in Args to indicate response6762// files end-of-lines. We only use this for the /LINK driver argument with6763// clang-cl.exe on Windows.6764bool MarkEOLs = ClangCLMode;67656766llvm::cl::TokenizerCallback Tokenizer;6767if (RSPQuoting == Windows || (RSPQuoting == Default && ClangCLMode))6768Tokenizer = &llvm::cl::TokenizeWindowsCommandLine;6769else6770Tokenizer = &llvm::cl::TokenizeGNUCommandLine;67716772if (MarkEOLs && Args.size() > 1 && StringRef(Args[1]).starts_with("-cc1"))6773MarkEOLs = false;67746775llvm::cl::ExpansionContext ECtx(Alloc, Tokenizer);6776ECtx.setMarkEOLs(MarkEOLs);6777if (FS)6778ECtx.setVFS(FS);67796780if (llvm::Error Err = ECtx.expandResponseFiles(Args))6781return Err;67826783// If -cc1 came from a response file, remove the EOL sentinels.6784auto FirstArg = llvm::find_if(llvm::drop_begin(Args),6785[](const char *A) { return A != nullptr; });6786if (FirstArg != Args.end() && StringRef(*FirstArg).starts_with("-cc1")) {6787// If -cc1 came from a response file, remove the EOL sentinels.6788if (MarkEOLs) {6789auto newEnd = std::remove(Args.begin(), Args.end(), nullptr);6790Args.resize(newEnd - Args.begin());6791}6792}67936794return llvm::Error::success();6795}67966797static const char *GetStableCStr(llvm::StringSet<> &SavedStrings, StringRef S) {6798return SavedStrings.insert(S).first->getKeyData();6799}68006801/// Apply a list of edits to the input argument lists.6802///6803/// The input string is a space separated list of edits to perform,6804/// they are applied in order to the input argument lists. Edits6805/// should be one of the following forms:6806///6807/// '#': Silence information about the changes to the command line arguments.6808///6809/// '^': Add FOO as a new argument at the beginning of the command line.6810///6811/// '+': Add FOO as a new argument at the end of the command line.6812///6813/// 's/XXX/YYY/': Substitute the regular expression XXX with YYY in the command6814/// line.6815///6816/// 'xOPTION': Removes all instances of the literal argument OPTION.6817///6818/// 'XOPTION': Removes all instances of the literal argument OPTION,6819/// and the following argument.6820///6821/// 'Ox': Removes all flags matching 'O' or 'O[sz0-9]' and adds 'Ox'6822/// at the end of the command line.6823///6824/// \param OS - The stream to write edit information to.6825/// \param Args - The vector of command line arguments.6826/// \param Edit - The override command to perform.6827/// \param SavedStrings - Set to use for storing string representations.6828static void applyOneOverrideOption(raw_ostream &OS,6829SmallVectorImpl<const char *> &Args,6830StringRef Edit,6831llvm::StringSet<> &SavedStrings) {6832// This does not need to be efficient.68336834if (Edit[0] == '^') {6835const char *Str = GetStableCStr(SavedStrings, Edit.substr(1));6836OS << "### Adding argument " << Str << " at beginning\n";6837Args.insert(Args.begin() + 1, Str);6838} else if (Edit[0] == '+') {6839const char *Str = GetStableCStr(SavedStrings, Edit.substr(1));6840OS << "### Adding argument " << Str << " at end\n";6841Args.push_back(Str);6842} else if (Edit[0] == 's' && Edit[1] == '/' && Edit.ends_with("/") &&6843Edit.slice(2, Edit.size() - 1).contains('/')) {6844StringRef MatchPattern = Edit.substr(2).split('/').first;6845StringRef ReplPattern = Edit.substr(2).split('/').second;6846ReplPattern = ReplPattern.slice(0, ReplPattern.size() - 1);68476848for (unsigned i = 1, e = Args.size(); i != e; ++i) {6849// Ignore end-of-line response file markers6850if (Args[i] == nullptr)6851continue;6852std::string Repl = llvm::Regex(MatchPattern).sub(ReplPattern, Args[i]);68536854if (Repl != Args[i]) {6855OS << "### Replacing '" << Args[i] << "' with '" << Repl << "'\n";6856Args[i] = GetStableCStr(SavedStrings, Repl);6857}6858}6859} else if (Edit[0] == 'x' || Edit[0] == 'X') {6860auto Option = Edit.substr(1);6861for (unsigned i = 1; i < Args.size();) {6862if (Option == Args[i]) {6863OS << "### Deleting argument " << Args[i] << '\n';6864Args.erase(Args.begin() + i);6865if (Edit[0] == 'X') {6866if (i < Args.size()) {6867OS << "### Deleting argument " << Args[i] << '\n';6868Args.erase(Args.begin() + i);6869} else6870OS << "### Invalid X edit, end of command line!\n";6871}6872} else6873++i;6874}6875} else if (Edit[0] == 'O') {6876for (unsigned i = 1; i < Args.size();) {6877const char *A = Args[i];6878// Ignore end-of-line response file markers6879if (A == nullptr)6880continue;6881if (A[0] == '-' && A[1] == 'O' &&6882(A[2] == '\0' || (A[3] == '\0' && (A[2] == 's' || A[2] == 'z' ||6883('0' <= A[2] && A[2] <= '9'))))) {6884OS << "### Deleting argument " << Args[i] << '\n';6885Args.erase(Args.begin() + i);6886} else6887++i;6888}6889OS << "### Adding argument " << Edit << " at end\n";6890Args.push_back(GetStableCStr(SavedStrings, '-' + Edit.str()));6891} else {6892OS << "### Unrecognized edit: " << Edit << "\n";6893}6894}68956896void driver::applyOverrideOptions(SmallVectorImpl<const char *> &Args,6897const char *OverrideStr,6898llvm::StringSet<> &SavedStrings,6899raw_ostream *OS) {6900if (!OS)6901OS = &llvm::nulls();69026903if (OverrideStr[0] == '#') {6904++OverrideStr;6905OS = &llvm::nulls();6906}69076908*OS << "### CCC_OVERRIDE_OPTIONS: " << OverrideStr << "\n";69096910// This does not need to be efficient.69116912const char *S = OverrideStr;6913while (*S) {6914const char *End = ::strchr(S, ' ');6915if (!End)6916End = S + strlen(S);6917if (End != S)6918applyOneOverrideOption(*OS, Args, std::string(S, End), SavedStrings);6919S = End;6920if (*S != '\0')6921++S;6922}6923}692469256926