aboutsummaryrefslogtreecommitdiff
path: root/clang/lib/Driver/Driver.cpp
diff options
context:
space:
mode:
authorDimitry Andric <dim@FreeBSD.org>2021-07-29 20:15:26 +0000
committerDimitry Andric <dim@FreeBSD.org>2021-07-29 20:15:26 +0000
commit344a3780b2e33f6ca763666c380202b18aab72a3 (patch)
treef0b203ee6eb71d7fdd792373e3c81eb18d6934dd /clang/lib/Driver/Driver.cpp
parentb60736ec1405bb0a8dd40989f67ef4c93da068ab (diff)
downloadsrc-344a3780b2e33f6ca763666c380202b18aab72a3.tar.gz
src-344a3780b2e33f6ca763666c380202b18aab72a3.zip
the upstream release/13.x branch was created.
Diffstat (limited to 'clang/lib/Driver/Driver.cpp')
-rw-r--r--clang/lib/Driver/Driver.cpp431
1 files changed, 310 insertions, 121 deletions
diff --git a/clang/lib/Driver/Driver.cpp b/clang/lib/Driver/Driver.cpp
index 418e1d3e8ec9..5c323cb6ea23 100644
--- a/clang/lib/Driver/Driver.cpp
+++ b/clang/lib/Driver/Driver.cpp
@@ -7,9 +7,9 @@
//===----------------------------------------------------------------------===//
#include "clang/Driver/Driver.h"
-#include "InputInfo.h"
#include "ToolChains/AIX.h"
#include "ToolChains/AMDGPU.h"
+#include "ToolChains/AMDGPUOpenMP.h"
#include "ToolChains/AVR.h"
#include "ToolChains/Ananas.h"
#include "ToolChains/BareMetal.h"
@@ -53,6 +53,7 @@
#include "clang/Driver/Action.h"
#include "clang/Driver/Compilation.h"
#include "clang/Driver/DriverDiagnostic.h"
+#include "clang/Driver/InputInfo.h"
#include "clang/Driver/Job.h"
#include "clang/Driver/Options.h"
#include "clang/Driver/SanitizerArgs.h"
@@ -62,6 +63,7 @@
#include "llvm/ADT/STLExtras.h"
#include "llvm/ADT/SmallSet.h"
#include "llvm/ADT/StringExtras.h"
+#include "llvm/ADT/StringRef.h"
#include "llvm/ADT/StringSet.h"
#include "llvm/ADT/StringSwitch.h"
#include "llvm/Config/llvm-config.h"
@@ -76,6 +78,7 @@
#include "llvm/Support/FileSystem.h"
#include "llvm/Support/FormatVariadic.h"
#include "llvm/Support/Host.h"
+#include "llvm/Support/MD5.h"
#include "llvm/Support/Path.h"
#include "llvm/Support/PrettyStackTrace.h"
#include "llvm/Support/Process.h"
@@ -133,13 +136,13 @@ Driver::Driver(StringRef ClangExecutable, StringRef TargetTriple,
: Diags(Diags), VFS(std::move(VFS)), Mode(GCCMode),
SaveTemps(SaveTempsNone), BitcodeEmbed(EmbedNone), LTOMode(LTOK_None),
ClangExecutable(ClangExecutable), SysRoot(DEFAULT_SYSROOT),
- DriverTitle(Title), CCPrintOptionsFilename(nullptr),
- CCPrintHeadersFilename(nullptr), CCLogDiagnosticsFilename(nullptr),
+ DriverTitle(Title), CCPrintStatReportFilename(), CCPrintOptionsFilename(),
+ CCPrintHeadersFilename(), CCLogDiagnosticsFilename(),
CCCPrintBindings(false), CCPrintOptions(false), CCPrintHeaders(false),
CCLogDiagnostics(false), CCGenDiagnostics(false),
- TargetTriple(TargetTriple), CCCGenericGCCName(""), Saver(Alloc),
- CheckInputsExist(true), GenReproducer(false),
- SuppressMissingInputWarning(false) {
+ CCPrintProcessStats(false), TargetTriple(TargetTriple),
+ CCCGenericGCCName(""), Saver(Alloc), CheckInputsExist(true),
+ GenReproducer(false), SuppressMissingInputWarning(false) {
// Provide a sane fallback if no VFS is specified.
if (!this->VFS)
this->VFS = llvm::vfs::getRealFileSystem();
@@ -166,28 +169,9 @@ Driver::Driver(StringRef ClangExecutable, StringRef TargetTriple,
ResourceDir = GetResourcesPath(ClangExecutable, CLANG_RESOURCE_DIR);
}
-void Driver::ParseDriverMode(StringRef ProgramName,
- ArrayRef<const char *> Args) {
- if (ClangNameParts.isEmpty())
- ClangNameParts = ToolChain::getTargetAndModeFromProgramName(ProgramName);
- setDriverModeFromOption(ClangNameParts.DriverMode);
-
- for (const char *ArgPtr : Args) {
- // Ignore nullptrs, they are the response file's EOL markers.
- if (ArgPtr == nullptr)
- continue;
- const StringRef Arg = ArgPtr;
- setDriverModeFromOption(Arg);
- }
-}
-
-void Driver::setDriverModeFromOption(StringRef Opt) {
- const std::string OptName =
+void Driver::setDriverMode(StringRef Value) {
+ static const std::string OptName =
getOpts().getOption(options::OPT_driver_mode).getPrefixedName();
- if (!Opt.startswith(OptName))
- return;
- StringRef Value = Opt.drop_front(OptName.size());
-
if (auto M = llvm::StringSwitch<llvm::Optional<DriverMode>>(Value)
.Case("gcc", GCCMode)
.Case("g++", GXXMode)
@@ -517,14 +501,21 @@ static llvm::Triple computeTargetTriple(const Driver &D,
AT = Target.get64BitArchVariant().getArch();
if (Target.getEnvironment() == llvm::Triple::GNUX32)
Target.setEnvironment(llvm::Triple::GNU);
+ else if (Target.getEnvironment() == llvm::Triple::MuslX32)
+ Target.setEnvironment(llvm::Triple::Musl);
} else if (A->getOption().matches(options::OPT_mx32) &&
Target.get64BitArchVariant().getArch() == llvm::Triple::x86_64) {
AT = llvm::Triple::x86_64;
- Target.setEnvironment(llvm::Triple::GNUX32);
+ if (Target.getEnvironment() == llvm::Triple::Musl)
+ Target.setEnvironment(llvm::Triple::MuslX32);
+ else
+ Target.setEnvironment(llvm::Triple::GNUX32);
} else if (A->getOption().matches(options::OPT_m32)) {
AT = Target.get32BitArchVariant().getArch();
if (Target.getEnvironment() == llvm::Triple::GNUX32)
Target.setEnvironment(llvm::Triple::GNU);
+ else if (Target.getEnvironment() == llvm::Triple::MuslX32)
+ Target.setEnvironment(llvm::Triple::Musl);
} else if (A->getOption().matches(options::OPT_m16) &&
Target.get32BitArchVariant().getArch() == llvm::Triple::x86) {
AT = llvm::Triple::x86;
@@ -582,9 +573,9 @@ static llvm::Triple computeTargetTriple(const Driver &D,
A = Args.getLastArg(options::OPT_march_EQ);
if (A && Target.isRISCV()) {
StringRef ArchName = A->getValue();
- if (ArchName.startswith_lower("rv32"))
+ if (ArchName.startswith_insensitive("rv32"))
Target.setArch(llvm::Triple::riscv32);
- else if (ArchName.startswith_lower("rv64"))
+ else if (ArchName.startswith_insensitive("rv64"))
Target.setArch(llvm::Triple::riscv64);
}
@@ -592,16 +583,24 @@ static llvm::Triple computeTargetTriple(const Driver &D,
}
// Parse the LTO options and record the type of LTO compilation
-// based on which -f(no-)?lto(=.*)? option occurs last.
-void Driver::setLTOMode(const llvm::opt::ArgList &Args) {
- LTOMode = LTOK_None;
- if (!Args.hasFlag(options::OPT_flto, options::OPT_flto_EQ,
- options::OPT_fno_lto, false))
- return;
+// based on which -f(no-)?lto(=.*)? or -f(no-)?offload-lto(=.*)?
+// option occurs last.
+static llvm::Optional<driver::LTOKind>
+parseLTOMode(Driver &D, const llvm::opt::ArgList &Args, OptSpecifier OptPos,
+ OptSpecifier OptNeg, OptSpecifier OptEq, bool IsOffload) {
+ driver::LTOKind LTOMode = LTOK_None;
+ // Non-offload LTO allows -flto=auto and -flto=jobserver. Offload LTO does
+ // not support those options.
+ if (!Args.hasFlag(OptPos, OptEq, OptNeg, false) &&
+ (IsOffload ||
+ (!Args.hasFlag(options::OPT_flto_EQ_auto, options::OPT_fno_lto, false) &&
+ !Args.hasFlag(options::OPT_flto_EQ_jobserver, options::OPT_fno_lto,
+ false))))
+ return None;
StringRef LTOName("full");
- const Arg *A = Args.getLastArg(options::OPT_flto_EQ);
+ const Arg *A = Args.getLastArg(OptEq);
if (A)
LTOName = A->getValue();
@@ -612,9 +611,27 @@ void Driver::setLTOMode(const llvm::opt::ArgList &Args) {
if (LTOMode == LTOK_Unknown) {
assert(A);
- Diag(diag::err_drv_unsupported_option_argument) << A->getOption().getName()
- << A->getValue();
+ D.Diag(diag::err_drv_unsupported_option_argument)
+ << A->getOption().getName() << A->getValue();
+ return None;
}
+ return LTOMode;
+}
+
+// Parse the LTO options.
+void Driver::setLTOMode(const llvm::opt::ArgList &Args) {
+ LTOMode = LTOK_None;
+ if (auto M = parseLTOMode(*this, Args, options::OPT_flto,
+ options::OPT_fno_lto, options::OPT_flto_EQ,
+ /*IsOffload=*/false))
+ LTOMode = M.getValue();
+
+ OffloadLTOMode = LTOK_None;
+ if (auto M = parseLTOMode(*this, Args, options::OPT_foffload_lto,
+ options::OPT_fno_offload_lto,
+ options::OPT_foffload_lto_EQ,
+ /*IsOffload=*/true))
+ OffloadLTOMode = M.getValue();
}
/// Compute the desired OpenMP runtime from the flags provided.
@@ -739,18 +756,27 @@ void Driver::CreateOffloadingDeviceToolChains(Compilation &C,
Diag(clang::diag::err_drv_invalid_omp_target) << Val;
else {
const ToolChain *TC;
- // CUDA toolchains have to be selected differently. They pair host
+ // Device toolchains have to be selected differently. They pair host
// and device in their implementation.
- if (TT.isNVPTX()) {
+ if (TT.isNVPTX() || TT.isAMDGCN()) {
const ToolChain *HostTC =
C.getSingleOffloadToolChain<Action::OFK_Host>();
assert(HostTC && "Host toolchain should be always defined.");
- auto &CudaTC =
+ auto &DeviceTC =
ToolChains[TT.str() + "/" + HostTC->getTriple().normalize()];
- if (!CudaTC)
- CudaTC = std::make_unique<toolchains::CudaToolChain>(
- *this, TT, *HostTC, C.getInputArgs(), Action::OFK_OpenMP);
- TC = CudaTC.get();
+ if (!DeviceTC) {
+ if (TT.isNVPTX())
+ DeviceTC = std::make_unique<toolchains::CudaToolChain>(
+ *this, TT, *HostTC, C.getInputArgs(), Action::OFK_OpenMP);
+ else if (TT.isAMDGCN())
+ DeviceTC =
+ std::make_unique<toolchains::AMDGPUOpenMPToolChain>(
+ *this, TT, *HostTC, C.getInputArgs());
+ else
+ assert(DeviceTC && "Device toolchain not defined.");
+ }
+
+ TC = DeviceTC.get();
} else
TC = &getToolChain(C.getInputArgs(), TT);
C.addOffloadDeviceToolChain(TC, Action::OFK_OpenMP);
@@ -987,7 +1013,10 @@ Compilation *Driver::BuildCompilation(ArrayRef<const char *> ArgList) {
// We look for the driver mode option early, because the mode can affect
// how other options are parsed.
- ParseDriverMode(ClangExecutable, ArgList.slice(1));
+
+ auto DriverMode = getDriverMode(ClangExecutable, ArgList.slice(1));
+ if (!DriverMode.empty())
+ setDriverMode(DriverMode);
// FIXME: What are we going to do with -V and -b?
@@ -1085,6 +1114,15 @@ Compilation *Driver::BuildCompilation(ArrayRef<const char *> ArgList) {
GenReproducer = Args.hasFlag(options::OPT_gen_reproducer,
options::OPT_fno_crash_diagnostics,
!!::getenv("FORCE_CLANG_DIAGNOSTICS_CRASH"));
+
+ // Process -fproc-stat-report options.
+ if (const Arg *A = Args.getLastArg(options::OPT_fproc_stat_report_EQ)) {
+ CCPrintProcessStats = true;
+ CCPrintStatReportFilename = A->getValue();
+ }
+ if (Args.hasArg(options::OPT_fproc_stat_report))
+ CCPrintProcessStats = true;
+
// FIXME: TargetTriple is used by the target-prefixed calls to as/ld
// and getToolChain is const.
if (IsCLMode()) {
@@ -1434,7 +1472,9 @@ void Driver::generateCompilationDiagnostics(
llvm::SmallString<128> Script(CrashInfo.Filename);
llvm::sys::path::replace_extension(Script, "sh");
std::error_code EC;
- llvm::raw_fd_ostream ScriptOS(Script, EC, llvm::sys::fs::CD_CreateNew);
+ llvm::raw_fd_ostream ScriptOS(Script, EC, llvm::sys::fs::CD_CreateNew,
+ llvm::sys::fs::FA_Write,
+ llvm::sys::fs::OF_Text);
if (EC) {
Diag(clang::diag::note_drv_command_failed_diag_msg)
<< "Error generating run script: " << Script << " " << EC.message();
@@ -1471,8 +1511,7 @@ void Driver::generateCompilationDiagnostics(
}
}
- for (const auto &A : C.getArgs().filtered(options::OPT_frewrite_map_file,
- options::OPT_frewrite_map_file_EQ))
+ for (const auto &A : C.getArgs().filtered(options::OPT_frewrite_map_file_EQ))
Diag(clang::diag::note_drv_command_failed_diag_msg) << A->getValue();
Diag(clang::diag::note_drv_command_failed_diag_msg)
@@ -1581,7 +1620,7 @@ void Driver::PrintHelp(bool ShowHidden) const {
ExcludedFlagsBitmask |= options::FlangOnlyOption;
std::string Usage = llvm::formatv("{0} [options] file...", Name).str();
- getOpts().PrintHelp(llvm::outs(), Usage.c_str(), DriverTitle.c_str(),
+ getOpts().printHelp(llvm::outs(), Usage.c_str(), DriverTitle.c_str(),
IncludedFlagsBitmask, ExcludedFlagsBitmask,
/*ShowAllAliases=*/false);
}
@@ -1701,7 +1740,7 @@ void Driver::HandleAutocompletions(StringRef PassedFlags) const {
// case-insensitive sorting for consistency with the -help option
// which prints out options in the case-insensitive alphabetical order.
llvm::sort(SuggestedCompletions, [](StringRef A, StringRef B) {
- if (int X = A.compare_lower(B))
+ if (int X = A.compare_insensitive(B))
return X < 0;
return A.compare(B) > 0;
});
@@ -1802,6 +1841,15 @@ bool Driver::HandleImmediateArgs(const Compilation &C) {
return false;
}
+ if (C.getArgs().hasArg(options::OPT_print_runtime_dir)) {
+ std::string CandidateRuntimePath = TC.getRuntimePath();
+ if (getVFS().exists(CandidateRuntimePath))
+ llvm::outs() << CandidateRuntimePath << '\n';
+ else
+ llvm::outs() << TC.getCompilerRTPath() << '\n';
+ return false;
+ }
+
// FIXME: The following handlers should use a callback mechanism, we don't
// know what the client would like to do.
if (Arg *A = C.getArgs().getLastArg(options::OPT_print_file_name_EQ)) {
@@ -1870,6 +1918,12 @@ bool Driver::HandleImmediateArgs(const Compilation &C) {
return false;
}
+ if (C.getArgs().hasArg(options::OPT_print_multiarch)) {
+ llvm::outs() << TC.getMultiarchTriple(*this, TC.getTriple(), SysRoot)
+ << "\n";
+ return false;
+ }
+
if (C.getArgs().hasArg(options::OPT_print_targets)) {
llvm::TargetRegistry::printRegisteredTargetsForVersion(llvm::outs());
return false;
@@ -2179,15 +2233,20 @@ void Driver::BuildInputs(const ToolChain &TC, DerivedArgList &Args,
// stdin must be handled specially.
if (memcmp(Value, "-", 2) == 0) {
- // If running with -E, treat as a C input (this changes the builtin
- // macros, for example). This may be overridden by -ObjC below.
- //
- // Otherwise emit an error but still use a valid type to avoid
- // spurious errors (e.g., no inputs).
- if (!Args.hasArgNoClaim(options::OPT_E) && !CCCIsCPP())
- Diag(IsCLMode() ? clang::diag::err_drv_unknown_stdin_type_clang_cl
- : clang::diag::err_drv_unknown_stdin_type);
- Ty = types::TY_C;
+ if (IsFlangMode()) {
+ Ty = types::TY_Fortran;
+ } else {
+ // If running with -E, treat as a C input (this changes the
+ // builtin macros, for example). This may be overridden by -ObjC
+ // below.
+ //
+ // Otherwise emit an error but still use a valid type to avoid
+ // spurious errors (e.g., no inputs).
+ if (!Args.hasArgNoClaim(options::OPT_E) && !CCCIsCPP())
+ Diag(IsCLMode() ? clang::diag::err_drv_unknown_stdin_type_clang_cl
+ : clang::diag::err_drv_unknown_stdin_type);
+ Ty = types::TY_C;
+ }
} else {
// Otherwise lookup by extension.
// Fallback is C if invoked as C preprocessor, C++ if invoked with
@@ -2443,6 +2502,14 @@ class OffloadingActionBuilder final {
/// Default GPU architecture if there's no one specified.
CudaArch DefaultCudaArch = CudaArch::UNKNOWN;
+ /// Method to generate compilation unit ID specified by option
+ /// '-fuse-cuid='.
+ enum UseCUIDKind { CUID_Hash, CUID_Random, CUID_None, CUID_Invalid };
+ UseCUIDKind UseCUID = CUID_Hash;
+
+ /// Compilation unit ID specified by option '-cuid='.
+ StringRef FixedCUID;
+
public:
CudaActionBuilderBase(Compilation &C, DerivedArgList &Args,
const Driver::InputList &Inputs,
@@ -2479,9 +2546,32 @@ class OffloadingActionBuilder final {
// Replicate inputs for each GPU architecture.
auto Ty = IA->getType() == types::TY_HIP ? types::TY_HIP_DEVICE
: types::TY_CUDA_DEVICE;
+ std::string CUID = FixedCUID.str();
+ if (CUID.empty()) {
+ if (UseCUID == CUID_Random)
+ CUID = llvm::utohexstr(llvm::sys::Process::GetRandomNumber(),
+ /*LowerCase=*/true);
+ else if (UseCUID == CUID_Hash) {
+ llvm::MD5 Hasher;
+ llvm::MD5::MD5Result Hash;
+ SmallString<256> RealPath;
+ llvm::sys::fs::real_path(IA->getInputArg().getValue(), RealPath,
+ /*expand_tilde=*/true);
+ Hasher.update(RealPath);
+ for (auto *A : Args) {
+ if (A->getOption().matches(options::OPT_INPUT))
+ continue;
+ Hasher.update(A->getAsString(Args));
+ }
+ Hasher.final(Hash);
+ CUID = llvm::utohexstr(Hash.low(), /*LowerCase=*/true);
+ }
+ }
+ IA->setId(CUID);
+
for (unsigned I = 0, E = GpuArchList.size(); I != E; ++I) {
CudaDeviceActions.push_back(
- C.MakeAction<InputAction>(IA->getInputArg(), Ty));
+ C.MakeAction<InputAction>(IA->getInputArg(), Ty, IA->getId()));
}
return ABRT_Success;
@@ -2603,6 +2693,21 @@ class OffloadingActionBuilder final {
options::OPT_cuda_device_only);
EmitLLVM = Args.getLastArg(options::OPT_emit_llvm);
EmitAsm = Args.getLastArg(options::OPT_S);
+ FixedCUID = Args.getLastArgValue(options::OPT_cuid_EQ);
+ if (Arg *A = Args.getLastArg(options::OPT_fuse_cuid_EQ)) {
+ StringRef UseCUIDStr = A->getValue();
+ UseCUID = llvm::StringSwitch<UseCUIDKind>(UseCUIDStr)
+ .Case("hash", CUID_Hash)
+ .Case("random", CUID_Random)
+ .Case("none", CUID_None)
+ .Default(CUID_Invalid);
+ if (UseCUID == CUID_Invalid) {
+ C.getDriver().Diag(diag::err_drv_invalid_value)
+ << A->getAsString(Args) << UseCUIDStr;
+ C.setContainsError();
+ return true;
+ }
+ }
// Collect all cuda_gpu_arch parameters, removing duplicates.
std::set<StringRef> GpuArchs;
@@ -2665,7 +2770,7 @@ class OffloadingActionBuilder final {
StringRef getCanonicalOffloadArch(StringRef ArchStr) override {
CudaArch Arch = StringToCudaArch(ArchStr);
- if (Arch == CudaArch::UNKNOWN) {
+ if (Arch == CudaArch::UNKNOWN || !IsNVIDIAGpuArch(Arch)) {
C.getDriver().Diag(clang::diag::err_drv_cuda_bad_gpu_arch) << ArchStr;
return StringRef();
}
@@ -2786,12 +2891,25 @@ class OffloadingActionBuilder final {
class HIPActionBuilder final : public CudaActionBuilderBase {
/// The linker inputs obtained for each device arch.
SmallVector<ActionList, 8> DeviceLinkerInputs;
+ bool GPUSanitize;
+ // The default bundling behavior depends on the type of output, therefore
+ // BundleOutput needs to be tri-value: None, true, or false.
+ // Bundle code objects except --no-gpu-output is specified for device
+ // only compilation. Bundle other type of output files only if
+ // --gpu-bundle-output is specified for device only compilation.
+ Optional<bool> BundleOutput;
public:
HIPActionBuilder(Compilation &C, DerivedArgList &Args,
const Driver::InputList &Inputs)
: CudaActionBuilderBase(C, Args, Inputs, Action::OFK_HIP) {
DefaultCudaArch = CudaArch::GFX803;
+ GPUSanitize = Args.hasFlag(options::OPT_fgpu_sanitize,
+ options::OPT_fno_gpu_sanitize, false);
+ if (Args.hasArg(options::OPT_gpu_bundle_output,
+ options::OPT_no_gpu_bundle_output))
+ BundleOutput = Args.hasFlag(options::OPT_gpu_bundle_output,
+ options::OPT_no_gpu_bundle_output);
}
bool canUseBundlerUnbundler() const override { return true; }
@@ -2840,17 +2958,31 @@ class OffloadingActionBuilder final {
// a fat binary containing all the code objects for different GPU's.
// The fat binary is then an input to the host action.
for (unsigned I = 0, E = GpuArchList.size(); I != E; ++I) {
- auto BackendAction = C.getDriver().ConstructPhaseAction(
- C, Args, phases::Backend, CudaDeviceActions[I],
- AssociatedOffloadKind);
- auto AssembleAction = C.getDriver().ConstructPhaseAction(
- C, Args, phases::Assemble, BackendAction, AssociatedOffloadKind);
- // Create a link action to link device IR with device library
- // and generate ISA.
- ActionList AL;
- AL.push_back(AssembleAction);
- CudaDeviceActions[I] =
- C.MakeAction<LinkJobAction>(AL, types::TY_Image);
+ if (C.getDriver().isUsingLTO(/*IsOffload=*/true)) {
+ // When LTO is enabled, skip the backend and assemble phases and
+ // use lld to link the bitcode.
+ ActionList AL;
+ AL.push_back(CudaDeviceActions[I]);
+ // Create a link action to link device IR with device library
+ // and generate ISA.
+ CudaDeviceActions[I] =
+ C.MakeAction<LinkJobAction>(AL, types::TY_Image);
+ } else {
+ // When LTO is not enabled, we follow the conventional
+ // compiler phases, including backend and assemble phases.
+ ActionList AL;
+ auto BackendAction = C.getDriver().ConstructPhaseAction(
+ C, Args, phases::Backend, CudaDeviceActions[I],
+ AssociatedOffloadKind);
+ auto AssembleAction = C.getDriver().ConstructPhaseAction(
+ C, Args, phases::Assemble, BackendAction,
+ AssociatedOffloadKind);
+ AL.push_back(AssembleAction);
+ // Create a link action to link device IR with device library
+ // and generate ISA.
+ CudaDeviceActions[I] =
+ C.MakeAction<LinkJobAction>(AL, types::TY_Image);
+ }
// OffloadingActionBuilder propagates device arch until an offload
// action. Since the next action for creating fatbin does
@@ -2864,22 +2996,25 @@ class OffloadingActionBuilder final {
CudaDeviceActions[I] = C.MakeAction<OffloadAction>(
DDep, CudaDeviceActions[I]->getType());
}
- // Create HIP fat binary with a special "link" action.
- CudaFatBinary =
- C.MakeAction<LinkJobAction>(CudaDeviceActions,
- types::TY_HIP_FATBIN);
- if (!CompileDeviceOnly) {
- DA.add(*CudaFatBinary, *ToolChains.front(), /*BoundArch=*/nullptr,
- AssociatedOffloadKind);
- // Clear the fat binary, it is already a dependence to an host
- // action.
- CudaFatBinary = nullptr;
- }
+ if (!CompileDeviceOnly || !BundleOutput.hasValue() ||
+ BundleOutput.getValue()) {
+ // Create HIP fat binary with a special "link" action.
+ CudaFatBinary = C.MakeAction<LinkJobAction>(CudaDeviceActions,
+ types::TY_HIP_FATBIN);
- // Remove the CUDA actions as they are already connected to an host
- // action or fat binary.
- CudaDeviceActions.clear();
+ if (!CompileDeviceOnly) {
+ DA.add(*CudaFatBinary, *ToolChains.front(), /*BoundArch=*/nullptr,
+ AssociatedOffloadKind);
+ // Clear the fat binary, it is already a dependence to an host
+ // action.
+ CudaFatBinary = nullptr;
+ }
+
+ // Remove the CUDA actions as they are already connected to an host
+ // action or fat binary.
+ CudaDeviceActions.clear();
+ }
return CompileDeviceOnly ? ABRT_Ignore_Host : ABRT_Success;
} else if (CurPhase == phases::Link) {
@@ -2906,6 +3041,20 @@ class OffloadingActionBuilder final {
A = C.getDriver().ConstructPhaseAction(C, Args, CurPhase, A,
AssociatedOffloadKind);
+ if (CompileDeviceOnly && CurPhase == FinalPhase &&
+ BundleOutput.hasValue() && BundleOutput.getValue()) {
+ for (unsigned I = 0, E = GpuArchList.size(); I != E; ++I) {
+ OffloadAction::DeviceDependences DDep;
+ DDep.add(*CudaDeviceActions[I], *ToolChains.front(), GpuArchList[I],
+ AssociatedOffloadKind);
+ CudaDeviceActions[I] = C.MakeAction<OffloadAction>(
+ DDep, CudaDeviceActions[I]->getType());
+ }
+ CudaFatBinary =
+ C.MakeAction<OffloadBundlingJobAction>(CudaDeviceActions);
+ CudaDeviceActions.clear();
+ }
+
return (CompileDeviceOnly && CurPhase == FinalPhase) ? ABRT_Ignore_Host
: ABRT_Success;
}
@@ -3343,7 +3492,7 @@ public:
return nullptr;
// Let builders add host linking actions.
- Action* HA;
+ Action* HA = nullptr;
for (DeviceActionBuilder *SB : SpecializedBuilders) {
if (!SB->isValid())
continue;
@@ -3418,7 +3567,8 @@ void Driver::handleArguments(Compilation &C, DerivedArgList &Args,
if (Args.hasArg(options::OPT_emit_llvm))
Diag(clang::diag::err_drv_emit_llvm_link);
if (IsCLMode() && LTOMode != LTOK_None &&
- !Args.getLastArgValue(options::OPT_fuse_ld_EQ).equals_lower("lld"))
+ !Args.getLastArgValue(options::OPT_fuse_ld_EQ)
+ .equals_insensitive("lld"))
Diag(clang::diag::err_drv_lto_without_lld);
}
@@ -3890,10 +4040,13 @@ void Driver::BuildJobs(Compilation &C) const {
}
const llvm::Triple &RawTriple = C.getDefaultToolChain().getTriple();
- if (RawTriple.isOSAIX())
+ if (RawTriple.isOSAIX()) {
if (Arg *A = C.getArgs().getLastArg(options::OPT_G))
Diag(diag::err_drv_unsupported_opt_for_target)
<< A->getSpelling() << RawTriple.str();
+ if (LTOMode == LTOK_Thin)
+ Diag(diag::err_drv_clang_unsupported) << "thinLTO on AIX";
+ }
// Collect the list of architectures.
llvm::StringSet<> ArchNames;
@@ -3927,66 +4080,64 @@ void Driver::BuildJobs(Compilation &C) const {
/*TargetDeviceOffloadKind*/ Action::OFK_None);
}
- StringRef StatReportFile;
- bool PrintProcessStat = false;
- if (const Arg *A = C.getArgs().getLastArg(options::OPT_fproc_stat_report_EQ))
- StatReportFile = A->getValue();
- if (C.getArgs().hasArg(options::OPT_fproc_stat_report))
- PrintProcessStat = true;
-
// If we have more than one job, then disable integrated-cc1 for now. Do this
// also when we need to report process execution statistics.
- if (C.getJobs().size() > 1 || !StatReportFile.empty() || PrintProcessStat)
+ if (C.getJobs().size() > 1 || CCPrintProcessStats)
for (auto &J : C.getJobs())
J.InProcess = false;
- if (!StatReportFile.empty() || PrintProcessStat) {
+ if (CCPrintProcessStats) {
C.setPostCallback([=](const Command &Cmd, int Res) {
Optional<llvm::sys::ProcessStatistics> ProcStat =
Cmd.getProcessStatistics();
if (!ProcStat)
return;
- if (PrintProcessStat) {
+
+ const char *LinkingOutput = nullptr;
+ if (FinalOutput)
+ LinkingOutput = FinalOutput->getValue();
+ else if (!Cmd.getOutputFilenames().empty())
+ LinkingOutput = Cmd.getOutputFilenames().front().c_str();
+ else
+ LinkingOutput = getDefaultImageName();
+
+ if (CCPrintStatReportFilename.empty()) {
using namespace llvm;
// Human readable output.
outs() << sys::path::filename(Cmd.getExecutable()) << ": "
- << "output=";
- if (Cmd.getOutputFilenames().empty())
- outs() << "\"\"";
- else
- outs() << Cmd.getOutputFilenames().front();
+ << "output=" << LinkingOutput;
outs() << ", total="
<< format("%.3f", ProcStat->TotalTime.count() / 1000.) << " ms"
<< ", user="
<< format("%.3f", ProcStat->UserTime.count() / 1000.) << " ms"
<< ", mem=" << ProcStat->PeakMemory << " Kb\n";
- }
- if (!StatReportFile.empty()) {
+ } else {
// CSV format.
std::string Buffer;
llvm::raw_string_ostream Out(Buffer);
llvm::sys::printArg(Out, llvm::sys::path::filename(Cmd.getExecutable()),
/*Quote*/ true);
Out << ',';
- if (Cmd.getOutputFilenames().empty())
- Out << "\"\"";
- else
- llvm::sys::printArg(Out, Cmd.getOutputFilenames().front(), true);
+ llvm::sys::printArg(Out, LinkingOutput, true);
Out << ',' << ProcStat->TotalTime.count() << ','
<< ProcStat->UserTime.count() << ',' << ProcStat->PeakMemory
<< '\n';
Out.flush();
std::error_code EC;
- llvm::raw_fd_ostream OS(StatReportFile, EC, llvm::sys::fs::OF_Append);
+ llvm::raw_fd_ostream OS(CCPrintStatReportFilename.c_str(), EC,
+ llvm::sys::fs::OF_Append |
+ llvm::sys::fs::OF_Text);
if (EC)
return;
auto L = OS.lock();
if (!L) {
- llvm::errs() << "ERROR: Cannot lock file " << StatReportFile << ": "
+ llvm::errs() << "ERROR: Cannot lock file "
+ << CCPrintStatReportFilename << ": "
<< toString(L.takeError()) << "\n";
return;
}
OS << Buffer;
+ OS.flush();
}
});
}
@@ -4479,6 +4630,25 @@ InputInfo Driver::BuildJobsForActionNoCache(
if (!T)
return InputInfo();
+ if (BuildingForOffloadDevice &&
+ A->getOffloadingDeviceKind() == Action::OFK_OpenMP) {
+ if (TC->getTriple().isAMDGCN()) {
+ // AMDGCN treats backend and assemble actions as no-op because
+ // linker does not support object files.
+ if (const BackendJobAction *BA = dyn_cast<BackendJobAction>(A)) {
+ return BuildJobsForAction(C, *BA->input_begin(), TC, BoundArch,
+ AtTopLevel, MultipleArchs, LinkingOutput,
+ CachedResults, TargetDeviceOffloadKind);
+ }
+
+ if (const AssembleJobAction *AA = dyn_cast<AssembleJobAction>(A)) {
+ return BuildJobsForAction(C, *AA->input_begin(), TC, BoundArch,
+ AtTopLevel, MultipleArchs, LinkingOutput,
+ CachedResults, TargetDeviceOffloadKind);
+ }
+ }
+ }
+
// If we've collapsed action list that contained OffloadAction we
// need to build jobs for host/device-side inputs it may have held.
for (const auto *OA : CollapsedOffloadActions)
@@ -4598,11 +4768,12 @@ InputInfo Driver::BuildJobsForActionNoCache(
/*CreatePrefixForHost=*/!!A->getOffloadingHostActiveKinds() &&
!AtTopLevel);
if (isa<OffloadWrapperJobAction>(JA)) {
- OffloadingPrefix += "-wrapper";
if (Arg *FinalOutput = C.getArgs().getLastArg(options::OPT_o))
BaseInput = FinalOutput->getValue();
else
BaseInput = getDefaultImageName();
+ BaseInput =
+ C.getArgs().MakeArgString(std::string(BaseInput) + "-wrapper");
}
Result = InputInfo(A, GetNamedOutputPath(C, *JA, BaseInput, BoundArch,
AtTopLevel, MultipleArchs,
@@ -4729,6 +4900,11 @@ const char *Driver::GetNamedOutputPath(Compilation &C, const JobAction &JA,
return "-";
}
+ if (JA.getType() == types::TY_ModuleFile &&
+ C.getArgs().getLastArg(options::OPT_module_file_info)) {
+ return "-";
+ }
+
// Is this the assembly listing for /FA?
if (JA.getType() == types::TY_PP_Asm &&
(C.getArgs().hasArg(options::OPT__SLASH_FA) ||
@@ -4963,11 +5139,6 @@ void Driver::generatePrefixedToolNames(
// FIXME: Needs a better variable than TargetTriple
Names.emplace_back((TargetTriple + "-" + Tool).str());
Names.emplace_back(Tool);
-
- // Allow the discovery of tools prefixed with LLVM's default target triple.
- std::string DefaultTargetTriple = llvm::sys::getDefaultTargetTriple();
- if (DefaultTargetTriple != TargetTriple)
- Names.emplace_back((DefaultTargetTriple + "-" + Tool).str());
}
static bool ScanDirForExecutable(SmallString<128> &Dir, StringRef Name) {
@@ -5158,7 +5329,7 @@ const ToolChain &Driver::getToolChain(const ArgList &Args,
case llvm::Triple::MSVC:
case llvm::Triple::UnknownEnvironment:
if (Args.getLastArgValue(options::OPT_fuse_ld_EQ)
- .startswith_lower("bfd"))
+ .startswith_insensitive("bfd"))
TC = std::make_unique<toolchains::CrossWindowsToolChain>(
*this, Target, Args);
else
@@ -5387,3 +5558,21 @@ bool clang::driver::willEmitRemarks(const ArgList &Args) {
return true;
return false;
}
+
+llvm::StringRef clang::driver::getDriverMode(StringRef ProgName,
+ ArrayRef<const char *> Args) {
+ static const std::string OptName =
+ getDriverOptTable().getOption(options::OPT_driver_mode).getPrefixedName();
+ llvm::StringRef Opt;
+ for (StringRef Arg : Args) {
+ if (!Arg.startswith(OptName))
+ continue;
+ Opt = Arg;
+ break;
+ }
+ if (Opt.empty())
+ Opt = ToolChain::getTargetAndModeFromProgramName(ProgName).DriverMode;
+ return Opt.consume_front(OptName) ? Opt : "";
+}
+
+bool driver::IsClangCL(StringRef DriverMode) { return DriverMode.equals("cl"); }