aboutsummaryrefslogtreecommitdiff
path: root/clang/lib/Driver
diff options
context:
space:
mode:
Diffstat (limited to 'clang/lib/Driver')
-rw-r--r--clang/lib/Driver/Action.cpp30
-rw-r--r--clang/lib/Driver/Compilation.cpp11
-rw-r--r--clang/lib/Driver/Distro.cpp3
-rw-r--r--clang/lib/Driver/Driver.cpp808
-rw-r--r--clang/lib/Driver/SanitizerArgs.cpp116
-rw-r--r--clang/lib/Driver/ToolChain.cpp53
-rw-r--r--clang/lib/Driver/ToolChains/AIX.cpp11
-rw-r--r--clang/lib/Driver/ToolChains/AMDGPU.cpp71
-rw-r--r--clang/lib/Driver/ToolChains/AMDGPU.h3
-rw-r--r--clang/lib/Driver/ToolChains/AMDGPUOpenMP.cpp20
-rw-r--r--clang/lib/Driver/ToolChains/AVR.cpp154
-rw-r--r--clang/lib/Driver/ToolChains/AVR.h17
-rw-r--r--clang/lib/Driver/ToolChains/Ananas.cpp14
-rw-r--r--clang/lib/Driver/ToolChains/Arch/AArch64.cpp177
-rw-r--r--clang/lib/Driver/ToolChains/Arch/AArch64.h1
-rw-r--r--clang/lib/Driver/ToolChains/Arch/ARM.cpp54
-rw-r--r--clang/lib/Driver/ToolChains/Arch/ARM.h1
-rw-r--r--clang/lib/Driver/ToolChains/Arch/CSKY.cpp170
-rw-r--r--clang/lib/Driver/ToolChains/Arch/CSKY.h47
-rw-r--r--clang/lib/Driver/ToolChains/Arch/RISCV.cpp2
-rw-r--r--clang/lib/Driver/ToolChains/Arch/VE.h2
-rw-r--r--clang/lib/Driver/ToolChains/Arch/X86.cpp26
-rw-r--r--clang/lib/Driver/ToolChains/CSKYToolChain.cpp204
-rw-r--r--clang/lib/Driver/ToolChains/CSKYToolChain.h63
-rw-r--r--clang/lib/Driver/ToolChains/Clang.cpp946
-rw-r--r--clang/lib/Driver/ToolChains/Clang.h13
-rw-r--r--clang/lib/Driver/ToolChains/CommonArgs.cpp227
-rw-r--r--clang/lib/Driver/ToolChains/CommonArgs.h20
-rw-r--r--clang/lib/Driver/ToolChains/Cuda.cpp99
-rw-r--r--clang/lib/Driver/ToolChains/Cuda.h4
-rw-r--r--clang/lib/Driver/ToolChains/Darwin.cpp402
-rw-r--r--clang/lib/Driver/ToolChains/Darwin.h31
-rw-r--r--clang/lib/Driver/ToolChains/DragonFly.cpp9
-rw-r--r--clang/lib/Driver/ToolChains/Flang.cpp55
-rw-r--r--clang/lib/Driver/ToolChains/FreeBSD.cpp2
-rw-r--r--clang/lib/Driver/ToolChains/Fuchsia.cpp26
-rw-r--r--clang/lib/Driver/ToolChains/Fuchsia.h25
-rw-r--r--clang/lib/Driver/ToolChains/Gnu.cpp221
-rw-r--r--clang/lib/Driver/ToolChains/HIPAMD.cpp60
-rw-r--r--clang/lib/Driver/ToolChains/HIPAMD.h4
-rw-r--r--clang/lib/Driver/ToolChains/HIPUtility.cpp12
-rw-r--r--clang/lib/Driver/ToolChains/HLSL.cpp183
-rw-r--r--clang/lib/Driver/ToolChains/HLSL.h40
-rw-r--r--clang/lib/Driver/ToolChains/Hexagon.cpp41
-rw-r--r--clang/lib/Driver/ToolChains/Hexagon.h3
-rw-r--r--clang/lib/Driver/ToolChains/Lanai.h2
-rw-r--r--clang/lib/Driver/ToolChains/Linux.cpp111
-rw-r--r--clang/lib/Driver/ToolChains/Linux.h2
-rw-r--r--clang/lib/Driver/ToolChains/MSP430.cpp2
-rw-r--r--clang/lib/Driver/ToolChains/MSVC.cpp819
-rw-r--r--clang/lib/Driver/ToolChains/MSVC.h31
-rw-r--r--clang/lib/Driver/ToolChains/MSVCSetupApi.h523
-rw-r--r--clang/lib/Driver/ToolChains/MinGW.cpp16
-rw-r--r--clang/lib/Driver/ToolChains/MinGW.h2
-rw-r--r--clang/lib/Driver/ToolChains/Minix.cpp9
-rw-r--r--clang/lib/Driver/ToolChains/NetBSD.cpp9
-rw-r--r--clang/lib/Driver/ToolChains/OpenBSD.cpp49
-rw-r--r--clang/lib/Driver/ToolChains/OpenBSD.h2
-rw-r--r--clang/lib/Driver/ToolChains/PPCLinux.cpp6
-rw-r--r--clang/lib/Driver/ToolChains/PS4CPU.cpp188
-rw-r--r--clang/lib/Driver/ToolChains/PS4CPU.h115
-rw-r--r--clang/lib/Driver/ToolChains/RISCVToolchain.cpp7
-rw-r--r--clang/lib/Driver/ToolChains/RISCVToolchain.h1
-rw-r--r--clang/lib/Driver/ToolChains/ROCm.h38
-rw-r--r--clang/lib/Driver/ToolChains/SPIRV.h3
-rw-r--r--clang/lib/Driver/ToolChains/Solaris.cpp33
-rw-r--r--clang/lib/Driver/ToolChains/VEToolchain.h1
-rw-r--r--clang/lib/Driver/ToolChains/WebAssembly.cpp110
-rw-r--r--clang/lib/Driver/ToolChains/WebAssembly.h9
-rw-r--r--clang/lib/Driver/ToolChains/ZOS.h2
-rw-r--r--clang/lib/Driver/Types.cpp41
71 files changed, 3987 insertions, 2625 deletions
diff --git a/clang/lib/Driver/Action.cpp b/clang/lib/Driver/Action.cpp
index eb08bfe9cde5..ead3a23da418 100644
--- a/clang/lib/Driver/Action.cpp
+++ b/clang/lib/Driver/Action.cpp
@@ -26,6 +26,8 @@ const char *Action::getClassName(ActionClass AC) {
case PreprocessJobClass: return "preprocessor";
case PrecompileJobClass: return "precompiler";
case HeaderModulePrecompileJobClass: return "header-module-precompiler";
+ case ExtractAPIJobClass:
+ return "api-extractor";
case AnalyzeJobClass: return "analyzer";
case MigrateJobClass: return "migrator";
case CompileJobClass: return "compiler";
@@ -43,6 +45,8 @@ const char *Action::getClassName(ActionClass AC) {
return "clang-offload-unbundler";
case OffloadWrapperJobClass:
return "clang-offload-wrapper";
+ case OffloadPackagerJobClass:
+ return "clang-offload-packager";
case LinkerWrapperJobClass:
return "clang-linker-wrapper";
case StaticLibJobClass:
@@ -52,7 +56,8 @@ const char *Action::getClassName(ActionClass AC) {
llvm_unreachable("invalid class");
}
-void Action::propagateDeviceOffloadInfo(OffloadKind OKind, const char *OArch) {
+void Action::propagateDeviceOffloadInfo(OffloadKind OKind, const char *OArch,
+ const ToolChain *OToolChain) {
// Offload action set its own kinds on their dependences.
if (Kind == OffloadClass)
return;
@@ -65,9 +70,10 @@ void Action::propagateDeviceOffloadInfo(OffloadKind OKind, const char *OArch) {
assert(!ActiveOffloadKindMask && "Setting a device kind in a host action??");
OffloadingDeviceKind = OKind;
OffloadingArch = OArch;
+ OffloadingToolChain = OToolChain;
for (auto *A : Inputs)
- A->propagateDeviceOffloadInfo(OffloadingDeviceKind, OArch);
+ A->propagateDeviceOffloadInfo(OffloadingDeviceKind, OArch, OToolChain);
}
void Action::propagateHostOffloadInfo(unsigned OKinds, const char *OArch) {
@@ -89,7 +95,8 @@ void Action::propagateOffloadInfo(const Action *A) {
propagateHostOffloadInfo(HK, A->getOffloadingArch());
else
propagateDeviceOffloadInfo(A->getOffloadingDeviceKind(),
- A->getOffloadingArch());
+ A->getOffloadingArch(),
+ A->getOffloadingToolChain());
}
std::string Action::getOffloadingKindPrefix() const {
@@ -190,6 +197,7 @@ OffloadAction::OffloadAction(const DeviceDependences &DDeps, types::ID Ty)
DevToolChains(DDeps.getToolChains()) {
auto &OKinds = DDeps.getOffloadKinds();
auto &BArchs = DDeps.getBoundArchs();
+ auto &OTCs = DDeps.getToolChains();
// If all inputs agree on the same kind, use it also for this action.
if (llvm::all_of(OKinds, [&](OffloadKind K) { return K == OKinds.front(); }))
@@ -201,7 +209,7 @@ OffloadAction::OffloadAction(const DeviceDependences &DDeps, types::ID Ty)
// Propagate info to the dependencies.
for (unsigned i = 0, e = getInputs().size(); i != e; ++i)
- getInputs()[i]->propagateDeviceOffloadInfo(OKinds[i], BArchs[i]);
+ getInputs()[i]->propagateDeviceOffloadInfo(OKinds[i], BArchs[i], OTCs[i]);
}
OffloadAction::OffloadAction(const HostDependence &HDep,
@@ -220,7 +228,8 @@ OffloadAction::OffloadAction(const HostDependence &HDep,
if (auto *A = DDeps.getActions()[i]) {
getInputs().push_back(A);
A->propagateDeviceOffloadInfo(DDeps.getOffloadKinds()[i],
- DDeps.getBoundArchs()[i]);
+ DDeps.getBoundArchs()[i],
+ DDeps.getToolChains()[i]);
}
}
@@ -339,6 +348,11 @@ HeaderModulePrecompileJobAction::HeaderModulePrecompileJobAction(
: PrecompileJobAction(HeaderModulePrecompileJobClass, Input, OutputType),
ModuleName(ModuleName) {}
+void ExtractAPIJobAction::anchor() {}
+
+ExtractAPIJobAction::ExtractAPIJobAction(Action *Inputs, types::ID OutputType)
+ : JobAction(ExtractAPIJobClass, Inputs, OutputType) {}
+
void AnalyzeJobAction::anchor() {}
AnalyzeJobAction::AnalyzeJobAction(Action *Input, types::ID OutputType)
@@ -420,6 +434,12 @@ OffloadWrapperJobAction::OffloadWrapperJobAction(ActionList &Inputs,
types::ID Type)
: JobAction(OffloadWrapperJobClass, Inputs, Type) {}
+void OffloadPackagerJobAction::anchor() {}
+
+OffloadPackagerJobAction::OffloadPackagerJobAction(ActionList &Inputs,
+ types::ID Type)
+ : JobAction(OffloadPackagerJobClass, Inputs, Type) {}
+
void LinkerWrapperJobAction::anchor() {}
LinkerWrapperJobAction::LinkerWrapperJobAction(ActionList &Inputs,
diff --git a/clang/lib/Driver/Compilation.cpp b/clang/lib/Driver/Compilation.cpp
index 67d941c6c2ab..b4367a0af81e 100644
--- a/clang/lib/Driver/Compilation.cpp
+++ b/clang/lib/Driver/Compilation.cpp
@@ -162,7 +162,8 @@ bool Compilation::CleanupFileMap(const ArgStringMap &Files,
}
int Compilation::ExecuteCommand(const Command &C,
- const Command *&FailingCommand) const {
+ const Command *&FailingCommand,
+ bool LogOnly) const {
if ((getDriver().CCPrintOptions ||
getArgs().hasArg(options::OPT_v)) && !getDriver().CCGenDiagnostics) {
raw_ostream *OS = &llvm::errs();
@@ -191,6 +192,9 @@ int Compilation::ExecuteCommand(const Command &C,
C.Print(*OS, "\n", /*Quote=*/getDriver().CCPrintOptions);
}
+ if (LogOnly)
+ return 0;
+
std::string Error;
bool ExecutionFailed;
int Res = C.Execute(Redirects, &Error, &ExecutionFailed);
@@ -237,7 +241,8 @@ static bool InputsOk(const Command &C,
}
void Compilation::ExecuteJobs(const JobList &Jobs,
- FailingCommandList &FailingCommands) const {
+ FailingCommandList &FailingCommands,
+ bool LogOnly) const {
// According to UNIX standard, driver need to continue compiling all the
// inputs on the command line even one of them failed.
// In all but CLMode, execute all the jobs unless the necessary inputs for the
@@ -246,7 +251,7 @@ void Compilation::ExecuteJobs(const JobList &Jobs,
if (!InputsOk(Job, FailingCommands))
continue;
const Command *FailingCommand = nullptr;
- if (int Res = ExecuteCommand(Job, FailingCommand)) {
+ if (int Res = ExecuteCommand(Job, FailingCommand, LogOnly)) {
FailingCommands.push_back(std::make_pair(Res, FailingCommand));
// Bail as soon as one command fails in cl driver mode.
if (TheDriver.IsCLMode())
diff --git a/clang/lib/Driver/Distro.cpp b/clang/lib/Driver/Distro.cpp
index 5ac38c34d112..1898667279cc 100644
--- a/clang/lib/Driver/Distro.cpp
+++ b/clang/lib/Driver/Distro.cpp
@@ -91,6 +91,7 @@ static Distro::DistroType DetectLsbRelease(llvm::vfs::FileSystem &VFS) {
.Case("hirsute", Distro::UbuntuHirsute)
.Case("impish", Distro::UbuntuImpish)
.Case("jammy", Distro::UbuntuJammy)
+ .Case("kinetic", Distro::UbuntuKinetic)
.Default(Distro::UnknownDistro);
return Version;
}
@@ -153,6 +154,8 @@ static Distro::DistroType DetectDistro(llvm::vfs::FileSystem &VFS) {
return Distro::DebianBullseye;
case 12:
return Distro::DebianBookworm;
+ case 13:
+ return Distro::DebianTrixie;
default:
return Distro::UnknownDistro;
}
diff --git a/clang/lib/Driver/Driver.cpp b/clang/lib/Driver/Driver.cpp
index 3bfddeefc7b2..0da32dae2ef6 100644
--- a/clang/lib/Driver/Driver.cpp
+++ b/clang/lib/Driver/Driver.cpp
@@ -13,6 +13,7 @@
#include "ToolChains/AVR.h"
#include "ToolChains/Ananas.h"
#include "ToolChains/BareMetal.h"
+#include "ToolChains/CSKYToolChain.h"
#include "ToolChains/Clang.h"
#include "ToolChains/CloudABI.h"
#include "ToolChains/Contiki.h"
@@ -25,6 +26,7 @@
#include "ToolChains/Gnu.h"
#include "ToolChains/HIPAMD.h"
#include "ToolChains/HIPSPV.h"
+#include "ToolChains/HLSL.h"
#include "ToolChains/Haiku.h"
#include "ToolChains/Hexagon.h"
#include "ToolChains/Hurd.h"
@@ -59,6 +61,7 @@
#include "clang/Driver/InputInfo.h"
#include "clang/Driver/Job.h"
#include "clang/Driver/Options.h"
+#include "clang/Driver/Phases.h"
#include "clang/Driver/SanitizerArgs.h"
#include "clang/Driver/Tool.h"
#include "clang/Driver/ToolChain.h"
@@ -188,12 +191,14 @@ Driver::Driver(StringRef ClangExecutable, StringRef TargetTriple,
DiagnosticsEngine &Diags, std::string Title,
IntrusiveRefCntPtr<llvm::vfs::FileSystem> VFS)
: Diags(Diags), VFS(std::move(VFS)), Mode(GCCMode),
- SaveTemps(SaveTempsNone), BitcodeEmbed(EmbedNone), LTOMode(LTOK_None),
+ SaveTemps(SaveTempsNone), BitcodeEmbed(EmbedNone),
+ Offload(OffloadHostDevice), CXX20HeaderType(HeaderMode_None),
+ ModulesModeCXX20(false), LTOMode(LTOK_None),
ClangExecutable(ClangExecutable), SysRoot(DEFAULT_SYSROOT),
DriverTitle(Title), CCCPrintBindings(false), CCPrintOptions(false),
CCPrintHeaders(false), CCLogDiagnostics(false), CCGenDiagnostics(false),
CCPrintProcessStats(false), TargetTriple(TargetTriple), Saver(Alloc),
- CheckInputsExist(true), GenReproducer(false),
+ CheckInputsExist(true), ProbePrecompiled(true),
SuppressMissingInputWarning(false) {
// Provide a sane fallback if no VFS is specified.
if (!this->VFS)
@@ -230,6 +235,7 @@ void Driver::setDriverMode(StringRef Value) {
.Case("cpp", CPPMode)
.Case("cl", CLMode)
.Case("flang", FlangMode)
+ .Case("dxc", DXCMode)
.Default(None))
Mode = *M;
else
@@ -333,11 +339,15 @@ phases::ID Driver::getFinalPhase(const DerivedArgList &DAL,
CCGenDiagnostics) {
FinalPhase = phases::Preprocess;
- // --precompile only runs up to precompilation.
- } else if ((PhaseArg = DAL.getLastArg(options::OPT__precompile))) {
+ // --precompile only runs up to precompilation.
+ // Options that cause the output of C++20 compiled module interfaces or
+ // header units have the same effect.
+ } else if ((PhaseArg = DAL.getLastArg(options::OPT__precompile)) ||
+ (PhaseArg = DAL.getLastArg(options::OPT_extract_api)) ||
+ (PhaseArg = DAL.getLastArg(options::OPT_fmodule_header,
+ options::OPT_fmodule_header_EQ))) {
FinalPhase = phases::Precompile;
-
- // -{fsyntax-only,-analyze,emit-ast} only run up to the compiler.
+ // -{fsyntax-only,-analyze,emit-ast} only run up to the compiler.
} else if ((PhaseArg = DAL.getLastArg(options::OPT_fsyntax_only)) ||
(PhaseArg = DAL.getLastArg(options::OPT_print_supported_cpus)) ||
(PhaseArg = DAL.getLastArg(options::OPT_module_file_info)) ||
@@ -346,8 +356,7 @@ phases::ID Driver::getFinalPhase(const DerivedArgList &DAL,
(PhaseArg = DAL.getLastArg(options::OPT_rewrite_legacy_objc)) ||
(PhaseArg = DAL.getLastArg(options::OPT__migrate)) ||
(PhaseArg = DAL.getLastArg(options::OPT__analyze)) ||
- (PhaseArg = DAL.getLastArg(options::OPT_emit_ast)) ||
- (PhaseArg = DAL.getLastArg(options::OPT_extract_api))) {
+ (PhaseArg = DAL.getLastArg(options::OPT_emit_ast))) {
FinalPhase = phases::Compile;
// -S only runs up to the backend.
@@ -773,76 +782,117 @@ void Driver::CreateOffloadingDeviceToolChains(Compilation &C,
// OpenMP
//
// We need to generate an OpenMP toolchain if the user specified targets with
- // the -fopenmp-targets option.
- if (Arg *OpenMPTargets =
- C.getInputArgs().getLastArg(options::OPT_fopenmp_targets_EQ)) {
- if (OpenMPTargets->getNumValues()) {
- // We expect that -fopenmp-targets is always used in conjunction with the
- // option -fopenmp specifying a valid runtime with offloading support,
- // i.e. libomp or libiomp.
- bool HasValidOpenMPRuntime = C.getInputArgs().hasFlag(
- options::OPT_fopenmp, options::OPT_fopenmp_EQ,
- options::OPT_fno_openmp, false);
- if (HasValidOpenMPRuntime) {
- OpenMPRuntimeKind OpenMPKind = getOpenMPRuntime(C.getInputArgs());
- HasValidOpenMPRuntime =
- OpenMPKind == OMPRT_OMP || OpenMPKind == OMPRT_IOMP5;
+ // the -fopenmp-targets option or used --offload-arch with OpenMP enabled.
+ bool IsOpenMPOffloading =
+ C.getInputArgs().hasFlag(options::OPT_fopenmp, options::OPT_fopenmp_EQ,
+ options::OPT_fno_openmp, false) &&
+ (C.getInputArgs().hasArg(options::OPT_fopenmp_targets_EQ) ||
+ C.getInputArgs().hasArg(options::OPT_offload_arch_EQ));
+ if (IsOpenMPOffloading) {
+ // We expect that -fopenmp-targets is always used in conjunction with the
+ // option -fopenmp specifying a valid runtime with offloading support, i.e.
+ // libomp or libiomp.
+ OpenMPRuntimeKind RuntimeKind = getOpenMPRuntime(C.getInputArgs());
+ if (RuntimeKind != OMPRT_OMP && RuntimeKind != OMPRT_IOMP5) {
+ Diag(clang::diag::err_drv_expecting_fopenmp_with_fopenmp_targets);
+ return;
+ }
+
+ llvm::StringMap<llvm::DenseSet<StringRef>> DerivedArchs;
+ llvm::StringMap<StringRef> FoundNormalizedTriples;
+ llvm::SmallVector<StringRef, 4> OpenMPTriples;
+
+ // If the user specified -fopenmp-targets= we create a toolchain for each
+ // valid triple. Otherwise, if only --offload-arch= was specified we instead
+ // attempt to derive the appropriate toolchains from the arguments.
+ if (Arg *OpenMPTargets =
+ C.getInputArgs().getLastArg(options::OPT_fopenmp_targets_EQ)) {
+ if (OpenMPTargets && !OpenMPTargets->getNumValues()) {
+ Diag(clang::diag::warn_drv_empty_joined_argument)
+ << OpenMPTargets->getAsString(C.getInputArgs());
+ return;
+ }
+ llvm::copy(OpenMPTargets->getValues(), std::back_inserter(OpenMPTriples));
+ } else if (C.getInputArgs().hasArg(options::OPT_offload_arch_EQ) &&
+ !IsHIP && !IsCuda) {
+ const ToolChain *HostTC = C.getSingleOffloadToolChain<Action::OFK_Host>();
+ auto AMDTriple = getHIPOffloadTargetTriple(*this, C.getInputArgs());
+ auto NVPTXTriple = getNVIDIAOffloadTargetTriple(*this, C.getInputArgs(),
+ HostTC->getTriple());
+
+ // Attempt to deduce the offloading triple from the set of architectures.
+ // We can only correctly deduce NVPTX / AMDGPU triples currently.
+ llvm::DenseSet<StringRef> Archs =
+ getOffloadArchs(C, C.getArgs(), Action::OFK_OpenMP, nullptr);
+ for (StringRef Arch : Archs) {
+ if (NVPTXTriple && IsNVIDIAGpuArch(StringToCudaArch(
+ getProcessorFromTargetID(*NVPTXTriple, Arch)))) {
+ DerivedArchs[NVPTXTriple->getTriple()].insert(Arch);
+ } else if (AMDTriple &&
+ IsAMDGpuArch(StringToCudaArch(
+ getProcessorFromTargetID(*AMDTriple, Arch)))) {
+ DerivedArchs[AMDTriple->getTriple()].insert(Arch);
+ } else {
+ Diag(clang::diag::err_drv_failed_to_deduce_target_from_arch) << Arch;
+ return;
+ }
}
- if (HasValidOpenMPRuntime) {
- llvm::StringMap<const char *> FoundNormalizedTriples;
- for (const char *Val : OpenMPTargets->getValues()) {
- llvm::Triple TT(ToolChain::getOpenMPTriple(Val));
- std::string NormalizedName = TT.normalize();
+ for (const auto &TripleAndArchs : DerivedArchs)
+ OpenMPTriples.push_back(TripleAndArchs.first());
+ }
- // Make sure we don't have a duplicate triple.
- auto Duplicate = FoundNormalizedTriples.find(NormalizedName);
- if (Duplicate != FoundNormalizedTriples.end()) {
- Diag(clang::diag::warn_drv_omp_offload_target_duplicate)
- << Val << Duplicate->second;
- continue;
- }
+ for (StringRef Val : OpenMPTriples) {
+ llvm::Triple TT(ToolChain::getOpenMPTriple(Val));
+ std::string NormalizedName = TT.normalize();
- // Store the current triple so that we can check for duplicates in the
- // following iterations.
- FoundNormalizedTriples[NormalizedName] = Val;
+ // Make sure we don't have a duplicate triple.
+ auto Duplicate = FoundNormalizedTriples.find(NormalizedName);
+ if (Duplicate != FoundNormalizedTriples.end()) {
+ Diag(clang::diag::warn_drv_omp_offload_target_duplicate)
+ << Val << Duplicate->second;
+ continue;
+ }
- // If the specified target is invalid, emit a diagnostic.
- if (TT.getArch() == llvm::Triple::UnknownArch)
- Diag(clang::diag::err_drv_invalid_omp_target) << Val;
- else {
- const ToolChain *TC;
- // Device toolchains have to be selected differently. They pair host
- // and device in their implementation.
- if (TT.isNVPTX() || TT.isAMDGCN()) {
- const ToolChain *HostTC =
- C.getSingleOffloadToolChain<Action::OFK_Host>();
- assert(HostTC && "Host toolchain should be always defined.");
- auto &DeviceTC =
- ToolChains[TT.str() + "/" + HostTC->getTriple().normalize()];
- 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.");
- }
+ // Store the current triple so that we can check for duplicates in the
+ // following iterations.
+ FoundNormalizedTriples[NormalizedName] = Val;
- TC = DeviceTC.get();
- } else
- TC = &getToolChain(C.getInputArgs(), TT);
- C.addOffloadDeviceToolChain(TC, Action::OFK_OpenMP);
+ // If the specified target is invalid, emit a diagnostic.
+ if (TT.getArch() == llvm::Triple::UnknownArch)
+ Diag(clang::diag::err_drv_invalid_omp_target) << Val;
+ else {
+ const ToolChain *TC;
+ // Device toolchains have to be selected differently. They pair host
+ // and device in their implementation.
+ if (TT.isNVPTX() || TT.isAMDGCN()) {
+ const ToolChain *HostTC =
+ C.getSingleOffloadToolChain<Action::OFK_Host>();
+ assert(HostTC && "Host toolchain should be always defined.");
+ auto &DeviceTC =
+ ToolChains[TT.str() + "/" + HostTC->getTriple().normalize()];
+ 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.");
}
- }
- } else
- Diag(clang::diag::err_drv_expecting_fopenmp_with_fopenmp_targets);
- } else
- Diag(clang::diag::warn_drv_empty_joined_argument)
- << OpenMPTargets->getAsString(C.getInputArgs());
+
+ TC = DeviceTC.get();
+ } else
+ TC = &getToolChain(C.getInputArgs(), TT);
+ C.addOffloadDeviceToolChain(TC, Action::OFK_OpenMP);
+ if (DerivedArchs.find(TT.getTriple()) != DerivedArchs.end())
+ KnownArchs[TC] = DerivedArchs[TT.getTriple()];
+ }
+ }
+ } else if (C.getInputArgs().hasArg(options::OPT_fopenmp_targets_EQ)) {
+ Diag(clang::diag::err_drv_expecting_fopenmp_with_fopenmp_targets);
+ return;
}
//
@@ -924,7 +974,7 @@ bool Driver::loadConfigFile() {
if (llvm::sys::fs::make_absolute(CfgDir).value() != 0)
SystemConfigDir.clear();
else
- SystemConfigDir = std::string(CfgDir.begin(), CfgDir.end());
+ SystemConfigDir = static_cast<std::string>(CfgDir);
}
}
if (CLOptions->hasArg(options::OPT_config_user_dir_EQ)) {
@@ -935,7 +985,7 @@ bool Driver::loadConfigFile() {
if (llvm::sys::fs::make_absolute(CfgDir).value() != 0)
UserConfigDir.clear();
else
- UserConfigDir = std::string(CfgDir.begin(), CfgDir.end());
+ UserConfigDir = static_cast<std::string>(CfgDir);
}
}
}
@@ -1167,9 +1217,6 @@ Compilation *Driver::BuildCompilation(ArrayRef<const char *> ArgList) {
CCCPrintBindings = Args.hasArg(options::OPT_ccc_print_bindings);
if (const Arg *A = Args.getLastArg(options::OPT_ccc_gcc_name))
CCCGenericGCCName = A->getValue();
- 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)) {
@@ -1189,7 +1236,22 @@ Compilation *Driver::BuildCompilation(ArrayRef<const char *> ArgList) {
T.setEnvironment(llvm::Triple::MSVC);
T.setObjectFormat(llvm::Triple::COFF);
TargetTriple = T.str();
+ } else if (IsDXCMode()) {
+ // Build TargetTriple from target_profile option for clang-dxc.
+ if (const Arg *A = Args.getLastArg(options::OPT_target_profile)) {
+ StringRef TargetProfile = A->getValue();
+ if (auto Triple =
+ toolchains::HLSLToolChain::parseTargetProfile(TargetProfile))
+ TargetTriple = *Triple;
+ else
+ Diag(diag::err_drv_invalid_directx_shader_module) << TargetProfile;
+
+ A->claim();
+ } else {
+ Diag(diag::err_drv_dxc_missing_target_profile);
+ }
}
+
if (const Arg *A = Args.getLastArg(options::OPT_target))
TargetTriple = A->getValue();
if (const Arg *A = Args.getLastArg(options::OPT_ccc_install_dir))
@@ -1223,6 +1285,17 @@ Compilation *Driver::BuildCompilation(ArrayRef<const char *> ArgList) {
.Default(SaveTempsCwd);
}
+ if (const Arg *A = Args.getLastArg(options::OPT_offload_host_only,
+ options::OPT_offload_device_only,
+ options::OPT_offload_host_device)) {
+ if (A->getOption().matches(options::OPT_offload_host_only))
+ Offload = OffloadHost;
+ else if (A->getOption().matches(options::OPT_offload_device_only))
+ Offload = OffloadDevice;
+ else
+ Offload = OffloadHostDevice;
+ }
+
setLTOMode(Args);
// Process -fembed-bitcode= flags.
@@ -1241,6 +1314,41 @@ Compilation *Driver::BuildCompilation(ArrayRef<const char *> ArgList) {
BitcodeEmbed = static_cast<BitcodeEmbedMode>(Model);
}
+ // Remove existing compilation database so that each job can append to it.
+ if (Arg *A = Args.getLastArg(options::OPT_MJ))
+ llvm::sys::fs::remove(A->getValue());
+
+ // Setting up the jobs for some precompile cases depends on whether we are
+ // treating them as PCH, implicit modules or C++20 ones.
+ // TODO: inferring the mode like this seems fragile (it meets the objective
+ // of not requiring anything new for operation, however).
+ const Arg *Std = Args.getLastArg(options::OPT_std_EQ);
+ ModulesModeCXX20 =
+ !Args.hasArg(options::OPT_fmodules) && Std &&
+ (Std->containsValue("c++20") || Std->containsValue("c++2b") ||
+ Std->containsValue("c++2a") || Std->containsValue("c++latest"));
+
+ // Process -fmodule-header{=} flags.
+ if (Arg *A = Args.getLastArg(options::OPT_fmodule_header_EQ,
+ options::OPT_fmodule_header)) {
+ // These flags force C++20 handling of headers.
+ ModulesModeCXX20 = true;
+ if (A->getOption().matches(options::OPT_fmodule_header))
+ CXX20HeaderType = HeaderMode_Default;
+ else {
+ StringRef ArgName = A->getValue();
+ unsigned Kind = llvm::StringSwitch<unsigned>(ArgName)
+ .Case("user", HeaderMode_User)
+ .Case("system", HeaderMode_System)
+ .Default(~0U);
+ if (Kind == ~0U) {
+ Diags.Report(diag::err_drv_invalid_value)
+ << A->getAsString(Args) << ArgName;
+ } else
+ CXX20HeaderType = static_cast<ModuleHeaderMode>(Kind);
+ }
+ }
+
std::unique_ptr<llvm::opt::InputArgList> UArgs =
std::make_unique<InputArgList>(std::move(Args));
@@ -1597,6 +1705,19 @@ void Driver::setUpResponseFiles(Compilation &C, Command &Cmd) {
int Driver::ExecuteCompilation(
Compilation &C,
SmallVectorImpl<std::pair<int, const Command *>> &FailingCommands) {
+ if (C.getArgs().hasArg(options::OPT_fdriver_only)) {
+ if (C.getArgs().hasArg(options::OPT_v))
+ C.getJobs().Print(llvm::errs(), "\n", true);
+
+ C.ExecuteJobs(C.getJobs(), FailingCommands, /*LogOnly=*/true);
+
+ // If there were errors building the compilation, quit now.
+ if (!FailingCommands.empty() || Diags.hasErrorOccurred())
+ return 1;
+
+ return 0;
+ }
+
// Just print if -### was present.
if (C.getArgs().hasArg(options::OPT__HASH_HASH_HASH)) {
C.getJobs().Print(llvm::errs(), "\n", true);
@@ -1918,6 +2039,13 @@ bool Driver::HandleImmediateArgs(const Compilation &C) {
return false;
}
+ if (C.getArgs().hasArg(options::OPT_print_diagnostic_options)) {
+ std::vector<std::string> Flags = DiagnosticIDs::getDiagnosticFlags();
+ for (std::size_t I = 0; I != Flags.size(); I += 2)
+ llvm::outs() << " " << Flags[I] << "\n " << Flags[I + 1] << "\n\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)) {
@@ -2209,6 +2337,14 @@ bool Driver::DiagnoseInputExistence(const DerivedArgList &Args, StringRef Value,
if (Value == "-")
return true;
+ // If it's a header to be found in the system or user search path, then defer
+ // complaints about its absence until those searches can be done. When we
+ // are definitely processing headers for C++20 header units, extend this to
+ // allow the user to put "-fmodule-header -xc++-header vector" for example.
+ if (Ty == types::TY_CXXSHeader || Ty == types::TY_CXXUHeader ||
+ (ModulesModeCXX20 && Ty == types::TY_CXXHeader))
+ return true;
+
if (getVFS().exists(Value))
return true;
@@ -2272,6 +2408,21 @@ bool Driver::DiagnoseInputExistence(const DerivedArgList &Args, StringRef Value,
return false;
}
+// Get the C++20 Header Unit type corresponding to the input type.
+static types::ID CXXHeaderUnitType(ModuleHeaderMode HM) {
+ switch (HM) {
+ case HeaderMode_User:
+ return types::TY_CXXUHeader;
+ case HeaderMode_System:
+ return types::TY_CXXSHeader;
+ case HeaderMode_Default:
+ break;
+ case HeaderMode_None:
+ llvm_unreachable("should not be called in this case");
+ }
+ return types::TY_CXXHUHeader;
+}
+
// Construct a the list of inputs and their types.
void Driver::BuildInputs(const ToolChain &TC, DerivedArgList &Args,
InputList &Inputs) const {
@@ -2308,6 +2459,14 @@ void Driver::BuildInputs(const ToolChain &TC, DerivedArgList &Args,
assert(!Args.hasArg(options::OPT_x) && "-x and /TC or /TP is not allowed");
}
+ // Warn -x after last input file has no effect
+ {
+ Arg *LastXArg = Args.getLastArgNoClaim(options::OPT_x);
+ Arg *LastInputArg = Args.getLastArgNoClaim(options::OPT_INPUT);
+ if (LastXArg && LastInputArg && LastInputArg->getIndex() < LastXArg->getIndex())
+ Diag(clang::diag::warn_drv_unused_x) << LastXArg->getValue();
+ }
+
for (Arg *A : Args) {
if (A->getOption().getKind() == Option::InputClass) {
const char *Value = A->getValue();
@@ -2360,7 +2519,9 @@ void Driver::BuildInputs(const ToolChain &TC, DerivedArgList &Args,
types::ID OldTy = Ty;
Ty = types::lookupCXXTypeForCType(Ty);
- if (Ty != OldTy)
+ // Do not complain about foo.h, when we are known to be processing
+ // it as a C++20 header unit.
+ if (Ty != OldTy && !(OldTy == types::TY_CHeader && hasHeaderMode()))
Diag(clang::diag::warn_drv_treating_input_as_cxx)
<< getTypeName(OldTy) << getTypeName(Ty);
}
@@ -2383,6 +2544,14 @@ void Driver::BuildInputs(const ToolChain &TC, DerivedArgList &Args,
else if (Args.hasArg(options::OPT_ObjCXX))
Ty = types::TY_ObjCXX;
}
+
+ // Disambiguate headers that are meant to be header units from those
+ // intended to be PCH. Avoid missing '.h' cases that are counted as
+ // C headers by default - we know we are in C++ mode and we do not
+ // want to issue a complaint about compiling things in the wrong mode.
+ if ((Ty == types::TY_CXXHeader || Ty == types::TY_CHeader) &&
+ hasHeaderMode())
+ Ty = CXXHeaderUnitType(CXX20HeaderType);
} else {
assert(InputTypeArg && "InputType set w/o InputTypeArg");
if (!InputTypeArg->getOption().matches(options::OPT_x)) {
@@ -2434,6 +2603,11 @@ void Driver::BuildInputs(const ToolChain &TC, DerivedArgList &Args,
Diag(clang::diag::err_drv_unknown_language) << A->getValue();
InputType = types::TY_Object;
}
+
+ // If the user has put -fmodule-header{,=} then we treat C++ headers as
+ // header unit inputs. So we 'promote' -xc++-header appropriately.
+ if (InputType == types::TY_CXXHeader && hasHeaderMode())
+ InputType = CXXHeaderUnitType(CXX20HeaderType);
} else if (A->getOption().getID() == options::OPT_U) {
assert(A->getNumValues() == 1 && "The /U option has one value.");
StringRef Val = A->getValue(0);
@@ -2465,6 +2639,9 @@ class OffloadingActionBuilder final {
/// Map between an input argument and the offload kinds used to process it.
std::map<const Arg *, unsigned> InputArgToOffloadKindMap;
+ /// Map between a host action and its originating input argument.
+ std::map<Action *, const Arg *> HostActionToInputArgMap;
+
/// Builder interface. It doesn't build anything or keep any state.
class DeviceActionBuilder {
public:
@@ -2692,6 +2869,7 @@ class OffloadingActionBuilder final {
UA->registerDependentActionInfo(ToolChains[0], Arch,
AssociatedOffloadKind);
}
+ IsActive = true;
return ABRT_Success;
}
@@ -2771,15 +2949,8 @@ class OffloadingActionBuilder final {
? C.getSingleOffloadToolChain<Action::OFK_Cuda>()
: C.getSingleOffloadToolChain<Action::OFK_HIP>());
- Arg *PartialCompilationArg = Args.getLastArg(
- options::OPT_cuda_host_only, options::OPT_cuda_device_only,
- options::OPT_cuda_compile_host_device);
- CompileHostOnly = PartialCompilationArg &&
- PartialCompilationArg->getOption().matches(
- options::OPT_cuda_host_only);
- CompileDeviceOnly = PartialCompilationArg &&
- PartialCompilationArg->getOption().matches(
- options::OPT_cuda_device_only);
+ CompileHostOnly = C.getDriver().offloadHostOnly();
+ CompileDeviceOnly = C.getDriver().offloadDeviceOnly();
EmitLLVM = Args.getLastArg(options::OPT_emit_llvm);
EmitAsm = Args.getLastArg(options::OPT_S);
FixedCUID = Args.getLastArgValue(options::OPT_cuid_EQ);
@@ -2806,7 +2977,7 @@ class OffloadingActionBuilder final {
<< "--offload";
}
- // Collect all cuda_gpu_arch parameters, removing duplicates.
+ // Collect all offload arch parameters, removing duplicates.
std::set<StringRef> GpuArchs;
bool Error = false;
for (Arg *A : Args) {
@@ -2815,28 +2986,28 @@ class OffloadingActionBuilder final {
continue;
A->claim();
- StringRef ArchStr = A->getValue();
- if (A->getOption().matches(options::OPT_no_offload_arch_EQ) &&
- ArchStr == "all") {
- GpuArchs.clear();
- continue;
+ for (StringRef ArchStr : llvm::split(A->getValue(), ",")) {
+ if (A->getOption().matches(options::OPT_no_offload_arch_EQ) &&
+ ArchStr == "all") {
+ GpuArchs.clear();
+ } else {
+ ArchStr = getCanonicalOffloadArch(ArchStr);
+ if (ArchStr.empty()) {
+ Error = true;
+ } else if (A->getOption().matches(options::OPT_offload_arch_EQ))
+ GpuArchs.insert(ArchStr);
+ else if (A->getOption().matches(options::OPT_no_offload_arch_EQ))
+ GpuArchs.erase(ArchStr);
+ else
+ llvm_unreachable("Unexpected option.");
+ }
}
- ArchStr = getCanonicalOffloadArch(ArchStr);
- if (ArchStr.empty()) {
- Error = true;
- } else if (A->getOption().matches(options::OPT_offload_arch_EQ))
- GpuArchs.insert(ArchStr);
- else if (A->getOption().matches(options::OPT_no_offload_arch_EQ))
- GpuArchs.erase(ArchStr);
- else
- llvm_unreachable("Unexpected option.");
}
auto &&ConflictingArchs = getConflictOffloadArchCombination(GpuArchs);
if (ConflictingArchs) {
C.getDriver().Diag(clang::diag::err_drv_bad_offload_arch_combo)
- << ConflictingArchs.getValue().first
- << ConflictingArchs.getValue().second;
+ << ConflictingArchs->first << ConflictingArchs->second;
C.setContainsError();
return true;
}
@@ -3007,7 +3178,7 @@ class OffloadingActionBuilder final {
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);
+ options::OPT_no_gpu_bundle_output, true);
}
bool canUseBundlerUnbundler() const override { return true; }
@@ -3024,7 +3195,7 @@ class OffloadingActionBuilder final {
C.setContainsError();
return StringRef();
}
- auto CanId = getCanonicalTargetID(ArchStr.getValue(), Features);
+ auto CanId = getCanonicalTargetID(*ArchStr, Features);
return Args.MakeArgStringRef(CanId);
};
@@ -3038,9 +3209,12 @@ class OffloadingActionBuilder final {
getDeviceDependences(OffloadAction::DeviceDependences &DA,
phases::ID CurPhase, phases::ID FinalPhase,
PhasesTy &Phases) override {
+ if (!IsActive)
+ return ABRT_Inactive;
+
// amdgcn does not support linking of object files, therefore we skip
// backend and assemble phases to output LLVM IR. Except for generating
- // non-relocatable device coee, where we generate fat binary for device
+ // non-relocatable device code, where we generate fat binary for device
// code and pass to host in Backend phase.
if (CudaDeviceActions.empty())
return ABRT_Success;
@@ -3049,7 +3223,7 @@ class OffloadingActionBuilder final {
CudaDeviceActions.size() == GpuArchList.size()) &&
"Expecting one action per GPU architecture.");
assert(!CompileHostOnly &&
- "Not expecting CUDA actions in host-only compilation.");
+ "Not expecting HIP actions in host-only compilation.");
if (!Relocatable && CurPhase == phases::Backend && !EmitLLVM &&
!EmitAsm) {
@@ -3108,8 +3282,7 @@ class OffloadingActionBuilder final {
DDep, CudaDeviceActions[I]->getType());
}
- if (!CompileDeviceOnly || !BundleOutput.hasValue() ||
- BundleOutput.getValue()) {
+ if (!CompileDeviceOnly || !BundleOutput || *BundleOutput) {
// Create HIP fat binary with a special "link" action.
CudaFatBinary = C.MakeAction<LinkJobAction>(CudaDeviceActions,
types::TY_HIP_FATBIN);
@@ -3152,8 +3325,8 @@ class OffloadingActionBuilder final {
A = C.getDriver().ConstructPhaseAction(C, Args, CurPhase, A,
AssociatedOffloadKind);
- if (CompileDeviceOnly && CurPhase == FinalPhase &&
- BundleOutput.hasValue() && BundleOutput.getValue()) {
+ if (CompileDeviceOnly && CurPhase == FinalPhase && BundleOutput &&
+ BundleOutput.getValue()) {
for (unsigned I = 0, E = GpuArchList.size(); I != E; ++I) {
OffloadAction::DeviceDependences DDep;
DDep.add(*CudaDeviceActions[I], *ToolChains.front(), GpuArchList[I],
@@ -3178,12 +3351,16 @@ class OffloadingActionBuilder final {
"Linker inputs and GPU arch list sizes do not match.");
ActionList Actions;
- // Append a new link action for each device.
unsigned I = 0;
+ // Append a new link action for each device.
+ // Each entry in DeviceLinkerInputs corresponds to a GPU arch.
for (auto &LI : DeviceLinkerInputs) {
- // Each entry in DeviceLinkerInputs corresponds to a GPU arch.
- auto *DeviceLinkAction =
- C.MakeAction<LinkJobAction>(LI, types::TY_Image);
+
+ types::ID Output = Args.hasArg(options::OPT_emit_llvm)
+ ? types::TY_LLVM_BC
+ : types::TY_Image;
+
+ auto *DeviceLinkAction = C.MakeAction<LinkJobAction>(LI, Output);
// Linking all inputs for the current GPU arch.
// LI contains all the inputs for the linker.
OffloadAction::DeviceDependences DeviceLinkDeps;
@@ -3195,12 +3372,17 @@ class OffloadingActionBuilder final {
}
DeviceLinkerInputs.clear();
+ // If emitting LLVM, do not generate final host/device compilation action
+ if (Args.hasArg(options::OPT_emit_llvm)) {
+ AL.append(Actions);
+ return;
+ }
+
// Create a host object from all the device images by embedding them
// in a fat binary for mixed host-device compilation. For device-only
// compilation, creates a fat binary.
OffloadAction::DeviceDependences DDeps;
- if (!CompileDeviceOnly || !BundleOutput.hasValue() ||
- BundleOutput.getValue()) {
+ if (!CompileDeviceOnly || !BundleOutput || *BundleOutput) {
auto *TopDeviceLinkAction = C.MakeAction<LinkJobAction>(
Actions,
CompileDeviceOnly ? types::TY_HIP_FATBIN : types::TY_Object);
@@ -3445,6 +3627,17 @@ public:
delete SB;
}
+ /// Record a host action and its originating input argument.
+ void recordHostAction(Action *HostAction, const Arg *InputArg) {
+ assert(HostAction && "Invalid host action");
+ assert(InputArg && "Invalid input argument");
+ auto Loc = HostActionToInputArgMap.find(HostAction);
+ if (Loc == HostActionToInputArgMap.end())
+ HostActionToInputArgMap[HostAction] = InputArg;
+ assert(HostActionToInputArgMap[HostAction] == InputArg &&
+ "host action mapped to multiple input arguments");
+ }
+
/// Generate an action that adds device dependences (if any) to a host action.
/// If no device dependence actions exist, just return the host action \a
/// HostAction. If an error is found or if no builder requires the host action
@@ -3460,6 +3653,7 @@ public:
return HostAction;
assert(HostAction && "Invalid host action!");
+ recordHostAction(HostAction, InputArg);
OffloadAction::DeviceDependences DDeps;
// Check if all the programming models agree we should not emit the host
@@ -3513,6 +3707,8 @@ public:
if (!IsValid)
return true;
+ recordHostAction(HostAction, InputArg);
+
// If we are supporting bundling/unbundling and the current action is an
// input action of non-source file, we replace the host action by the
// unbundling action. The bundler tool has the logic to detect if an input
@@ -3529,6 +3725,7 @@ public:
C.getSingleOffloadToolChain<Action::OFK_Host>(),
/*BoundArch=*/StringRef(), Action::OFK_Host);
HostAction = UnbundlingHostAction;
+ recordHostAction(HostAction, InputArg);
}
assert(HostAction && "Invalid host action!");
@@ -3565,6 +3762,9 @@ public:
/// programming models allow it.
bool appendTopLevelActions(ActionList &AL, Action *HostAction,
const Arg *InputArg) {
+ if (HostAction)
+ recordHostAction(HostAction, InputArg);
+
// Get the device actions to be appended.
ActionList OffloadAL;
for (auto *SB : SpecializedBuilders) {
@@ -3586,6 +3786,7 @@ public:
// before this method was called.
assert(HostAction == AL.back() && "Host action not in the list??");
HostAction = C.MakeAction<OffloadBundlingJobAction>(OffloadAL);
+ recordHostAction(HostAction, InputArg);
AL.back() = HostAction;
} else
AL.append(OffloadAL.begin(), OffloadAL.end());
@@ -3619,6 +3820,11 @@ public:
if (!SB->isValid())
continue;
HA = SB->appendLinkHostActions(DeviceAL);
+ // This created host action has no originating input argument, therefore
+ // needs to set its offloading kind directly.
+ if (HA)
+ HA->propagateHostOffloadInfo(SB->getAssociatedOffloadKind(),
+ /*BoundArch=*/nullptr);
}
return HA;
}
@@ -3645,10 +3851,22 @@ public:
// If we don't have device dependencies, we don't have to create an offload
// action.
if (DDeps.getActions().empty()) {
- // Propagate all the active kinds to host action. Given that it is a link
- // action it is assumed to depend on all actions generated so far.
- HostAction->propagateHostOffloadInfo(ActiveOffloadKinds,
- /*BoundArch=*/nullptr);
+ // Set all the active offloading kinds to the link action. Given that it
+ // is a link action it is assumed to depend on all actions generated so
+ // far.
+ HostAction->setHostOffloadInfo(ActiveOffloadKinds,
+ /*BoundArch=*/nullptr);
+ // Propagate active offloading kinds for each input to the link action.
+ // Each input may have different active offloading kind.
+ for (auto A : HostAction->inputs()) {
+ auto ArgLoc = HostActionToInputArgMap.find(A);
+ if (ArgLoc == HostActionToInputArgMap.end())
+ continue;
+ auto OFKLoc = InputArgToOffloadKindMap.find(ArgLoc->second);
+ if (OFKLoc == InputArgToOffloadKindMap.end())
+ continue;
+ A->propagateHostOffloadInfo(OFKLoc->second, /*BoundArch=*/nullptr);
+ }
return HostAction;
}
@@ -3686,7 +3904,8 @@ void Driver::handleArguments(Compilation &C, DerivedArgList &Args,
phases::ID FinalPhase = getFinalPhase(Args, &FinalPhaseArg);
if (FinalPhase == phases::Link) {
- if (Args.hasArg(options::OPT_emit_llvm))
+ // Emitting LLVM while linking disabled except in HIPAMD Toolchain
+ if (Args.hasArg(options::OPT_emit_llvm) && !Args.hasArg(options::OPT_hip_link))
Diag(clang::diag::err_drv_emit_llvm_link);
if (IsCLMode() && LTOMode != LTOK_None &&
!Args.getLastArgValue(options::OPT_fuse_ld_EQ)
@@ -3830,13 +4049,16 @@ void Driver::BuildActions(Compilation &C, DerivedArgList &Args,
// Builder to be used to build offloading actions.
OffloadingActionBuilder OffloadBuilder(C, Args, Inputs);
- // Offload kinds active for this compilation.
- unsigned OffloadKinds = Action::OFK_None;
- if (C.hasOffloadToolChain<Action::OFK_OpenMP>())
- OffloadKinds |= Action::OFK_OpenMP;
+ bool UseNewOffloadingDriver =
+ (C.isOffloadingHostKind(Action::OFK_OpenMP) &&
+ Args.hasFlag(options::OPT_fopenmp_new_driver,
+ options::OPT_no_offload_new_driver, true)) ||
+ Args.hasFlag(options::OPT_offload_new_driver,
+ options::OPT_no_offload_new_driver, false);
// Construct the actions to perform.
HeaderModulePrecompileJobAction *HeaderModuleAction = nullptr;
+ ExtractAPIJobAction *ExtractAPIAction = nullptr;
ActionList LinkerInputs;
ActionList MergerInputs;
@@ -3855,14 +4077,14 @@ void Driver::BuildActions(Compilation &C, DerivedArgList &Args,
// Use the current host action in any of the offloading actions, if
// required.
- if (!Args.hasArg(options::OPT_fopenmp_new_driver))
+ if (!UseNewOffloadingDriver)
if (OffloadBuilder.addHostDependenceToDeviceActions(Current, InputArg))
break;
for (phases::ID Phase : PL) {
// Add any offload action the host action depends on.
- if (!Args.hasArg(options::OPT_fopenmp_new_driver))
+ if (!UseNewOffloadingDriver)
Current = OffloadBuilder.addDeviceDependencesToHostAction(
Current, InputArg, Phase, PL.back(), FullPL);
if (!Current)
@@ -3871,7 +4093,10 @@ void Driver::BuildActions(Compilation &C, DerivedArgList &Args,
// Queue linker inputs.
if (Phase == phases::Link) {
assert(Phase == PL.back() && "linking must be final compilation step.");
- LinkerInputs.push_back(Current);
+ // We don't need to generate additional link commands if emitting AMD bitcode
+ if (!(C.getInputArgs().hasArg(options::OPT_hip_link) &&
+ (C.getInputArgs().hasArg(options::OPT_emit_llvm))))
+ LinkerInputs.push_back(Current);
Current = nullptr;
break;
}
@@ -3897,10 +4122,11 @@ void Driver::BuildActions(Compilation &C, DerivedArgList &Args,
break;
}
- // Try to build the offloading actions and add the result as a dependency
- // to the host.
- if (Args.hasArg(options::OPT_fopenmp_new_driver))
- Current = BuildOffloadingActions(C, Args, I, Current);
+ if (Phase == phases::Precompile && ExtractAPIAction) {
+ ExtractAPIAction->addHeaderInput(Current);
+ Current = nullptr;
+ break;
+ }
// FIXME: Should we include any prior module file outputs as inputs of
// later actions in the same command line?
@@ -3914,15 +4140,22 @@ void Driver::BuildActions(Compilation &C, DerivedArgList &Args,
if (auto *HMA = dyn_cast<HeaderModulePrecompileJobAction>(NewCurrent))
HeaderModuleAction = HMA;
+ else if (auto *EAA = dyn_cast<ExtractAPIJobAction>(NewCurrent))
+ ExtractAPIAction = EAA;
Current = NewCurrent;
// Use the current host action in any of the offloading actions, if
// required.
- if (!Args.hasArg(options::OPT_fopenmp_new_driver))
+ if (!UseNewOffloadingDriver)
if (OffloadBuilder.addHostDependenceToDeviceActions(Current, InputArg))
break;
+ // Try to build the offloading actions and add the result as a dependency
+ // to the host.
+ if (UseNewOffloadingDriver)
+ Current = BuildOffloadingActions(C, Args, I, Current);
+
if (Current->getType() == types::TY_Nothing)
break;
}
@@ -3932,10 +4165,10 @@ void Driver::BuildActions(Compilation &C, DerivedArgList &Args,
Actions.push_back(Current);
// Add any top level actions generated for offloading.
- if (!Args.hasArg(options::OPT_fopenmp_new_driver))
+ if (!UseNewOffloadingDriver)
OffloadBuilder.appendTopLevelActions(Actions, Current, InputArg);
else if (Current)
- Current->propagateHostOffloadInfo(OffloadKinds,
+ Current->propagateHostOffloadInfo(C.getActiveOffloadKinds(),
/*BoundArch=*/nullptr);
}
@@ -3944,26 +4177,27 @@ void Driver::BuildActions(Compilation &C, DerivedArgList &Args,
if (LinkerInputs.empty()) {
Arg *FinalPhaseArg;
if (getFinalPhase(Args, &FinalPhaseArg) == phases::Link)
- OffloadBuilder.appendDeviceLinkActions(Actions);
+ if (!UseNewOffloadingDriver)
+ OffloadBuilder.appendDeviceLinkActions(Actions);
}
if (!LinkerInputs.empty()) {
- if (!Args.hasArg(options::OPT_fopenmp_new_driver))
+ if (!UseNewOffloadingDriver)
if (Action *Wrapper = OffloadBuilder.makeHostLinkAction())
LinkerInputs.push_back(Wrapper);
Action *LA;
// Check if this Linker Job should emit a static library.
if (ShouldEmitStaticLibrary(Args)) {
LA = C.MakeAction<StaticLibJobAction>(LinkerInputs, types::TY_Image);
- } else if (Args.hasArg(options::OPT_fopenmp_new_driver) &&
- OffloadKinds != Action::OFK_None) {
+ } else if (UseNewOffloadingDriver ||
+ Args.hasArg(options::OPT_offload_link)) {
LA = C.MakeAction<LinkerWrapperJobAction>(LinkerInputs, types::TY_Image);
- LA->propagateHostOffloadInfo(OffloadKinds,
+ LA->propagateHostOffloadInfo(C.getActiveOffloadKinds(),
/*BoundArch=*/nullptr);
} else {
LA = C.MakeAction<LinkJobAction>(LinkerInputs, types::TY_Image);
}
- if (!Args.hasArg(options::OPT_fopenmp_new_driver))
+ if (!UseNewOffloadingDriver)
LA = OffloadBuilder.processHostLinkAction(LA);
Actions.push_back(LA);
}
@@ -4043,73 +4277,216 @@ void Driver::BuildActions(Compilation &C, DerivedArgList &Args,
// Claim ignored clang-cl options.
Args.ClaimAllArgs(options::OPT_cl_ignored_Group);
+}
+
+/// Returns the canonical name for the offloading architecture when using a HIP
+/// or CUDA architecture.
+static StringRef getCanonicalArchString(Compilation &C,
+ const llvm::opt::DerivedArgList &Args,
+ StringRef ArchStr,
+ const llvm::Triple &Triple) {
+ // Lookup the CUDA / HIP architecture string. Only report an error if we were
+ // expecting the triple to be only NVPTX / AMDGPU.
+ CudaArch Arch = StringToCudaArch(getProcessorFromTargetID(Triple, ArchStr));
+ if (Triple.isNVPTX() &&
+ (Arch == CudaArch::UNKNOWN || !IsNVIDIAGpuArch(Arch))) {
+ C.getDriver().Diag(clang::diag::err_drv_offload_bad_gpu_arch)
+ << "CUDA" << ArchStr;
+ return StringRef();
+ } else if (Triple.isAMDGPU() &&
+ (Arch == CudaArch::UNKNOWN || !IsAMDGpuArch(Arch))) {
+ C.getDriver().Diag(clang::diag::err_drv_offload_bad_gpu_arch)
+ << "HIP" << ArchStr;
+ return StringRef();
+ }
+
+ if (IsNVIDIAGpuArch(Arch))
+ return Args.MakeArgStringRef(CudaArchToString(Arch));
+
+ if (IsAMDGpuArch(Arch)) {
+ llvm::StringMap<bool> Features;
+ auto HIPTriple = getHIPOffloadTargetTriple(C.getDriver(), C.getInputArgs());
+ if (!HIPTriple)
+ return StringRef();
+ auto Arch = parseTargetID(*HIPTriple, ArchStr, &Features);
+ if (!Arch) {
+ C.getDriver().Diag(clang::diag::err_drv_bad_target_id) << ArchStr;
+ C.setContainsError();
+ return StringRef();
+ }
+ return Args.MakeArgStringRef(getCanonicalTargetID(*Arch, Features));
+ }
- // Claim --cuda-host-only and --cuda-compile-host-device, which may be passed
- // to non-CUDA compilations and should not trigger warnings there.
- Args.ClaimAllArgs(options::OPT_cuda_host_only);
- Args.ClaimAllArgs(options::OPT_cuda_compile_host_device);
+ // If the input isn't CUDA or HIP just return the architecture.
+ return ArchStr;
+}
+
+/// Checks if the set offloading architectures does not conflict. Returns the
+/// incompatible pair if a conflict occurs.
+static llvm::Optional<std::pair<llvm::StringRef, llvm::StringRef>>
+getConflictOffloadArchCombination(const llvm::DenseSet<StringRef> &Archs,
+ Action::OffloadKind Kind) {
+ if (Kind != Action::OFK_HIP)
+ return None;
+
+ std::set<StringRef> ArchSet;
+ llvm::copy(Archs, std::inserter(ArchSet, ArchSet.begin()));
+ return getConflictTargetIDCombination(ArchSet);
+}
+
+llvm::DenseSet<StringRef>
+Driver::getOffloadArchs(Compilation &C, const llvm::opt::DerivedArgList &Args,
+ Action::OffloadKind Kind, const ToolChain *TC) const {
+ if (!TC)
+ TC = &C.getDefaultToolChain();
+
+ // --offload and --offload-arch options are mutually exclusive.
+ if (Args.hasArgNoClaim(options::OPT_offload_EQ) &&
+ Args.hasArgNoClaim(options::OPT_offload_arch_EQ,
+ options::OPT_no_offload_arch_EQ)) {
+ C.getDriver().Diag(diag::err_opt_not_valid_with_opt)
+ << "--offload"
+ << (Args.hasArgNoClaim(options::OPT_offload_arch_EQ)
+ ? "--offload-arch"
+ : "--no-offload-arch");
+ }
+
+ if (KnownArchs.find(TC) != KnownArchs.end())
+ return KnownArchs.lookup(TC);
+
+ llvm::DenseSet<StringRef> Archs;
+ for (auto &Arg : Args) {
+ if (Arg->getOption().matches(options::OPT_offload_arch_EQ)) {
+ for (StringRef Arch : llvm::split(Arg->getValue(), ","))
+ Archs.insert(getCanonicalArchString(C, Args, Arch, TC->getTriple()));
+ } else if (Arg->getOption().matches(options::OPT_no_offload_arch_EQ)) {
+ for (StringRef Arch : llvm::split(Arg->getValue(), ",")) {
+ if (Arch == StringRef("all"))
+ Archs.clear();
+ else
+ Archs.erase(getCanonicalArchString(C, Args, Arch, TC->getTriple()));
+ }
+ }
+ }
+
+ if (auto ConflictingArchs = getConflictOffloadArchCombination(Archs, Kind)) {
+ C.getDriver().Diag(clang::diag::err_drv_bad_offload_arch_combo)
+ << ConflictingArchs->first << ConflictingArchs->second;
+ C.setContainsError();
+ }
+
+ if (Archs.empty()) {
+ if (Kind == Action::OFK_Cuda)
+ Archs.insert(CudaArchToString(CudaArch::CudaDefault));
+ else if (Kind == Action::OFK_HIP)
+ Archs.insert(CudaArchToString(CudaArch::HIPDefault));
+ else if (Kind == Action::OFK_OpenMP)
+ Archs.insert(StringRef());
+ } else {
+ Args.ClaimAllArgs(options::OPT_offload_arch_EQ);
+ Args.ClaimAllArgs(options::OPT_no_offload_arch_EQ);
+ }
+
+ return Archs;
}
Action *Driver::BuildOffloadingActions(Compilation &C,
llvm::opt::DerivedArgList &Args,
const InputTy &Input,
Action *HostAction) const {
- if (!isa<CompileJobAction>(HostAction))
+ // Don't build offloading actions if explicitly disabled or we do not have a
+ // valid source input and compile action to embed it in. If preprocessing only
+ // ignore embedding.
+ if (offloadHostOnly() || !types::isSrcFile(Input.first) ||
+ !(isa<CompileJobAction>(HostAction) ||
+ getFinalPhase(Args) == phases::Preprocess))
return HostAction;
- SmallVector<const ToolChain *, 2> ToolChains;
- ActionList DeviceActions;
+ ActionList OffloadActions;
+ OffloadAction::DeviceDependences DDeps;
- types::ID InputType = Input.first;
- const Arg *InputArg = Input.second;
+ const Action::OffloadKind OffloadKinds[] = {
+ Action::OFK_OpenMP, Action::OFK_Cuda, Action::OFK_HIP};
- auto OpenMPTCRange = C.getOffloadToolChains<Action::OFK_OpenMP>();
- for (auto TI = OpenMPTCRange.first, TE = OpenMPTCRange.second; TI != TE; ++TI)
- ToolChains.push_back(TI->second);
+ for (Action::OffloadKind Kind : OffloadKinds) {
+ SmallVector<const ToolChain *, 2> ToolChains;
+ ActionList DeviceActions;
- for (unsigned I = 0; I < ToolChains.size(); ++I)
- DeviceActions.push_back(C.MakeAction<InputAction>(*InputArg, InputType));
+ auto TCRange = C.getOffloadToolChains(Kind);
+ for (auto TI = TCRange.first, TE = TCRange.second; TI != TE; ++TI)
+ ToolChains.push_back(TI->second);
- if (DeviceActions.empty())
- return HostAction;
+ if (ToolChains.empty())
+ continue;
- auto PL = types::getCompilationPhases(*this, Args, InputType);
+ types::ID InputType = Input.first;
+ const Arg *InputArg = Input.second;
- for (phases::ID Phase : PL) {
- if (Phase == phases::Link) {
- assert(Phase == PL.back() && "linking must be final compilation step.");
- break;
- }
+ // Get the product of all bound architectures and toolchains.
+ SmallVector<std::pair<const ToolChain *, StringRef>> TCAndArchs;
+ for (const ToolChain *TC : ToolChains)
+ for (StringRef Arch : getOffloadArchs(
+ C, C.getArgsForToolChain(TC, "generic", Kind), Kind, TC))
+ TCAndArchs.push_back(std::make_pair(TC, Arch));
- auto TC = ToolChains.begin();
- for (Action *&A : DeviceActions) {
- A = ConstructPhaseAction(C, Args, Phase, A, Action::OFK_OpenMP);
+ for (unsigned I = 0, E = TCAndArchs.size(); I != E; ++I)
+ DeviceActions.push_back(C.MakeAction<InputAction>(*InputArg, InputType));
- if (isa<CompileJobAction>(A)) {
- HostAction->setCannotBeCollapsedWithNextDependentAction();
- OffloadAction::HostDependence HDep(
- *HostAction, *C.getSingleOffloadToolChain<Action::OFK_Host>(),
- /*BourdArch=*/nullptr, Action::OFK_OpenMP);
- OffloadAction::DeviceDependences DDep;
- DDep.add(*A, **TC, /*BoundArch=*/nullptr, Action::OFK_OpenMP);
- A = C.MakeAction<OffloadAction>(HDep, DDep);
+ if (DeviceActions.empty())
+ return HostAction;
+
+ auto PL = types::getCompilationPhases(*this, Args, InputType);
+
+ for (phases::ID Phase : PL) {
+ if (Phase == phases::Link) {
+ assert(Phase == PL.back() && "linking must be final compilation step.");
+ break;
}
- ++TC;
- }
- }
- OffloadAction::DeviceDependences DDeps;
+ auto TCAndArch = TCAndArchs.begin();
+ for (Action *&A : DeviceActions) {
+ A = ConstructPhaseAction(C, Args, Phase, A, Kind);
- auto TC = ToolChains.begin();
- for (Action *A : DeviceActions) {
- DDeps.add(*A, **TC, /*BoundArch=*/nullptr, Action::OFK_OpenMP);
- TC++;
+ if (isa<CompileJobAction>(A) && isa<CompileJobAction>(HostAction) &&
+ Kind == Action::OFK_OpenMP) {
+ // OpenMP offloading has a dependency on the host compile action to
+ // identify which declarations need to be emitted. This shouldn't be
+ // collapsed with any other actions so we can use it in the device.
+ HostAction->setCannotBeCollapsedWithNextDependentAction();
+ OffloadAction::HostDependence HDep(
+ *HostAction, *C.getSingleOffloadToolChain<Action::OFK_Host>(),
+ TCAndArch->second.data(), Kind);
+ OffloadAction::DeviceDependences DDep;
+ DDep.add(*A, *TCAndArch->first, TCAndArch->second.data(), Kind);
+ A = C.MakeAction<OffloadAction>(HDep, DDep);
+ }
+ ++TCAndArch;
+ }
+ }
+
+ auto TCAndArch = TCAndArchs.begin();
+ for (Action *A : DeviceActions) {
+ DDeps.add(*A, *TCAndArch->first, TCAndArch->second.data(), Kind);
+ OffloadAction::DeviceDependences DDep;
+ DDep.add(*A, *TCAndArch->first, TCAndArch->second.data(), Kind);
+ OffloadActions.push_back(C.MakeAction<OffloadAction>(DDep, A->getType()));
+ ++TCAndArch;
+ }
}
+ if (offloadDeviceOnly())
+ return C.MakeAction<OffloadAction>(DDeps, types::TY_Nothing);
+
+ Action *OffloadPackager =
+ C.MakeAction<OffloadPackagerJobAction>(OffloadActions, types::TY_Image);
+ OffloadAction::DeviceDependences DDep;
+ DDep.add(*OffloadPackager, *C.getSingleOffloadToolChain<Action::OFK_Host>(),
+ nullptr, Action::OFK_None);
OffloadAction::HostDependence HDep(
*HostAction, *C.getSingleOffloadToolChain<Action::OFK_Host>(),
- /*BoundArch=*/nullptr, DDeps);
- return C.MakeAction<OffloadAction>(HDep, DDeps);
+ /*BoundArch=*/nullptr, isa<CompileJobAction>(HostAction) ? DDep : DDeps);
+ return C.MakeAction<OffloadAction>(
+ HDep, isa<CompileJobAction>(HostAction) ? DDep : DDeps);
}
Action *Driver::ConstructPhaseAction(
@@ -4138,10 +4515,14 @@ Action *Driver::ConstructPhaseAction(
OutputTy = types::TY_Dependencies;
} else {
OutputTy = Input->getType();
+ // For these cases, the preprocessor is only translating forms, the Output
+ // still needs preprocessing.
if (!Args.hasFlag(options::OPT_frewrite_includes,
options::OPT_fno_rewrite_includes, false) &&
!Args.hasFlag(options::OPT_frewrite_imports,
options::OPT_fno_rewrite_imports, false) &&
+ !Args.hasFlag(options::OPT_fdirectives_only,
+ options::OPT_fno_directives_only, false) &&
!CCGenDiagnostics)
OutputTy = types::getPreprocessedType(OutputTy);
assert(OutputTy != types::TY_INVALID &&
@@ -4150,6 +4531,10 @@ Action *Driver::ConstructPhaseAction(
return C.MakeAction<PreprocessJobAction>(Input, OutputTy);
}
case phases::Precompile: {
+ // API extraction should not generate an actual precompilation action.
+ if (Args.hasArg(options::OPT_extract_api))
+ return C.MakeAction<ExtractAPIJobAction>(Input, types::TY_API_INFO);
+
types::ID OutputTy = getPrecompiledType(Input->getType());
assert(OutputTy != types::TY_INVALID &&
"Cannot precompile this input type!");
@@ -4164,8 +4549,7 @@ Action *Driver::ConstructPhaseAction(
OutputTy = types::TY_ModuleFile;
}
- if (Args.hasArg(options::OPT_fsyntax_only) ||
- Args.hasArg(options::OPT_extract_api)) {
+ if (Args.hasArg(options::OPT_fsyntax_only)) {
// Syntax checks should not emit a PCH file
OutputTy = types::TY_Nothing;
}
@@ -4194,7 +4578,7 @@ Action *Driver::ConstructPhaseAction(
if (Args.hasArg(options::OPT_verify_pch))
return C.MakeAction<VerifyPCHJobAction>(Input, types::TY_Nothing);
if (Args.hasArg(options::OPT_extract_api))
- return C.MakeAction<CompileJobAction>(Input, types::TY_API_INFO);
+ return C.MakeAction<ExtractAPIJobAction>(Input, types::TY_API_INFO);
return C.MakeAction<CompileJobAction>(Input, types::TY_LLVM_BC);
}
case phases::Backend: {
@@ -4204,7 +4588,7 @@ Action *Driver::ConstructPhaseAction(
return C.MakeAction<BackendJobAction>(Input, Output);
}
if (isUsingLTO(/* IsOffload */ true) &&
- TargetDeviceOffloadKind == Action::OFK_OpenMP) {
+ TargetDeviceOffloadKind != Action::OFK_None) {
types::ID Output =
Args.hasArg(options::OPT_S) ? types::TY_LTO_IR : types::TY_LTO_BC;
return C.MakeAction<BackendJobAction>(Input, Output);
@@ -4372,6 +4756,8 @@ void Driver::BuildJobs(Compilation &C) const {
C.getArgs().hasArg(options::OPT_Qunused_arguments))
return;
+ // Claim -fdriver-only here.
+ (void)C.getArgs().hasArg(options::OPT_fdriver_only);
// Claim -### here.
(void)C.getArgs().hasArg(options::OPT__HASH_HASH_HASH);
@@ -5020,8 +5406,9 @@ InputInfoList Driver::BuildJobsForActionNoCache(
// action.
std::string OffloadingPrefix = Action::GetOffloadingFileNamePrefix(
A->getOffloadingDeviceKind(), TC->getTriple().normalize(),
- /*CreatePrefixForHost=*/!!A->getOffloadingHostActiveKinds() &&
- !AtTopLevel);
+ /*CreatePrefixForHost=*/isa<OffloadPackagerJobAction>(A) ||
+ !(A->getOffloadingHostActiveKinds() == Action::OFK_None ||
+ AtTopLevel));
if (isa<OffloadWrapperJobAction>(JA)) {
if (Arg *FinalOutput = C.getArgs().getLastArg(options::OPT_o))
BaseInput = FinalOutput->getValue();
@@ -5258,7 +5645,8 @@ const char *Driver::GetNamedOutputPath(Compilation &C, const JobAction &JA,
bool IsHIPNoRDC = JA.getOffloadingDeviceKind() == Action::OFK_HIP &&
!C.getArgs().hasFlag(options::OPT_fgpu_rdc,
options::OPT_fno_gpu_rdc, false);
- if (IsHIPNoRDC) {
+ bool UseOutExtension = IsHIPNoRDC || isa<OffloadPackagerJobAction>(JA);
+ if (UseOutExtension) {
Output = BaseName;
llvm::sys::path::replace_extension(Output, "");
}
@@ -5267,12 +5655,20 @@ const char *Driver::GetNamedOutputPath(Compilation &C, const JobAction &JA,
Output += "-";
Output.append(BoundArch);
}
- if (IsHIPNoRDC)
+ if (UseOutExtension)
Output += ".out";
NamedOutput = C.getArgs().MakeArgString(Output.c_str());
}
} else if (JA.getType() == types::TY_PCH && IsCLMode()) {
NamedOutput = C.getArgs().MakeArgString(GetClPchPath(C, BaseName));
+ } else if ((JA.getType() == types::TY_Plist || JA.getType() == types::TY_AST) &&
+ C.getArgs().hasArg(options::OPT__SLASH_o)) {
+ StringRef Val =
+ C.getArgs()
+ .getLastArg(options::OPT__SLASH_o)
+ ->getValue();
+ NamedOutput =
+ MakeCLOutputFilename(C.getArgs(), Val, BaseName, types::TY_Object);
} else {
const char *Suffix = types::getTypeTempSuffix(JA.getType(), IsCLMode());
assert(Suffix && "All types used for output should have a suffix.");
@@ -5519,6 +5915,7 @@ const ToolChain &Driver::getToolChain(const ArgList &Args,
case llvm::Triple::IOS:
case llvm::Triple::TvOS:
case llvm::Triple::WatchOS:
+ case llvm::Triple::DriverKit:
TC = std::make_unique<toolchains::DarwinClang>(*this, Target, Args);
break;
case llvm::Triple::DragonFly:
@@ -5606,6 +6003,9 @@ const ToolChain &Driver::getToolChain(const ArgList &Args,
case llvm::Triple::PS4:
TC = std::make_unique<toolchains::PS4CPU>(*this, Target, Args);
break;
+ case llvm::Triple::PS5:
+ TC = std::make_unique<toolchains::PS5CPU>(*this, Target, Args);
+ break;
case llvm::Triple::Contiki:
TC = std::make_unique<toolchains::Contiki>(*this, Target, Args);
break;
@@ -5615,6 +6015,9 @@ const ToolChain &Driver::getToolChain(const ArgList &Args,
case llvm::Triple::ZOS:
TC = std::make_unique<toolchains::ZOS>(*this, Target, Args);
break;
+ case llvm::Triple::ShaderModel:
+ TC = std::make_unique<toolchains::HLSLToolChain>(*this, Target, Args);
+ break;
default:
// Of these targets, Hexagon is the only one that might have
// an OS of Linux, in which case it got handled above already.
@@ -5661,6 +6064,9 @@ const ToolChain &Driver::getToolChain(const ArgList &Args,
case llvm::Triple::spirv64:
TC = std::make_unique<toolchains::SPIRVToolChain>(*this, Target, Args);
break;
+ case llvm::Triple::csky:
+ TC = std::make_unique<toolchains::CSKYToolChain>(*this, Target, Args);
+ break;
default:
if (Target.getVendor() == llvm::Triple::Myriad)
TC = std::make_unique<toolchains::MyriadToolChain>(*this, Target,
@@ -5725,7 +6131,8 @@ bool Driver::ShouldUseClangCompiler(const JobAction &JA) const {
// And say "no" if this is not a kind of action clang understands.
if (!isa<PreprocessJobAction>(JA) && !isa<PrecompileJobAction>(JA) &&
- !isa<CompileJobAction>(JA) && !isa<BackendJobAction>(JA))
+ !isa<CompileJobAction>(JA) && !isa<BackendJobAction>(JA) &&
+ !isa<ExtractAPIJobAction>(JA))
return false;
return true;
@@ -5734,11 +6141,12 @@ bool Driver::ShouldUseClangCompiler(const JobAction &JA) const {
bool Driver::ShouldUseFlangCompiler(const JobAction &JA) const {
// Say "no" if there is not exactly one input of a type flang understands.
if (JA.size() != 1 ||
- !types::isFortran((*JA.input_begin())->getType()))
+ !types::isAcceptedByFlang((*JA.input_begin())->getType()))
return false;
// And say "no" if this is not a kind of action flang understands.
- if (!isa<PreprocessJobAction>(JA) && !isa<CompileJobAction>(JA) && !isa<BackendJobAction>(JA))
+ if (!isa<PreprocessJobAction>(JA) && !isa<CompileJobAction>(JA) &&
+ !isa<BackendJobAction>(JA))
return false;
return true;
@@ -5829,7 +6237,13 @@ Driver::getIncludeExcludeOptionFlagMasks(bool IsClCompatMode) const {
} else {
ExcludedFlagsBitmask |= options::CLOption;
}
-
+ if (IsDXCMode()) {
+ // Include DXC and Core options.
+ IncludedFlagsBitmask |= options::DXCOption;
+ IncludedFlagsBitmask |= options::CoreOption;
+ } else {
+ ExcludedFlagsBitmask |= options::DXCOption;
+ }
return std::make_pair(IncludedFlagsBitmask, ExcludedFlagsBitmask);
}
diff --git a/clang/lib/Driver/SanitizerArgs.cpp b/clang/lib/Driver/SanitizerArgs.cpp
index 403fac76f060..68fe90c7a69d 100644
--- a/clang/lib/Driver/SanitizerArgs.cpp
+++ b/clang/lib/Driver/SanitizerArgs.cpp
@@ -14,9 +14,9 @@
#include "clang/Driver/ToolChain.h"
#include "llvm/ADT/StringExtras.h"
#include "llvm/ADT/StringSwitch.h"
+#include "llvm/Support/AArch64TargetParser.h"
#include "llvm/Support/Path.h"
#include "llvm/Support/SpecialCaseList.h"
-#include "llvm/Support/AArch64TargetParser.h"
#include "llvm/Support/TargetParser.h"
#include "llvm/Support/VirtualFileSystem.h"
#include "llvm/Transforms/Instrumentation/AddressSanitizerOptions.h"
@@ -44,7 +44,8 @@ static const SanitizerMask NeedsUnwindTables =
static const SanitizerMask SupportsCoverage =
SanitizerKind::Address | SanitizerKind::HWAddress |
SanitizerKind::KernelAddress | SanitizerKind::KernelHWAddress |
- SanitizerKind::MemTag | SanitizerKind::Memory |
+ SanitizerKind::MemtagStack | SanitizerKind::MemtagHeap |
+ SanitizerKind::MemtagGlobals | SanitizerKind::Memory |
SanitizerKind::KernelMemory | SanitizerKind::Leak |
SanitizerKind::Undefined | SanitizerKind::Integer | SanitizerKind::Bounds |
SanitizerKind::ImplicitConversion | SanitizerKind::Nullability |
@@ -73,7 +74,8 @@ static const SanitizerMask CFIClasses =
SanitizerKind::CFIUnrelatedCast;
static const SanitizerMask CompatibleWithMinimalRuntime =
TrappingSupported | SanitizerKind::Scudo | SanitizerKind::ShadowCallStack |
- SanitizerKind::MemTag;
+ SanitizerKind::MemtagStack | SanitizerKind::MemtagHeap |
+ SanitizerKind::MemtagGlobals;
enum CoverageFeature {
CoverageFunc = 1 << 0,
@@ -168,14 +170,14 @@ static void addDefaultIgnorelists(const Driver &D, SanitizerMask Kinds,
else if (BL.Mask == SanitizerKind::CFI && DiagnoseErrors)
// If cfi_ignorelist.txt cannot be found in the resource dir, driver
// should fail.
- D.Diag(clang::diag::err_drv_no_such_file) << Path;
+ D.Diag(clang::diag::err_drv_missing_sanitizer_ignorelist) << Path;
}
validateSpecialCaseListFormat(
D, IgnorelistFiles, clang::diag::err_drv_malformed_sanitizer_ignorelist,
DiagnoseErrors);
}
-/// Parse -f(no-)?sanitize-(coverage-)?(white|ignore)list argument's values,
+/// Parse -f(no-)?sanitize-(coverage-)?(allow|ignore)list argument's values,
/// diagnosing any invalid file paths and validating special case list format.
static void parseSpecialCaseListArg(const Driver &D,
const llvm::opt::ArgList &Args,
@@ -185,7 +187,7 @@ static void parseSpecialCaseListArg(const Driver &D,
unsigned MalformedSCLErrorDiagID,
bool DiagnoseErrors) {
for (const auto *Arg : Args) {
- // Match -fsanitize-(coverage-)?(white|ignore)list.
+ // Match -fsanitize-(coverage-)?(allow|ignore)list.
if (Arg->getOption().matches(SCLOptionID)) {
Arg->claim();
std::string SCLPath = Arg->getValue();
@@ -218,9 +220,9 @@ static SanitizerMask setGroupBits(SanitizerMask Kinds) {
static SanitizerMask parseSanitizeTrapArgs(const Driver &D,
const llvm::opt::ArgList &Args,
bool DiagnoseErrors) {
- SanitizerMask TrapRemove; // During the loop below, the accumulated set of
- // sanitizers disabled by the current sanitizer
- // argument or any argument after it.
+ SanitizerMask TrapRemove; // During the loop below, the accumulated set of
+ // sanitizers disabled by the current sanitizer
+ // argument or any argument after it.
SanitizerMask TrappingKinds;
SanitizerMask TrappingSupportedWithGroups = setGroupBits(TrappingSupported);
@@ -233,8 +235,8 @@ static SanitizerMask parseSanitizeTrapArgs(const Driver &D,
if (InvalidValues && DiagnoseErrors) {
SanitizerSet S;
S.Mask = InvalidValues;
- D.Diag(diag::err_drv_unsupported_option_argument) << "-fsanitize-trap"
- << toString(S);
+ D.Diag(diag::err_drv_unsupported_option_argument)
+ << Arg->getOption().getName() << toString(S);
}
TrappingKinds |= expandSanitizerGroups(Add) & ~TrapRemove;
} else if (Arg->getOption().matches(options::OPT_fno_sanitize_trap_EQ)) {
@@ -293,13 +295,13 @@ SanitizerArgs::SanitizerArgs(const ToolChain &TC,
SanitizerMask AllRemove; // During the loop below, the accumulated set of
// sanitizers disabled by the current sanitizer
// argument or any argument after it.
- SanitizerMask AllAddedKinds; // Mask of all sanitizers ever enabled by
- // -fsanitize= flags (directly or via group
- // expansion), some of which may be disabled
- // later. Used to carefully prune
- // unused-argument diagnostics.
- SanitizerMask DiagnosedKinds; // All Kinds we have diagnosed up to now.
- // Used to deduplicate diagnostics.
+ SanitizerMask AllAddedKinds; // Mask of all sanitizers ever enabled by
+ // -fsanitize= flags (directly or via group
+ // expansion), some of which may be disabled
+ // later. Used to carefully prune
+ // unused-argument diagnostics.
+ SanitizerMask DiagnosedKinds; // All Kinds we have diagnosed up to now.
+ // Used to deduplicate diagnostics.
SanitizerMask Kinds;
const SanitizerMask Supported = setGroupBits(TC.getSupportedSanitizers());
@@ -367,6 +369,19 @@ SanitizerArgs::SanitizerArgs(const ToolChain &TC,
Add &= ~NotAllowedWithMinimalRuntime;
}
+ if (llvm::opt::Arg *A = Args.getLastArg(options::OPT_mcmodel_EQ)) {
+ StringRef CM = A->getValue();
+ if (CM != "small" &&
+ (Add & SanitizerKind::Function & ~DiagnosedKinds)) {
+ if (DiagnoseErrors)
+ D.Diag(diag::err_drv_argument_only_allowed_with)
+ << "-fsanitize=function"
+ << "-mcmodel=small";
+ Add &= ~SanitizerKind::Function;
+ DiagnosedKinds |= SanitizerKind::Function;
+ }
+ }
+
// FIXME: Make CFI on member function calls compatible with cross-DSO CFI.
// There are currently two problems:
// - Virtual function call checks need to pass a pointer to the function
@@ -402,7 +417,7 @@ SanitizerArgs::SanitizerArgs(const ToolChain &TC,
if ((Add & SanitizerKind::Vptr) && (RTTIMode == ToolChain::RM_Disabled)) {
if (const llvm::opt::Arg *NoRTTIArg = TC.getRTTIArg()) {
assert(NoRTTIArg->getOption().matches(options::OPT_fno_rtti) &&
- "RTTI disabled without -fno-rtti option?");
+ "RTTI disabled without -fno-rtti option?");
// The user explicitly passed -fno-rtti with -fsanitize=vptr, but
// the vptr sanitizer requires RTTI, so this is a user error.
if (DiagnoseErrors)
@@ -638,20 +653,36 @@ SanitizerArgs::SanitizerArgs(const ToolChain &TC,
}
}
}
- MsanUseAfterDtor =
- Args.hasFlag(options::OPT_fsanitize_memory_use_after_dtor,
- options::OPT_fno_sanitize_memory_use_after_dtor,
- MsanUseAfterDtor);
+ MsanUseAfterDtor = Args.hasFlag(
+ options::OPT_fsanitize_memory_use_after_dtor,
+ options::OPT_fno_sanitize_memory_use_after_dtor, MsanUseAfterDtor);
MsanParamRetval = Args.hasFlag(
options::OPT_fsanitize_memory_param_retval,
options::OPT_fno_sanitize_memory_param_retval, MsanParamRetval);
NeedPIE |= !(TC.getTriple().isOSLinux() &&
TC.getTriple().getArch() == llvm::Triple::x86_64);
+ } else if (AllAddedKinds & SanitizerKind::KernelMemory) {
+ MsanUseAfterDtor = false;
+ MsanParamRetval = Args.hasFlag(
+ options::OPT_fsanitize_memory_param_retval,
+ options::OPT_fno_sanitize_memory_param_retval, MsanParamRetval);
} else {
MsanUseAfterDtor = false;
MsanParamRetval = false;
}
+ if (AllAddedKinds & SanitizerKind::MemTag) {
+ StringRef S =
+ Args.getLastArgValue(options::OPT_fsanitize_memtag_mode_EQ, "sync");
+ if (S == "async" || S == "sync") {
+ MemtagMode = S.str();
+ } else {
+ D.Diag(clang::diag::err_drv_invalid_value_with_suggestion)
+ << "-fsanitize-memtag-mode=" << S << "{async, sync}";
+ MemtagMode = "sync";
+ }
+ }
+
if (AllAddedKinds & SanitizerKind::Thread) {
TsanMemoryAccess = Args.hasFlag(
options::OPT_fsanitize_thread_memory_access,
@@ -777,7 +808,7 @@ SanitizerArgs::SanitizerArgs(const ToolChain &TC,
CoverageFeatures |= CoverageFunc;
}
- // Parse -fsanitize-coverage-(ignore|white)list options if coverage enabled.
+ // Parse -fsanitize-coverage-(allow|ignore)list options if coverage enabled.
// This also validates special case lists format.
// Here, OptSpecifier() acts as a never-matching command-line argument.
// So, there is no way to clear coverage lists but you can append to them.
@@ -805,13 +836,13 @@ SanitizerArgs::SanitizerArgs(const ToolChain &TC,
NeedPIE |= TC.getTriple().isOSFuchsia();
if (Arg *A =
Args.getLastArg(options::OPT_fsanitize_address_field_padding)) {
- StringRef S = A->getValue();
- // Legal values are 0 and 1, 2, but in future we may add more levels.
- if ((S.getAsInteger(0, AsanFieldPadding) || AsanFieldPadding < 0 ||
- AsanFieldPadding > 2) &&
- DiagnoseErrors) {
- D.Diag(clang::diag::err_drv_invalid_value) << A->getAsString(Args) << S;
- }
+ StringRef S = A->getValue();
+ // Legal values are 0 and 1, 2, but in future we may add more levels.
+ if ((S.getAsInteger(0, AsanFieldPadding) || AsanFieldPadding < 0 ||
+ AsanFieldPadding > 2) &&
+ DiagnoseErrors) {
+ D.Diag(clang::diag::err_drv_invalid_value) << A->getAsString(Args) << S;
+ }
}
if (Arg *WindowsDebugRTArg =
@@ -846,12 +877,13 @@ SanitizerArgs::SanitizerArgs(const ToolChain &TC,
AsanOutlineInstrumentation);
// As a workaround for a bug in gold 2.26 and earlier, dead stripping of
- // globals in ASan is disabled by default on ELF targets.
+ // globals in ASan is disabled by default on most ELF targets.
// See https://sourceware.org/bugzilla/show_bug.cgi?id=19002
- AsanGlobalsDeadStripping =
+ AsanGlobalsDeadStripping = Args.hasFlag(
+ options::OPT_fsanitize_address_globals_dead_stripping,
+ options::OPT_fno_sanitize_address_globals_dead_stripping,
!TC.getTriple().isOSBinFormatELF() || TC.getTriple().isOSFuchsia() ||
- TC.getTriple().isPS4() ||
- Args.hasArg(options::OPT_fsanitize_address_globals_dead_stripping);
+ TC.getTriple().isPS());
AsanUseOdrIndicator =
Args.hasFlag(options::OPT_fsanitize_address_use_odr_indicator,
@@ -994,7 +1026,8 @@ static void addIncludeLinkerOption(const ToolChain &TC,
}
static bool hasTargetFeatureMTE(const llvm::opt::ArgStringList &CmdArgs) {
- for (auto Start = CmdArgs.begin(), End = CmdArgs.end(); Start != End; ++Start) {
+ for (auto Start = CmdArgs.begin(), End = CmdArgs.end(); Start != End;
+ ++Start) {
auto It = std::find(Start, End, StringRef("+mte"));
if (It == End)
break;
@@ -1015,8 +1048,8 @@ void SanitizerArgs::addArgs(const ToolChain &TC, const llvm::opt::ArgList &Args,
// AMDGPU sanitizer support is experimental and controlled by -fgpu-sanitize.
if (TC.getTriple().isNVPTX() ||
(TC.getTriple().isAMDGPU() &&
- !Args.hasFlag(options::OPT_fgpu_sanitize,
- options::OPT_fno_gpu_sanitize)))
+ !Args.hasFlag(options::OPT_fgpu_sanitize, options::OPT_fno_gpu_sanitize,
+ true)))
return;
// Translate available CoverageFeatures to corresponding clang-cc1 flags.
@@ -1230,7 +1263,8 @@ void SanitizerArgs::addArgs(const ToolChain &TC, const llvm::opt::ArgList &Args,
<< "-fvisibility=";
}
- if (Sanitizers.has(SanitizerKind::MemTag) && !hasTargetFeatureMTE(CmdArgs))
+ if (Sanitizers.has(SanitizerKind::MemtagStack) &&
+ !hasTargetFeatureMTE(CmdArgs))
TC.getDriver().Diag(diag::err_stack_tagging_requires_hardware_feature);
}
@@ -1319,8 +1353,8 @@ std::string lastArgumentForMask(const Driver &D, const llvm::opt::ArgList &Args,
}
std::string describeSanitizeArg(const llvm::opt::Arg *A, SanitizerMask Mask) {
- assert(A->getOption().matches(options::OPT_fsanitize_EQ)
- && "Invalid argument in describeSanitizerArg!");
+ assert(A->getOption().matches(options::OPT_fsanitize_EQ) &&
+ "Invalid argument in describeSanitizerArg!");
std::string Sanitizers;
for (int i = 0, n = A->getNumValues(); i != n; ++i) {
diff --git a/clang/lib/Driver/ToolChain.cpp b/clang/lib/Driver/ToolChain.cpp
index d657d21bfcdb..5130eb9b72c1 100644
--- a/clang/lib/Driver/ToolChain.cpp
+++ b/clang/lib/Driver/ToolChain.cpp
@@ -67,8 +67,9 @@ static ToolChain::RTTIMode CalculateRTTIMode(const ArgList &Args,
return ToolChain::RM_Disabled;
}
- // -frtti is default, except for the PS4 CPU.
- return (Triple.isPS4CPU()) ? ToolChain::RM_Disabled : ToolChain::RM_Enabled;
+ // -frtti is default, except for the PS4/PS5 and DriverKit.
+ bool NoRTTI = Triple.isPS() || Triple.isDriverKit();
+ return NoRTTI ? ToolChain::RM_Disabled : ToolChain::RM_Enabled;
}
ToolChain::ToolChain(const Driver &D, const llvm::Triple &T,
@@ -105,6 +106,34 @@ bool ToolChain::useIntegratedAs() const {
IsIntegratedAssemblerDefault());
}
+bool ToolChain::useIntegratedBackend() const {
+ assert(
+ ((IsIntegratedBackendDefault() && IsIntegratedBackendSupported()) ||
+ (!IsIntegratedBackendDefault() || IsNonIntegratedBackendSupported())) &&
+ "(Non-)integrated backend set incorrectly!");
+
+ bool IBackend = Args.hasFlag(options::OPT_fintegrated_objemitter,
+ options::OPT_fno_integrated_objemitter,
+ IsIntegratedBackendDefault());
+
+ // Diagnose when integrated-objemitter options are not supported by this
+ // toolchain.
+ unsigned DiagID;
+ if ((IBackend && !IsIntegratedBackendSupported()) ||
+ (!IBackend && !IsNonIntegratedBackendSupported()))
+ DiagID = clang::diag::err_drv_unsupported_opt_for_target;
+ else
+ DiagID = clang::diag::warn_drv_unsupported_opt_for_target;
+ Arg *A = Args.getLastArg(options::OPT_fno_integrated_objemitter);
+ if (A && !IsNonIntegratedBackendSupported())
+ D.Diag(DiagID) << A->getAsString(Args) << Triple.getTriple();
+ A = Args.getLastArg(options::OPT_fintegrated_objemitter);
+ if (A && !IsIntegratedBackendSupported())
+ D.Diag(DiagID) << A->getAsString(Args) << Triple.getTriple();
+
+ return IBackend;
+}
+
bool ToolChain::useRelaxRelocations() const {
return ENABLE_X86_RELAX_RELOCATIONS;
}
@@ -153,6 +182,7 @@ static const DriverSuffix *FindDriverSuffix(StringRef ProgName, size_t &Pos) {
{"cl", "--driver-mode=cl"},
{"++", "--driver-mode=g++"},
{"flang", "--driver-mode=flang"},
+ {"clang-dxc", "--driver-mode=dxc"},
};
for (size_t i = 0; i < llvm::array_lengthof(DriverSuffixes); ++i) {
@@ -327,6 +357,12 @@ Tool *ToolChain::getOffloadWrapper() const {
return OffloadWrapper.get();
}
+Tool *ToolChain::getOffloadPackager() const {
+ if (!OffloadPackager)
+ OffloadPackager.reset(new tools::OffloadPackager(*this));
+ return OffloadPackager.get();
+}
+
Tool *ToolChain::getLinkerWrapper() const {
if (!LinkerWrapper)
LinkerWrapper.reset(new tools::LinkerWrapper(*this, getLink()));
@@ -359,6 +395,7 @@ Tool *ToolChain::getTool(Action::ActionClass AC) const {
case Action::PrecompileJobClass:
case Action::HeaderModulePrecompileJobClass:
case Action::PreprocessJobClass:
+ case Action::ExtractAPIJobClass:
case Action::AnalyzeJobClass:
case Action::MigrateJobClass:
case Action::VerifyPCHJobClass:
@@ -371,6 +408,8 @@ Tool *ToolChain::getTool(Action::ActionClass AC) const {
case Action::OffloadWrapperJobClass:
return getOffloadWrapper();
+ case Action::OffloadPackagerJobClass:
+ return getOffloadPackager();
case Action::LinkerWrapperJobClass:
return getLinkerWrapper();
}
@@ -903,6 +942,14 @@ void ToolChain::addExternCSystemIncludeIfExists(const ArgList &DriverArgs,
}
}
+/*static*/ std::string ToolChain::concat(StringRef Path, const Twine &A,
+ const Twine &B, const Twine &C,
+ const Twine &D) {
+ SmallString<128> Result(Path);
+ llvm::sys::path::append(Result, llvm::sys::path::Style::posix, A, B, C, D);
+ return std::string(Result);
+}
+
std::string ToolChain::detectLibcxxVersion(StringRef IncludePath) const {
std::error_code EC;
int MaxVersion = 0;
@@ -1032,7 +1079,7 @@ SanitizerMask ToolChain::getSupportedSanitizers() const {
if (getTriple().getArch() == llvm::Triple::x86 ||
getTriple().getArch() == llvm::Triple::x86_64 ||
getTriple().getArch() == llvm::Triple::arm || getTriple().isWasm() ||
- getTriple().isAArch64())
+ getTriple().isAArch64() || getTriple().isRISCV())
Res |= SanitizerKind::CFIICall;
if (getTriple().getArch() == llvm::Triple::x86_64 ||
getTriple().isAArch64(64) || getTriple().isRISCV())
diff --git a/clang/lib/Driver/ToolChains/AIX.cpp b/clang/lib/Driver/ToolChains/AIX.cpp
index e4bbf498b9cd..878b84a77702 100644
--- a/clang/lib/Driver/ToolChains/AIX.cpp
+++ b/clang/lib/Driver/ToolChains/AIX.cpp
@@ -98,9 +98,10 @@ void aix::Linker::ConstructJob(Compilation &C, const JobAction &JA,
CmdArgs.push_back("-bnoentry");
}
- // Specify PGO linker option without LTO
- if (!D.isUsingLTO() &&
- (Args.hasFlag(options::OPT_fprofile_arcs, options::OPT_fno_profile_arcs,
+ // PGO instrumentation generates symbols belonging to special sections, and
+ // the linker needs to place all symbols in a particular section together in
+ // memory; the AIX linker does that under an option.
+ if (Args.hasFlag(options::OPT_fprofile_arcs, options::OPT_fno_profile_arcs,
false) ||
Args.hasFlag(options::OPT_fprofile_generate,
options::OPT_fno_profile_generate, false) ||
@@ -115,8 +116,8 @@ void aix::Linker::ConstructJob(Compilation &C, const JobAction &JA,
Args.hasFlag(options::OPT_fcs_profile_generate_EQ,
options::OPT_fno_profile_generate, false) ||
Args.hasArg(options::OPT_fcreate_profile) ||
- Args.hasArg(options::OPT_coverage)))
- CmdArgs.push_back("-bdbg:namedsects");
+ Args.hasArg(options::OPT_coverage))
+ CmdArgs.push_back("-bdbg:namedsects:ss");
// Specify linker output file.
assert((Output.isFilename() || Output.isNothing()) && "Invalid output.");
diff --git a/clang/lib/Driver/ToolChains/AMDGPU.cpp b/clang/lib/Driver/ToolChains/AMDGPU.cpp
index 43ce33750eba..8718ab53ac1a 100644
--- a/clang/lib/Driver/ToolChains/AMDGPU.cpp
+++ b/clang/lib/Driver/ToolChains/AMDGPU.cpp
@@ -91,6 +91,7 @@ void RocmInstallationDetector::scanLibDevicePath(llvm::StringRef Path) {
else if (FileName.endswith(Suffix))
BaseName = FileName.drop_back(Suffix.size());
+ const StringRef ABIVersionPrefix = "oclc_abi_version_";
if (BaseName == "ocml") {
OCML = FilePath;
} else if (BaseName == "ockl") {
@@ -121,6 +122,12 @@ void RocmInstallationDetector::scanLibDevicePath(llvm::StringRef Path) {
WavefrontSize64.On = FilePath;
} else if (BaseName == "oclc_wavefrontsize64_off") {
WavefrontSize64.Off = FilePath;
+ } else if (BaseName.startswith(ABIVersionPrefix)) {
+ unsigned ABIVersionNumber;
+ if (BaseName.drop_front(ABIVersionPrefix.size())
+ .getAsInteger(/*Redex=*/0, ABIVersionNumber))
+ continue;
+ ABIVersionMap[ABIVersionNumber] = FilePath.str();
} else {
// Process all bitcode filenames that look like
// ocl_isa_version_XXX.amdgcn.bc
@@ -510,7 +517,7 @@ void RocmInstallationDetector::AddHIPIncludeArgs(const ArgList &DriverArgs,
return;
}
- CC1Args.push_back("-internal-isystem");
+ CC1Args.push_back("-idirafter");
CC1Args.push_back(DriverArgs.MakeArgString(getIncludePath()));
if (UsesRuntimeWrapper)
CC1Args.append({"-include", "__clang_hip_runtime_wrapper.h"});
@@ -545,7 +552,7 @@ void amdgpu::getAMDGPUTargetFeatures(const Driver &D,
llvm::StringMap<bool> FeatureMap;
auto OptionalGpuArch = parseTargetID(Triple, TargetID, &FeatureMap);
if (OptionalGpuArch) {
- StringRef GpuArch = OptionalGpuArch.getValue();
+ StringRef GpuArch = *OptionalGpuArch;
// Iterate through all possible target ID features for the given GPU.
// If it is mapped to true, add +feature.
// If it is mapped to false, add -feature.
@@ -723,7 +730,7 @@ AMDGPUToolChain::getParsedTargetID(const llvm::opt::ArgList &DriverArgs) const {
if (!OptionalGpuArch)
return {TargetID.str(), None, None};
- return {TargetID.str(), OptionalGpuArch.getValue().str(), FeatureMap};
+ return {TargetID.str(), OptionalGpuArch->str(), FeatureMap};
}
void AMDGPUToolChain::checkTargetID(
@@ -731,7 +738,7 @@ void AMDGPUToolChain::checkTargetID(
auto PTID = getParsedTargetID(DriverArgs);
if (PTID.OptionalTargetID && !PTID.OptionalGPUArch) {
getDriver().Diag(clang::diag::err_drv_bad_target_id)
- << PTID.OptionalTargetID.getValue();
+ << *PTID.OptionalTargetID;
}
}
@@ -822,20 +829,16 @@ void ROCMToolChain::addClangTargetOptions(
if (DriverArgs.hasArg(options::OPT_nogpulib))
return;
- if (!RocmInstallation.hasDeviceLibrary()) {
- getDriver().Diag(diag::err_drv_no_rocm_device_lib) << 0;
- return;
- }
-
// Get the device name and canonicalize it
const StringRef GpuArch = getGPUArch(DriverArgs);
auto Kind = llvm::AMDGPU::parseArchAMDGCN(GpuArch);
const StringRef CanonArch = llvm::AMDGPU::getArchNameAMDGCN(Kind);
std::string LibDeviceFile = RocmInstallation.getLibDeviceFile(CanonArch);
- if (LibDeviceFile.empty()) {
- getDriver().Diag(diag::err_drv_no_rocm_device_lib) << 1 << GpuArch;
+ auto ABIVer = DeviceLibABIVersion::fromCodeObjectVersion(
+ getAMDGPUCodeObjectVersion(getDriver(), DriverArgs));
+ if (!RocmInstallation.checkCommonBitcodeLibs(CanonArch, LibDeviceFile,
+ ABIVer))
return;
- }
bool Wave64 = isWave64(DriverArgs, Kind);
@@ -858,20 +861,37 @@ void ROCMToolChain::addClangTargetOptions(
// Add the generic set of libraries.
BCLibs.append(RocmInstallation.getCommonBitcodeLibs(
DriverArgs, LibDeviceFile, Wave64, DAZ, FiniteOnly, UnsafeMathOpt,
- FastRelaxedMath, CorrectSqrt));
+ FastRelaxedMath, CorrectSqrt, ABIVer, false));
- llvm::for_each(BCLibs, [&](StringRef BCFile) {
+ for (StringRef BCFile : BCLibs) {
CC1Args.push_back("-mlink-builtin-bitcode");
CC1Args.push_back(DriverArgs.MakeArgString(BCFile));
- });
+ }
+}
+
+bool RocmInstallationDetector::checkCommonBitcodeLibs(
+ StringRef GPUArch, StringRef LibDeviceFile,
+ DeviceLibABIVersion ABIVer) const {
+ if (!hasDeviceLibrary()) {
+ D.Diag(diag::err_drv_no_rocm_device_lib) << 0;
+ return false;
+ }
+ if (LibDeviceFile.empty()) {
+ D.Diag(diag::err_drv_no_rocm_device_lib) << 1 << GPUArch;
+ return false;
+ }
+ if (ABIVer.requiresLibrary() && getABIVersionPath(ABIVer).empty()) {
+ D.Diag(diag::err_drv_no_rocm_device_lib) << 2 << ABIVer.toString();
+ return false;
+ }
+ return true;
}
llvm::SmallVector<std::string, 12>
RocmInstallationDetector::getCommonBitcodeLibs(
const llvm::opt::ArgList &DriverArgs, StringRef LibDeviceFile, bool Wave64,
bool DAZ, bool FiniteOnly, bool UnsafeMathOpt, bool FastRelaxedMath,
- bool CorrectSqrt) const {
-
+ bool CorrectSqrt, DeviceLibABIVersion ABIVer, bool isOpenMP = false) const {
llvm::SmallVector<std::string, 12> BCLibs;
auto AddBCLib = [&](StringRef BCFile) { BCLibs.push_back(BCFile.str()); };
@@ -884,6 +904,9 @@ RocmInstallationDetector::getCommonBitcodeLibs(
AddBCLib(getCorrectlyRoundedSqrtPath(CorrectSqrt));
AddBCLib(getWavefrontSize64Path(Wave64));
AddBCLib(LibDeviceFile);
+ auto ABIVerPath = getABIVersionPath(ABIVer);
+ if (!ABIVerPath.empty())
+ AddBCLib(ABIVerPath);
return BCLibs;
}
@@ -897,15 +920,17 @@ bool AMDGPUToolChain::shouldSkipArgument(const llvm::opt::Arg *A) const {
llvm::SmallVector<std::string, 12>
ROCMToolChain::getCommonDeviceLibNames(const llvm::opt::ArgList &DriverArgs,
- const std::string &GPUArch) const {
+ const std::string &GPUArch,
+ bool isOpenMP) const {
auto Kind = llvm::AMDGPU::parseArchAMDGCN(GPUArch);
const StringRef CanonArch = llvm::AMDGPU::getArchNameAMDGCN(Kind);
std::string LibDeviceFile = RocmInstallation.getLibDeviceFile(CanonArch);
- if (LibDeviceFile.empty()) {
- getDriver().Diag(diag::err_drv_no_rocm_device_lib) << 1 << GPUArch;
+ auto ABIVer = DeviceLibABIVersion::fromCodeObjectVersion(
+ getAMDGPUCodeObjectVersion(getDriver(), DriverArgs));
+ if (!RocmInstallation.checkCommonBitcodeLibs(CanonArch, LibDeviceFile,
+ ABIVer))
return {};
- }
// If --hip-device-lib is not set, add the default bitcode libraries.
// TODO: There are way too many flags that change this. Do we need to check
@@ -922,10 +947,10 @@ ROCMToolChain::getCommonDeviceLibNames(const llvm::opt::ArgList &DriverArgs,
options::OPT_fno_fast_math, false);
bool CorrectSqrt = DriverArgs.hasFlag(
options::OPT_fhip_fp32_correctly_rounded_divide_sqrt,
- options::OPT_fno_hip_fp32_correctly_rounded_divide_sqrt);
+ options::OPT_fno_hip_fp32_correctly_rounded_divide_sqrt, true);
bool Wave64 = isWave64(DriverArgs, Kind);
return RocmInstallation.getCommonBitcodeLibs(
DriverArgs, LibDeviceFile, Wave64, DAZ, FiniteOnly, UnsafeMathOpt,
- FastRelaxedMath, CorrectSqrt);
+ FastRelaxedMath, CorrectSqrt, ABIVer, isOpenMP);
}
diff --git a/clang/lib/Driver/ToolChains/AMDGPU.h b/clang/lib/Driver/ToolChains/AMDGPU.h
index 156bfd1fbdb2..ddcc124b25ba 100644
--- a/clang/lib/Driver/ToolChains/AMDGPU.h
+++ b/clang/lib/Driver/ToolChains/AMDGPU.h
@@ -142,7 +142,8 @@ public:
// Returns a list of device library names shared by different languages
llvm::SmallVector<std::string, 12>
getCommonDeviceLibNames(const llvm::opt::ArgList &DriverArgs,
- const std::string &GPUArch) const;
+ const std::string &GPUArch,
+ bool isOpenMP = false) const;
};
} // end namespace toolchains
diff --git a/clang/lib/Driver/ToolChains/AMDGPUOpenMP.cpp b/clang/lib/Driver/ToolChains/AMDGPUOpenMP.cpp
index d7cf41e4b660..efcd565b510b 100644
--- a/clang/lib/Driver/ToolChains/AMDGPUOpenMP.cpp
+++ b/clang/lib/Driver/ToolChains/AMDGPUOpenMP.cpp
@@ -125,9 +125,8 @@ const char *AMDGCN::OpenMPLinker::constructLLVMLinkCommand(
// the device-libs bitcode through that on the way to this llvm-link
SmallVector<std::string, 12> BCLibs =
AMDGPUOpenMPTC.getCommonDeviceLibNames(Args, SubArchName.str());
- llvm::for_each(BCLibs, [&](StringRef BCFile) {
+ for (StringRef BCFile : BCLibs)
CmdArgs.push_back(Args.MakeArgString(BCFile));
- });
}
}
@@ -289,15 +288,7 @@ void AMDGPUOpenMPToolChain::addClangTargetOptions(
if (getDriver().isUsingLTO(/* IsOffload */ true))
return;
- std::string BitcodeSuffix;
- if (DriverArgs.hasFlag(options::OPT_fopenmp_target_new_runtime,
- options::OPT_fno_openmp_target_new_runtime, true))
- BitcodeSuffix = "new-amdgpu-" + GPUArch;
- else
- BitcodeSuffix = "amdgcn-" + GPUArch;
-
- addOpenMPDeviceRTL(getDriver(), DriverArgs, CC1Args, BitcodeSuffix,
- getTriple());
+ addOpenMPDeviceRTL(getDriver(), DriverArgs, CC1Args, GPUArch, getTriple());
}
llvm::opt::DerivedArgList *AMDGPUOpenMPToolChain::TranslateArgs(
@@ -315,9 +306,10 @@ llvm::opt::DerivedArgList *AMDGPUOpenMPToolChain::TranslateArgs(
if (!llvm::is_contained(*DAL, A))
DAL->append(A);
- std::string Arch = DAL->getLastArgValue(options::OPT_march_EQ).str();
- if (Arch.empty()) {
- checkSystemForAMDGPU(Args, *this, Arch);
+ if (!DAL->hasArg(options::OPT_march_EQ)) {
+ std::string Arch = BoundArch.str();
+ if (BoundArch.empty())
+ checkSystemForAMDGPU(Args, *this, Arch);
DAL->AddJoinedArg(nullptr, Opts.getOption(options::OPT_march_EQ), Arch);
}
diff --git a/clang/lib/Driver/ToolChains/AVR.cpp b/clang/lib/Driver/ToolChains/AVR.cpp
index 2cf16cf9fdb4..1e866553d826 100644
--- a/clang/lib/Driver/ToolChains/AVR.cpp
+++ b/clang/lib/Driver/ToolChains/AVR.cpp
@@ -28,6 +28,7 @@ using namespace llvm::opt;
namespace {
+// NOTE: This list has been synchronized with gcc-avr 7.3.0 and avr-libc 2.0.0.
constexpr struct {
StringRef Name;
StringRef SubPath;
@@ -62,6 +63,7 @@ constexpr struct {
{"attiny261a", "avr25/tiny-stack", "avr25", 0x800060},
{"at86rf401", "avr25", "avr25", 0x800060},
{"ata5272", "avr25", "avr25", 0x800100},
+ {"ata6616c", "avr25", "avr25", 0x800100},
{"attiny4313", "avr25", "avr25", 0x800060},
{"attiny44", "avr25", "avr25", 0x800060},
{"attiny44a", "avr25", "avr25", 0x800060},
@@ -88,6 +90,8 @@ constexpr struct {
{"at90usb82", "avr35", "avr35", 0x800100},
{"at90usb162", "avr35", "avr35", 0x800100},
{"ata5505", "avr35", "avr35", 0x800100},
+ {"ata6617c", "avr35", "avr35", 0x800100},
+ {"ata664251", "avr35", "avr35", 0x800100},
{"atmega8u2", "avr35", "avr35", 0x800100},
{"atmega16u2", "avr35", "avr35", 0x800100},
{"atmega32u2", "avr35", "avr35", 0x800100},
@@ -97,6 +101,7 @@ constexpr struct {
{"atmega8a", "avr4", "avr4", 0x800060},
{"ata6285", "avr4", "avr4", 0x800100},
{"ata6286", "avr4", "avr4", 0x800100},
+ {"ata6612c", "avr4", "avr4", 0x800100},
{"atmega48", "avr4", "avr4", 0x800100},
{"atmega48a", "avr4", "avr4", 0x800100},
{"atmega48pa", "avr4", "avr4", 0x800100},
@@ -116,8 +121,17 @@ constexpr struct {
{"at90pwm3", "avr4", "avr4", 0x800100},
{"at90pwm3b", "avr4", "avr4", 0x800100},
{"at90pwm81", "avr4", "avr4", 0x800100},
+ {"ata5702m322", "avr5", "avr5", 0x800200},
+ {"ata5782", "avr5", "avr5", 0x800200},
{"ata5790", "avr5", "avr5", 0x800100},
+ {"ata5790n", "avr5", "avr5", 0x800100},
+ {"ata5791", "avr5", "avr5", 0x800100},
{"ata5795", "avr5", "avr5", 0x800100},
+ {"ata5831", "avr5", "avr5", 0x800200},
+ {"ata6613c", "avr5", "avr5", 0x800100},
+ {"ata6614q", "avr5", "avr5", 0x800100},
+ {"ata8210", "avr5", "avr5", 0x800200},
+ {"ata8510", "avr5", "avr5", 0x800200},
{"atmega16", "avr5", "avr5", 0x800060},
{"atmega16a", "avr5", "avr5", 0x800060},
{"atmega161", "avr5", "avr5", 0x800060},
@@ -145,6 +159,7 @@ constexpr struct {
{"atmega324a", "avr5", "avr5", 0x800100},
{"atmega324p", "avr5", "avr5", 0x800100},
{"atmega324pa", "avr5", "avr5", 0x800100},
+ {"atmega324pb", "avr5", "avr5", 0x800100},
{"atmega325", "avr5", "avr5", 0x800100},
{"atmega325a", "avr5", "avr5", 0x800100},
{"atmega325p", "avr5", "avr5", 0x800100},
@@ -155,6 +170,7 @@ constexpr struct {
{"atmega3250pa", "avr5", "avr5", 0x800100},
{"atmega328", "avr5", "avr5", 0x800100},
{"atmega328p", "avr5", "avr5", 0x800100},
+ {"atmega328pb", "avr5", "avr5", 0x800100},
{"atmega329", "avr5", "avr5", 0x800100},
{"atmega329a", "avr5", "avr5", 0x800100},
{"atmega329p", "avr5", "avr5", 0x800100},
@@ -192,6 +208,7 @@ constexpr struct {
{"atmega32hvb", "avr5", "avr5", 0x800100},
{"atmega32hvbrevb", "avr5", "avr5", 0x800100},
{"atmega64hve", "avr5", "avr5", 0x800100},
+ {"atmega64hve2", "avr5", "avr5", 0x800100},
{"at90can32", "avr5", "avr5", 0x800100},
{"at90can64", "avr5", "avr5", 0x800100},
{"at90pwm161", "avr5", "avr5", 0x800100},
@@ -232,17 +249,22 @@ constexpr struct {
{"attiny10", "avrtiny", "avrtiny", 0x800040},
{"attiny20", "avrtiny", "avrtiny", 0x800040},
{"attiny40", "avrtiny", "avrtiny", 0x800040},
+ {"attiny102", "avrtiny", "avrtiny", 0x800040},
+ {"attiny104", "avrtiny", "avrtiny", 0x800040},
{"atxmega16a4", "avrxmega2", "avrxmega2", 0x802000},
{"atxmega16a4u", "avrxmega2", "avrxmega2", 0x802000},
{"atxmega16c4", "avrxmega2", "avrxmega2", 0x802000},
{"atxmega16d4", "avrxmega2", "avrxmega2", 0x802000},
{"atxmega32a4", "avrxmega2", "avrxmega2", 0x802000},
{"atxmega32a4u", "avrxmega2", "avrxmega2", 0x802000},
+ {"atxmega32c3", "avrxmega2", "avrxmega2", 0x802000},
{"atxmega32c4", "avrxmega2", "avrxmega2", 0x802000},
+ {"atxmega32d3", "avrxmega2", "avrxmega2", 0x802000},
{"atxmega32d4", "avrxmega2", "avrxmega2", 0x802000},
{"atxmega32e5", "avrxmega2", "avrxmega2", 0x802000},
{"atxmega16e5", "avrxmega2", "avrxmega2", 0x802000},
{"atxmega8e5", "avrxmega2", "avrxmega2", 0x802000},
+ {"atxmega64a3", "avrxmega4", "avrxmega4", 0x802000},
{"atxmega64a3u", "avrxmega4", "avrxmega4", 0x802000},
{"atxmega64a4u", "avrxmega4", "avrxmega4", 0x802000},
{"atxmega64b1", "avrxmega4", "avrxmega4", 0x802000},
@@ -274,6 +296,42 @@ constexpr struct {
{"atxmega128a1", "avrxmega7", "avrxmega7", 0x802000},
{"atxmega128a1u", "avrxmega7", "avrxmega7", 0x802000},
{"atxmega128a4u", "avrxmega7", "avrxmega7", 0x802000},
+ {"attiny202", "avrxmega3/short-calls", "avrxmega3", 0x803F80},
+ {"attiny204", "avrxmega3/short-calls", "avrxmega3", 0x803F80},
+ {"attiny212", "avrxmega3/short-calls", "avrxmega3", 0x803F80},
+ {"attiny214", "avrxmega3/short-calls", "avrxmega3", 0x803F80},
+ {"attiny402", "avrxmega3/short-calls", "avrxmega3", 0x803F00},
+ {"attiny404", "avrxmega3/short-calls", "avrxmega3", 0x803F00},
+ {"attiny406", "avrxmega3/short-calls", "avrxmega3", 0x803F00},
+ {"attiny412", "avrxmega3/short-calls", "avrxmega3", 0x803F00},
+ {"attiny414", "avrxmega3/short-calls", "avrxmega3", 0x803F00},
+ {"attiny416", "avrxmega3/short-calls", "avrxmega3", 0x803F00},
+ {"attiny417", "avrxmega3/short-calls", "avrxmega3", 0x803F00},
+ {"attiny804", "avrxmega3/short-calls", "avrxmega3", 0x803E00},
+ {"attiny806", "avrxmega3/short-calls", "avrxmega3", 0x803E00},
+ {"attiny807", "avrxmega3/short-calls", "avrxmega3", 0x803E00},
+ {"attiny814", "avrxmega3/short-calls", "avrxmega3", 0x803E00},
+ {"attiny816", "avrxmega3/short-calls", "avrxmega3", 0x803E00},
+ {"attiny817", "avrxmega3/short-calls", "avrxmega3", 0x803E00},
+ {"atmega808", "avrxmega3/short-calls", "avrxmega3", 0x803C00},
+ {"atmega809", "avrxmega3/short-calls", "avrxmega3", 0x803C00},
+ {"atmega1608", "avrxmega3", "avrxmega3", 0x803800},
+ {"atmega1609", "avrxmega3", "avrxmega3", 0x803800},
+ {"atmega3208", "avrxmega3", "avrxmega3", 0x803000},
+ {"atmega3209", "avrxmega3", "avrxmega3", 0x803000},
+ {"atmega4808", "avrxmega3", "avrxmega3", 0x802800},
+ {"atmega4809", "avrxmega3", "avrxmega3", 0x802800},
+ {"attiny1604", "avrxmega3", "avrxmega3", 0x803C00},
+ {"attiny1606", "avrxmega3", "avrxmega3", 0x803C00},
+ {"attiny1607", "avrxmega3", "avrxmega3", 0x803C00},
+ {"attiny1614", "avrxmega3", "avrxmega3", 0x803800},
+ {"attiny1616", "avrxmega3", "avrxmega3", 0x803800},
+ {"attiny1617", "avrxmega3", "avrxmega3", 0x803800},
+ {"attiny1624", "avrxmega3", "avrxmega3", 0x803800},
+ {"attiny1626", "avrxmega3", "avrxmega3", 0x803800},
+ {"attiny1627", "avrxmega3", "avrxmega3", 0x803800},
+ {"attiny3216", "avrxmega3", "avrxmega3", 0x803800},
+ {"attiny3217", "avrxmega3", "avrxmega3", 0x803800},
};
std::string GetMCUSubPath(StringRef MCUName) {
@@ -308,49 +366,19 @@ const StringRef PossibleAVRLibcLocations[] = {
/// AVR Toolchain
AVRToolChain::AVRToolChain(const Driver &D, const llvm::Triple &Triple,
const ArgList &Args)
- : Generic_ELF(D, Triple, Args), LinkStdlib(false) {
+ : Generic_ELF(D, Triple, Args) {
GCCInstallation.init(Triple, Args);
+ std::string CPU = getCPUName(D, Args, Triple);
+ if (CPU.empty())
+ D.Diag(diag::warn_drv_avr_mcu_not_specified);
+
// Only add default libraries if the user hasn't explicitly opted out.
if (!Args.hasArg(options::OPT_nostdlib) &&
- !Args.hasArg(options::OPT_nodefaultlibs) &&
- !Args.hasArg(options::OPT_c /* does not apply when not linking */)) {
- std::string CPU = getCPUName(D, Args, Triple);
-
- if (CPU.empty()) {
- // We cannot link any standard libraries without an MCU specified.
- D.Diag(diag::warn_drv_avr_mcu_not_specified);
- } else {
- Optional<StringRef> FamilyName = GetMCUFamilyName(CPU);
- Optional<std::string> AVRLibcRoot = findAVRLibcInstallation();
-
- if (!FamilyName.hasValue()) {
- // We do not have an entry for this CPU in the family
- // mapping table yet.
- D.Diag(diag::warn_drv_avr_family_linking_stdlibs_not_implemented)
- << CPU;
- } else if (!GCCInstallation.isValid()) {
- // No avr-gcc found and so no runtime linked.
- D.Diag(diag::warn_drv_avr_gcc_not_found);
- } else if (!AVRLibcRoot.hasValue()) {
- // No avr-libc found and so no runtime linked.
- D.Diag(diag::warn_drv_avr_libc_not_found);
- } else { // We have enough information to link stdlibs
- std::string GCCRoot(GCCInstallation.getInstallPath());
- std::string GCCParentPath(GCCInstallation.getParentLibPath());
- std::string LibcRoot = AVRLibcRoot.getValue();
- std::string SubPath = GetMCUSubPath(CPU);
-
- getProgramPaths().push_back(GCCParentPath + "/../bin");
- getFilePaths().push_back(LibcRoot + std::string("/lib/") + SubPath);
- getFilePaths().push_back(GCCRoot + std::string("/") + SubPath);
-
- LinkStdlib = true;
- }
- }
-
- if (!LinkStdlib)
- D.Diag(diag::warn_drv_avr_stdlib_not_linked);
+ !Args.hasArg(options::OPT_nodefaultlibs) && GCCInstallation.isValid()) {
+ GCCInstallPath = GCCInstallation.getInstallPath();
+ std::string GCCParentPath(GCCInstallation.getParentLibPath());
+ getProgramPaths().push_back(GCCParentPath + "/../bin");
}
}
@@ -362,11 +390,11 @@ void AVRToolChain::AddClangSystemIncludeArgs(const ArgList &DriverArgs,
// Omit if there is no avr-libc installed.
Optional<std::string> AVRLibcRoot = findAVRLibcInstallation();
- if (!AVRLibcRoot.hasValue())
+ if (!AVRLibcRoot)
return;
// Add 'avr-libc/include' to clang system include paths if applicable.
- std::string AVRInc = AVRLibcRoot.getValue() + "/include";
+ std::string AVRInc = *AVRLibcRoot + "/include";
if (llvm::sys::fs::is_directory(AVRInc))
addSystemInclude(DriverArgs, CC1Args, AVRInc);
}
@@ -387,21 +415,27 @@ void AVRToolChain::addClangTargetOptions(
}
Tool *AVRToolChain::buildLinker() const {
- return new tools::AVR::Linker(getTriple(), *this, LinkStdlib);
+ return new tools::AVR::Linker(getTriple(), *this);
}
void AVR::Linker::ConstructJob(Compilation &C, const JobAction &JA,
const InputInfo &Output,
const InputInfoList &Inputs, const ArgList &Args,
const char *LinkingOutput) const {
+ const auto &TC = static_cast<const AVRToolChain &>(getToolChain());
const Driver &D = getToolChain().getDriver();
// Compute information about the target AVR.
std::string CPU = getCPUName(D, Args, getToolChain().getTriple());
llvm::Optional<StringRef> FamilyName = GetMCUFamilyName(CPU);
+ llvm::Optional<std::string> AVRLibcRoot = TC.findAVRLibcInstallation();
llvm::Optional<unsigned> SectionAddressData = GetMCUSectionAddressData(CPU);
- std::string Linker = getToolChain().GetProgramPath(getShortName());
+ // Compute the linker program path, and use GNU "avr-ld" as default.
+ const Arg *A = Args.getLastArg(options::OPT_fuse_ld_EQ);
+ std::string Linker = A ? getToolChain().GetLinkerPath(nullptr)
+ : getToolChain().GetProgramPath(getShortName());
+
ArgStringList CmdArgs;
AddLinkerInputs(getToolChain(), Inputs, Args, CmdArgs, JA);
@@ -415,7 +449,33 @@ void AVR::Linker::ConstructJob(Compilation &C, const JobAction &JA,
Args.AddAllArgs(CmdArgs, options::OPT_L);
getToolChain().AddFilePathLibArgs(Args, CmdArgs);
- if (SectionAddressData.hasValue()) {
+ // Only add default libraries if the user hasn't explicitly opted out.
+ bool LinkStdlib = false;
+ if (!Args.hasArg(options::OPT_nostdlib) &&
+ !Args.hasArg(options::OPT_nodefaultlibs)) {
+ if (!CPU.empty()) {
+ if (!FamilyName) {
+ // We do not have an entry for this CPU in the family
+ // mapping table yet.
+ D.Diag(diag::warn_drv_avr_family_linking_stdlibs_not_implemented)
+ << CPU;
+ } else if (!AVRLibcRoot) {
+ // No avr-libc found and so no runtime linked.
+ D.Diag(diag::warn_drv_avr_libc_not_found);
+ } else {
+ std::string SubPath = GetMCUSubPath(CPU);
+ CmdArgs.push_back(
+ Args.MakeArgString(Twine("-L") + *AVRLibcRoot + "/lib/" + SubPath));
+ CmdArgs.push_back(
+ Args.MakeArgString("-L" + TC.getGCCInstallPath() + "/" + SubPath));
+ LinkStdlib = true;
+ }
+ }
+ if (!LinkStdlib)
+ D.Diag(diag::warn_drv_avr_stdlib_not_linked);
+ }
+
+ if (SectionAddressData) {
std::string DataSectionArg = std::string("-Tdata=0x") +
llvm::utohexstr(SectionAddressData.getValue());
CmdArgs.push_back(Args.MakeArgString(DataSectionArg));
@@ -445,11 +505,15 @@ void AVR::Linker::ConstructJob(Compilation &C, const JobAction &JA,
CmdArgs.push_back("--end-group");
+ // Add user specified linker script.
+ Args.AddAllArgs(CmdArgs, options::OPT_T);
+
// Specify the family name as the emulation mode to use.
// This is almost always required because otherwise avr-ld
// will assume 'avr2' and warn about the program being larger
// than the bare minimum supports.
- CmdArgs.push_back(Args.MakeArgString(std::string("-m") + *FamilyName));
+ if (Linker.find("avr-ld") != std::string::npos)
+ CmdArgs.push_back(Args.MakeArgString(std::string("-m") + *FamilyName));
}
C.addCommand(std::make_unique<Command>(
diff --git a/clang/lib/Driver/ToolChains/AVR.h b/clang/lib/Driver/ToolChains/AVR.h
index 2d027957ed76..ab147d852ad7 100644
--- a/clang/lib/Driver/ToolChains/AVR.h
+++ b/clang/lib/Driver/ToolChains/AVR.h
@@ -31,17 +31,14 @@ public:
llvm::opt::ArgStringList &CC1Args,
Action::OffloadKind DeviceOffloadKind) const override;
+ llvm::Optional<std::string> findAVRLibcInstallation() const;
+ StringRef getGCCInstallPath() const { return GCCInstallPath; }
+
protected:
Tool *buildLinker() const override;
private:
- /// Whether libgcc, libct, and friends should be linked.
- ///
- /// This is not done if the user does not specify a
- /// microcontroller on the command line.
- bool LinkStdlib;
-
- llvm::Optional<std::string> findAVRLibcInstallation() const;
+ StringRef GCCInstallPath;
};
} // end namespace toolchains
@@ -50,9 +47,8 @@ namespace tools {
namespace AVR {
class LLVM_LIBRARY_VISIBILITY Linker : public Tool {
public:
- Linker(const llvm::Triple &Triple, const ToolChain &TC, bool LinkStdlib)
- : Tool("AVR::Linker", "avr-ld", TC), Triple(Triple),
- LinkStdlib(LinkStdlib) {}
+ Linker(const llvm::Triple &Triple, const ToolChain &TC)
+ : Tool("AVR::Linker", "avr-ld", TC), Triple(Triple) {}
bool hasIntegratedCPP() const override { return false; }
bool isLinkJob() const override { return true; }
@@ -63,7 +59,6 @@ public:
protected:
const llvm::Triple &Triple;
- bool LinkStdlib;
};
} // end namespace AVR
} // end namespace tools
diff --git a/clang/lib/Driver/ToolChains/Ananas.cpp b/clang/lib/Driver/ToolChains/Ananas.cpp
index be1476a7636c..40f9e56b38e9 100644
--- a/clang/lib/Driver/ToolChains/Ananas.cpp
+++ b/clang/lib/Driver/ToolChains/Ananas.cpp
@@ -85,7 +85,8 @@ void ananas::Linker::ConstructJob(Compilation &C, const JobAction &JA,
assert(Output.isNothing() && "Invalid output.");
}
- if (!Args.hasArg(options::OPT_nostdlib, options::OPT_nostartfiles)) {
+ if (!Args.hasArg(options::OPT_nostdlib, options::OPT_nostartfiles,
+ options::OPT_r)) {
if (!Args.hasArg(options::OPT_shared)) {
CmdArgs.push_back(Args.MakeArgString(ToolChain.GetFilePath("crt0.o")));
}
@@ -111,12 +112,15 @@ void ananas::Linker::ConstructJob(Compilation &C, const JobAction &JA,
AddLinkerInputs(ToolChain, Inputs, Args, CmdArgs, JA);
- if (ToolChain.ShouldLinkCXXStdlib(Args))
- ToolChain.AddCXXStdlibLibArgs(Args, CmdArgs);
- if (!Args.hasArg(options::OPT_nostdlib, options::OPT_nodefaultlibs))
+ if (!Args.hasArg(options::OPT_nostdlib, options::OPT_nodefaultlibs,
+ options::OPT_r)) {
+ if (ToolChain.ShouldLinkCXXStdlib(Args))
+ ToolChain.AddCXXStdlibLibArgs(Args, CmdArgs);
CmdArgs.push_back("-lc");
+ }
- if (!Args.hasArg(options::OPT_nostdlib, options::OPT_nostartfiles)) {
+ if (!Args.hasArg(options::OPT_nostdlib, options::OPT_nostartfiles,
+ options::OPT_r)) {
if (Args.hasArg(options::OPT_shared) || Args.hasArg(options::OPT_pie))
CmdArgs.push_back(Args.MakeArgString(ToolChain.GetFilePath("crtendS.o")));
else
diff --git a/clang/lib/Driver/ToolChains/Arch/AArch64.cpp b/clang/lib/Driver/ToolChains/Arch/AArch64.cpp
index ca0ca4bf4eea..cf7e201b4972 100644
--- a/clang/lib/Driver/ToolChains/Arch/AArch64.cpp
+++ b/clang/lib/Driver/ToolChains/Arch/AArch64.cpp
@@ -151,6 +151,8 @@ getAArch64ArchFeaturesFromMarch(const Driver &D, StringRef March,
std::pair<StringRef, StringRef> Split = StringRef(MarchLowerCase).split("+");
llvm::AArch64::ArchKind ArchKind = llvm::AArch64::parseArch(Split.first);
+ if (Split.first == "native")
+ ArchKind = llvm::AArch64::getCPUArchKind(llvm::sys::getHostCPUName().str());
if (ArchKind == llvm::AArch64::ArchKind::INVALID ||
!llvm::AArch64::getArchFeatures(ArchKind, Features))
return false;
@@ -222,7 +224,6 @@ getAArch64MicroArchFeaturesFromMcpu(const Driver &D, StringRef Mcpu,
void aarch64::getAArch64TargetFeatures(const Driver &D,
const llvm::Triple &Triple,
const ArgList &Args,
- llvm::opt::ArgStringList &CmdArgs,
std::vector<StringRef> &Features,
bool ForAS) {
Arg *A;
@@ -264,13 +265,13 @@ void aarch64::getAArch64TargetFeatures(const Driver &D,
D, getAArch64TargetCPU(Args, Triple, A), Args, Features);
if (!success) {
- auto Diag = D.Diag(diag::err_drv_clang_unsupported);
+ auto Diag = D.Diag(diag::err_drv_unsupported_option_argument);
// If "-Wa,-march=" is used, 'WaMArch' will contain the argument's value,
// while 'A' is uninitialized. Only dereference 'A' in the other case.
if (!WaMArch.empty())
- Diag << "-march=" + WaMArch.str();
+ Diag << "march=" << WaMArch;
else
- Diag << A->getAsString(Args);
+ Diag << A->getOption().getName() << A->getValue();
}
if (Args.getLastArg(options::OPT_mgeneral_regs_only)) {
@@ -323,8 +324,8 @@ void aarch64::getAArch64TargetFeatures(const Driver &D,
DisableComdat = true;
continue;
}
- D.Diag(diag::err_invalid_sls_hardening)
- << Scope << A->getAsString(Args);
+ D.Diag(diag::err_drv_unsupported_option_argument)
+ << A->getOption().getName() << Scope;
break;
}
}
@@ -346,28 +347,85 @@ void aarch64::getAArch64TargetFeatures(const Driver &D,
Features.push_back("-crc");
}
+ int V8Version = -1;
+ int V9Version = -1;
+ bool HasNoSM4 = false;
+ bool HasNoSHA3 = false;
+ bool HasNoSHA2 = false;
+ bool HasNoAES = false;
+ bool HasSM4 = false;
+ bool HasSHA3 = false;
+ bool HasSHA2 = false;
+ bool HasAES = false;
+ bool HasCrypto = false;
+ bool HasNoCrypto = false;
+ int FullFP16Pos = -1;
+ int NoFullFP16Pos = -1;
+ int FP16FMLPos = -1;
+ int NoFP16FMLPos = -1;
+ int ArchFeatPos = -1;
+
+ for (auto I = Features.begin(), E = Features.end(); I != E; I++) {
+ if (*I == "+v8a") V8Version = 0;
+ else if (*I == "+v8.1a") V8Version = 1;
+ else if (*I == "+v8.2a") V8Version = 2;
+ else if (*I == "+v8.3a") V8Version = 3;
+ else if (*I == "+v8.4a") V8Version = 4;
+ else if (*I == "+v8.5a") V8Version = 5;
+ else if (*I == "+v8.6a") V8Version = 6;
+ else if (*I == "+v8.7a") V8Version = 7;
+ else if (*I == "+v8.8a") V8Version = 8;
+ else if (*I == "+v8.9a") V8Version = 9;
+ else if (*I == "+v9a") V9Version = 0;
+ else if (*I == "+v9.1a") V9Version = 1;
+ else if (*I == "+v9.2a") V9Version = 2;
+ else if (*I == "+v9.3a") V9Version = 3;
+ else if (*I == "+v9.4a") V9Version = 4;
+ else if (*I == "+sm4") HasSM4 = true;
+ else if (*I == "+sha3") HasSHA3 = true;
+ else if (*I == "+sha2") HasSHA2 = true;
+ else if (*I == "+aes") HasAES = true;
+ else if (*I == "-sm4") HasNoSM4 = true;
+ else if (*I == "-sha3") HasNoSHA3 = true;
+ else if (*I == "-sha2") HasNoSHA2 = true;
+ else if (*I == "-aes") HasNoAES = true;
+ else if (*I == "+fp16fml") FP16FMLPos = I - Features.begin();
+ else if (*I == "-fp16fml") NoFP16FMLPos = I - Features.begin();
+ else if (*I == "-fullfp16") NoFullFP16Pos = I - Features.begin();
+ else if (*I == "+fullfp16") FullFP16Pos = I - Features.begin();
+ // Whichever option comes after (right-most option) will win
+ else if (*I == "+crypto") {
+ HasCrypto = true;
+ HasNoCrypto = false;
+ } else if (*I == "-crypto") {
+ HasCrypto = false;
+ HasNoCrypto = true;
+ }
+ // Register the iterator position if this is an architecture feature
+ if (ArchFeatPos == -1 && (V8Version != -1 || V9Version != -1))
+ ArchFeatPos = I - Features.begin();
+ }
+
// Handle (arch-dependent) fp16fml/fullfp16 relationship.
// FIXME: this fp16fml option handling will be reimplemented after the
// TargetParser rewrite.
- const auto ItRNoFullFP16 = std::find(Features.rbegin(), Features.rend(), "-fullfp16");
- const auto ItRFP16FML = std::find(Features.rbegin(), Features.rend(), "+fp16fml");
- if (llvm::is_contained(Features, "+v8.4a")) {
- const auto ItRFullFP16 = std::find(Features.rbegin(), Features.rend(), "+fullfp16");
- if (ItRFullFP16 < ItRNoFullFP16 && ItRFullFP16 < ItRFP16FML) {
+ if (V8Version >= 4) {
+ // "-fullfp16" "+fullfp16" && "+fp16fml" "+fullfp16" && no "+fullfp16" "-fp16fml" = "+fp16fml"
+ if (FullFP16Pos > NoFullFP16Pos && FullFP16Pos > FP16FMLPos && FullFP16Pos > NoFP16FMLPos)
// Only entangled feature that can be to the right of this +fullfp16 is -fp16fml.
// Only append the +fp16fml if there is no -fp16fml after the +fullfp16.
- if (std::find(Features.rbegin(), ItRFullFP16, "-fp16fml") == ItRFullFP16)
- Features.push_back("+fp16fml");
- }
+ Features.push_back("+fp16fml");
else
goto fp16_fml_fallthrough;
} else {
fp16_fml_fallthrough:
// In both of these cases, putting the 'other' feature on the end of the vector will
// result in the same effect as placing it immediately after the current feature.
- if (ItRNoFullFP16 < ItRFP16FML)
+ // "+fp16fml" "-fullfp16" = "-fp16fml"
+ if (NoFullFP16Pos > FP16FMLPos)
Features.push_back("-fp16fml");
- else if (ItRNoFullFP16 > ItRFP16FML)
+ // "-fullfp16" "+fp16fml" = "+fullfp16"
+ else if (NoFullFP16Pos < FP16FMLPos)
Features.push_back("+fullfp16");
}
@@ -376,53 +434,23 @@ fp16_fml_fallthrough:
// Context sensitive meaning of Crypto:
// 1) For Arch >= ARMv8.4a: crypto = sm4 + sha3 + sha2 + aes
// 2) For Arch <= ARMv8.3a: crypto = sha2 + aes
- const auto ItBegin = Features.begin();
- const auto ItEnd = Features.end();
- const auto ItRBegin = Features.rbegin();
- const auto ItREnd = Features.rend();
- const auto ItRCrypto = std::find(ItRBegin, ItREnd, "+crypto");
- const auto ItRNoCrypto = std::find(ItRBegin, ItREnd, "-crypto");
- const auto HasCrypto = ItRCrypto != ItREnd;
- const auto HasNoCrypto = ItRNoCrypto != ItREnd;
- const ptrdiff_t PosCrypto = ItRCrypto - ItRBegin;
- const ptrdiff_t PosNoCrypto = ItRNoCrypto - ItRBegin;
-
- bool NoCrypto = false;
- if (HasCrypto && HasNoCrypto) {
- if (PosNoCrypto < PosCrypto)
- NoCrypto = true;
- }
-
- if (std::find(ItBegin, ItEnd, "+v8.4a") != ItEnd ||
- std::find(ItBegin, ItEnd, "+v8.8a") != ItEnd ||
- std::find(ItBegin, ItEnd, "+v9a") != ItEnd ||
- std::find(ItBegin, ItEnd, "+v9.1a") != ItEnd ||
- std::find(ItBegin, ItEnd, "+v9.2a") != ItEnd ||
- std::find(ItBegin, ItEnd, "+v9.3a") != ItEnd) {
- if (HasCrypto && !NoCrypto) {
+ if (V8Version >= 4 || V9Version >= 0) {
+ if (HasCrypto && !HasNoCrypto) {
// Check if we have NOT disabled an algorithm with something like:
// +crypto, -algorithm
// And if "-algorithm" does not occur, we enable that crypto algorithm.
- const bool HasSM4 = (std::find(ItBegin, ItEnd, "-sm4") == ItEnd);
- const bool HasSHA3 = (std::find(ItBegin, ItEnd, "-sha3") == ItEnd);
- const bool HasSHA2 = (std::find(ItBegin, ItEnd, "-sha2") == ItEnd);
- const bool HasAES = (std::find(ItBegin, ItEnd, "-aes") == ItEnd);
- if (HasSM4)
+ if (!HasNoSM4)
Features.push_back("+sm4");
- if (HasSHA3)
+ if (!HasNoSHA3)
Features.push_back("+sha3");
- if (HasSHA2)
+ if (!HasNoSHA2)
Features.push_back("+sha2");
- if (HasAES)
+ if (!HasNoAES)
Features.push_back("+aes");
} else if (HasNoCrypto) {
// Check if we have NOT enabled a crypto algorithm with something like:
// -crypto, +algorithm
// And if "+algorithm" does not occur, we disable that crypto algorithm.
- const bool HasSM4 = (std::find(ItBegin, ItEnd, "+sm4") != ItEnd);
- const bool HasSHA3 = (std::find(ItBegin, ItEnd, "+sha3") != ItEnd);
- const bool HasSHA2 = (std::find(ItBegin, ItEnd, "+sha2") != ItEnd);
- const bool HasAES = (std::find(ItBegin, ItEnd, "+aes") != ItEnd);
if (!HasSM4)
Features.push_back("-sm4");
if (!HasSHA3)
@@ -433,49 +461,41 @@ fp16_fml_fallthrough:
Features.push_back("-aes");
}
} else {
- if (HasCrypto && !NoCrypto) {
- const bool HasSHA2 = (std::find(ItBegin, ItEnd, "-sha2") == ItEnd);
- const bool HasAES = (std::find(ItBegin, ItEnd, "-aes") == ItEnd);
- if (HasSHA2)
+ if (HasCrypto && !HasNoCrypto) {
+ if (!HasNoSHA2)
Features.push_back("+sha2");
- if (HasAES)
+ if (!HasNoAES)
Features.push_back("+aes");
} else if (HasNoCrypto) {
- const bool HasSHA2 = (std::find(ItBegin, ItEnd, "+sha2") != ItEnd);
- const bool HasAES = (std::find(ItBegin, ItEnd, "+aes") != ItEnd);
- const bool HasV82a = (std::find(ItBegin, ItEnd, "+v8.2a") != ItEnd);
- const bool HasV83a = (std::find(ItBegin, ItEnd, "+v8.3a") != ItEnd);
- const bool HasV84a = (std::find(ItBegin, ItEnd, "+v8.4a") != ItEnd);
if (!HasSHA2)
Features.push_back("-sha2");
if (!HasAES)
Features.push_back("-aes");
- if (HasV82a || HasV83a || HasV84a) {
+ if (V8Version == 2 || V8Version == 3) {
Features.push_back("-sm4");
Features.push_back("-sha3");
}
}
}
- const char *Archs[] = {"+v8.6a", "+v8.7a", "+v8.8a",
- "+v9.1a", "+v9.2a", "+v9.3a"};
- auto Pos = std::find_first_of(Features.begin(), Features.end(),
- std::begin(Archs), std::end(Archs));
- if (Pos != std::end(Features))
- Pos = Features.insert(std::next(Pos), {"+i8mm", "+bf16"});
+ // FIXME: these insertions should ideally be automated using default
+ // extensions support from the backend target parser.
+ if (V8Version >= 6 || V9Version >= 1)
+ Features.insert(std::next(Features.begin() + ArchFeatPos),
+ {"+i8mm", "+bf16"});
+
+ // For Armv8.8-a/Armv9.3-a or later, FEAT_HBC and FEAT_MOPS are enabled by
+ // default.
+ if (V8Version >= 8 || V9Version >= 3)
+ Features.insert(std::next(Features.begin() + ArchFeatPos),
+ {"+hbc", "+mops"});
if (Arg *A = Args.getLastArg(options::OPT_mno_unaligned_access,
options::OPT_munaligned_access)) {
- if (A->getOption().matches(options::OPT_mno_unaligned_access)) {
+ if (A->getOption().matches(options::OPT_mno_unaligned_access))
Features.push_back("+strict-align");
- if (!ForAS)
- CmdArgs.push_back("-Wunaligned-access");
- }
- } else if (Triple.isOSOpenBSD()) {
+ } else if (Triple.isOSOpenBSD())
Features.push_back("+strict-align");
- if (!ForAS)
- CmdArgs.push_back("-Wunaligned-access");
- }
if (Args.hasArg(options::OPT_ffixed_x1))
Features.push_back("+reserve-x1");
@@ -592,4 +612,7 @@ fp16_fml_fallthrough:
// Enabled A53 errata (835769) workaround by default on android
Features.push_back("+fix-cortex-a53-835769");
}
+
+ if (Args.getLastArg(options::OPT_mno_bti_at_return_twice))
+ Features.push_back("+no-bti-at-return-twice");
}
diff --git a/clang/lib/Driver/ToolChains/Arch/AArch64.h b/clang/lib/Driver/ToolChains/Arch/AArch64.h
index 0cdc2ec725e0..d47c402d4a42 100644
--- a/clang/lib/Driver/ToolChains/Arch/AArch64.h
+++ b/clang/lib/Driver/ToolChains/Arch/AArch64.h
@@ -22,7 +22,6 @@ namespace aarch64 {
void getAArch64TargetFeatures(const Driver &D, const llvm::Triple &Triple,
const llvm::opt::ArgList &Args,
- llvm::opt::ArgStringList &CmdArgs,
std::vector<llvm::StringRef> &Features,
bool ForAS);
diff --git a/clang/lib/Driver/ToolChains/Arch/ARM.cpp b/clang/lib/Driver/ToolChains/Arch/ARM.cpp
index 16af9f6d7129..5c49db2f0837 100644
--- a/clang/lib/Driver/ToolChains/Arch/ARM.cpp
+++ b/clang/lib/Driver/ToolChains/Arch/ARM.cpp
@@ -121,7 +121,8 @@ static void checkARMArchName(const Driver &D, const Arg *A, const ArgList &Args,
if (ArchKind == llvm::ARM::ArchKind::INVALID ||
(Split.second.size() && !DecodeARMFeatures(D, Split.second, CPUName,
ArchKind, Features, ArgFPUID)))
- D.Diag(clang::diag::err_drv_clang_unsupported) << A->getAsString(Args);
+ D.Diag(clang::diag::err_drv_unsupported_option_argument)
+ << A->getOption().getName() << A->getValue();
}
// Check -mcpu=. Needs ArchName to handle -mcpu=generic.
@@ -137,7 +138,8 @@ static void checkARMCPUName(const Driver &D, const Arg *A, const ArgList &Args,
if (ArchKind == llvm::ARM::ArchKind::INVALID ||
(Split.second.size() &&
!DecodeARMFeatures(D, Split.second, CPU, ArchKind, Features, ArgFPUID)))
- D.Diag(clang::diag::err_drv_clang_unsupported) << A->getAsString(Args);
+ D.Diag(clang::diag::err_drv_unsupported_option_argument)
+ << A->getOption().getName() << A->getValue();
}
bool arm::useAAPCSForMachO(const llvm::Triple &T) {
@@ -320,6 +322,7 @@ arm::FloatABI arm::getDefaultFloatABI(const llvm::Triple &Triple) {
case llvm::Triple::MacOSX:
case llvm::Triple::IOS:
case llvm::Triple::TvOS:
+ case llvm::Triple::DriverKit:
// Darwin defaults to "softfp" for v6 and v7.
if (Triple.isWatchABI())
return FloatABI::Hard;
@@ -434,7 +437,7 @@ static bool hasIntegerMVE(const std::vector<StringRef> &F) {
}
void arm::getARMTargetFeatures(const Driver &D, const llvm::Triple &Triple,
- const ArgList &Args, ArgStringList &CmdArgs,
+ const ArgList &Args,
std::vector<StringRef> &Features, bool ForAS) {
bool KernelOrKext =
Args.hasArg(options::OPT_mkernel, options::OPT_fapple_kext);
@@ -717,6 +720,15 @@ fp16_fml_fallthrough:
}
}
+ // Propagate frame-chain model selection
+ if (Arg *A = Args.getLastArg(options::OPT_mframe_chain)) {
+ StringRef FrameChainOption = A->getValue();
+ if (FrameChainOption.startswith("aapcs"))
+ Features.push_back("+aapcs-frame-chain");
+ if (FrameChainOption == "aapcs+leaf")
+ Features.push_back("+aapcs-frame-chain-leaf");
+ }
+
// CMSE: Check for target 8M (for -mcmse to be applicable) is performed later.
if (Args.getLastArg(options::OPT_mcmse))
Features.push_back("+8msecext");
@@ -733,6 +745,16 @@ fp16_fml_fallthrough:
Features.push_back("-fix-cmse-cve-2021-35465");
}
+ // This also handles the -m(no-)fix-cortex-a72-1655431 arguments via aliases.
+ if (Arg *A = Args.getLastArg(options::OPT_mfix_cortex_a57_aes_1742098,
+ options::OPT_mno_fix_cortex_a57_aes_1742098)) {
+ if (A->getOption().matches(options::OPT_mfix_cortex_a57_aes_1742098)) {
+ Features.push_back("+fix-cortex-a57-aes-1742098");
+ } else {
+ Features.push_back("-fix-cortex-a57-aes-1742098");
+ }
+ }
+
// Look for the last occurrence of -mlong-calls or -mno-long-calls. If
// neither options are specified, see if we are compiling for kernel/kext and
// decide whether to pass "+long-calls" based on the OS and its version.
@@ -772,8 +794,6 @@ fp16_fml_fallthrough:
// Kernel code has more strict alignment requirements.
if (KernelOrKext) {
Features.push_back("+strict-align");
- if (!ForAS)
- CmdArgs.push_back("-Wunaligned-access");
} else if (Arg *A = Args.getLastArg(options::OPT_mno_unaligned_access,
options::OPT_munaligned_access)) {
if (A->getOption().matches(options::OPT_munaligned_access)) {
@@ -784,11 +804,8 @@ fp16_fml_fallthrough:
// access either.
else if (Triple.getSubArch() == llvm::Triple::SubArchType::ARMSubArch_v8m_baseline)
D.Diag(diag::err_target_unsupported_unaligned) << "v8m.base";
- } else {
+ } else
Features.push_back("+strict-align");
- if (!ForAS)
- CmdArgs.push_back("-Wunaligned-access");
- }
} else {
// Assume pre-ARMv6 doesn't support unaligned accesses.
//
@@ -807,23 +824,14 @@ fp16_fml_fallthrough:
int VersionNum = getARMSubArchVersionNumber(Triple);
if (Triple.isOSDarwin() || Triple.isOSNetBSD()) {
if (VersionNum < 6 ||
- Triple.getSubArch() == llvm::Triple::SubArchType::ARMSubArch_v6m) {
+ Triple.getSubArch() == llvm::Triple::SubArchType::ARMSubArch_v6m)
Features.push_back("+strict-align");
- if (!ForAS)
- CmdArgs.push_back("-Wunaligned-access");
- }
} else if (Triple.isOSLinux() || Triple.isOSNaCl() ||
Triple.isOSWindows()) {
- if (VersionNum < 7) {
+ if (VersionNum < 7)
Features.push_back("+strict-align");
- if (!ForAS)
- CmdArgs.push_back("-Wunaligned-access");
- }
- } else {
+ } else
Features.push_back("+strict-align");
- if (!ForAS)
- CmdArgs.push_back("-Wunaligned-access");
- }
}
// llvm does not support reserving registers in general. There is support
@@ -871,8 +879,8 @@ fp16_fml_fallthrough:
DisableComdat = true;
continue;
}
- D.Diag(diag::err_invalid_sls_hardening)
- << Scope << A->getAsString(Args);
+ D.Diag(diag::err_drv_unsupported_option_argument)
+ << A->getOption().getName() << Scope;
break;
}
}
diff --git a/clang/lib/Driver/ToolChains/Arch/ARM.h b/clang/lib/Driver/ToolChains/Arch/ARM.h
index 862a2f2796be..782bdf3d0202 100644
--- a/clang/lib/Driver/ToolChains/Arch/ARM.h
+++ b/clang/lib/Driver/ToolChains/Arch/ARM.h
@@ -66,7 +66,6 @@ void getARMArchCPUFromArgs(const llvm::opt::ArgList &Args,
bool FromAs = false);
void getARMTargetFeatures(const Driver &D, const llvm::Triple &Triple,
const llvm::opt::ArgList &Args,
- llvm::opt::ArgStringList &CmdArgs,
std::vector<llvm::StringRef> &Features, bool ForAS);
int getARMSubArchVersionNumber(const llvm::Triple &Triple);
bool isARMMProfile(const llvm::Triple &Triple);
diff --git a/clang/lib/Driver/ToolChains/Arch/CSKY.cpp b/clang/lib/Driver/ToolChains/Arch/CSKY.cpp
new file mode 100644
index 000000000000..3a8f92785609
--- /dev/null
+++ b/clang/lib/Driver/ToolChains/Arch/CSKY.cpp
@@ -0,0 +1,170 @@
+//===--- CSKY.cpp - CSKY Helpers for Tools --------------------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#include "CSKY.h"
+#include "ToolChains/CommonArgs.h"
+#include "clang/Basic/CharInfo.h"
+#include "clang/Driver/Driver.h"
+#include "clang/Driver/DriverDiagnostic.h"
+#include "clang/Driver/Options.h"
+#include "llvm/ADT/Optional.h"
+#include "llvm/ADT/StringSwitch.h"
+#include "llvm/Option/ArgList.h"
+#include "llvm/Support/CSKYTargetParser.h"
+#include "llvm/Support/Host.h"
+#include "llvm/Support/TargetParser.h"
+#include "llvm/Support/raw_ostream.h"
+
+using namespace clang::driver;
+using namespace clang::driver::tools;
+using namespace clang;
+using namespace llvm::opt;
+
+llvm::Optional<llvm::StringRef>
+csky::getCSKYArchName(const Driver &D, const ArgList &Args,
+ const llvm::Triple &Triple) {
+ if (const Arg *A = Args.getLastArg(options::OPT_march_EQ)) {
+ llvm::CSKY::ArchKind ArchKind = llvm::CSKY::parseArch(A->getValue());
+
+ if (ArchKind == llvm::CSKY::ArchKind::INVALID) {
+ D.Diag(clang::diag::err_drv_invalid_arch_name) << A->getAsString(Args);
+ return llvm::Optional<llvm::StringRef>();
+ }
+ return llvm::Optional<llvm::StringRef>(A->getValue());
+ }
+
+ if (const Arg *A = Args.getLastArg(clang::driver::options::OPT_mcpu_EQ)) {
+ llvm::CSKY::ArchKind ArchKind = llvm::CSKY::parseCPUArch(A->getValue());
+ if (ArchKind == llvm::CSKY::ArchKind::INVALID) {
+ D.Diag(clang::diag::err_drv_clang_unsupported) << A->getAsString(Args);
+ return llvm::Optional<llvm::StringRef>();
+ }
+ return llvm::Optional<llvm::StringRef>(llvm::CSKY::getArchName(ArchKind));
+ }
+
+ return llvm::Optional<llvm::StringRef>("ck810");
+}
+
+csky::FloatABI csky::getCSKYFloatABI(const Driver &D, const ArgList &Args) {
+ csky::FloatABI ABI = FloatABI::Soft;
+ if (Arg *A =
+ Args.getLastArg(options::OPT_msoft_float, options::OPT_mhard_float,
+ options::OPT_mfloat_abi_EQ)) {
+ if (A->getOption().matches(options::OPT_msoft_float)) {
+ ABI = FloatABI::Soft;
+ } else if (A->getOption().matches(options::OPT_mhard_float)) {
+ ABI = FloatABI::Hard;
+ } else {
+ ABI = llvm::StringSwitch<csky::FloatABI>(A->getValue())
+ .Case("soft", FloatABI::Soft)
+ .Case("softfp", FloatABI::SoftFP)
+ .Case("hard", FloatABI::Hard)
+ .Default(FloatABI::Invalid);
+ if (ABI == FloatABI::Invalid) {
+ D.Diag(diag::err_drv_invalid_mfloat_abi) << A->getAsString(Args);
+ ABI = FloatABI::Soft;
+ }
+ }
+ }
+
+ return ABI;
+}
+
+// Handle -mfpu=.
+static llvm::CSKY::CSKYFPUKind
+getCSKYFPUFeatures(const Driver &D, const Arg *A, const ArgList &Args,
+ StringRef FPU, std::vector<StringRef> &Features) {
+
+ llvm::CSKY::CSKYFPUKind FPUID =
+ llvm::StringSwitch<llvm::CSKY::CSKYFPUKind>(FPU)
+ .Case("auto", llvm::CSKY::FK_AUTO)
+ .Case("fpv2", llvm::CSKY::FK_FPV2)
+ .Case("fpv2_divd", llvm::CSKY::FK_FPV2_DIVD)
+ .Case("fpv2_sf", llvm::CSKY::FK_FPV2_SF)
+ .Case("fpv3", llvm::CSKY::FK_FPV3)
+ .Case("fpv3_hf", llvm::CSKY::FK_FPV3_HF)
+ .Case("fpv3_hsf", llvm::CSKY::FK_FPV3_HSF)
+ .Case("fpv3_sdf", llvm::CSKY::FK_FPV3_SDF)
+ .Default(llvm::CSKY::FK_INVALID);
+ if (FPUID == llvm::CSKY::FK_INVALID) {
+ D.Diag(clang::diag::err_drv_clang_unsupported) << A->getAsString(Args);
+ return llvm::CSKY::FK_INVALID;
+ }
+
+ auto RemoveTargetFPUFeature =
+ [&Features](ArrayRef<const char *> FPUFeatures) {
+ for (auto FPUFeature : FPUFeatures) {
+ auto it = std::find(Features.begin(), Features.end(), FPUFeature);
+ if (it != Features.end())
+ Features.erase(it);
+ }
+ };
+
+ RemoveTargetFPUFeature({"+fpuv2_sf", "+fpuv2_df", "+fdivdu", "+fpuv3_hi",
+ "+fpuv3_hf", "+fpuv3_sf", "+fpuv3_df"});
+
+ if (!llvm::CSKY::getFPUFeatures(FPUID, Features)) {
+ D.Diag(clang::diag::err_drv_clang_unsupported) << A->getAsString(Args);
+ return llvm::CSKY::FK_INVALID;
+ }
+
+ return FPUID;
+}
+
+void csky::getCSKYTargetFeatures(const Driver &D, const llvm::Triple &Triple,
+ const ArgList &Args, ArgStringList &CmdArgs,
+ std::vector<llvm::StringRef> &Features) {
+ llvm::StringRef archName;
+ llvm::StringRef cpuName;
+ llvm::CSKY::ArchKind ArchKind = llvm::CSKY::ArchKind::INVALID;
+ if (const Arg *A = Args.getLastArg(options::OPT_march_EQ)) {
+ ArchKind = llvm::CSKY::parseArch(A->getValue());
+ if (ArchKind == llvm::CSKY::ArchKind::INVALID) {
+ D.Diag(clang::diag::err_drv_invalid_arch_name) << A->getAsString(Args);
+ return;
+ }
+ archName = A->getValue();
+ }
+
+ if (const Arg *A = Args.getLastArg(clang::driver::options::OPT_mcpu_EQ)) {
+ llvm::CSKY::ArchKind Kind = llvm::CSKY::parseCPUArch(A->getValue());
+ if (Kind == llvm::CSKY::ArchKind::INVALID) {
+ D.Diag(clang::diag::err_drv_clang_unsupported) << A->getAsString(Args);
+ return;
+ }
+ if (!archName.empty() && Kind != ArchKind) {
+ D.Diag(clang::diag::err_drv_clang_unsupported) << A->getAsString(Args);
+ return;
+ }
+ cpuName = A->getValue();
+ if (archName.empty())
+ archName = llvm::CSKY::getArchName(Kind);
+ }
+
+ if (archName.empty() && cpuName.empty()) {
+ archName = "ck810";
+ cpuName = "ck810";
+ } else if (!archName.empty() && cpuName.empty()) {
+ cpuName = archName;
+ }
+
+ csky::FloatABI FloatABI = csky::getCSKYFloatABI(D, Args);
+
+ if (FloatABI == csky::FloatABI::Hard) {
+ Features.push_back("+hard-float-abi");
+ Features.push_back("+hard-float");
+ } else if (FloatABI == csky::FloatABI::SoftFP) {
+ Features.push_back("+hard-float");
+ }
+
+ uint64_t Extension = llvm::CSKY::getDefaultExtensions(cpuName);
+ llvm::CSKY::getExtensionFeatures(Extension, Features);
+
+ if (const Arg *FPUArg = Args.getLastArg(options::OPT_mfpu_EQ))
+ getCSKYFPUFeatures(D, FPUArg, Args, FPUArg->getValue(), Features);
+}
diff --git a/clang/lib/Driver/ToolChains/Arch/CSKY.h b/clang/lib/Driver/ToolChains/Arch/CSKY.h
new file mode 100644
index 000000000000..d23da1d66e35
--- /dev/null
+++ b/clang/lib/Driver/ToolChains/Arch/CSKY.h
@@ -0,0 +1,47 @@
+//===--- CSKY.h - CSKY-specific Tool Helpers ------------------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_LIB_DRIVER_TOOLCHAINS_ARCH_CSKY_H
+#define LLVM_CLANG_LIB_DRIVER_TOOLCHAINS_ARCH_CSKY_H
+
+#include "clang/Driver/Driver.h"
+#include "llvm/ADT/StringRef.h"
+#include "llvm/Option/ArgList.h"
+#include "llvm/Option/Option.h"
+#include <string>
+#include <vector>
+
+namespace clang {
+namespace driver {
+namespace tools {
+namespace csky {
+
+enum class FloatABI {
+ Invalid,
+ Soft,
+ SoftFP,
+ Hard,
+};
+
+FloatABI getCSKYFloatABI(const Driver &D, const llvm::opt::ArgList &Args);
+
+void getCSKYTargetFeatures(const Driver &D, const llvm::Triple &Triple,
+ const llvm::opt::ArgList &Args,
+ llvm::opt::ArgStringList &CmdArgs,
+ std::vector<llvm::StringRef> &Features);
+
+llvm::Optional<llvm::StringRef> getCSKYArchName(const Driver &D,
+ const llvm::opt::ArgList &Args,
+ const llvm::Triple &Triple);
+
+} // end namespace csky
+} // namespace tools
+} // end namespace driver
+} // end namespace clang
+
+#endif // LLVM_CLANG_LIB_DRIVER_TOOLCHAINS_ARCH_CSKY_H
diff --git a/clang/lib/Driver/ToolChains/Arch/RISCV.cpp b/clang/lib/Driver/ToolChains/Arch/RISCV.cpp
index 7ad8ca69bed5..8a8ed20986c5 100644
--- a/clang/lib/Driver/ToolChains/Arch/RISCV.cpp
+++ b/clang/lib/Driver/ToolChains/Arch/RISCV.cpp
@@ -198,7 +198,7 @@ StringRef riscv::getRISCVABI(const ArgList &Args, const llvm::Triple &Triple) {
// Ignore parsing error, just go 3rd step.
consumeError(ParseResult.takeError());
else
- return llvm::RISCV::computeDefaultABIFromArch(**ParseResult);
+ return (*ParseResult)->computeDefaultABI();
// 3. Choose a default based on the triple
//
diff --git a/clang/lib/Driver/ToolChains/Arch/VE.h b/clang/lib/Driver/ToolChains/Arch/VE.h
index 531433534914..c47a41df25bc 100644
--- a/clang/lib/Driver/ToolChains/Arch/VE.h
+++ b/clang/lib/Driver/ToolChains/Arch/VE.h
@@ -24,7 +24,7 @@ void getVETargetFeatures(const Driver &D, const llvm::opt::ArgList &Args,
std::vector<llvm::StringRef> &Features);
} // end namespace ve
-} // namespace tools
+} // end namespace tools
} // end namespace driver
} // end namespace clang
diff --git a/clang/lib/Driver/ToolChains/Arch/X86.cpp b/clang/lib/Driver/ToolChains/Arch/X86.cpp
index bfa008f964e1..cd7c014faa5e 100644
--- a/clang/lib/Driver/ToolChains/Arch/X86.cpp
+++ b/clang/lib/Driver/ToolChains/Arch/X86.cpp
@@ -84,13 +84,19 @@ std::string x86::getX86TargetCPU(const Driver &D, const ArgList &Args,
// Simulators can still run on 10.11 though, like Xcode.
if (Triple.isMacOSX() && !Triple.isOSVersionLT(10, 12))
return "penryn";
+
+ if (Triple.isDriverKit())
+ return "nehalem";
+
// The oldest x86_64 Macs have core2/Merom; the oldest x86 Macs have Yonah.
return Is64Bit ? "core2" : "yonah";
}
- // Set up default CPU name for PS4 compilers.
- if (Triple.isPS4CPU())
+ // Set up default CPU name for PS4/PS5 compilers.
+ if (Triple.isPS4())
return "btver2";
+ if (Triple.isPS5())
+ return "znver2";
// On Android use targets compatible with gcc
if (Triple.isAndroid())
@@ -240,4 +246,20 @@ void x86::getX86TargetFeatures(const Driver &D, const llvm::Triple &Triple,
Name = Name.substr(3);
Features.push_back(Args.MakeArgString((IsNegative ? "-" : "+") + Name));
}
+
+ // Enable/disable straight line speculation hardening.
+ if (Arg *A = Args.getLastArg(options::OPT_mharden_sls_EQ)) {
+ StringRef Scope = A->getValue();
+ if (Scope == "all") {
+ Features.push_back("+harden-sls-ijmp");
+ Features.push_back("+harden-sls-ret");
+ } else if (Scope == "return") {
+ Features.push_back("+harden-sls-ret");
+ } else if (Scope == "indirect-jmp") {
+ Features.push_back("+harden-sls-ijmp");
+ } else if (Scope != "none") {
+ D.Diag(diag::err_drv_unsupported_option_argument)
+ << A->getOption().getName() << Scope;
+ }
+ }
}
diff --git a/clang/lib/Driver/ToolChains/CSKYToolChain.cpp b/clang/lib/Driver/ToolChains/CSKYToolChain.cpp
new file mode 100644
index 000000000000..de286faaca6d
--- /dev/null
+++ b/clang/lib/Driver/ToolChains/CSKYToolChain.cpp
@@ -0,0 +1,204 @@
+//===--- CSKYToolchain.cpp - CSKY ToolChain Implementations ---*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#include "CSKYToolChain.h"
+#include "CommonArgs.h"
+#include "clang/Driver/Compilation.h"
+#include "clang/Driver/InputInfo.h"
+#include "clang/Driver/Options.h"
+#include "llvm/Option/ArgList.h"
+#include "llvm/Support/FileSystem.h"
+#include "llvm/Support/Path.h"
+#include "llvm/Support/raw_ostream.h"
+
+using namespace clang::driver;
+using namespace clang::driver::toolchains;
+using namespace clang::driver::tools;
+using namespace clang;
+using namespace llvm::opt;
+
+static void addMultilibsFilePaths(const Driver &D, const MultilibSet &Multilibs,
+ const Multilib &Multilib,
+ StringRef InstallPath,
+ ToolChain::path_list &Paths) {
+ if (const auto &PathsCallback = Multilibs.filePathsCallback())
+ for (const auto &Path : PathsCallback(Multilib))
+ addPathIfExists(D, InstallPath + Path, Paths);
+}
+
+/// CSKY Toolchain
+CSKYToolChain::CSKYToolChain(const Driver &D, const llvm::Triple &Triple,
+ const ArgList &Args)
+ : Generic_ELF(D, Triple, Args) {
+ GCCInstallation.init(Triple, Args);
+ if (GCCInstallation.isValid()) {
+ Multilibs = GCCInstallation.getMultilibs();
+ SelectedMultilib = GCCInstallation.getMultilib();
+ path_list &Paths = getFilePaths();
+ // Add toolchain/multilib specific file paths.
+ addMultilibsFilePaths(D, Multilibs, SelectedMultilib,
+ GCCInstallation.getInstallPath(), Paths);
+ getFilePaths().push_back(GCCInstallation.getInstallPath().str() +
+ SelectedMultilib.osSuffix());
+ ToolChain::path_list &PPaths = getProgramPaths();
+ // Multilib cross-compiler GCC installations put ld in a triple-prefixed
+ // directory off of the parent of the GCC installation.
+ PPaths.push_back(Twine(GCCInstallation.getParentLibPath() + "/../" +
+ GCCInstallation.getTriple().str() + "/bin")
+ .str());
+ PPaths.push_back((GCCInstallation.getParentLibPath() + "/../bin").str());
+ } else {
+ getProgramPaths().push_back(D.Dir);
+ }
+ getFilePaths().push_back(computeSysRoot() + "/lib" +
+ SelectedMultilib.osSuffix());
+}
+
+Tool *CSKYToolChain::buildLinker() const {
+ return new tools::CSKY::Linker(*this);
+}
+
+ToolChain::RuntimeLibType CSKYToolChain::GetDefaultRuntimeLibType() const {
+ return GCCInstallation.isValid() ? ToolChain::RLT_Libgcc
+ : ToolChain::RLT_CompilerRT;
+}
+
+ToolChain::UnwindLibType
+CSKYToolChain::GetUnwindLibType(const llvm::opt::ArgList &Args) const {
+ return ToolChain::UNW_None;
+}
+
+void CSKYToolChain::addClangTargetOptions(const llvm::opt::ArgList &DriverArgs,
+ llvm::opt::ArgStringList &CC1Args,
+ Action::OffloadKind) const {
+ CC1Args.push_back("-nostdsysteminc");
+}
+
+void CSKYToolChain::AddClangSystemIncludeArgs(const ArgList &DriverArgs,
+ ArgStringList &CC1Args) const {
+ if (DriverArgs.hasArg(options::OPT_nostdinc))
+ return;
+
+ if (!DriverArgs.hasArg(options::OPT_nostdlibinc)) {
+ SmallString<128> Dir(computeSysRoot());
+ llvm::sys::path::append(Dir, "include");
+ addSystemInclude(DriverArgs, CC1Args, Dir.str());
+ SmallString<128> Dir2(computeSysRoot());
+ llvm::sys::path::append(Dir2, "sys-include");
+ addSystemInclude(DriverArgs, CC1Args, Dir2.str());
+ }
+}
+
+void CSKYToolChain::addLibStdCxxIncludePaths(
+ const llvm::opt::ArgList &DriverArgs,
+ llvm::opt::ArgStringList &CC1Args) const {
+ const GCCVersion &Version = GCCInstallation.getVersion();
+ StringRef TripleStr = GCCInstallation.getTriple().str();
+ const Multilib &Multilib = GCCInstallation.getMultilib();
+ addLibStdCXXIncludePaths(computeSysRoot() + "/include/c++/" + Version.Text,
+ TripleStr, Multilib.includeSuffix(), DriverArgs,
+ CC1Args);
+}
+
+std::string CSKYToolChain::computeSysRoot() const {
+ if (!getDriver().SysRoot.empty())
+ return getDriver().SysRoot;
+
+ SmallString<128> SysRootDir;
+ if (GCCInstallation.isValid()) {
+ StringRef LibDir = GCCInstallation.getParentLibPath();
+ StringRef TripleStr = GCCInstallation.getTriple().str();
+ llvm::sys::path::append(SysRootDir, LibDir, "..", TripleStr);
+ } else {
+ // Use the triple as provided to the driver. Unlike the parsed triple
+ // this has not been normalized to always contain every field.
+ llvm::sys::path::append(SysRootDir, getDriver().Dir, "..",
+ getDriver().getTargetTriple());
+ }
+
+ if (!llvm::sys::fs::exists(SysRootDir))
+ return std::string();
+
+ return std::string(SysRootDir.str());
+}
+
+void CSKY::Linker::ConstructJob(Compilation &C, const JobAction &JA,
+ const InputInfo &Output,
+ const InputInfoList &Inputs,
+ const ArgList &Args,
+ const char *LinkingOutput) const {
+ const ToolChain &ToolChain = getToolChain();
+ const Driver &D = ToolChain.getDriver();
+ ArgStringList CmdArgs;
+
+ if (!D.SysRoot.empty())
+ CmdArgs.push_back(Args.MakeArgString("--sysroot=" + D.SysRoot));
+
+ CmdArgs.push_back("-m");
+ CmdArgs.push_back("cskyelf");
+
+ std::string Linker = getToolChain().GetLinkerPath();
+
+ bool WantCRTs =
+ !Args.hasArg(options::OPT_nostdlib, options::OPT_nostartfiles);
+
+ const char *crtbegin, *crtend;
+ auto RuntimeLib = ToolChain.GetRuntimeLibType(Args);
+ if (RuntimeLib == ToolChain::RLT_Libgcc) {
+ crtbegin = "crtbegin.o";
+ crtend = "crtend.o";
+ } else {
+ assert(RuntimeLib == ToolChain::RLT_CompilerRT);
+ crtbegin = ToolChain.getCompilerRTArgString(Args, "crtbegin",
+ ToolChain::FT_Object);
+ crtend =
+ ToolChain.getCompilerRTArgString(Args, "crtend", ToolChain::FT_Object);
+ }
+
+ if (WantCRTs) {
+ CmdArgs.push_back(Args.MakeArgString(ToolChain.GetFilePath("crt0.o")));
+ CmdArgs.push_back(Args.MakeArgString(ToolChain.GetFilePath("crti.o")));
+ CmdArgs.push_back(Args.MakeArgString(ToolChain.GetFilePath(crtbegin)));
+ }
+
+ Args.AddAllArgs(CmdArgs, options::OPT_L);
+ ToolChain.AddFilePathLibArgs(Args, CmdArgs);
+ Args.AddAllArgs(CmdArgs,
+ {options::OPT_T_Group, options::OPT_e, options::OPT_s,
+ options::OPT_t, options::OPT_Z_Flag, options::OPT_r});
+
+ AddLinkerInputs(ToolChain, Inputs, Args, CmdArgs, JA);
+
+ // TODO: add C++ includes and libs if compiling C++.
+
+ if (!Args.hasArg(options::OPT_nostdlib) &&
+ !Args.hasArg(options::OPT_nodefaultlibs)) {
+ if (ToolChain.ShouldLinkCXXStdlib(Args))
+ ToolChain.AddCXXStdlibLibArgs(Args, CmdArgs);
+ CmdArgs.push_back("--start-group");
+ CmdArgs.push_back("-lc");
+ if (Args.hasArg(options::OPT_msim))
+ CmdArgs.push_back("-lsemi");
+ else
+ CmdArgs.push_back("-lnosys");
+ CmdArgs.push_back("--end-group");
+ AddRunTimeLibs(ToolChain, ToolChain.getDriver(), CmdArgs, Args);
+ }
+
+ if (WantCRTs) {
+ CmdArgs.push_back(Args.MakeArgString(ToolChain.GetFilePath(crtend)));
+ CmdArgs.push_back(Args.MakeArgString(ToolChain.GetFilePath("crtn.o")));
+ }
+
+ CmdArgs.push_back("-o");
+ CmdArgs.push_back(Output.getFilename());
+ C.addCommand(std::make_unique<Command>(
+ JA, *this, ResponseFileSupport::AtFileCurCP(), Args.MakeArgString(Linker),
+ CmdArgs, Inputs, Output));
+}
+// CSKY tools end.
diff --git a/clang/lib/Driver/ToolChains/CSKYToolChain.h b/clang/lib/Driver/ToolChains/CSKYToolChain.h
new file mode 100644
index 000000000000..52b37539cc5f
--- /dev/null
+++ b/clang/lib/Driver/ToolChains/CSKYToolChain.h
@@ -0,0 +1,63 @@
+//===--- CSKYToolchain.h - CSKY ToolChain Implementations -----*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_LIB_DRIVER_TOOLCHAINS_CSKYTOOLCHAIN_H
+#define LLVM_CLANG_LIB_DRIVER_TOOLCHAINS_CSKYTOOLCHAIN_H
+
+#include "Gnu.h"
+#include "clang/Driver/ToolChain.h"
+
+namespace clang {
+namespace driver {
+namespace toolchains {
+
+class LLVM_LIBRARY_VISIBILITY CSKYToolChain : public Generic_ELF {
+public:
+ CSKYToolChain(const Driver &D, const llvm::Triple &Triple,
+ const llvm::opt::ArgList &Args);
+
+ void addClangTargetOptions(const llvm::opt::ArgList &DriverArgs,
+ llvm::opt::ArgStringList &CC1Args,
+ Action::OffloadKind) const override;
+ RuntimeLibType GetDefaultRuntimeLibType() const override;
+ UnwindLibType GetUnwindLibType(const llvm::opt::ArgList &Args) const override;
+ void
+ AddClangSystemIncludeArgs(const llvm::opt::ArgList &DriverArgs,
+ llvm::opt::ArgStringList &CC1Args) const override;
+ void
+ addLibStdCxxIncludePaths(const llvm::opt::ArgList &DriverArgs,
+ llvm::opt::ArgStringList &CC1Args) const override;
+
+protected:
+ Tool *buildLinker() const override;
+
+private:
+ std::string computeSysRoot() const override;
+};
+
+} // end namespace toolchains
+
+namespace tools {
+namespace CSKY {
+class LLVM_LIBRARY_VISIBILITY Linker : public Tool {
+public:
+ Linker(const ToolChain &TC) : Tool("CSKY::Linker", "ld", TC) {}
+ bool hasIntegratedCPP() const override { return false; }
+ bool isLinkJob() const override { return true; }
+ void ConstructJob(Compilation &C, const JobAction &JA,
+ const InputInfo &Output, const InputInfoList &Inputs,
+ const llvm::opt::ArgList &TCArgs,
+ const char *LinkingOutput) const override;
+};
+} // end namespace CSKY
+} // end namespace tools
+
+} // end namespace driver
+} // end namespace clang
+
+#endif // LLVM_CLANG_LIB_DRIVER_TOOLCHAINS_CSKYTOOLCHAIN_H
diff --git a/clang/lib/Driver/ToolChains/Clang.cpp b/clang/lib/Driver/ToolChains/Clang.cpp
index 7aac977209eb..c9bbdb2ac72e 100644
--- a/clang/lib/Driver/ToolChains/Clang.cpp
+++ b/clang/lib/Driver/ToolChains/Clang.cpp
@@ -10,6 +10,7 @@
#include "AMDGPU.h"
#include "Arch/AArch64.h"
#include "Arch/ARM.h"
+#include "Arch/CSKY.h"
#include "Arch/M68k.h"
#include "Arch/Mips.h"
#include "Arch/PPC.h"
@@ -28,6 +29,8 @@
#include "clang/Basic/LangOptions.h"
#include "clang/Basic/ObjCRuntime.h"
#include "clang/Basic/Version.h"
+#include "clang/Config/config.h"
+#include "clang/Driver/Action.h"
#include "clang/Driver/Distro.h"
#include "clang/Driver/DriverDiagnostic.h"
#include "clang/Driver/InputInfo.h"
@@ -35,6 +38,7 @@
#include "clang/Driver/SanitizerArgs.h"
#include "clang/Driver/Types.h"
#include "clang/Driver/XRayArgs.h"
+#include "llvm/ADT/SmallSet.h"
#include "llvm/ADT/StringExtras.h"
#include "llvm/Config/llvm-config.h"
#include "llvm/Option/ArgList.h"
@@ -223,12 +227,16 @@ static void ParseMRecip(const Driver &D, const ArgList &Args,
llvm::StringMap<bool> OptionStrings;
OptionStrings.insert(std::make_pair("divd", false));
OptionStrings.insert(std::make_pair("divf", false));
+ OptionStrings.insert(std::make_pair("divh", false));
OptionStrings.insert(std::make_pair("vec-divd", false));
OptionStrings.insert(std::make_pair("vec-divf", false));
+ OptionStrings.insert(std::make_pair("vec-divh", false));
OptionStrings.insert(std::make_pair("sqrtd", false));
OptionStrings.insert(std::make_pair("sqrtf", false));
+ OptionStrings.insert(std::make_pair("sqrth", false));
OptionStrings.insert(std::make_pair("vec-sqrtd", false));
OptionStrings.insert(std::make_pair("vec-sqrtf", false));
+ OptionStrings.insert(std::make_pair("vec-sqrth", false));
for (unsigned i = 0; i != NumOptions; ++i) {
StringRef Val = A->getValue(i);
@@ -252,10 +260,11 @@ static void ParseMRecip(const Driver &D, const ArgList &Args,
D.Diag(diag::err_drv_unknown_argument) << Val;
return;
}
- // The option was specified without a float or double suffix.
- // Make sure that the double entry was not already specified.
+ // The option was specified without a half or float or double suffix.
+ // Make sure that the double or half entry was not already specified.
// The float entry will be checked below.
- if (OptionStrings[ValBase.str() + 'd']) {
+ if (OptionStrings[ValBase.str() + 'd'] ||
+ OptionStrings[ValBase.str() + 'h']) {
D.Diag(diag::err_drv_invalid_value) << A->getOption().getName() << Val;
return;
}
@@ -270,9 +279,12 @@ static void ParseMRecip(const Driver &D, const ArgList &Args,
// Mark the matched option as found. Do not allow duplicate specifiers.
OptionIter->second = true;
- // If the precision was not specified, also mark the double entry as found.
- if (ValBase.back() != 'f' && ValBase.back() != 'd')
+ // If the precision was not specified, also mark the double and half entry
+ // as found.
+ if (ValBase.back() != 'f' && ValBase.back() != 'd' && ValBase.back() != 'h') {
OptionStrings[ValBase.str() + 'd'] = true;
+ OptionStrings[ValBase.str() + 'h'] = true;
+ }
// Build the output string.
StringRef Prefix = IsDisabled ? DisabledPrefixOut : EnabledPrefixOut;
@@ -328,7 +340,7 @@ static void getTargetFeatures(const Driver &D, const llvm::Triple &Triple,
case llvm::Triple::armeb:
case llvm::Triple::thumb:
case llvm::Triple::thumbeb:
- arm::getARMTargetFeatures(D, Triple, Args, CmdArgs, Features, ForAS);
+ arm::getARMTargetFeatures(D, Triple, Args, Features, ForAS);
break;
case llvm::Triple::ppc:
@@ -347,8 +359,7 @@ static void getTargetFeatures(const Driver &D, const llvm::Triple &Triple,
case llvm::Triple::aarch64:
case llvm::Triple::aarch64_32:
case llvm::Triple::aarch64_be:
- aarch64::getAArch64TargetFeatures(D, Triple, Args, CmdArgs, Features,
- ForAS);
+ aarch64::getAArch64TargetFeatures(D, Triple, Args, Features, ForAS);
break;
case llvm::Triple::x86:
case llvm::Triple::x86_64:
@@ -370,6 +381,10 @@ static void getTargetFeatures(const Driver &D, const llvm::Triple &Triple,
case llvm::Triple::amdgcn:
amdgpu::getAMDGPUTargetFeatures(D, Triple, Args, Features);
break;
+ case llvm::Triple::nvptx:
+ case llvm::Triple::nvptx64:
+ NVPTX::getNVPTXTargetFeatures(D, Triple, Args, Features);
+ break;
case llvm::Triple::m68k:
m68k::getM68kTargetFeatures(D, Triple, Args, Features);
break;
@@ -379,6 +394,9 @@ static void getTargetFeatures(const Driver &D, const llvm::Triple &Triple,
case llvm::Triple::ve:
ve::getVETargetFeatures(D, Args, Features);
break;
+ case llvm::Triple::csky:
+ csky::getCSKYTargetFeatures(D, Triple, Args, CmdArgs, Features);
+ break;
}
for (auto Feature : unifyTargetFeatures(Features)) {
@@ -450,9 +468,9 @@ static bool addExceptionArgs(const ArgList &Args, types::ID InputType,
}
if (types::isCXX(InputType)) {
- // Disable C++ EH by default on XCore and PS4.
- bool CXXExceptionsEnabled =
- Triple.getArch() != llvm::Triple::xcore && !Triple.isPS4CPU();
+ // Disable C++ EH by default on XCore and PS4/PS5.
+ bool CXXExceptionsEnabled = Triple.getArch() != llvm::Triple::xcore &&
+ !Triple.isPS() && !Triple.isDriverKit();
Arg *ExceptionArg = Args.getLastArg(
options::OPT_fcxx_exceptions, options::OPT_fno_cxx_exceptions,
options::OPT_fexceptions, options::OPT_fno_exceptions);
@@ -543,6 +561,7 @@ static bool useFramePointerForTargetByDefault(const ArgList &Args,
case llvm::Triple::riscv64:
case llvm::Triple::amdgcn:
case llvm::Triple::r600:
+ case llvm::Triple::csky:
return !areOptimizationsEnabled(Args);
default:
break;
@@ -613,10 +632,10 @@ getFramePointerKind(const ArgList &Args, const llvm::Triple &Triple) {
bool OmitFP = A && A->getOption().matches(options::OPT_fomit_frame_pointer);
bool NoOmitFP =
A && A->getOption().matches(options::OPT_fno_omit_frame_pointer);
- bool OmitLeafFP = Args.hasFlag(options::OPT_momit_leaf_frame_pointer,
- options::OPT_mno_omit_leaf_frame_pointer,
- Triple.isAArch64() || Triple.isPS4CPU() ||
- Triple.isVE());
+ bool OmitLeafFP =
+ Args.hasFlag(options::OPT_momit_leaf_frame_pointer,
+ options::OPT_mno_omit_leaf_frame_pointer,
+ Triple.isAArch64() || Triple.isPS() || Triple.isVE());
if (NoOmitFP || mustUseNonLeafFramePointerForTarget(Triple) ||
(!OmitFP && useFramePointerForTargetByDefault(Args, Triple))) {
if (OmitLeafFP)
@@ -669,17 +688,24 @@ static void addDebugObjectName(const ArgList &Args, ArgStringList &CmdArgs,
}
/// Add a CC1 and CC1AS option to specify the debug file path prefix map.
-static void addDebugPrefixMapArg(const Driver &D, const ArgList &Args, ArgStringList &CmdArgs) {
- for (const Arg *A : Args.filtered(options::OPT_ffile_prefix_map_EQ,
- options::OPT_fdebug_prefix_map_EQ)) {
- StringRef Map = A->getValue();
+static void addDebugPrefixMapArg(const Driver &D, const ToolChain &TC,
+ const ArgList &Args, ArgStringList &CmdArgs) {
+ auto AddOneArg = [&](StringRef Map, StringRef Name) {
if (!Map.contains('='))
- D.Diag(diag::err_drv_invalid_argument_to_option)
- << Map << A->getOption().getName();
+ D.Diag(diag::err_drv_invalid_argument_to_option) << Map << Name;
else
CmdArgs.push_back(Args.MakeArgString("-fdebug-prefix-map=" + Map));
+ };
+
+ for (const Arg *A : Args.filtered(options::OPT_ffile_prefix_map_EQ,
+ options::OPT_fdebug_prefix_map_EQ)) {
+ AddOneArg(A->getValue(), A->getOption().getName());
A->claim();
}
+ std::string GlobalRemapEntry = TC.GetGlobalDebugPathRemapping();
+ if (GlobalRemapEntry.empty())
+ return;
+ AddOneArg(GlobalRemapEntry, "environment");
}
/// Add a CC1 and CC1AS option to specify the macro file path prefix map.
@@ -1150,7 +1176,8 @@ static const char *RelocationModelName(llvm::Reloc::Model Model) {
}
static void handleAMDGPUCodeObjectVersionOptions(const Driver &D,
const ArgList &Args,
- ArgStringList &CmdArgs) {
+ ArgStringList &CmdArgs,
+ bool IsCC1As = false) {
// If no version was requested by the user, use the default value from the
// back end. This is consistent with the value returned from
// getAMDGPUCodeObjectVersion. This lets clang emit IR for amdgpu without
@@ -1162,6 +1189,11 @@ static void handleAMDGPUCodeObjectVersionOptions(const Driver &D,
Args.MakeArgString(Twine("--amdhsa-code-object-version=") +
Twine(CodeObjVer)));
CmdArgs.insert(CmdArgs.begin() + 1, "-mllvm");
+ // -cc1as does not accept -mcode-object-version option.
+ if (!IsCC1As)
+ CmdArgs.insert(CmdArgs.begin() + 1,
+ Args.MakeArgString(Twine("-mcode-object-version=") +
+ Twine(CodeObjVer)));
}
}
@@ -1277,6 +1309,7 @@ void Clang::AddPreprocessingOptions(Compilation &C, const JobAction &JA,
// If we are offloading to a target via OpenMP we need to include the
// openmp_wrappers folder which contains alternative system headers.
if (JA.isDeviceOffloading(Action::OFK_OpenMP) &&
+ !Args.hasArg(options::OPT_nostdinc) &&
(getToolChain().getTriple().isNVPTX() ||
getToolChain().getTriple().isAMDGCN())) {
if (!Args.hasArg(options::OPT_nobuiltininc)) {
@@ -1333,7 +1366,8 @@ void Clang::AddPreprocessingOptions(Compilation &C, const JobAction &JA,
bool RenderedImplicitInclude = false;
for (const Arg *A : Args.filtered(options::OPT_clang_i_Group)) {
- if (A->getOption().matches(options::OPT_include)) {
+ if (A->getOption().matches(options::OPT_include) &&
+ D.getProbePrecompiled()) {
// Handling of gcc-style gch precompiled headers.
bool IsFirstImplicitInclude = !RenderedImplicitInclude;
RenderedImplicitInclude = true;
@@ -1344,12 +1378,12 @@ void Clang::AddPreprocessingOptions(Compilation &C, const JobAction &JA,
// so that replace_extension does the right thing.
P += ".dummy";
llvm::sys::path::replace_extension(P, "pch");
- if (llvm::sys::fs::exists(P))
+ if (D.getVFS().exists(P))
FoundPCH = true;
if (!FoundPCH) {
llvm::sys::path::replace_extension(P, "gch");
- if (llvm::sys::fs::exists(P)) {
+ if (D.getVFS().exists(P)) {
FoundPCH = true;
}
}
@@ -1453,6 +1487,9 @@ void Clang::AddPreprocessingOptions(Compilation &C, const JobAction &JA,
addMacroPrefixMapArg(D, Args, CmdArgs);
addCoveragePrefixMapArg(D, Args, CmdArgs);
+
+ Args.AddLastArg(CmdArgs, options::OPT_ffile_reproducible,
+ options::OPT_fno_file_reproducible);
}
// FIXME: Move to target hook.
@@ -1625,6 +1662,16 @@ void RenderARMABI(const Driver &D, const llvm::Triple &Triple,
CmdArgs.push_back("-target-abi");
CmdArgs.push_back(ABIName);
}
+
+void AddUnalignedAccessWarning(ArgStringList &CmdArgs) {
+ auto StrictAlignIter =
+ std::find_if(CmdArgs.rbegin(), CmdArgs.rend(), [](StringRef Arg) {
+ return Arg == "+strict-align" || Arg == "-strict-align";
+ });
+ if (StrictAlignIter != CmdArgs.rend() &&
+ StringRef(*StrictAlignIter) == "+strict-align")
+ CmdArgs.push_back("-Wunaligned-access");
+}
}
static void CollectARMPACBTIOptions(const ToolChain &TC, const ArgList &Args,
@@ -1639,7 +1686,7 @@ static void CollectARMPACBTIOptions(const ToolChain &TC, const ArgList &Args,
const Driver &D = TC.getDriver();
const llvm::Triple &Triple = TC.getEffectiveTriple();
if (!(isAArch64 || (Triple.isArmT32() && Triple.isArmMClass())))
- D.Diag(diag::warn_target_unsupported_branch_protection_option)
+ D.Diag(diag::warn_incompatible_branch_protection_option)
<< Triple.getArchName();
StringRef Scope, Key;
@@ -1647,18 +1694,17 @@ static void CollectARMPACBTIOptions(const ToolChain &TC, const ArgList &Args,
if (A->getOption().matches(options::OPT_msign_return_address_EQ)) {
Scope = A->getValue();
- if (!Scope.equals("none") && !Scope.equals("non-leaf") &&
- !Scope.equals("all"))
- D.Diag(diag::err_invalid_branch_protection)
- << Scope << A->getAsString(Args);
+ if (Scope != "none" && Scope != "non-leaf" && Scope != "all")
+ D.Diag(diag::err_drv_unsupported_option_argument)
+ << A->getOption().getName() << Scope;
Key = "a_key";
IndirectBranches = false;
} else {
StringRef DiagMsg;
llvm::ARM::ParsedBranchProtection PBP;
if (!llvm::ARM::parseBranchProtection(A->getValue(), PBP, DiagMsg))
- D.Diag(diag::err_invalid_branch_protection)
- << DiagMsg << A->getAsString(Args);
+ D.Diag(diag::err_drv_unsupported_option_argument)
+ << A->getOption().getName() << DiagMsg;
if (!isAArch64 && PBP.Key == "b_key")
D.Diag(diag::warn_unsupported_branch_protection)
<< "b-key" << A->getAsString(Args);
@@ -1720,6 +1766,8 @@ void Clang::AddARMTargetArgs(const llvm::Triple &Triple, const ArgList &Args,
// Enable/disable return address signing and indirect branch targets.
CollectARMPACBTIOptions(getToolChain(), Args, CmdArgs, false /*isAArch64*/);
+
+ AddUnalignedAccessWarning(CmdArgs);
}
void Clang::RenderTargetOptions(const llvm::Triple &EffectiveTriple,
@@ -1893,6 +1941,8 @@ void Clang::AddAArch64TargetArgs(const ArgList &Args,
CmdArgs.push_back(Args.MakeArgString(TuneCPU));
}
}
+
+ AddUnalignedAccessWarning(CmdArgs);
}
void Clang::AddMIPSTargetArgs(const ArgList &Args,
@@ -2259,10 +2309,10 @@ void Clang::AddX86TargetArgs(const ArgList &Args,
// Handle -mtune.
- // Default to "generic" unless -march is present or targetting the PS4.
+ // Default to "generic" unless -march is present or targetting the PS4/PS5.
std::string TuneCPU;
if (!Args.hasArg(clang::driver::options::OPT_march_EQ) &&
- !getToolChain().getTriple().isPS4CPU())
+ !getToolChain().getTriple().isPS())
TuneCPU = "generic";
// Override based on -mtune.
@@ -2356,7 +2406,8 @@ void Clang::DumpCompilationDatabase(Compilation &C, StringRef Filename,
if (!CompilationDatabase) {
std::error_code EC;
auto File = std::make_unique<llvm::raw_fd_ostream>(
- Filename, EC, llvm::sys::fs::OF_TextWithCRLF);
+ Filename, EC,
+ llvm::sys::fs::OF_TextWithCRLF | llvm::sys::fs::OF_Append);
if (EC) {
D.Diag(clang::diag::err_drv_compilationdatabase) << Filename
<< EC.message();
@@ -2382,6 +2433,7 @@ void Clang::DumpCompilationDatabase(Compilation &C, StringRef Filename,
CDB << ", \"" << escape(Buf) << "\"";
}
CDB << ", \"" << escape(Input.getFilename()) << "\"";
+ CDB << ", \"-o\", \"" << escape(Output.getFilename()) << "\"";
for (auto &A: Args) {
auto &O = A->getOption();
// Skip language selection, which is positional.
@@ -2395,6 +2447,9 @@ void Clang::DumpCompilationDatabase(Compilation &C, StringRef Filename,
// Skip inputs.
if (O.getKind() == Option::InputClass)
continue;
+ // Skip output.
+ if (O.getID() == options::OPT_o)
+ continue;
// All other arguments are quoted and appended.
ArgStringList ASL;
A->render(Args, ASL);
@@ -2468,6 +2523,8 @@ static void CollectArgsForIntegratedAssembler(Compilation &C,
DefaultIncrementalLinkerCompatible))
CmdArgs.push_back("-mincremental-linker-compatible");
+ Args.AddLastArg(CmdArgs, options::OPT_femit_dwarf_unwind_EQ);
+
// If you add more args here, also add them to the block below that
// starts with "// If CollectArgsForIntegratedAssembler() isn't called below".
@@ -2700,6 +2757,8 @@ static void RenderFloatingPointOptions(const ToolChain &TC, const Driver &D,
StringRef FPModel = "";
// -ffp-exception-behavior options: strict, maytrap, ignore
StringRef FPExceptionBehavior = "";
+ // -ffp-eval-method options: double, extended, source
+ StringRef FPEvalMethod = "";
const llvm::DenormalMode DefaultDenormalFPMath =
TC.getDefaultDenormalModeForType(Args, JA);
const llvm::DenormalMode DefaultDenormalFP32Math =
@@ -2837,6 +2896,7 @@ static void RenderFloatingPointOptions(const ToolChain &TC, const Driver &D,
case options::OPT_fdenormal_fp_math_EQ:
DenormalFPMath = llvm::parseDenormalFPAttribute(A->getValue());
+ DenormalFP32Math = DenormalFPMath;
if (!DenormalFPMath.isValid()) {
D.Diag(diag::err_drv_invalid_value)
<< A->getAsString(Args) << A->getValue();
@@ -2895,6 +2955,18 @@ static void RenderFloatingPointOptions(const ToolChain &TC, const Driver &D,
break;
}
+ // Validate and pass through -ffp-eval-method option.
+ case options::OPT_ffp_eval_method_EQ: {
+ StringRef Val = A->getValue();
+ if (Val.equals("double") || Val.equals("extended") ||
+ Val.equals("source"))
+ FPEvalMethod = Val;
+ else
+ D.Diag(diag::err_drv_unsupported_option_argument)
+ << A->getOption().getName() << Val;
+ break;
+ }
+
case options::OPT_ffinite_math_only:
HonorINFs = false;
HonorNaNs = false;
@@ -3050,6 +3122,9 @@ static void RenderFloatingPointOptions(const ToolChain &TC, const Driver &D,
CmdArgs.push_back(Args.MakeArgString("-ffp-exception-behavior=" +
FPExceptionBehavior));
+ if (!FPEvalMethod.empty())
+ CmdArgs.push_back(Args.MakeArgString("-ffp-eval-method=" + FPEvalMethod));
+
ParseMRecip(D, Args, CmdArgs);
// -ffast-math enables the __FAST_MATH__ preprocessor macro, but check for the
@@ -3090,12 +3165,6 @@ static void RenderFloatingPointOptions(const ToolChain &TC, const Driver &D,
static void RenderAnalyzerOptions(const ArgList &Args, ArgStringList &CmdArgs,
const llvm::Triple &Triple,
const InputInfo &Input) {
- // Enable region store model by default.
- CmdArgs.push_back("-analyzer-store=region");
-
- // Treat blocks as analysis entry points.
- CmdArgs.push_back("-analyzer-opt-analyze-nested-blocks");
-
// Add default argument set.
if (!Args.hasArg(options::OPT__analyzer_no_default_checks)) {
CmdArgs.push_back("-analyzer-checker=core");
@@ -3113,8 +3182,8 @@ static void RenderAnalyzerOptions(const ArgList &Args, ArgStringList &CmdArgs,
CmdArgs.push_back("-analyzer-checker=unix.cstring.NullArg");
}
- // Disable some unix checkers for PS4.
- if (Triple.isPS4CPU()) {
+ // Disable some unix checkers for PS4/PS5.
+ if (Triple.isPS()) {
CmdArgs.push_back("-analyzer-disable-checker=unix.API");
CmdArgs.push_back("-analyzer-disable-checker=unix.Vfork");
}
@@ -3132,7 +3201,7 @@ static void RenderAnalyzerOptions(const ArgList &Args, ArgStringList &CmdArgs,
if (types::isCXX(Input.getType()))
CmdArgs.push_back("-analyzer-checker=cplusplus");
- if (!Triple.isPS4CPU()) {
+ if (!Triple.isPS()) {
CmdArgs.push_back("-analyzer-checker=security.insecureAPI.UncheckedReturn");
CmdArgs.push_back("-analyzer-checker=security.insecureAPI.getpw");
CmdArgs.push_back("-analyzer-checker=security.insecureAPI.gets");
@@ -3306,9 +3375,8 @@ static void RenderSCPOptions(const ToolChain &TC, const ArgList &Args,
!EffectiveTriple.isPPC64())
return;
- if (Args.hasFlag(options::OPT_fstack_clash_protection,
- options::OPT_fno_stack_clash_protection, false))
- CmdArgs.push_back("-fstack-clash-protection");
+ Args.addOptInFlag(CmdArgs, options::OPT_fstack_clash_protection,
+ options::OPT_fno_stack_clash_protection);
}
static void RenderTrivialAutoVarInitOptions(const Driver &D,
@@ -3391,6 +3459,9 @@ static void RenderOpenCLOptions(const ArgList &Args, ArgStringList &CmdArgs,
if (Arg *A = Args.getLastArg(options::OPT_cl_std_EQ)) {
std::string CLStdStr = std::string("-cl-std=") + A->getValue();
CmdArgs.push_back(Args.MakeArgString(CLStdStr));
+ } else if (Arg *A = Args.getLastArg(options::OPT_cl_ext_EQ)) {
+ std::string CLExtStr = std::string("-cl-ext=") + A->getValue();
+ CmdArgs.push_back(Args.MakeArgString(CLExtStr));
}
for (const auto &Arg : ForwardedArguments)
@@ -3406,6 +3477,24 @@ static void RenderOpenCLOptions(const ArgList &Args, ArgStringList &CmdArgs,
}
}
+static void RenderHLSLOptions(const ArgList &Args, ArgStringList &CmdArgs,
+ types::ID InputType) {
+ const unsigned ForwardedArguments[] = {options::OPT_dxil_validator_version,
+ options::OPT_D,
+ options::OPT_S,
+ options::OPT_emit_llvm,
+ options::OPT_disable_llvm_passes,
+ options::OPT_fnative_half_type};
+
+ for (const auto &Arg : ForwardedArguments)
+ if (const auto *A = Args.getLastArg(Arg))
+ A->renderAsInput(Args, CmdArgs);
+ // Add the default headers if dxc_no_stdinc is not set.
+ if (!Args.hasArg(options::OPT_dxc_no_stdinc))
+ CmdArgs.push_back("-finclude-default-header");
+ CmdArgs.push_back("-fallow-half-arguments-and-returns");
+}
+
static void RenderARCMigrateToolOptions(const Driver &D, const ArgList &Args,
ArgStringList &CmdArgs) {
bool ARCMTEnabled = false;
@@ -3492,20 +3581,13 @@ static void RenderBuiltinOptions(const ToolChain &TC, const llvm::Triple &T,
UseBuiltins = false;
// Process the -fno-builtin-* options.
- for (const auto &Arg : Args) {
- const Option &O = Arg->getOption();
- if (!O.matches(options::OPT_fno_builtin_))
- continue;
-
- Arg->claim();
+ for (const Arg *A : Args.filtered(options::OPT_fno_builtin_)) {
+ A->claim();
// If -fno-builtin is specified, then there's no need to pass the option to
// the frontend.
- if (!UseBuiltins)
- continue;
-
- StringRef FuncName = Arg->getValue();
- CmdArgs.push_back(Args.MakeArgString("-fno-builtin-" + FuncName));
+ if (UseBuiltins)
+ A->render(Args, CmdArgs);
}
// le32-specific flags:
@@ -3516,6 +3598,11 @@ static void RenderBuiltinOptions(const ToolChain &TC, const llvm::Triple &T,
}
bool Driver::getDefaultModuleCachePath(SmallVectorImpl<char> &Result) {
+ if (const char *Str = std::getenv("CLANG_MODULE_CACHE_PATH")) {
+ Twine Path{Str};
+ Path.toVector(Result);
+ return Path.getSingleStringRef() != "";
+ }
if (llvm::sys::path::cache_directory(Result)) {
llvm::sys::path::append(Result, "clang");
llvm::sys::path::append(Result, "ModuleCache");
@@ -3554,9 +3641,8 @@ static void RenderModulesOptions(Compilation &C, const Driver &D,
CmdArgs.push_back("-fimplicit-module-maps");
// -fmodules-decluse checks that modules used are declared so (off by default)
- if (Args.hasFlag(options::OPT_fmodules_decluse,
- options::OPT_fno_modules_decluse, false))
- CmdArgs.push_back("-fmodules-decluse");
+ Args.addOptInFlag(CmdArgs, options::OPT_fmodules_decluse,
+ options::OPT_fno_modules_decluse);
// -fmodules-strict-decluse is like -fmodule-decluse, but also checks that
// all #included headers are part of modules.
@@ -3855,15 +3941,10 @@ static void RenderDiagnosticsOptions(const Driver &D, const ArgList &Args,
options::OPT_fno_caret_diagnostics, CaretDefault))
CmdArgs.push_back("-fno-caret-diagnostics");
- // -fdiagnostics-fixit-info is default, only pass non-default.
- if (!Args.hasFlag(options::OPT_fdiagnostics_fixit_info,
- options::OPT_fno_diagnostics_fixit_info))
- CmdArgs.push_back("-fno-diagnostics-fixit-info");
-
- // Enable -fdiagnostics-show-option by default.
- if (!Args.hasFlag(options::OPT_fdiagnostics_show_option,
- options::OPT_fno_diagnostics_show_option, true))
- CmdArgs.push_back("-fno-diagnostics-show-option");
+ Args.addOptOutFlag(CmdArgs, options::OPT_fdiagnostics_fixit_info,
+ options::OPT_fno_diagnostics_fixit_info);
+ Args.addOptOutFlag(CmdArgs, options::OPT_fdiagnostics_show_option,
+ options::OPT_fno_diagnostics_show_option);
if (const Arg *A =
Args.getLastArg(options::OPT_fdiagnostics_show_category_EQ)) {
@@ -3871,9 +3952,8 @@ static void RenderDiagnosticsOptions(const Driver &D, const ArgList &Args,
CmdArgs.push_back(A->getValue());
}
- if (Args.hasFlag(options::OPT_fdiagnostics_show_hotness,
- options::OPT_fno_diagnostics_show_hotness, false))
- CmdArgs.push_back("-fdiagnostics-show-hotness");
+ Args.addOptInFlag(CmdArgs, options::OPT_fdiagnostics_show_hotness,
+ options::OPT_fno_diagnostics_show_hotness);
if (const Arg *A =
Args.getLastArg(options::OPT_fdiagnostics_hotness_threshold_EQ)) {
@@ -3901,22 +3981,13 @@ static void RenderDiagnosticsOptions(const Driver &D, const ArgList &Args,
// re-parsed to construct this job; claim any possible color diagnostic here
// to avoid warn_drv_unused_argument and diagnose bad
// OPT_fdiagnostics_color_EQ values.
- for (const Arg *A : Args) {
- const Option &O = A->getOption();
- if (!O.matches(options::OPT_fcolor_diagnostics) &&
- !O.matches(options::OPT_fdiagnostics_color) &&
- !O.matches(options::OPT_fno_color_diagnostics) &&
- !O.matches(options::OPT_fno_diagnostics_color) &&
- !O.matches(options::OPT_fdiagnostics_color_EQ))
- continue;
-
- if (O.matches(options::OPT_fdiagnostics_color_EQ)) {
- StringRef Value(A->getValue());
- if (Value != "always" && Value != "never" && Value != "auto")
- D.Diag(diag::err_drv_clang_unsupported)
- << ("-fdiagnostics-color=" + Value).str();
- }
- A->claim();
+ Args.getLastArg(options::OPT_fcolor_diagnostics,
+ options::OPT_fno_color_diagnostics);
+ if (const Arg *A = Args.getLastArg(options::OPT_fdiagnostics_color_EQ)) {
+ StringRef Value(A->getValue());
+ if (Value != "always" && Value != "never" && Value != "auto")
+ D.Diag(diag::err_drv_invalid_argument_to_option)
+ << Value << A->getOption().getName();
}
if (D.getDiags().getDiagnosticOptions().ShowColors)
@@ -3925,9 +3996,8 @@ static void RenderDiagnosticsOptions(const Driver &D, const ArgList &Args,
if (Args.hasArg(options::OPT_fansi_escape_codes))
CmdArgs.push_back("-fansi-escape-codes");
- if (!Args.hasFlag(options::OPT_fshow_source_location,
- options::OPT_fno_show_source_location))
- CmdArgs.push_back("-fno-show-source-location");
+ Args.addOptOutFlag(CmdArgs, options::OPT_fshow_source_location,
+ options::OPT_fno_show_source_location);
if (Args.hasArg(options::OPT_fdiagnostics_absolute_paths))
CmdArgs.push_back("-fdiagnostics-absolute-paths");
@@ -3936,9 +4006,8 @@ static void RenderDiagnosticsOptions(const Driver &D, const ArgList &Args,
ColumnDefault))
CmdArgs.push_back("-fno-show-column");
- if (!Args.hasFlag(options::OPT_fspell_checking,
- options::OPT_fno_spell_checking))
- CmdArgs.push_back("-fno-spell-checking");
+ Args.addOptOutFlag(CmdArgs, options::OPT_fspell_checking,
+ options::OPT_fno_spell_checking);
}
enum class DwarfFissionKind { None, Split, Single };
@@ -4247,8 +4316,8 @@ static void renderDebugOptions(const ToolChain &TC, const Driver &D,
? "-gpubnames"
: "-ggnu-pubnames");
const auto *SimpleTemplateNamesArg =
- Args.getLastArg(options::OPT_gsimple_template_names, options::OPT_gno_simple_template_names,
- options::OPT_gsimple_template_names_EQ);
+ Args.getLastArg(options::OPT_gsimple_template_names,
+ options::OPT_gno_simple_template_names);
bool ForwardTemplateParams = DebuggerTuning == llvm::DebuggerKind::SCE;
if (SimpleTemplateNamesArg &&
checkDebugInfoOption(SimpleTemplateNamesArg, Args, D, TC)) {
@@ -4256,17 +4325,6 @@ static void renderDebugOptions(const ToolChain &TC, const Driver &D,
if (Opt.matches(options::OPT_gsimple_template_names)) {
ForwardTemplateParams = true;
CmdArgs.push_back("-gsimple-template-names=simple");
- } else if (Opt.matches(options::OPT_gsimple_template_names_EQ)) {
- ForwardTemplateParams = true;
- StringRef Value = SimpleTemplateNamesArg->getValue();
- if (Value == "simple") {
- CmdArgs.push_back("-gsimple-template-names=simple");
- } else if (Value == "mangled") {
- CmdArgs.push_back("-gsimple-template-names=mangled");
- } else {
- D.Diag(diag::err_drv_unsupported_option_argument)
- << Opt.getName() << SimpleTemplateNamesArg->getValue();
- }
}
}
@@ -4344,17 +4402,26 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,
// CUDA/HIP compilation may have multiple inputs (source file + results of
// device-side compilations). OpenMP device jobs also take the host IR as a
// second input. Module precompilation accepts a list of header files to
- // include as part of the module. All other jobs are expected to have exactly
- // one input.
+ // include as part of the module. API extraction accepts a list of header
+ // files whose API information is emitted in the output. All other jobs are
+ // expected to have exactly one input.
bool IsCuda = JA.isOffloading(Action::OFK_Cuda);
bool IsCudaDevice = JA.isDeviceOffloading(Action::OFK_Cuda);
bool IsHIP = JA.isOffloading(Action::OFK_HIP);
bool IsHIPDevice = JA.isDeviceOffloading(Action::OFK_HIP);
bool IsOpenMPDevice = JA.isDeviceOffloading(Action::OFK_OpenMP);
- bool IsOpenMPHost = JA.isHostOffloading(Action::OFK_OpenMP);
bool IsHeaderModulePrecompile = isa<HeaderModulePrecompileJobAction>(JA);
+ bool IsExtractAPI = isa<ExtractAPIJobAction>(JA);
bool IsDeviceOffloadAction = !(JA.isDeviceOffloading(Action::OFK_None) ||
JA.isDeviceOffloading(Action::OFK_Host));
+ bool IsHostOffloadingAction =
+ (JA.isHostOffloading(Action::OFK_OpenMP) &&
+ Args.hasFlag(options::OPT_fopenmp_new_driver,
+ options::OPT_no_offload_new_driver, true)) ||
+ (JA.isHostOffloading(C.getActiveOffloadKinds()) &&
+ Args.hasFlag(options::OPT_offload_new_driver,
+ options::OPT_no_offload_new_driver, false));
+
bool IsUsingLTO = D.isUsingLTO(IsDeviceOffloadAction);
auto LTOMode = D.getLTOMode(IsDeviceOffloadAction);
@@ -4366,11 +4433,22 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,
}();
InputInfo HeaderModuleInput(Inputs[0].getType(), ModuleName, ModuleName);
- const InputInfo &Input =
- IsHeaderModulePrecompile ? HeaderModuleInput : Inputs[0];
+ // Extract API doesn't have a main input file, so invent a fake one as a
+ // placeholder.
+ InputInfo ExtractAPIPlaceholderInput(Inputs[0].getType(), "extract-api",
+ "extract-api");
+
+ const InputInfo &Input = [&]() -> const InputInfo & {
+ if (IsHeaderModulePrecompile)
+ return HeaderModuleInput;
+ if (IsExtractAPI)
+ return ExtractAPIPlaceholderInput;
+ return Inputs[0];
+ }();
InputInfoList ModuleHeaderInputs;
- InputInfoList OpenMPHostInputs;
+ InputInfoList ExtractAPIInputs;
+ InputInfoList HostOffloadingInputs;
const InputInfo *CudaDeviceInput = nullptr;
const InputInfo *OpenMPDeviceInput = nullptr;
for (const InputInfo &I : Inputs) {
@@ -4385,12 +4463,20 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,
<< types::getTypeName(Expected);
}
ModuleHeaderInputs.push_back(I);
+ } else if (IsExtractAPI) {
+ auto ExpectedInputType = ExtractAPIPlaceholderInput.getType();
+ if (I.getType() != ExpectedInputType) {
+ D.Diag(diag::err_drv_extract_api_wrong_kind)
+ << I.getFilename() << types::getTypeName(I.getType())
+ << types::getTypeName(ExpectedInputType);
+ }
+ ExtractAPIInputs.push_back(I);
+ } else if (IsHostOffloadingAction) {
+ HostOffloadingInputs.push_back(I);
} else if ((IsCuda || IsHIP) && !CudaDeviceInput) {
CudaDeviceInput = &I;
} else if (IsOpenMPDevice && !OpenMPDeviceInput) {
OpenMPDeviceInput = &I;
- } else if (IsOpenMPHost) {
- OpenMPHostInputs.push_back(I);
} else {
llvm_unreachable("unexpectedly given multiple inputs");
}
@@ -4534,6 +4620,7 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,
}
Args.ClaimAllArgs(options::OPT_Wa_COMMA);
Args.ClaimAllArgs(options::OPT_Xassembler);
+ Args.ClaimAllArgs(options::OPT_femit_dwarf_unwind_EQ);
}
if (isa<AnalyzeJobAction>(JA)) {
@@ -4549,6 +4636,8 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,
if (Args.hasArg(options::OPT_rewrite_objc) &&
!Args.hasArg(options::OPT_g_Group))
CmdArgs.push_back("-P");
+ else if (JA.getType() == types::TY_PP_CXXHeaderUnit)
+ CmdArgs.push_back("-fdirectives-only");
}
} else if (isa<AssembleJobAction>(JA)) {
CmdArgs.push_back("-emit-obj");
@@ -4564,10 +4653,18 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,
CmdArgs.push_back(IsHeaderModulePrecompile
? "-emit-header-module"
: "-emit-module-interface");
+ else if (JA.getType() == types::TY_HeaderUnit)
+ CmdArgs.push_back("-emit-header-unit");
else
CmdArgs.push_back("-emit-pch");
} else if (isa<VerifyPCHJobAction>(JA)) {
CmdArgs.push_back("-verify-pch");
+ } else if (isa<ExtractAPIJobAction>(JA)) {
+ assert(JA.getType() == types::TY_API_INFO &&
+ "Extract API actions must generate a API information.");
+ CmdArgs.push_back("-extract-api");
+ if (Arg *ProductNameArg = Args.getLastArg(options::OPT_product_name_EQ))
+ ProductNameArg->render(Args, CmdArgs);
} else {
assert((isa<CompileJobAction>(JA) || isa<BackendJobAction>(JA)) &&
"Invalid action for clang tool.");
@@ -4606,8 +4703,6 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,
} else if (JA.getType() == types::TY_RewrittenLegacyObjC) {
CmdArgs.push_back("-rewrite-objc");
rewriteKind = RK_Fragile;
- } else if (JA.getType() == types::TY_API_INFO) {
- CmdArgs.push_back("-extract-api");
} else {
assert(JA.getType() == types::TY_PP_Asm && "Unexpected output type!");
}
@@ -4619,9 +4714,14 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,
if (JA.getType() == types::TY_LLVM_BC)
CmdArgs.push_back("-emit-llvm-uselists");
- if (IsUsingLTO && !Args.hasArg(options::OPT_fopenmp_new_driver)) {
+ if (IsUsingLTO) {
// Only AMDGPU supports device-side LTO.
- if (IsDeviceOffloadAction && !Triple.isAMDGPU()) {
+ if (IsDeviceOffloadAction &&
+ !Args.hasFlag(options::OPT_fopenmp_new_driver,
+ options::OPT_no_offload_new_driver, true) &&
+ !Args.hasFlag(options::OPT_offload_new_driver,
+ options::OPT_no_offload_new_driver, false) &&
+ !Triple.isAMDGPU()) {
D.Diag(diag::err_drv_unsupported_opt_for_target)
<< Args.getLastArg(options::OPT_foffload_lto,
options::OPT_foffload_lto_EQ)
@@ -4717,9 +4817,8 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,
D.Diag(diag::err_drv_unsupported_embed_bitcode) << A->getSpelling();
// Render the CodeGen options that need to be passed.
- if (!Args.hasFlag(options::OPT_foptimize_sibling_calls,
- options::OPT_fno_optimize_sibling_calls))
- CmdArgs.push_back("-mdisable-tail-calls");
+ Args.addOptOutFlag(CmdArgs, options::OPT_foptimize_sibling_calls,
+ options::OPT_fno_optimize_sibling_calls);
RenderFloatingPointOptions(TC, D, isOptimizationLevelFast(Args), Args,
CmdArgs, JA);
@@ -5008,17 +5107,12 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,
A->claim();
}
- if (!Args.hasFlag(options::OPT_fjump_tables, options::OPT_fno_jump_tables,
- true))
- CmdArgs.push_back("-fno-jump-tables");
-
- if (Args.hasFlag(options::OPT_fprofile_sample_accurate,
- options::OPT_fno_profile_sample_accurate, false))
- CmdArgs.push_back("-fprofile-sample-accurate");
-
- if (!Args.hasFlag(options::OPT_fpreserve_as_comments,
- options::OPT_fno_preserve_as_comments, true))
- CmdArgs.push_back("-fno-preserve-as-comments");
+ Args.addOptOutFlag(CmdArgs, options::OPT_fjump_tables,
+ options::OPT_fno_jump_tables);
+ Args.addOptInFlag(CmdArgs, options::OPT_fprofile_sample_accurate,
+ options::OPT_fno_profile_sample_accurate);
+ Args.addOptOutFlag(CmdArgs, options::OPT_fpreserve_as_comments,
+ options::OPT_fno_preserve_as_comments);
if (Arg *A = Args.getLastArg(options::OPT_mregparm_EQ)) {
CmdArgs.push_back("-mregparm");
@@ -5078,9 +5172,8 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,
assert(FPKeepKindStr && "unknown FramePointerKind");
CmdArgs.push_back(FPKeepKindStr);
- if (!Args.hasFlag(options::OPT_fzero_initialized_in_bss,
- options::OPT_fno_zero_initialized_in_bss, true))
- CmdArgs.push_back("-fno-zero-initialized-in-bss");
+ Args.addOptOutFlag(CmdArgs, options::OPT_fzero_initialized_in_bss,
+ options::OPT_fno_zero_initialized_in_bss);
bool OFastEnabled = isOptimizationLevelFast(Args);
// If -Ofast is the optimization level, then -fstrict-aliasing should be
@@ -5094,31 +5187,22 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,
options::OPT_fno_strict_aliasing, TBAAOnByDefault))
CmdArgs.push_back("-relaxed-aliasing");
if (!Args.hasFlag(options::OPT_fstruct_path_tbaa,
- options::OPT_fno_struct_path_tbaa))
+ options::OPT_fno_struct_path_tbaa, true))
CmdArgs.push_back("-no-struct-path-tbaa");
- if (Args.hasFlag(options::OPT_fstrict_enums, options::OPT_fno_strict_enums,
- false))
- CmdArgs.push_back("-fstrict-enums");
- if (!Args.hasFlag(options::OPT_fstrict_return, options::OPT_fno_strict_return,
- true))
- CmdArgs.push_back("-fno-strict-return");
- if (Args.hasFlag(options::OPT_fallow_editor_placeholders,
- options::OPT_fno_allow_editor_placeholders, false))
- CmdArgs.push_back("-fallow-editor-placeholders");
- if (Args.hasFlag(options::OPT_fstrict_vtable_pointers,
- options::OPT_fno_strict_vtable_pointers,
- false))
- CmdArgs.push_back("-fstrict-vtable-pointers");
- if (Args.hasFlag(options::OPT_fforce_emit_vtables,
- options::OPT_fno_force_emit_vtables,
- false))
- CmdArgs.push_back("-fforce-emit-vtables");
- if (!Args.hasFlag(options::OPT_foptimize_sibling_calls,
- options::OPT_fno_optimize_sibling_calls))
- CmdArgs.push_back("-mdisable-tail-calls");
- if (Args.hasFlag(options::OPT_fno_escaping_block_tail_calls,
- options::OPT_fescaping_block_tail_calls, false))
- CmdArgs.push_back("-fno-escaping-block-tail-calls");
+ Args.addOptInFlag(CmdArgs, options::OPT_fstrict_enums,
+ options::OPT_fno_strict_enums);
+ Args.addOptOutFlag(CmdArgs, options::OPT_fstrict_return,
+ options::OPT_fno_strict_return);
+ Args.addOptInFlag(CmdArgs, options::OPT_fallow_editor_placeholders,
+ options::OPT_fno_allow_editor_placeholders);
+ Args.addOptInFlag(CmdArgs, options::OPT_fstrict_vtable_pointers,
+ options::OPT_fno_strict_vtable_pointers);
+ Args.addOptInFlag(CmdArgs, options::OPT_fforce_emit_vtables,
+ options::OPT_fno_force_emit_vtables);
+ Args.addOptOutFlag(CmdArgs, options::OPT_foptimize_sibling_calls,
+ options::OPT_fno_optimize_sibling_calls);
+ Args.addOptOutFlag(CmdArgs, options::OPT_fescaping_block_tail_calls,
+ options::OPT_fno_escaping_block_tail_calls);
Args.AddLastArg(CmdArgs, options::OPT_ffine_grained_bitfield_accesses,
options::OPT_fno_fine_grained_bitfield_accesses);
@@ -5246,6 +5330,8 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,
if (Freestanding)
CmdArgs.push_back("-ffreestanding");
+ Args.AddLastArg(CmdArgs, options::OPT_fno_knr_functions);
+
// This is a coarse approximation of what llvm-gcc actually does, both
// -fasynchronous-unwind-tables and -fnon-call-exceptions interact in more
// complicated ways.
@@ -5349,6 +5435,19 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,
types::isLLVMIR(InputType), CmdArgs, DebugInfoKind,
DwarfFission);
+ // This controls whether or not we perform JustMyCode instrumentation.
+ if (Args.hasFlag(options::OPT_fjmc, options::OPT_fno_jmc, false)) {
+ if (TC.getTriple().isOSBinFormatELF()) {
+ if (DebugInfoKind >= codegenoptions::DebugInfoConstructor)
+ CmdArgs.push_back("-fjmc");
+ else
+ D.Diag(clang::diag::warn_drv_jmc_requires_debuginfo) << "-fjmc"
+ << "-g";
+ } else {
+ D.Diag(clang::diag::warn_drv_fjmc_for_elf_only);
+ }
+ }
+
// Add the split debug info name to the command lines here so we
// can propagate it to the backend.
bool SplitDWARF = (DwarfFission != DwarfFissionKind::None) &&
@@ -5464,17 +5563,12 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,
CmdArgs.push_back("-fdata-sections");
}
- if (!Args.hasFlag(options::OPT_funique_section_names,
- options::OPT_fno_unique_section_names, true))
- CmdArgs.push_back("-fno-unique-section-names");
-
- if (Args.hasFlag(options::OPT_funique_internal_linkage_names,
- options::OPT_fno_unique_internal_linkage_names, false))
- CmdArgs.push_back("-funique-internal-linkage-names");
-
- if (Args.hasFlag(options::OPT_funique_basic_block_section_names,
- options::OPT_fno_unique_basic_block_section_names, false))
- CmdArgs.push_back("-funique-basic-block-section-names");
+ Args.addOptOutFlag(CmdArgs, options::OPT_funique_section_names,
+ options::OPT_fno_unique_section_names);
+ Args.addOptInFlag(CmdArgs, options::OPT_funique_internal_linkage_names,
+ options::OPT_fno_unique_internal_linkage_names);
+ Args.addOptInFlag(CmdArgs, options::OPT_funique_basic_block_section_names,
+ options::OPT_fno_unique_basic_block_section_names);
if (Arg *A = Args.getLastArg(options::OPT_fsplit_machine_functions,
options::OPT_fno_split_machine_functions)) {
@@ -5500,11 +5594,11 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,
Args.AddLastArg(CmdArgs, options::OPT_fclang_abi_compat_EQ);
- // Add runtime flag for PS4 when PGO, coverage, or sanitizers are enabled.
- if (RawTriple.isPS4CPU() &&
+ // Add runtime flag for PS4/PS5 when PGO, coverage, or sanitizers are enabled.
+ if (RawTriple.isPS() &&
!Args.hasArg(options::OPT_nostdlib, options::OPT_nodefaultlibs)) {
- PS4cpu::addProfileRTArgs(TC, Args, CmdArgs);
- PS4cpu::addSanitizerArgs(TC, Args, CmdArgs);
+ PScpu::addProfileRTArgs(TC, Args, CmdArgs);
+ PScpu::addSanitizerArgs(TC, Args, CmdArgs);
}
// Pass options for controlling the default header search paths.
@@ -5698,7 +5792,7 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,
const char *DebugCompilationDir =
addDebugCompDirArg(Args, CmdArgs, D.getVFS());
- addDebugPrefixMapArg(D, Args, CmdArgs);
+ addDebugPrefixMapArg(D, TC, Args, CmdArgs);
if (Arg *A = Args.getLastArg(options::OPT_ftemplate_depth_,
options::OPT_ftemplate_depth_EQ)) {
@@ -5721,6 +5815,13 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,
CmdArgs.push_back(A->getValue());
}
+ if (Args.hasArg(options::OPT_funstable)) {
+ CmdArgs.push_back("-funstable");
+ if (!Args.hasArg(options::OPT_fno_coroutines_ts))
+ CmdArgs.push_back("-fcoroutines-ts");
+ CmdArgs.push_back("-fmodules-ts");
+ }
+
if (Args.hasArg(options::OPT_fexperimental_new_constant_interpreter))
CmdArgs.push_back("-fexperimental-new-constant-interpreter");
@@ -5746,7 +5847,7 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,
"standalone", "objc", "swift", "swift-5.0", "swift-4.2", "swift-4.1",
};
- if (find(kCFABIs, StringRef(A->getValue())) == std::end(kCFABIs))
+ if (!llvm::is_contained(kCFABIs, StringRef(A->getValue())))
D.Diag(diag::err_drv_invalid_cf_runtime_abi) << A->getValue();
else
A->render(Args, CmdArgs);
@@ -5820,6 +5921,14 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,
CmdArgs.push_back(
Args.MakeArgString("-fmessage-length=" + Twine(MessageLength)));
+ if (Arg *A = Args.getLastArg(options::OPT_frandomize_layout_seed_EQ))
+ CmdArgs.push_back(
+ Args.MakeArgString("-frandomize-layout-seed=" + Twine(A->getValue(0))));
+
+ if (Arg *A = Args.getLastArg(options::OPT_frandomize_layout_seed_file_EQ))
+ CmdArgs.push_back(Args.MakeArgString("-frandomize-layout-seed-file=" +
+ Twine(A->getValue(0))));
+
// -fvisibility= and -fvisibility-ms-compat are of a piece.
if (const Arg *A = Args.getLastArg(options::OPT_fvisibility_EQ,
options::OPT_fvisibility_ms_compat)) {
@@ -5864,6 +5973,14 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,
<< A->getAsString(Args) << TripleStr;
}
+ if (const Arg *A =
+ Args.getLastArg(options::OPT_mdefault_visibility_export_mapping_EQ)) {
+ if (Triple.isOSAIX())
+ A->render(Args, CmdArgs);
+ else
+ D.Diag(diag::err_drv_unsupported_opt_for_target)
+ << A->getAsString(Args) << TripleStr;
+ }
if (Args.hasFlag(options::OPT_fvisibility_inlines_hidden,
options::OPT_fno_visibility_inlines_hidden, false))
@@ -5888,6 +6005,16 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,
Args.AddLastArg(CmdArgs, options::OPT_fdigraphs, options::OPT_fno_digraphs);
Args.AddLastArg(CmdArgs, options::OPT_femulated_tls,
options::OPT_fno_emulated_tls);
+ Args.AddLastArg(CmdArgs, options::OPT_fzero_call_used_regs_EQ);
+
+ if (Arg *A = Args.getLastArg(options::OPT_fzero_call_used_regs_EQ)) {
+ // FIXME: There's no reason for this to be restricted to X86. The backend
+ // code needs to be changed to include the appropriate function calls
+ // automatically.
+ if (!Triple.isX86() && !Triple.isAArch64())
+ D.Diag(diag::err_drv_unsupported_opt_for_target)
+ << A->getAsString(Args) << TripleStr;
+ }
// AltiVec-like language extensions aren't relevant for assembling.
if (!isa<PreprocessJobAction>(JA) || Output.getType() != types::TY_PP_Asm)
@@ -5936,13 +6063,6 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,
options::OPT_fno_openmp_cuda_mode, /*Default=*/false))
CmdArgs.push_back("-fopenmp-cuda-mode");
- // When in OpenMP offloading mode, enable or disable the new device
- // runtime.
- if (Args.hasFlag(options::OPT_fopenmp_target_new_runtime,
- options::OPT_fno_openmp_target_new_runtime,
- /*Default=*/true))
- CmdArgs.push_back("-fopenmp-target-new-runtime");
-
// When in OpenMP offloading mode, enable debugging on the device.
Args.AddAllArgs(CmdArgs, options::OPT_fopenmp_target_debug_EQ);
if (Args.hasFlag(options::OPT_fopenmp_target_debug,
@@ -5966,6 +6086,10 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,
options::OPT_fno_openmp_assume_threads_oversubscription,
/*Default=*/false))
CmdArgs.push_back("-fopenmp-assume-threads-oversubscription");
+ if (Args.hasArg(options::OPT_fopenmp_assume_no_thread_state))
+ CmdArgs.push_back("-fopenmp-assume-no-thread-state");
+ if (Args.hasArg(options::OPT_fopenmp_offload_mandatory))
+ CmdArgs.push_back("-fopenmp-offload-mandatory");
break;
default:
// By default, if Clang doesn't know how to generate useful OpenMP code
@@ -5980,11 +6104,14 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,
Args.AddLastArg(CmdArgs, options::OPT_fopenmp_simd,
options::OPT_fno_openmp_simd);
Args.AddAllArgs(CmdArgs, options::OPT_fopenmp_version_EQ);
- if (!Args.hasFlag(options::OPT_fopenmp_extensions,
- options::OPT_fno_openmp_extensions, /*Default=*/true))
- CmdArgs.push_back("-fno-openmp-extensions");
+ Args.addOptOutFlag(CmdArgs, options::OPT_fopenmp_extensions,
+ options::OPT_fno_openmp_extensions);
}
+ // Forward the new driver to change offloading code generation.
+ if (Args.hasArg(options::OPT_offload_new_driver))
+ CmdArgs.push_back("--offload-new-driver");
+
SanitizeArgs.addArgs(TC, Args, CmdArgs, InputType);
const XRayArgs &XRay = TC.getXRayArgs();
@@ -6125,9 +6252,8 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,
CmdArgs.push_back("-mstack-probe-size=0");
}
- if (!Args.hasFlag(options::OPT_mstack_arg_probe,
- options::OPT_mno_stack_arg_probe, true))
- CmdArgs.push_back(Args.MakeArgString("-mno-stack-arg-probe"));
+ Args.addOptOutFlag(CmdArgs, options::OPT_mstack_arg_probe,
+ options::OPT_mno_stack_arg_probe);
if (Arg *A = Args.getLastArg(options::OPT_mrestrict_it,
options::OPT_mno_restrict_it)) {
@@ -6136,19 +6262,17 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,
CmdArgs.push_back("-arm-restrict-it");
} else {
CmdArgs.push_back("-mllvm");
- CmdArgs.push_back("-arm-no-restrict-it");
+ CmdArgs.push_back("-arm-default-it");
}
- } else if (Triple.isOSWindows() &&
- (Triple.getArch() == llvm::Triple::arm ||
- Triple.getArch() == llvm::Triple::thumb)) {
- // Windows on ARM expects restricted IT blocks
- CmdArgs.push_back("-mllvm");
- CmdArgs.push_back("-arm-restrict-it");
}
// Forward -cl options to -cc1
RenderOpenCLOptions(Args, CmdArgs, InputType);
+ // Forward hlsl options to -cc1
+ if (C.getDriver().IsDXCMode())
+ RenderHLSLOptions(Args, CmdArgs, InputType);
+
if (IsHIP) {
if (Args.hasFlag(options::OPT_fhip_new_launch_api,
options::OPT_fno_hip_new_launch_api, true))
@@ -6156,9 +6280,14 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,
if (Args.hasFlag(options::OPT_fgpu_allow_device_init,
options::OPT_fno_gpu_allow_device_init, false))
CmdArgs.push_back("-fgpu-allow-device-init");
+ Args.addOptInFlag(CmdArgs, options::OPT_fhip_kernel_arg_name,
+ options::OPT_fno_hip_kernel_arg_name);
}
if (IsCuda || IsHIP) {
+ if (!Args.hasFlag(options::OPT_fgpu_rdc, options::OPT_fno_gpu_rdc, false) &&
+ Args.hasArg(options::OPT_offload_new_driver))
+ D.Diag(diag::err_drv_no_rdc_new_driver);
if (Args.hasFlag(options::OPT_fgpu_rdc, options::OPT_fno_gpu_rdc, false))
CmdArgs.push_back("-fgpu-rdc");
if (Args.hasFlag(options::OPT_fgpu_defer_diag,
@@ -6172,6 +6301,10 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,
}
}
+ // Forward -nogpulib to -cc1.
+ if (Args.hasArg(options::OPT_nogpulib))
+ CmdArgs.push_back("-nogpulib");
+
if (Arg *A = Args.getLastArg(options::OPT_fcf_protection_EQ)) {
CmdArgs.push_back(
Args.MakeArgString(Twine("-fcf-protection=") + A->getValue()));
@@ -6214,9 +6347,8 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,
}
RenderBuiltinOptions(TC, RawTriple, Args, CmdArgs);
- if (!Args.hasFlag(options::OPT_fassume_sane_operator_new,
- options::OPT_fno_assume_sane_operator_new))
- CmdArgs.push_back("-fno-assume-sane-operator-new");
+ Args.addOptOutFlag(CmdArgs, options::OPT_fassume_sane_operator_new,
+ options::OPT_fno_assume_sane_operator_new);
// -fblocks=0 is default.
if (Args.hasFlag(options::OPT_fblocks, options::OPT_fno_blocks,
@@ -6243,15 +6375,10 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,
Args.AddLastArg(CmdArgs, options::OPT_fdouble_square_bracket_attributes,
options::OPT_fno_double_square_bracket_attributes);
- // -faccess-control is default.
- if (Args.hasFlag(options::OPT_fno_access_control,
- options::OPT_faccess_control, false))
- CmdArgs.push_back("-fno-access-control");
-
- // -felide-constructors is the default.
- if (Args.hasFlag(options::OPT_fno_elide_constructors,
- options::OPT_felide_constructors, false))
- CmdArgs.push_back("-fno-elide-constructors");
+ Args.addOptOutFlag(CmdArgs, options::OPT_faccess_control,
+ options::OPT_fno_access_control);
+ Args.addOptOutFlag(CmdArgs, options::OPT_felide_constructors,
+ options::OPT_fno_elide_constructors);
ToolChain::RTTIMode RTTIMode = TC.getRTTIMode();
@@ -6280,10 +6407,8 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,
RawTriple.isOSDarwin() && !KernelOrKext))
CmdArgs.push_back("-fregister-global-dtors-with-atexit");
- // -fno-use-line-directives is default.
- if (Args.hasFlag(options::OPT_fuse_line_directives,
- options::OPT_fno_use_line_directives, false))
- CmdArgs.push_back("-fuse-line-directives");
+ Args.addOptInFlag(CmdArgs, options::OPT_fuse_line_directives,
+ options::OPT_fno_use_line_directives);
// -fno-minimize-whitespace is default.
if (Args.hasFlag(options::OPT_fminimize_whitespace,
@@ -6316,8 +6441,8 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,
StringRef Val = A->getValue();
Val = Val.empty() ? "0" : Val; // Treat "" as 0 or disable.
bool Invalid = GNUCVer.tryParse(Val);
- unsigned Minor = GNUCVer.getMinor().getValueOr(0);
- unsigned Patch = GNUCVer.getSubminor().getValueOr(0);
+ unsigned Minor = GNUCVer.getMinor().value_or(0);
+ unsigned Patch = GNUCVer.getSubminor().value_or(0);
if (Invalid || GNUCVer.getBuild() || Minor >= 100 || Patch >= 100) {
D.Diag(diag::err_drv_invalid_value)
<< A->getAsString(Args) << A->getValue();
@@ -6376,14 +6501,12 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,
CmdArgs.push_back(LanguageStandard.data());
}
- // -fno-borland-extensions is default.
- if (Args.hasFlag(options::OPT_fborland_extensions,
- options::OPT_fno_borland_extensions, false))
- CmdArgs.push_back("-fborland-extensions");
+ Args.addOptInFlag(CmdArgs, options::OPT_fborland_extensions,
+ options::OPT_fno_borland_extensions);
- // -fno-declspec is default, except for PS4.
+ // -fno-declspec is default, except for PS4/PS5.
if (Args.hasFlag(options::OPT_fdeclspec, options::OPT_fno_declspec,
- RawTriple.isPS4()))
+ RawTriple.isPS()))
CmdArgs.push_back("-fdeclspec");
else if (Args.hasArg(options::OPT_fno_declspec))
CmdArgs.push_back("-fno-declspec"); // Explicitly disabling __declspec.
@@ -6409,16 +6532,18 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,
Args.AddLastArg(CmdArgs, options::OPT_fgnu_keywords,
options::OPT_fno_gnu_keywords);
- if (Args.hasFlag(options::OPT_fgnu89_inline, options::OPT_fno_gnu89_inline,
- false))
- CmdArgs.push_back("-fgnu89-inline");
-
- if (Args.hasArg(options::OPT_fno_inline))
- CmdArgs.push_back("-fno-inline");
+ Args.addOptInFlag(CmdArgs, options::OPT_fgnu89_inline,
+ options::OPT_fno_gnu89_inline);
- Args.AddLastArg(CmdArgs, options::OPT_finline_functions,
- options::OPT_finline_hint_functions,
- options::OPT_fno_inline_functions);
+ const Arg *InlineArg = Args.getLastArg(options::OPT_finline_functions,
+ options::OPT_finline_hint_functions,
+ options::OPT_fno_inline_functions);
+ if (Arg *A = Args.getLastArg(options::OPT_finline, options::OPT_fno_inline)) {
+ if (A->getOption().matches(options::OPT_fno_inline))
+ A->render(Args, CmdArgs);
+ } else if (InlineArg) {
+ InlineArg->render(Args, CmdArgs);
+ }
// FIXME: Find a better way to determine whether the language has modules
// support by default, or just assume that all languages do.
@@ -6440,8 +6565,8 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,
false))
CmdArgs.push_back("-fmodules-debuginfo");
- Args.AddLastArg(CmdArgs, options::OPT_flegacy_pass_manager,
- options::OPT_fno_legacy_pass_manager);
+ if (!CLANG_ENABLE_OPAQUE_POINTERS_INTERNAL)
+ CmdArgs.push_back("-no-opaque-pointers");
ObjCRuntime Runtime = AddObjCRuntimeArgs(Args, Inputs, CmdArgs, rewriteKind);
RenderObjCOptions(TC, D, RawTriple, Args, Runtime, rewriteKind != RK_None,
@@ -6493,22 +6618,19 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,
}
// C++ "sane" operator new.
- if (!Args.hasFlag(options::OPT_fassume_sane_operator_new,
- options::OPT_fno_assume_sane_operator_new))
- CmdArgs.push_back("-fno-assume-sane-operator-new");
+ Args.addOptOutFlag(CmdArgs, options::OPT_fassume_sane_operator_new,
+ options::OPT_fno_assume_sane_operator_new);
// -frelaxed-template-template-args is off by default, as it is a severe
// breaking change until a corresponding change to template partial ordering
// is provided.
- if (Args.hasFlag(options::OPT_frelaxed_template_template_args,
- options::OPT_fno_relaxed_template_template_args, false))
- CmdArgs.push_back("-frelaxed-template-template-args");
+ Args.addOptInFlag(CmdArgs, options::OPT_frelaxed_template_template_args,
+ options::OPT_fno_relaxed_template_template_args);
// -fsized-deallocation is off by default, as it is an ABI-breaking change for
// most platforms.
- if (Args.hasFlag(options::OPT_fsized_deallocation,
- options::OPT_fno_sized_deallocation, false))
- CmdArgs.push_back("-fsized-deallocation");
+ Args.addOptInFlag(CmdArgs, options::OPT_fsized_deallocation,
+ options::OPT_fno_sized_deallocation);
// -faligned-allocation is on by default in C++17 onwards and otherwise off
// by default.
@@ -6531,15 +6653,13 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,
// -fconstant-cfstrings is default, and may be subject to argument translation
// on Darwin.
if (!Args.hasFlag(options::OPT_fconstant_cfstrings,
- options::OPT_fno_constant_cfstrings) ||
+ options::OPT_fno_constant_cfstrings, true) ||
!Args.hasFlag(options::OPT_mconstant_cfstrings,
- options::OPT_mno_constant_cfstrings))
+ options::OPT_mno_constant_cfstrings, true))
CmdArgs.push_back("-fno-constant-cfstrings");
- // -fno-pascal-strings is default, only pass non-default.
- if (Args.hasFlag(options::OPT_fpascal_strings,
- options::OPT_fno_pascal_strings, false))
- CmdArgs.push_back("-fpascal-strings");
+ Args.addOptInFlag(CmdArgs, options::OPT_fpascal_strings,
+ options::OPT_fno_pascal_strings);
// Honor -fpack-struct= and -fpack-struct, if given. Note that
// -fno-pack-struct doesn't apply to -fpack-struct=.
@@ -6571,18 +6691,17 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,
CmdArgs.push_back("-Qn");
// -fno-common is the default, set -fcommon only when that flag is set.
- if (Args.hasFlag(options::OPT_fcommon, options::OPT_fno_common, false))
- CmdArgs.push_back("-fcommon");
+ Args.addOptInFlag(CmdArgs, options::OPT_fcommon, options::OPT_fno_common);
// -fsigned-bitfields is default, and clang doesn't yet support
// -funsigned-bitfields.
if (!Args.hasFlag(options::OPT_fsigned_bitfields,
- options::OPT_funsigned_bitfields))
+ options::OPT_funsigned_bitfields, true))
D.Diag(diag::warn_drv_clang_unsupported)
<< Args.getLastArg(options::OPT_funsigned_bitfields)->getAsString(Args);
// -fsigned-bitfields is default, and clang doesn't support -fno-for-scope.
- if (!Args.hasFlag(options::OPT_ffor_scope, options::OPT_fno_for_scope))
+ if (!Args.hasFlag(options::OPT_ffor_scope, options::OPT_fno_for_scope, true))
D.Diag(diag::err_drv_clang_unsupported)
<< Args.getLastArg(options::OPT_fno_for_scope)->getAsString(Args);
@@ -6604,10 +6723,8 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,
RenderDiagnosticsOptions(D, Args, CmdArgs);
- // -fno-asm-blocks is default.
- if (Args.hasFlag(options::OPT_fasm_blocks, options::OPT_fno_asm_blocks,
- false))
- CmdArgs.push_back("-fasm-blocks");
+ Args.addOptInFlag(CmdArgs, options::OPT_fasm_blocks,
+ options::OPT_fno_asm_blocks);
// -fgnu-inline-asm is default.
if (!Args.hasFlag(options::OPT_fgnu_inline_asm,
@@ -6648,17 +6765,8 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,
CmdArgs.push_back("-fno-dollars-in-identifiers");
}
- // -funit-at-a-time is default, and we don't support -fno-unit-at-a-time for
- // practical purposes.
- if (Arg *A = Args.getLastArg(options::OPT_funit_at_a_time,
- options::OPT_fno_unit_at_a_time)) {
- if (A->getOption().matches(options::OPT_fno_unit_at_a_time))
- D.Diag(diag::warn_drv_clang_unsupported) << A->getAsString(Args);
- }
-
- if (Args.hasFlag(options::OPT_fapple_pragma_pack,
- options::OPT_fno_apple_pragma_pack, false))
- CmdArgs.push_back("-fapple-pragma-pack");
+ Args.addOptInFlag(CmdArgs, options::OPT_fapple_pragma_pack,
+ options::OPT_fno_apple_pragma_pack);
if (Args.hasFlag(options::OPT_fxl_pragma_pack,
options::OPT_fno_xl_pragma_pack, RawTriple.isOSAIX()))
@@ -6673,6 +6781,10 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,
if (RewriteImports)
CmdArgs.push_back("-frewrite-imports");
+ if (Args.hasFlag(options::OPT_fdirectives_only,
+ options::OPT_fno_directives_only, false))
+ CmdArgs.push_back("-fdirectives-only");
+
// Enable rewrite includes if the user's asked for it or if we're generating
// diagnostics.
// TODO: Once -module-dependency-dir works with -frewrite-includes it'd be
@@ -6871,8 +6983,10 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,
CmdArgs.push_back(Args.MakeArgString(Twine("-cuid=") + Twine(CUID)));
}
- if (IsHIP)
+ if (IsHIP) {
CmdArgs.push_back("-fcuda-allow-variadic-functions");
+ Args.AddLastArg(CmdArgs, options::OPT_fgpu_default_stream_EQ);
+ }
if (IsCudaDevice || IsHIPDevice) {
StringRef InlineThresh =
@@ -6897,50 +7011,29 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,
}
}
- // Host-side OpenMP offloading recieves the device object files and embeds it
- // in a named section including the associated target triple and architecture.
- if (IsOpenMPHost && !OpenMPHostInputs.empty()) {
- auto InputFile = OpenMPHostInputs.begin();
- auto OpenMPTCs = C.getOffloadToolChains<Action::OFK_OpenMP>();
- for (auto TI = OpenMPTCs.first, TE = OpenMPTCs.second; TI != TE;
- ++TI, ++InputFile) {
- const ToolChain *TC = TI->second;
- const ArgList &TCArgs = C.getArgsForToolChain(TC, "", Action::OFK_OpenMP);
- StringRef File =
- C.getArgs().MakeArgString(TC->getInputFilename(*InputFile));
- StringRef InputName = Clang::getBaseInputStem(Args, Inputs);
-
- CmdArgs.push_back(Args.MakeArgString(
- "-fembed-offload-object=" + File + "," + TC->getTripleString() + "." +
- TCArgs.getLastArgValue(options::OPT_march_EQ) + "." + InputName));
- }
- }
+ // Host-side offloading recieves the device object files and embeds it in a
+ // named section including the associated target triple and architecture.
+ for (const InputInfo Input : HostOffloadingInputs)
+ CmdArgs.push_back(Args.MakeArgString("-fembed-offload-object=" +
+ TC.getInputFilename(Input)));
if (Triple.isAMDGPU()) {
handleAMDGPUCodeObjectVersionOptions(D, Args, CmdArgs);
- if (Args.hasFlag(options::OPT_munsafe_fp_atomics,
- options::OPT_mno_unsafe_fp_atomics, /*Default=*/false))
- CmdArgs.push_back("-munsafe-fp-atomics");
+ Args.addOptInFlag(CmdArgs, options::OPT_munsafe_fp_atomics,
+ options::OPT_mno_unsafe_fp_atomics);
}
// For all the host OpenMP offloading compile jobs we need to pass the targets
// information using -fopenmp-targets= option.
if (JA.isHostOffloading(Action::OFK_OpenMP)) {
- SmallString<128> TargetInfo("-fopenmp-targets=");
+ SmallString<128> Targets("-fopenmp-targets=");
- Arg *Tgts = Args.getLastArg(options::OPT_fopenmp_targets_EQ);
- assert(Tgts && Tgts->getNumValues() &&
- "OpenMP offloading has to have targets specified.");
- for (unsigned i = 0; i < Tgts->getNumValues(); ++i) {
- if (i)
- TargetInfo += ',';
- // We need to get the string from the triple because it may be not exactly
- // the same as the one we get directly from the arguments.
- llvm::Triple T(Tgts->getValue(i));
- TargetInfo += T.getTriple();
- }
- CmdArgs.push_back(Args.MakeArgString(TargetInfo.str()));
+ SmallVector<std::string, 4> Triples;
+ auto TCRange = C.getOffloadToolChains<Action::OFK_OpenMP>();
+ std::transform(TCRange.first, TCRange.second, std::back_inserter(Triples),
+ [](auto TC) { return TC.second->getTripleString(); });
+ CmdArgs.push_back(Args.MakeArgString(Targets + llvm::join(Triples, ",")));
}
bool VirtualFunctionElimination =
@@ -7041,13 +7134,10 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,
CmdArgs.push_back("-fforce-enable-int128");
}
- if (Args.hasFlag(options::OPT_fkeep_static_consts,
- options::OPT_fno_keep_static_consts, false))
- CmdArgs.push_back("-fkeep-static-consts");
-
- if (Args.hasFlag(options::OPT_fcomplete_member_pointers,
- options::OPT_fno_complete_member_pointers, false))
- CmdArgs.push_back("-fcomplete-member-pointers");
+ Args.addOptInFlag(CmdArgs, options::OPT_fkeep_static_consts,
+ options::OPT_fno_keep_static_consts);
+ Args.addOptInFlag(CmdArgs, options::OPT_fcomplete_member_pointers,
+ options::OPT_fno_complete_member_pointers);
if (!Args.hasFlag(options::OPT_fcxx_static_destructors,
options::OPT_fno_cxx_static_destructors, true))
@@ -7127,6 +7217,8 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,
ArrayRef<InputInfo> FrontendInputs = Input;
if (IsHeaderModulePrecompile)
FrontendInputs = ModuleHeaderInputs;
+ else if (IsExtractAPI)
+ FrontendInputs = ExtractAPIInputs;
else if (Input.isNothing())
FrontendInputs = {};
@@ -7378,6 +7470,12 @@ static EHFlags parseClangCLEHFlags(const Driver &D, const ArgList &Args) {
EH.NoUnwindC = true;
}
+ if (Args.hasArg(options::OPT__SLASH_kernel)) {
+ EH.Synch = false;
+ EH.NoUnwindC = false;
+ EH.Asynch = false;
+ }
+
return EH;
}
@@ -7473,6 +7571,17 @@ void Clang::AddClangCLArgs(const ArgList &Args, types::ID InputType,
}
const Driver &D = getToolChain().getDriver();
+
+ // This controls whether or not we perform JustMyCode instrumentation.
+ if (Args.hasFlag(options::OPT__SLASH_JMC, options::OPT__SLASH_JMC_,
+ /*Default=*/false)) {
+ if (*EmitCodeView && *DebugInfoKind >= codegenoptions::DebugInfoConstructor)
+ CmdArgs.push_back("-fjmc");
+ else
+ D.Diag(clang::diag::warn_drv_jmc_requires_debuginfo) << "/JMC"
+ << "'/Zi', '/Z7'";
+ }
+
EHFlags EH = parseClangCLEHFlags(D, Args);
if (!isNVPTX && (EH.Synch || EH.Asynch)) {
if (types::isCXX(InputType))
@@ -7506,6 +7615,32 @@ void Clang::AddClangCLArgs(const ArgList &Args, types::ID InputType,
CmdArgs.push_back("-fno-dllexport-inlines");
}
+ if (Args.hasFlag(options::OPT__SLASH_Zc_wchar_t_,
+ options::OPT__SLASH_Zc_wchar_t, false)) {
+ CmdArgs.push_back("-fno-wchar");
+ }
+
+ if (Args.hasArg(options::OPT__SLASH_kernel)) {
+ llvm::Triple::ArchType Arch = getToolChain().getArch();
+ std::vector<std::string> Values =
+ Args.getAllArgValues(options::OPT__SLASH_arch);
+ if (!Values.empty()) {
+ llvm::SmallSet<std::string, 4> SupportedArches;
+ if (Arch == llvm::Triple::x86)
+ SupportedArches.insert("IA32");
+
+ for (auto &V : Values)
+ if (!SupportedArches.contains(V))
+ D.Diag(diag::err_drv_argument_not_allowed_with)
+ << std::string("/arch:").append(V) << "/kernel";
+ }
+
+ CmdArgs.push_back("-fno-rtti");
+ if (Args.hasFlag(options::OPT__SLASH_GR, options::OPT__SLASH_GR_, false))
+ D.Diag(diag::err_drv_argument_not_allowed_with) << "/GR"
+ << "/kernel";
+ }
+
Arg *MostGeneralArg = Args.getLastArg(options::OPT__SLASH_vmg);
Arg *BestCaseArg = Args.getLastArg(options::OPT__SLASH_vmb);
if (MostGeneralArg && BestCaseArg)
@@ -7575,6 +7710,9 @@ void Clang::AddClangCLArgs(const ArgList &Args, types::ID InputType,
CmdArgs.push_back("msvc");
}
+ if (Args.hasArg(options::OPT__SLASH_kernel))
+ CmdArgs.push_back("-fms-kernel");
+
if (Arg *A = Args.getLastArg(options::OPT__SLASH_guard)) {
StringRef GuardArgs = A->getValue();
// The only valid options are "cf", "cf,nochecks", "cf-", "ehcont" and
@@ -7675,6 +7813,8 @@ void ClangAs::ConstructJob(Compilation &C, const JobAction &JA,
const llvm::Triple &Triple = getToolChain().getEffectiveTriple();
const std::string &TripleStr = Triple.getTriple();
+ const Optional<llvm::Triple> TargetVariantTriple =
+ getToolChain().getTargetVariantTriple();
const auto &D = getToolChain().getDriver();
// Don't warn about "clang -w -c foo.s"
@@ -7692,6 +7832,10 @@ void ClangAs::ConstructJob(Compilation &C, const JobAction &JA,
// Add the "effective" target triple.
CmdArgs.push_back("-triple");
CmdArgs.push_back(Args.MakeArgString(TripleStr));
+ if (TargetVariantTriple) {
+ CmdArgs.push_back("-darwin-target-variant-triple");
+ CmdArgs.push_back(Args.MakeArgString(TargetVariantTriple->getTriple()));
+ }
// Set the output mode, we currently only expect to be used as a real
// assembler.
@@ -7759,7 +7903,8 @@ void ClangAs::ConstructJob(Compilation &C, const JobAction &JA,
DebugInfoKind = (WantDebug ? codegenoptions::DebugInfoConstructor
: codegenoptions::NoDebugInfo);
- addDebugPrefixMapArg(getToolChain().getDriver(), Args, CmdArgs);
+ addDebugPrefixMapArg(getToolChain().getDriver(), getToolChain(), Args,
+ CmdArgs);
// Set the AT_producer to the clang version when using the integrated
// assembler on assembly source files.
@@ -7774,7 +7919,6 @@ void ClangAs::ConstructJob(Compilation &C, const JobAction &JA,
renderDwarfFormat(D, Triple, Args, CmdArgs, DwarfVersion);
RenderDebugInfoCompressionArgs(Args, CmdArgs, D, getToolChain());
-
// Handle -fPIC et al -- the relocation-model affects the assembler
// for some targets.
llvm::Reloc::Model RelocationModel;
@@ -7904,7 +8048,7 @@ void ClangAs::ConstructJob(Compilation &C, const JobAction &JA,
}
if (Triple.isAMDGPU())
- handleAMDGPUCodeObjectVersionOptions(D, Args, CmdArgs);
+ handleAMDGPUCodeObjectVersionOptions(D, Args, CmdArgs, /*IsCC1As=*/true);
assert(Input.isFilename() && "Invalid input.");
CmdArgs.push_back(Input.getFilename());
@@ -7935,8 +8079,10 @@ void OffloadBundler::ConstructJob(Compilation &C, const JobAction &JA,
// The bundling command looks like this:
// clang-offload-bundler -type=bc
// -targets=host-triple,openmp-triple1,openmp-triple2
- // -outputs=input_file
- // -inputs=unbundle_file_host,unbundle_file_tgt1,unbundle_file_tgt2"
+ // -output=output_file
+ // -input=unbundle_file_host
+ // -input=unbundle_file_tgt1
+ // -input=unbundle_file_tgt2
ArgStringList CmdArgs;
@@ -7997,14 +8143,12 @@ void OffloadBundler::ConstructJob(Compilation &C, const JobAction &JA,
// Get bundled file command.
CmdArgs.push_back(
- TCArgs.MakeArgString(Twine("-outputs=") + Output.getFilename()));
+ TCArgs.MakeArgString(Twine("-output=") + Output.getFilename()));
// Get unbundled files command.
- SmallString<128> UB;
- UB += "-inputs=";
for (unsigned I = 0; I < Inputs.size(); ++I) {
- if (I)
- UB += ',';
+ SmallString<128> UB;
+ UB += "-input=";
// Find ToolChain for this input.
const ToolChain *CurTC = &getToolChain();
@@ -8019,9 +8163,8 @@ void OffloadBundler::ConstructJob(Compilation &C, const JobAction &JA,
} else {
UB += CurTC->getInputFilename(Inputs[I]);
}
+ CmdArgs.push_back(TCArgs.MakeArgString(UB));
}
- CmdArgs.push_back(TCArgs.MakeArgString(UB));
-
// All the inputs are encoded as commands.
C.addCommand(std::make_unique<Command>(
JA, *this, ResponseFileSupport::None(),
@@ -8039,8 +8182,10 @@ void OffloadBundler::ConstructJobMultipleOutputs(
// The unbundling command looks like this:
// clang-offload-bundler -type=bc
// -targets=host-triple,openmp-triple1,openmp-triple2
- // -inputs=input_file
- // -outputs=unbundle_file_host,unbundle_file_tgt1,unbundle_file_tgt2"
+ // -input=input_file
+ // -output=unbundle_file_host
+ // -output=unbundle_file_tgt1
+ // -output=unbundle_file_tgt2
// -unbundle
ArgStringList CmdArgs;
@@ -8092,17 +8237,15 @@ void OffloadBundler::ConstructJobMultipleOutputs(
// Get bundled file command.
CmdArgs.push_back(
- TCArgs.MakeArgString(Twine("-inputs=") + Input.getFilename()));
+ TCArgs.MakeArgString(Twine("-input=") + Input.getFilename()));
// Get unbundled files command.
- SmallString<128> UB;
- UB += "-outputs=";
for (unsigned I = 0; I < Outputs.size(); ++I) {
- if (I)
- UB += ',';
+ SmallString<128> UB;
+ UB += "-output=";
UB += DepInfo[I].DependentToolChain->getInputFilename(Outputs[I]);
+ CmdArgs.push_back(TCArgs.MakeArgString(UB));
}
- CmdArgs.push_back(TCArgs.MakeArgString(UB));
CmdArgs.push_back("-unbundle");
CmdArgs.push_back("-allow-missing-bundles");
@@ -8143,54 +8286,107 @@ void OffloadWrapper::ConstructJob(Compilation &C, const JobAction &JA,
CmdArgs, Inputs, Output));
}
+void OffloadPackager::ConstructJob(Compilation &C, const JobAction &JA,
+ const InputInfo &Output,
+ const InputInfoList &Inputs,
+ const llvm::opt::ArgList &Args,
+ const char *LinkingOutput) const {
+ ArgStringList CmdArgs;
+
+ // Add the output file name.
+ assert(Output.isFilename() && "Invalid output.");
+ CmdArgs.push_back("-o");
+ CmdArgs.push_back(Output.getFilename());
+
+ // Create the inputs to bundle the needed metadata.
+ for (const InputInfo &Input : Inputs) {
+ const Action *OffloadAction = Input.getAction();
+ const ToolChain *TC = OffloadAction->getOffloadingToolChain();
+ const ArgList &TCArgs =
+ C.getArgsForToolChain(TC, OffloadAction->getOffloadingArch(),
+ OffloadAction->getOffloadingDeviceKind());
+ StringRef File = C.getArgs().MakeArgString(TC->getInputFilename(Input));
+ StringRef Arch = (OffloadAction->getOffloadingArch())
+ ? OffloadAction->getOffloadingArch()
+ : TCArgs.getLastArgValue(options::OPT_march_EQ);
+ StringRef Kind =
+ Action::GetOffloadKindName(OffloadAction->getOffloadingDeviceKind());
+
+ ArgStringList Features;
+ SmallVector<StringRef> FeatureArgs;
+ getTargetFeatures(TC->getDriver(), TC->getTriple(), Args, Features, false);
+ llvm::copy_if(Features, std::back_inserter(FeatureArgs),
+ [](StringRef Arg) { return !Arg.startswith("-target"); });
+
+ SmallVector<std::string> Parts{
+ "file=" + File.str(),
+ "triple=" + TC->getTripleString(),
+ "arch=" + Arch.str(),
+ "kind=" + Kind.str(),
+ };
+
+ if (TC->getDriver().isUsingLTO(/* IsOffload */ true))
+ for (StringRef Feature : FeatureArgs)
+ Parts.emplace_back("feature=" + Feature.str());
+
+ CmdArgs.push_back(Args.MakeArgString("--image=" + llvm::join(Parts, ",")));
+ }
+
+ C.addCommand(std::make_unique<Command>(
+ JA, *this, ResponseFileSupport::None(),
+ Args.MakeArgString(getToolChain().GetProgramPath(getShortName())),
+ CmdArgs, Inputs, Output));
+}
+
void LinkerWrapper::ConstructJob(Compilation &C, const JobAction &JA,
const InputInfo &Output,
const InputInfoList &Inputs,
const ArgList &Args,
const char *LinkingOutput) const {
+ const Driver &D = getToolChain().getDriver();
+ const llvm::Triple TheTriple = getToolChain().getTriple();
+ auto OpenMPTCRange = C.getOffloadToolChains<Action::OFK_OpenMP>();
ArgStringList CmdArgs;
- if (getToolChain().getDriver().isUsingLTO(/* IsOffload */ true)) {
- // Pass in target features for each toolchain.
- auto OpenMPTCRange = C.getOffloadToolChains<Action::OFK_OpenMP>();
- for (auto &I :
- llvm::make_range(OpenMPTCRange.first, OpenMPTCRange.second)) {
+ // Pass the CUDA path to the linker wrapper tool.
+ for (Action::OffloadKind Kind : {Action::OFK_Cuda, Action::OFK_OpenMP}) {
+ auto TCRange = C.getOffloadToolChains(Kind);
+ for (auto &I : llvm::make_range(TCRange.first, TCRange.second)) {
const ToolChain *TC = I.second;
- const ArgList &TCArgs = C.getArgsForToolChain(TC, "", Action::OFK_OpenMP);
- ArgStringList FeatureArgs;
- TC->addClangTargetOptions(TCArgs, FeatureArgs, Action::OFK_OpenMP);
- auto FeatureIt = llvm::find(FeatureArgs, "-target-feature");
- CmdArgs.push_back(Args.MakeArgString(
- "-target-feature=" + TC->getTripleString() + "=" + *(FeatureIt + 1)));
+ if (TC->getTriple().isNVPTX()) {
+ CudaInstallationDetector CudaInstallation(D, TheTriple, Args);
+ if (CudaInstallation.isValid())
+ CmdArgs.push_back(Args.MakeArgString(
+ "--cuda-path=" + CudaInstallation.getInstallPath()));
+ break;
+ }
}
+ }
- // Pass in the bitcode library to be linked during LTO.
- for (auto &I : llvm::make_range(OpenMPTCRange.first, OpenMPTCRange.second)) {
- const ToolChain *TC = I.second;
- const Driver &D = TC->getDriver();
- const ArgList &TCArgs = C.getArgsForToolChain(TC, "", Action::OFK_OpenMP);
- StringRef Arch = TCArgs.getLastArgValue(options::OPT_march_EQ);
+ // Get the AMDGPU math libraries.
+ // FIXME: This method is bad, remove once AMDGPU has a proper math library
+ // (see AMDGCN::OpenMPLinker::constructLLVMLinkCommand).
+ for (auto &I : llvm::make_range(OpenMPTCRange.first, OpenMPTCRange.second)) {
+ const ToolChain *TC = I.second;
- std::string BitcodeSuffix;
- if (TCArgs.hasFlag(options::OPT_fopenmp_target_new_runtime,
- options::OPT_fno_openmp_target_new_runtime, true))
- BitcodeSuffix += "new-";
- if (TC->getTriple().isNVPTX())
- BitcodeSuffix += "nvptx-";
- else if (TC->getTriple().isAMDGPU())
- BitcodeSuffix += "amdgpu-";
- BitcodeSuffix += Arch;
+ if (!TC->getTriple().isAMDGPU() || Args.hasArg(options::OPT_nogpulib))
+ continue;
- ArgStringList BitcodeLibrary;
- addOpenMPDeviceRTL(D, TCArgs, BitcodeLibrary, BitcodeSuffix,
- TC->getTriple());
+ const ArgList &TCArgs = C.getArgsForToolChain(TC, "", Action::OFK_OpenMP);
+ StringRef Arch = TCArgs.getLastArgValue(options::OPT_march_EQ);
+ const toolchains::ROCMToolChain RocmTC(TC->getDriver(), TC->getTriple(),
+ TCArgs);
- if (!BitcodeLibrary.empty())
- CmdArgs.push_back(
- Args.MakeArgString("-target-library=" + TC->getTripleString() +
- "-" + Arch + "=" + BitcodeLibrary.back()));
- }
+ SmallVector<std::string, 12> BCLibs =
+ RocmTC.getCommonDeviceLibNames(TCArgs, Arch.str());
+ for (StringRef LibName : BCLibs)
+ CmdArgs.push_back(Args.MakeArgString(
+ "-target-library=" + Action::GetOffloadKindName(Action::OFK_OpenMP) +
+ "-" + TC->getTripleString() + "-" + Arch + "=" + LibName));
+ }
+
+ if (D.isUsingLTO(/* IsOffload */ true)) {
// Pass in the optimization level to use for LTO.
if (const Arg *A = Args.getLastArg(options::OPT_O_Group)) {
StringRef OOpt;
@@ -8210,12 +8406,8 @@ void LinkerWrapper::ConstructJob(Compilation &C, const JobAction &JA,
}
}
- // Construct the link job so we can wrap around it.
- Linker->ConstructJob(C, JA, Output, Inputs, Args, LinkingOutput);
- const auto &LinkCommand = C.getJobs().getJobs().back();
-
CmdArgs.push_back("-host-triple");
- CmdArgs.push_back(Args.MakeArgString(getToolChain().getTripleString()));
+ CmdArgs.push_back(Args.MakeArgString(TheTriple.getTriple()));
if (Args.hasArg(options::OPT_v))
CmdArgs.push_back("-v");
@@ -8246,6 +8438,24 @@ void LinkerWrapper::ConstructJob(Compilation &C, const JobAction &JA,
if (Args.getLastArg(options::OPT_save_temps_EQ))
CmdArgs.push_back("-save-temps");
+ // Construct the link job so we can wrap around it.
+ Linker->ConstructJob(C, JA, Output, Inputs, Args, LinkingOutput);
+ const auto &LinkCommand = C.getJobs().getJobs().back();
+
+ // Forward -Xoffload-linker<-triple> arguments to the device link job.
+ for (auto *Arg : Args.filtered(options::OPT_Xoffload_linker)) {
+ StringRef Val = Arg->getValue(0);
+ if (Val.empty())
+ CmdArgs.push_back(
+ Args.MakeArgString(Twine("-device-linker=") + Arg->getValue(1)));
+ else
+ CmdArgs.push_back(Args.MakeArgString(
+ "-device-linker=" +
+ ToolChain::getOpenMPTriple(Val.drop_front()).getTriple() + "=" +
+ Arg->getValue(1)));
+ }
+ Args.ClaimAllArgs(options::OPT_Xoffload_linker);
+
// Add the linker arguments to be forwarded by the wrapper.
CmdArgs.push_back("-linker-path");
CmdArgs.push_back(LinkCommand->getExecutable());
diff --git a/clang/lib/Driver/ToolChains/Clang.h b/clang/lib/Driver/ToolChains/Clang.h
index 79407c9884d5..37263efd57a5 100644
--- a/clang/lib/Driver/ToolChains/Clang.h
+++ b/clang/lib/Driver/ToolChains/Clang.h
@@ -170,6 +170,19 @@ public:
const char *LinkingOutput) const override;
};
+/// Offload binary tool.
+class LLVM_LIBRARY_VISIBILITY OffloadPackager final : public Tool {
+public:
+ OffloadPackager(const ToolChain &TC)
+ : Tool("Offload::Packager", "clang-offload-packager", TC) {}
+
+ bool hasIntegratedCPP() const override { return false; }
+ void ConstructJob(Compilation &C, const JobAction &JA,
+ const InputInfo &Output, const InputInfoList &Inputs,
+ const llvm::opt::ArgList &TCArgs,
+ const char *LinkingOutput) const override;
+};
+
/// Linker wrapper tool.
class LLVM_LIBRARY_VISIBILITY LinkerWrapper final : public Tool {
const Tool *Linker;
diff --git a/clang/lib/Driver/ToolChains/CommonArgs.cpp b/clang/lib/Driver/ToolChains/CommonArgs.cpp
index 6364cd133e0b..2d53b829b01c 100644
--- a/clang/lib/Driver/ToolChains/CommonArgs.cpp
+++ b/clang/lib/Driver/ToolChains/CommonArgs.cpp
@@ -143,28 +143,16 @@ void tools::handleTargetFeaturesGroup(const ArgList &Args,
}
}
-std::vector<StringRef>
-tools::unifyTargetFeatures(const std::vector<StringRef> &Features) {
- std::vector<StringRef> UnifiedFeatures;
- // Find the last of each feature.
- llvm::StringMap<unsigned> LastOpt;
- for (unsigned I = 0, N = Features.size(); I < N; ++I) {
- StringRef Name = Features[I];
- assert(Name[0] == '-' || Name[0] == '+');
- LastOpt[Name.drop_front(1)] = I;
+SmallVector<StringRef>
+tools::unifyTargetFeatures(ArrayRef<StringRef> Features) {
+ // Only add a feature if it hasn't been seen before starting from the end.
+ SmallVector<StringRef> UnifiedFeatures;
+ llvm::DenseSet<StringRef> UsedFeatures;
+ for (StringRef Feature : llvm::reverse(Features)) {
+ if (UsedFeatures.insert(Feature.drop_front()).second)
+ UnifiedFeatures.insert(UnifiedFeatures.begin(), Feature);
}
- for (unsigned I = 0, N = Features.size(); I < N; ++I) {
- // If this feature was overridden, ignore it.
- StringRef Name = Features[I];
- llvm::StringMap<unsigned>::iterator LastI = LastOpt.find(Name.drop_front(1));
- assert(LastI != LastOpt.end());
- unsigned Last = LastI->second;
- if (Last != I)
- continue;
-
- UnifiedFeatures.push_back(Name);
- }
return UnifiedFeatures;
}
@@ -255,6 +243,10 @@ void tools::AddLinkerInputs(const ToolChain &TC, const InputInfoList &Inputs,
continue;
}
+ // In some error cases, the input could be Nothing; skip those.
+ if (II.isNothing())
+ continue;
+
// Otherwise, this is a linker input argument.
const Arg &A = II.getInputArg();
@@ -424,6 +416,13 @@ std::string tools::getCPUName(const Driver &D, const ArgList &Args,
return TargetCPUName;
}
+ case llvm::Triple::csky:
+ if (const Arg *A = Args.getLastArg(options::OPT_mcpu_EQ))
+ return A->getValue();
+ else if (const Arg *A = Args.getLastArg(options::OPT_march_EQ))
+ return A->getValue();
+ else
+ return "ck810";
case llvm::Triple::riscv32:
case llvm::Triple::riscv64:
if (const Arg *A = Args.getLastArg(options::OPT_mcpu_EQ))
@@ -475,9 +474,9 @@ llvm::StringRef tools::getLTOParallelism(const ArgList &Args, const Driver &D) {
return LtoJobsArg->getValue();
}
-// CloudABI uses -ffunction-sections and -fdata-sections by default.
+// CloudABI and PS4/PS5 use -ffunction-sections and -fdata-sections by default.
bool tools::isUseSeparateSections(const llvm::Triple &Triple) {
- return Triple.getOS() == llvm::Triple::CloudABI;
+ return Triple.getOS() == llvm::Triple::CloudABI || Triple.isPS();
}
void tools::addLTOOptions(const ToolChain &ToolChain, const ArgList &Args,
@@ -548,6 +547,9 @@ void tools::addLTOOptions(const ToolChain &ToolChain, const ArgList &Args,
CmdArgs.push_back(
Args.MakeArgString("-plugin-opt=jobs=" + Twine(Parallelism)));
+ if (!CLANG_ENABLE_OPAQUE_POINTERS_INTERNAL)
+ CmdArgs.push_back(Args.MakeArgString("-plugin-opt=no-opaque-pointers"));
+
// If an explicit debugger tuning argument appeared, pass it along.
if (Arg *A = Args.getLastArg(options::OPT_gTune_Group,
options::OPT_ggdbN_Group)) {
@@ -574,6 +576,13 @@ void tools::addLTOOptions(const ToolChain &ToolChain, const ArgList &Args,
CmdArgs.push_back("-plugin-opt=-data-sections");
}
+ // Pass an option to enable split machine functions.
+ if (auto *A = Args.getLastArg(options::OPT_fsplit_machine_functions,
+ options::OPT_fno_split_machine_functions)) {
+ if (A->getOption().matches(options::OPT_fsplit_machine_functions))
+ CmdArgs.push_back("-plugin-opt=-split-machine-functions");
+ }
+
if (Arg *A = getLastProfileSampleUseArg(Args)) {
StringRef FName = A->getValue();
if (!llvm::sys::fs::exists(FName))
@@ -612,15 +621,6 @@ void tools::addLTOOptions(const ToolChain &ToolChain, const ArgList &Args,
Path));
}
- // Pass an option to enable/disable the new pass manager.
- if (auto *A = Args.getLastArg(options::OPT_flegacy_pass_manager,
- options::OPT_fno_legacy_pass_manager)) {
- if (A->getOption().matches(options::OPT_flegacy_pass_manager))
- CmdArgs.push_back("-plugin-opt=legacy-pass-manager");
- else
- CmdArgs.push_back("-plugin-opt=new-pass-manager");
- }
-
// Setup statistics file output.
SmallString<128> StatsFile = getStatsFileName(Args, Output, Input, D);
if (!StatsFile.empty())
@@ -661,6 +661,17 @@ void tools::addOpenMPRuntimeSpecificRPath(const ToolChain &TC,
}
}
+void tools::addOpenMPRuntimeLibraryPath(const ToolChain &TC,
+ const ArgList &Args,
+ ArgStringList &CmdArgs) {
+ // Default to clang lib / lib64 folder, i.e. the same location as device
+ // runtime.
+ SmallString<256> DefaultLibPath =
+ llvm::sys::path::parent_path(TC.getDriver().Dir);
+ llvm::sys::path::append(DefaultLibPath, Twine("lib") + CLANG_LIBDIR_SUFFIX);
+ CmdArgs.push_back(Args.MakeArgString("-L" + DefaultLibPath));
+}
+
void tools::addArchSpecificRPath(const ToolChain &TC, const ArgList &Args,
ArgStringList &CmdArgs) {
// Enable -frtlib-add-rpath by default for the case of VE.
@@ -716,14 +727,53 @@ bool tools::addOpenMPRuntime(ArgStringList &CmdArgs, const ToolChain &TC,
if (IsOffloadingHost)
CmdArgs.push_back("-lomptarget");
+ if (IsOffloadingHost && TC.getDriver().isUsingLTO(/* IsOffload */ true))
+ CmdArgs.push_back("-lomptarget.devicertl");
+
addArchSpecificRPath(TC, Args, CmdArgs);
if (RTKind == Driver::OMPRT_OMP)
addOpenMPRuntimeSpecificRPath(TC, Args, CmdArgs);
+ addOpenMPRuntimeLibraryPath(TC, Args, CmdArgs);
return true;
}
+void tools::addFortranRuntimeLibs(const ToolChain &TC,
+ llvm::opt::ArgStringList &CmdArgs) {
+ if (TC.getTriple().isKnownWindowsMSVCEnvironment()) {
+ CmdArgs.push_back("Fortran_main.lib");
+ CmdArgs.push_back("FortranRuntime.lib");
+ CmdArgs.push_back("FortranDecimal.lib");
+ } else {
+ CmdArgs.push_back("-lFortran_main");
+ CmdArgs.push_back("-lFortranRuntime");
+ CmdArgs.push_back("-lFortranDecimal");
+ }
+}
+
+void tools::addFortranRuntimeLibraryPath(const ToolChain &TC,
+ const llvm::opt::ArgList &Args,
+ ArgStringList &CmdArgs) {
+ // NOTE: Generating executables by Flang is considered an "experimental"
+ // feature and hence this is guarded with a command line option.
+ // TODO: Make this work unconditionally once Flang is mature enough.
+ if (!Args.hasArg(options::OPT_flang_experimental_exec))
+ return;
+
+ // Default to the <driver-path>/../lib directory. This works fine on the
+ // platforms that we have tested so far. We will probably have to re-fine
+ // this in the future. In particular, on some platforms, we may need to use
+ // lib64 instead of lib.
+ SmallString<256> DefaultLibPath =
+ llvm::sys::path::parent_path(TC.getDriver().Dir);
+ llvm::sys::path::append(DefaultLibPath, "lib");
+ if (TC.getTriple().isKnownWindowsMSVCEnvironment())
+ CmdArgs.push_back(Args.MakeArgString("-libpath:" + DefaultLibPath));
+ else
+ CmdArgs.push_back(Args.MakeArgString("-L" + DefaultLibPath));
+}
+
static void addSanitizerRuntime(const ToolChain &TC, const ArgList &Args,
ArgStringList &CmdArgs, StringRef Sanitizer,
bool IsShared, bool IsWhole) {
@@ -756,7 +806,7 @@ static bool addSanitizerDynamicList(const ToolChain &TC, const ArgList &Args,
return false;
}
-static const char *getAsNeededOption(const ToolChain &TC, bool as_needed) {
+const char *tools::getAsNeededOption(const ToolChain &TC, bool as_needed) {
assert(!TC.getTriple().isOSAIX() &&
"AIX linker does not support any form of --as-needed option yet.");
@@ -771,11 +821,6 @@ static const char *getAsNeededOption(const ToolChain &TC, bool as_needed) {
void tools::linkSanitizerRuntimeDeps(const ToolChain &TC,
ArgStringList &CmdArgs) {
- // Fuchsia never needs these. Any sanitizer runtimes with system
- // dependencies use the `.deplibs` feature instead.
- if (TC.getTriple().isOSFuchsia())
- return;
-
// Force linking against the system libraries sanitizers depends on
// (see PR15823 why this is necessary).
CmdArgs.push_back(getAsNeededOption(TC, false));
@@ -797,6 +842,12 @@ void tools::linkSanitizerRuntimeDeps(const ToolChain &TC,
TC.getTriple().isOSNetBSD() ||
TC.getTriple().isOSOpenBSD())
CmdArgs.push_back("-lexecinfo");
+ // There is no libresolv on Android, FreeBSD, OpenBSD, etc. On musl
+ // libresolv.a, even if exists, is an empty archive to satisfy POSIX -lresolv
+ // requirement.
+ if (TC.getTriple().isOSLinux() && !TC.getTriple().isAndroid() &&
+ !TC.getTriple().isMusl())
+ CmdArgs.push_back("-lresolv");
}
static void
@@ -838,6 +889,8 @@ collectSanitizerRuntimes(const ToolChain &TC, const ArgList &Args,
SharedRuntimes.push_back("hwasan_aliases");
else
SharedRuntimes.push_back("hwasan");
+ if (!Args.hasArg(options::OPT_shared))
+ HelperStaticRuntimes.push_back("hwasan-preinit");
}
}
@@ -991,6 +1044,19 @@ bool tools::addSanitizerRuntimes(const ToolChain &TC, const ArgList &Args,
if (SanArgs.hasCrossDsoCfi() && !AddExportDynamic)
CmdArgs.push_back("--export-dynamic-symbol=__cfi_check");
+ if (SanArgs.hasMemTag()) {
+ if (!TC.getTriple().isAndroid()) {
+ TC.getDriver().Diag(diag::err_drv_unsupported_opt_for_target)
+ << "-fsanitize=memtag*" << TC.getTriple().str();
+ }
+ CmdArgs.push_back(
+ Args.MakeArgString("--android-memtag-mode=" + SanArgs.getMemtagMode()));
+ if (SanArgs.hasMemtagHeap())
+ CmdArgs.push_back("--android-memtag-heap");
+ if (SanArgs.hasMemtagStack())
+ CmdArgs.push_back("--android-memtag-stack");
+ }
+
return !StaticRuntimes.empty() || !NonWholeStaticRuntimes.empty();
}
@@ -1233,30 +1299,31 @@ tools::ParsePICArgs(const ToolChain &ToolChain, const ArgList &Args) {
O.matches(options::OPT_fPIE) || O.matches(options::OPT_fPIC);
} else {
PIE = PIC = false;
- if (EffectiveTriple.isPS4CPU()) {
+ if (EffectiveTriple.isPS()) {
Arg *ModelArg = Args.getLastArg(options::OPT_mcmodel_EQ);
StringRef Model = ModelArg ? ModelArg->getValue() : "";
if (Model != "kernel") {
PIC = true;
- ToolChain.getDriver().Diag(diag::warn_drv_ps4_force_pic)
- << LastPICArg->getSpelling();
+ ToolChain.getDriver().Diag(diag::warn_drv_ps_force_pic)
+ << LastPICArg->getSpelling()
+ << (EffectiveTriple.isPS4() ? "PS4" : "PS5");
}
}
}
}
}
- // Introduce a Darwin and PS4-specific hack. If the default is PIC, but the
- // PIC level would've been set to level 1, force it back to level 2 PIC
+ // Introduce a Darwin and PS4/PS5-specific hack. If the default is PIC, but
+ // the PIC level would've been set to level 1, force it back to level 2 PIC
// instead.
- if (PIC && (Triple.isOSDarwin() || EffectiveTriple.isPS4CPU()))
+ if (PIC && (Triple.isOSDarwin() || EffectiveTriple.isPS()))
IsPICLevelTwo |= ToolChain.isPICDefault();
// This kernel flags are a trump-card: they will disable PIC/PIE
// generation, independent of the argument order.
if (KernelOrKext &&
((!EffectiveTriple.isiOS() || EffectiveTriple.isOSVersionLT(6)) &&
- !EffectiveTriple.isWatchOS()))
+ !EffectiveTriple.isWatchOS() && !EffectiveTriple.isDriverKit()))
PIC = PIE = false;
if (Arg *A = Args.getLastArg(options::OPT_mdynamic_no_pic)) {
@@ -1411,17 +1478,12 @@ enum class LibGccType { UnspecifiedLibGcc, StaticLibGcc, SharedLibGcc };
static LibGccType getLibGccType(const ToolChain &TC, const Driver &D,
const ArgList &Args) {
if (Args.hasArg(options::OPT_static_libgcc) ||
- Args.hasArg(options::OPT_static) || Args.hasArg(options::OPT_static_pie))
+ Args.hasArg(options::OPT_static) || Args.hasArg(options::OPT_static_pie) ||
+ // The Android NDK only provides libunwind.a, not libunwind.so.
+ TC.getTriple().isAndroid())
return LibGccType::StaticLibGcc;
if (Args.hasArg(options::OPT_shared_libgcc))
return LibGccType::SharedLibGcc;
- // The Android NDK only provides libunwind.a, not libunwind.so.
- if (TC.getTriple().isAndroid())
- return LibGccType::StaticLibGcc;
- // For MinGW, don't imply a shared libgcc here, we only want to return
- // SharedLibGcc if that was explicitly requested.
- if (D.CCCIsCXX() && !TC.getTriple().isOSCygMing())
- return LibGccType::SharedLibGcc;
return LibGccType::UnspecifiedLibGcc;
}
@@ -1449,6 +1511,7 @@ static void AddUnwindLibrary(const ToolChain &TC, const Driver &D,
LibGccType LGT = getLibGccType(TC, D, Args);
bool AsNeeded = LGT == LibGccType::UnspecifiedLibGcc &&
+ (UNW == ToolChain::UNW_CompilerRT || !D.CCCIsCXX()) &&
!TC.getTriple().isAndroid() &&
!TC.getTriple().isOSCygMing() && !TC.getTriple().isOSAIX();
if (AsNeeded)
@@ -1472,15 +1535,15 @@ static void AddUnwindLibrary(const ToolChain &TC, const Driver &D,
CmdArgs.push_back("-lunwind");
} else if (LGT == LibGccType::StaticLibGcc) {
CmdArgs.push_back("-l:libunwind.a");
- } else if (TC.getTriple().isOSCygMing()) {
- if (LGT == LibGccType::SharedLibGcc)
+ } else if (LGT == LibGccType::SharedLibGcc) {
+ if (TC.getTriple().isOSCygMing())
CmdArgs.push_back("-l:libunwind.dll.a");
else
- // Let the linker choose between libunwind.dll.a and libunwind.a
- // depending on what's available, and depending on the -static flag
- CmdArgs.push_back("-lunwind");
+ CmdArgs.push_back("-l:libunwind.so");
} else {
- CmdArgs.push_back("-l:libunwind.so");
+ // Let the linker choose between libunwind.so and libunwind.a
+ // depending on what's available, and depending on the -static flag
+ CmdArgs.push_back("-lunwind");
}
break;
}
@@ -1492,10 +1555,12 @@ static void AddUnwindLibrary(const ToolChain &TC, const Driver &D,
static void AddLibgcc(const ToolChain &TC, const Driver &D,
ArgStringList &CmdArgs, const ArgList &Args) {
LibGccType LGT = getLibGccType(TC, D, Args);
- if (LGT != LibGccType::SharedLibGcc)
+ if (LGT == LibGccType::StaticLibGcc ||
+ (LGT == LibGccType::UnspecifiedLibGcc && !D.CCCIsCXX()))
CmdArgs.push_back("-lgcc");
AddUnwindLibrary(TC, D, CmdArgs, Args);
- if (LGT == LibGccType::SharedLibGcc)
+ if (LGT == LibGccType::SharedLibGcc ||
+ (LGT == LibGccType::UnspecifiedLibGcc && D.CCCIsCXX()))
CmdArgs.push_back("-lgcc");
}
@@ -1728,8 +1793,13 @@ bool tools::GetSDLFromOffloadArchive(
for (auto LPath : LibraryPaths) {
ArchiveOfBundles.clear();
- AOBFileNames.push_back(Twine(LPath + "/libdevice/lib" + Lib + ".a").str());
- AOBFileNames.push_back(Twine(LPath + "/lib" + Lib + ".a").str());
+ llvm::Triple Triple(D.getTargetTriple());
+ bool IsMSVC = Triple.isWindowsMSVCEnvironment();
+ for (auto Prefix : {"/libdevice/", "/"}) {
+ if (IsMSVC)
+ AOBFileNames.push_back(Twine(LPath + Prefix + Lib + ".lib").str());
+ AOBFileNames.push_back(Twine(LPath + Prefix + "lib" + Lib + ".a").str());
+ }
for (auto AOB : AOBFileNames) {
if (llvm::sys::fs::exists(AOB)) {
@@ -1761,9 +1831,9 @@ bool tools::GetSDLFromOffloadArchive(
std::string UnbundleArg("-unbundle");
std::string TypeArg("-type=a");
- std::string InputArg("-inputs=" + ArchiveOfBundles);
+ std::string InputArg("-input=" + ArchiveOfBundles);
std::string OffloadArg("-targets=" + std::string(DeviceTriple));
- std::string OutputArg("-outputs=" + OutputLib);
+ std::string OutputArg("-output=" + OutputLib);
const char *UBProgram = DriverArgs.MakeArgString(
T.getToolChain().GetProgramPath("clang-offload-bundler"));
@@ -1780,6 +1850,12 @@ bool tools::GetSDLFromOffloadArchive(
std::string AdditionalArgs("-allow-missing-bundles");
UBArgs.push_back(C.getArgs().MakeArgString(AdditionalArgs));
+ // Add this flag to treat hip and hipv4 offload kinds as compatible with
+ // openmp offload kind while extracting code objects from a heterogenous
+ // archive library. Vice versa is also considered compatible.
+ std::string HipCompatibleArgs("-hip-openmp-compatible");
+ UBArgs.push_back(C.getArgs().MakeArgString(HipCompatibleArgs));
+
C.addCommand(std::make_unique<Command>(
JA, T, ResponseFileSupport::AtFileCurCP(), UBProgram, UBArgs, Inputs,
InputInfo(&JA, C.getArgs().MakeArgString(OutputLib))));
@@ -1908,7 +1984,7 @@ getAMDGPUCodeObjectArgument(const Driver &D, const llvm::opt::ArgList &Args) {
void tools::checkAMDGPUCodeObjectVersion(const Driver &D,
const llvm::opt::ArgList &Args) {
const unsigned MinCodeObjVer = 2;
- const unsigned MaxCodeObjVer = 4;
+ const unsigned MaxCodeObjVer = 5;
// Emit warnings for legacy options even if they are overridden.
if (Args.hasArg(options::OPT_mno_code_object_v3_legacy))
@@ -2011,11 +2087,12 @@ void tools::addOpenMPDeviceRTL(const Driver &D,
}
OptSpecifier LibomptargetBCPathOpt =
- Triple.isAMDGCN() ? options::OPT_libomptarget_amdgcn_bc_path_EQ
+ Triple.isAMDGCN() ? options::OPT_libomptarget_amdgpu_bc_path_EQ
: options::OPT_libomptarget_nvptx_bc_path_EQ;
- StringRef ArchPrefix = Triple.isAMDGCN() ? "amdgcn" : "nvptx";
- std::string LibOmpTargetName = "libomptarget-" + BitcodeSuffix.str() + ".bc";
+ StringRef ArchPrefix = Triple.isAMDGCN() ? "amdgpu" : "nvptx";
+ std::string LibOmpTargetName =
+ ("libomptarget-" + ArchPrefix + "-" + BitcodeSuffix + ".bc").str();
// First check whether user specifies bc library
if (const Arg *A = DriverArgs.getLastArg(LibomptargetBCPathOpt)) {
@@ -2051,3 +2128,17 @@ void tools::addOpenMPDeviceRTL(const Driver &D,
<< LibOmpTargetName << ArchPrefix;
}
}
+void tools::addHIPRuntimeLibArgs(const ToolChain &TC,
+ const llvm::opt::ArgList &Args,
+ llvm::opt::ArgStringList &CmdArgs) {
+ if (Args.hasArg(options::OPT_hip_link) &&
+ !Args.hasArg(options::OPT_nostdlib) &&
+ !Args.hasArg(options::OPT_no_hip_rt)) {
+ TC.AddHIPRuntimeLibArgs(Args, CmdArgs);
+ } else {
+ // Claim "no HIP libraries" arguments if any
+ for (auto Arg : Args.filtered(options::OPT_no_hip_rt)) {
+ Arg->claim();
+ }
+ }
+}
diff --git a/clang/lib/Driver/ToolChains/CommonArgs.h b/clang/lib/Driver/ToolChains/CommonArgs.h
index 646fa76949b7..8e62af70ff7f 100644
--- a/clang/lib/Driver/ToolChains/CommonArgs.h
+++ b/clang/lib/Driver/ToolChains/CommonArgs.h
@@ -111,12 +111,29 @@ void addOpenMPRuntimeSpecificRPath(const ToolChain &TC,
llvm::opt::ArgStringList &CmdArgs);
void addArchSpecificRPath(const ToolChain &TC, const llvm::opt::ArgList &Args,
llvm::opt::ArgStringList &CmdArgs);
+void addOpenMPRuntimeLibraryPath(const ToolChain &TC,
+ const llvm::opt::ArgList &Args,
+ llvm::opt::ArgStringList &CmdArgs);
/// Returns true, if an OpenMP runtime has been added.
bool addOpenMPRuntime(llvm::opt::ArgStringList &CmdArgs, const ToolChain &TC,
const llvm::opt::ArgList &Args,
bool ForceStaticHostRuntime = false,
bool IsOffloadingHost = false, bool GompNeedsRT = false);
+/// Adds Fortran runtime libraries to \p CmdArgs.
+void addFortranRuntimeLibs(const ToolChain &TC,
+ llvm::opt::ArgStringList &CmdArgs);
+
+/// Adds the path for the Fortran runtime libraries to \p CmdArgs.
+void addFortranRuntimeLibraryPath(const ToolChain &TC,
+ const llvm::opt::ArgList &Args,
+ llvm::opt::ArgStringList &CmdArgs);
+
+void addHIPRuntimeLibArgs(const ToolChain &TC, const llvm::opt::ArgList &Args,
+ llvm::opt::ArgStringList &CmdArgs);
+
+const char *getAsNeededOption(const ToolChain &TC, bool as_needed);
+
llvm::opt::Arg *getLastProfileUseArg(const llvm::opt::ArgList &Args);
llvm::opt::Arg *getLastProfileSampleUseArg(const llvm::opt::ArgList &Args);
@@ -157,8 +174,7 @@ void handleTargetFeaturesGroup(const llvm::opt::ArgList &Args,
llvm::opt::OptSpecifier Group);
/// If there are multiple +xxx or -xxx features, keep the last one.
-std::vector<StringRef>
-unifyTargetFeatures(const std::vector<StringRef> &Features);
+SmallVector<StringRef> unifyTargetFeatures(ArrayRef<StringRef> Features);
/// Handles the -save-stats option and returns the filename to save statistics
/// to.
diff --git a/clang/lib/Driver/ToolChains/Cuda.cpp b/clang/lib/Driver/ToolChains/Cuda.cpp
index 4a9f6d4c4e3e..5e59677947e6 100644
--- a/clang/lib/Driver/ToolChains/Cuda.cpp
+++ b/clang/lib/Driver/ToolChains/Cuda.cpp
@@ -447,7 +447,10 @@ void NVPTX::Assembler::ConstructJob(Compilation &C, const JobAction &JA,
CmdArgs.push_back("--gpu-name");
CmdArgs.push_back(Args.MakeArgString(CudaArchToString(gpu_arch)));
CmdArgs.push_back("--output-file");
- CmdArgs.push_back(Args.MakeArgString(TC.getInputFilename(Output)));
+ const char *OutputFileName = Args.MakeArgString(TC.getInputFilename(Output));
+ if (std::string(OutputFileName) != std::string(Output.getFilename()))
+ C.addTempFile(OutputFileName);
+ CmdArgs.push_back(OutputFileName);
for (const auto& II : Inputs)
CmdArgs.push_back(Args.MakeArgString(II.getFilename()));
@@ -533,8 +536,9 @@ void NVPTX::Linker::ConstructJob(Compilation &C, const JobAction &JA,
const char *Arch = (II.getType() == types::TY_PP_Asm)
? CudaArchToVirtualArchString(gpu_arch)
: gpu_arch_str;
- CmdArgs.push_back(Args.MakeArgString(llvm::Twine("--image=profile=") +
- Arch + ",file=" + II.getFilename()));
+ CmdArgs.push_back(
+ Args.MakeArgString(llvm::Twine("--image=profile=") + Arch +
+ ",file=" + getToolChain().getInputFilename(II)));
}
for (const auto& A : Args.getAllArgValues(options::OPT_Xcuda_fatbinary))
@@ -606,8 +610,8 @@ void NVPTX::OpenMPLinker::ConstructJob(Compilation &C, const JobAction &JA,
if (!II.isFilename())
continue;
- const char *CubinF = C.addTempFile(
- C.getArgs().MakeArgString(getToolChain().getInputFilename(II)));
+ const char *CubinF =
+ C.getArgs().MakeArgString(getToolChain().getInputFilename(II));
CmdArgs.push_back(CubinF);
}
@@ -630,6 +634,45 @@ void NVPTX::OpenMPLinker::ConstructJob(Compilation &C, const JobAction &JA,
Exec, CmdArgs, Inputs, Output));
}
+void NVPTX::getNVPTXTargetFeatures(const Driver &D, const llvm::Triple &Triple,
+ const llvm::opt::ArgList &Args,
+ std::vector<StringRef> &Features) {
+ if (Args.hasArg(options::OPT_cuda_feature_EQ)) {
+ StringRef PtxFeature =
+ Args.getLastArgValue(options::OPT_cuda_feature_EQ, "+ptx42");
+ Features.push_back(Args.MakeArgString(PtxFeature));
+ return;
+ }
+ CudaInstallationDetector CudaInstallation(D, Triple, Args);
+
+ // New CUDA versions often introduce new instructions that are only supported
+ // by new PTX version, so we need to raise PTX level to enable them in NVPTX
+ // back-end.
+ const char *PtxFeature = nullptr;
+ switch (CudaInstallation.version()) {
+#define CASE_CUDA_VERSION(CUDA_VER, PTX_VER) \
+ case CudaVersion::CUDA_##CUDA_VER: \
+ PtxFeature = "+ptx" #PTX_VER; \
+ break;
+ CASE_CUDA_VERSION(115, 75);
+ CASE_CUDA_VERSION(114, 74);
+ CASE_CUDA_VERSION(113, 73);
+ CASE_CUDA_VERSION(112, 72);
+ CASE_CUDA_VERSION(111, 71);
+ CASE_CUDA_VERSION(110, 70);
+ CASE_CUDA_VERSION(102, 65);
+ CASE_CUDA_VERSION(101, 64);
+ CASE_CUDA_VERSION(100, 63);
+ CASE_CUDA_VERSION(92, 61);
+ CASE_CUDA_VERSION(91, 61);
+ CASE_CUDA_VERSION(90, 60);
+#undef CASE_CUDA_VERSION
+ default:
+ PtxFeature = "+ptx42";
+ }
+ Features.push_back(PtxFeature);
+}
+
/// CUDA toolchain. Our assembler is ptxas, and our "linker" is fatbinary,
/// which isn't properly a linker but nonetheless performs the step of stitching
/// together object files from the assembler into a single blob.
@@ -650,9 +693,8 @@ CudaToolChain::CudaToolChain(const Driver &D, const llvm::Triple &Triple,
std::string CudaToolChain::getInputFilename(const InputInfo &Input) const {
// Only object files are changed, for example assembly files keep their .s
- // extensions. CUDA also continues to use .o as they don't use nvlink but
- // fatbinary.
- if (!(OK == Action::OFK_OpenMP && Input.getType() == types::TY_Object))
+ // extensions.
+ if (Input.getType() != types::TY_Object)
return ToolChain::getInputFilename(Input);
// Replace extension for object files with cubin because nvlink relies on
@@ -701,32 +743,6 @@ void CudaToolChain::addClangTargetOptions(
clang::CudaVersion CudaInstallationVersion = CudaInstallation.version();
- // New CUDA versions often introduce new instructions that are only supported
- // by new PTX version, so we need to raise PTX level to enable them in NVPTX
- // back-end.
- const char *PtxFeature = nullptr;
- switch (CudaInstallationVersion) {
-#define CASE_CUDA_VERSION(CUDA_VER, PTX_VER) \
- case CudaVersion::CUDA_##CUDA_VER: \
- PtxFeature = "+ptx" #PTX_VER; \
- break;
- CASE_CUDA_VERSION(115, 75);
- CASE_CUDA_VERSION(114, 74);
- CASE_CUDA_VERSION(113, 73);
- CASE_CUDA_VERSION(112, 72);
- CASE_CUDA_VERSION(111, 71);
- CASE_CUDA_VERSION(110, 70);
- CASE_CUDA_VERSION(102, 65);
- CASE_CUDA_VERSION(101, 64);
- CASE_CUDA_VERSION(100, 63);
- CASE_CUDA_VERSION(92, 61);
- CASE_CUDA_VERSION(91, 61);
- CASE_CUDA_VERSION(90, 60);
-#undef CASE_CUDA_VERSION
- default:
- PtxFeature = "+ptx42";
- }
- CC1Args.append({"-target-feature", PtxFeature});
if (DriverArgs.hasFlag(options::OPT_fcuda_short_ptr,
options::OPT_fno_cuda_short_ptr, false))
CC1Args.append({"-mllvm", "--nvptx-short-ptr"});
@@ -748,14 +764,7 @@ void CudaToolChain::addClangTargetOptions(
if (getDriver().isUsingLTO(/* IsOffload */ true))
return;
- std::string BitcodeSuffix;
- if (DriverArgs.hasFlag(options::OPT_fopenmp_target_new_runtime,
- options::OPT_fno_openmp_target_new_runtime, true))
- BitcodeSuffix = "new-nvptx-" + GpuArch.str();
- else
- BitcodeSuffix = "nvptx-" + GpuArch.str();
-
- addOpenMPDeviceRTL(getDriver(), DriverArgs, CC1Args, BitcodeSuffix,
+ addOpenMPDeviceRTL(getDriver(), DriverArgs, CC1Args, GpuArch.str(),
getTriple());
AddStaticDeviceLibsPostLinking(getDriver(), DriverArgs, CC1Args, "nvptx",
GpuArch, /*isBitCodeSDL=*/true,
@@ -835,10 +844,10 @@ CudaToolChain::TranslateArgs(const llvm::opt::DerivedArgList &Args,
if (!llvm::is_contained(*DAL, A))
DAL->append(A);
- StringRef Arch = DAL->getLastArgValue(options::OPT_march_EQ);
- if (Arch.empty())
+ if (!DAL->hasArg(options::OPT_march_EQ))
DAL->AddJoinedArg(nullptr, Opts.getOption(options::OPT_march_EQ),
- CLANG_OPENMP_NVPTX_DEFAULT_ARCH);
+ !BoundArch.empty() ? BoundArch
+ : CLANG_OPENMP_NVPTX_DEFAULT_ARCH);
return DAL;
}
diff --git a/clang/lib/Driver/ToolChains/Cuda.h b/clang/lib/Driver/ToolChains/Cuda.h
index a7e6e84f4902..809a25227ac4 100644
--- a/clang/lib/Driver/ToolChains/Cuda.h
+++ b/clang/lib/Driver/ToolChains/Cuda.h
@@ -124,6 +124,10 @@ class LLVM_LIBRARY_VISIBILITY OpenMPLinker : public Tool {
const char *LinkingOutput) const override;
};
+void getNVPTXTargetFeatures(const Driver &D, const llvm::Triple &Triple,
+ const llvm::opt::ArgList &Args,
+ std::vector<StringRef> &Features);
+
} // end namespace NVPTX
} // end namespace tools
diff --git a/clang/lib/Driver/ToolChains/Darwin.cpp b/clang/lib/Driver/ToolChains/Darwin.cpp
index f7da3f187814..0a8a9c6eb6ff 100644
--- a/clang/lib/Driver/ToolChains/Darwin.cpp
+++ b/clang/lib/Driver/ToolChains/Darwin.cpp
@@ -209,19 +209,18 @@ static bool shouldLinkerNotDedup(bool IsLinkerOnlyAction, const ArgList &Args) {
void darwin::Linker::AddLinkArgs(Compilation &C, const ArgList &Args,
ArgStringList &CmdArgs,
const InputInfoList &Inputs,
- unsigned Version[5], bool LinkerIsLLD) const {
+ VersionTuple Version, bool LinkerIsLLD) const {
const Driver &D = getToolChain().getDriver();
const toolchains::MachO &MachOTC = getMachOToolChain();
// Newer linkers support -demangle. Pass it if supported and not disabled by
// the user.
- if ((Version[0] >= 100 || LinkerIsLLD) &&
+ if ((Version >= VersionTuple(100) || LinkerIsLLD) &&
!Args.hasArg(options::OPT_Z_Xlinker__no_demangle))
CmdArgs.push_back("-demangle");
- // FIXME: Pass most of the flags below that check Version if LinkerIsLLD too.
-
- if (Args.hasArg(options::OPT_rdynamic) && Version[0] >= 137)
+ if (Args.hasArg(options::OPT_rdynamic) &&
+ (Version >= VersionTuple(137) || LinkerIsLLD))
CmdArgs.push_back("-export_dynamic");
// If we are using App Extension restrictions, pass a flag to the linker
@@ -230,7 +229,8 @@ void darwin::Linker::AddLinkArgs(Compilation &C, const ArgList &Args,
options::OPT_fno_application_extension, false))
CmdArgs.push_back("-application_extension");
- if (D.isUsingLTO() && Version[0] >= 116 && NeedsTempPath(Inputs)) {
+ if (D.isUsingLTO() && (Version >= VersionTuple(116) || LinkerIsLLD) &&
+ NeedsTempPath(Inputs)) {
std::string TmpPathName;
if (D.getLTOMode() == LTOK_Full) {
// If we are using full LTO, then automatically create a temporary file
@@ -259,7 +259,7 @@ void darwin::Linker::AddLinkArgs(Compilation &C, const ArgList &Args,
// clang version won't work anyways.
// lld is built at the same revision as clang and statically links in
// LLVM libraries, so it doesn't need libLTO.dylib.
- if (Version[0] >= 133 && !LinkerIsLLD) {
+ if (Version >= VersionTuple(133) && !LinkerIsLLD) {
// Search for libLTO in <InstalledDir>/../lib/libLTO.dylib
StringRef P = llvm::sys::path::parent_path(D.Dir);
SmallString<128> LibLTOPath(P);
@@ -269,8 +269,11 @@ void darwin::Linker::AddLinkArgs(Compilation &C, const ArgList &Args,
CmdArgs.push_back(C.getArgs().MakeArgString(LibLTOPath));
}
- // ld64 version 262 and above run the deduplicate pass by default.
- if (Version[0] >= 262 && shouldLinkerNotDedup(C.getJobs().empty(), Args))
+ // ld64 version 262 and above runs the deduplicate pass by default.
+ // FIXME: lld doesn't dedup by default. Should we pass `--icf=safe`
+ // if `!shouldLinkerNotDedup()` if LinkerIsLLD here?
+ if (Version >= VersionTuple(262) &&
+ shouldLinkerNotDedup(C.getJobs().empty(), Args))
CmdArgs.push_back("-no_deduplicate");
// Derived from the "link" spec.
@@ -342,7 +345,7 @@ void darwin::Linker::AddLinkArgs(Compilation &C, const ArgList &Args,
Args.AddAllArgs(CmdArgs, options::OPT_init);
// Add the deployment target.
- if (Version[0] >= 520 || LinkerIsLLD)
+ if (Version >= VersionTuple(520) || LinkerIsLLD)
MachOTC.addPlatformVersionArgs(Args, CmdArgs);
else
MachOTC.addMinVersionArgs(Args, CmdArgs);
@@ -368,7 +371,9 @@ void darwin::Linker::AddLinkArgs(Compilation &C, const ArgList &Args,
// Check if the toolchain supports bitcode build flow.
if (MachOTC.SupportsEmbeddedBitcode()) {
CmdArgs.push_back("-bitcode_bundle");
- if (C.getDriver().embedBitcodeMarkerOnly() && Version[0] >= 278) {
+ // FIXME: Pass this if LinkerIsLLD too, once it implements this flag.
+ if (C.getDriver().embedBitcodeMarkerOnly() &&
+ Version >= VersionTuple(278)) {
CmdArgs.push_back("-bitcode_process_mode");
CmdArgs.push_back("marker");
}
@@ -548,12 +553,7 @@ void darwin::Linker::ConstructJob(Compilation &C, const JobAction &JA,
return;
}
- unsigned Version[5] = {0, 0, 0, 0, 0};
- if (Arg *A = Args.getLastArg(options::OPT_mlinker_version_EQ)) {
- if (!Driver::GetReleaseVersion(A->getValue(), Version))
- getToolChain().getDriver().Diag(diag::err_drv_invalid_version_number)
- << A->getAsString(Args);
- }
+ VersionTuple Version = getMachOToolChain().getLinkerVersion(Args);
bool LinkerIsLLD;
const char *Exec =
@@ -635,6 +635,13 @@ void darwin::Linker::ConstructJob(Compilation &C, const JobAction &JA,
InputFileList.push_back(II.getFilename());
}
+ // Additional linker set-up and flags for Fortran. This is required in order
+ // to generate executables.
+ if (getToolChain().getDriver().IsFlangMode()) {
+ addFortranRuntimeLibraryPath(getToolChain(), Args, CmdArgs);
+ addFortranRuntimeLibs(getToolChain(), CmdArgs);
+ }
+
if (!Args.hasArg(options::OPT_nostdlib, options::OPT_nodefaultlibs))
addOpenMPRuntime(CmdArgs, getToolChain(), Args);
@@ -712,8 +719,28 @@ void darwin::Linker::ConstructJob(Compilation &C, const JobAction &JA,
}
}
+ // DriverKit's framework doesn't have the same layout as other frameworks.
+ // Add missing search paths if necessary.
+ if (getToolChain().getTriple().getOS() == llvm::Triple::DriverKit) {
+ if (const Arg *Root = Args.getLastArg(options::OPT_isysroot)) {
+ // ld64 fixed the implicit -F and -L paths in ld64-605.1+.
+ if (Version.getMajor() < 605 ||
+ (Version.getMajor() == 605 && Version.getMinor().value_or(0) < 1)) {
+
+ SmallString<128> L(Root->getValue());
+ llvm::sys::path::append(L, "System", "DriverKit", "usr", "lib");
+ CmdArgs.push_back(Args.MakeArgString(std::string("-L") + L));
+
+ SmallString<128> F(Root->getValue());
+ llvm::sys::path::append(F, "System", "DriverKit");
+ llvm::sys::path::append(F, "System", "Library", "Frameworks");
+ CmdArgs.push_back(Args.MakeArgString(std::string("-F") + F));
+ }
+ }
+ }
+
ResponseFileSupport ResponseSupport;
- if (Version[0] >= 705 || LinkerIsLLD) {
+ if (Version >= VersionTuple(705) || LinkerIsLLD) {
ResponseSupport = ResponseFileSupport::AtFileUTF8();
} else {
// For older versions of the linker, use the legacy filelist method instead.
@@ -869,13 +896,13 @@ types::ID MachO::LookupTypeForExtension(StringRef Ext) const {
bool MachO::HasNativeLLVMSupport() const { return true; }
ToolChain::CXXStdlibType Darwin::GetDefaultCXXStdlibType() const {
- // Default to use libc++ on OS X 10.9+ and iOS 7+.
- if ((isTargetMacOSBased() && !isMacosxVersionLT(10, 9)) ||
- (isTargetIOSBased() && !isIPhoneOSVersionLT(7, 0)) ||
- isTargetWatchOSBased())
- return ToolChain::CST_Libcxx;
+ // Use libstdc++ on old targets (OSX < 10.9 and iOS < 7)
+ if ((isTargetMacOSBased() && isMacosxVersionLT(10, 9)) ||
+ (isTargetIOSBased() && isIPhoneOSVersionLT(7, 0)))
+ return ToolChain::CST_Libstdcxx;
- return ToolChain::CST_Libstdcxx;
+ // On all other targets, use libc++
+ return ToolChain::CST_Libcxx;
}
/// Darwin provides an ARC runtime starting in MacOS X 10.7 and iOS 5.0.
@@ -891,7 +918,7 @@ ObjCRuntime Darwin::getDefaultObjCRuntime(bool isNonFragile) const {
/// Darwin provides a blocks runtime starting in MacOS X 10.6 and iOS 3.2.
bool Darwin::hasBlocksRuntime() const {
- if (isTargetWatchOSBased())
+ if (isTargetWatchOSBased() || isTargetDriverKit())
return true;
else if (isTargetIOSBased())
return !isIPhoneOSVersionLT(3, 2);
@@ -979,6 +1006,27 @@ StringRef MachO::getMachOArchName(const ArgList &Args) const {
}
}
+VersionTuple MachO::getLinkerVersion(const llvm::opt::ArgList &Args) const {
+ if (LinkerVersion) {
+#ifndef NDEBUG
+ VersionTuple NewLinkerVersion;
+ if (Arg *A = Args.getLastArg(options::OPT_mlinker_version_EQ))
+ (void)NewLinkerVersion.tryParse(A->getValue());
+ assert(NewLinkerVersion == LinkerVersion);
+#endif
+ return *LinkerVersion;
+ }
+
+ VersionTuple NewLinkerVersion;
+ if (Arg *A = Args.getLastArg(options::OPT_mlinker_version_EQ))
+ if (NewLinkerVersion.tryParse(A->getValue()))
+ getDriver().Diag(diag::err_drv_invalid_version_number)
+ << A->getAsString(Args);
+
+ LinkerVersion = NewLinkerVersion;
+ return *LinkerVersion;
+}
+
Darwin::~Darwin() {}
MachO::~MachO() {}
@@ -997,6 +1045,8 @@ std::string Darwin::ComputeEffectiveClangTriple(const ArgList &Args,
Str += "watchos";
else if (isTargetTvOSBased())
Str += "tvos";
+ else if (isTargetDriverKit())
+ Str += "driverkit";
else if (isTargetIOSBased() || isTargetMacCatalyst())
Str += "ios";
else
@@ -1152,8 +1202,9 @@ void MachO::AddLinkRuntimeLib(const ArgList &Args, ArgStringList &CmdArgs,
DarwinLibName += getOSLibraryNameSuffix();
DarwinLibName += IsShared ? "_dynamic.dylib" : ".a";
SmallString<128> Dir(getDriver().ResourceDir);
- llvm::sys::path::append(
- Dir, "lib", (Opts & RLO_IsEmbedded) ? "macho_embedded" : "darwin");
+ llvm::sys::path::append(Dir, "lib", "darwin");
+ if (Opts & RLO_IsEmbedded)
+ llvm::sys::path::append(Dir, "macho_embedded");
SmallString<128> P(Dir);
llvm::sys::path::append(P, DarwinLibName);
@@ -1197,6 +1248,8 @@ StringRef Darwin::getPlatformFamily() const {
return "AppleTV";
case DarwinPlatformKind::WatchOS:
return "Watch";
+ case DarwinPlatformKind::DriverKit:
+ return "DriverKit";
}
llvm_unreachable("Unsupported platform");
}
@@ -1228,6 +1281,8 @@ StringRef Darwin::getOSLibraryNameSuffix(bool IgnoreSim) const {
case DarwinPlatformKind::WatchOS:
return TargetEnvironment == NativeEnvironment || IgnoreSim ? "watchos"
: "watchossim";
+ case DarwinPlatformKind::DriverKit:
+ return "driverkit";
}
llvm_unreachable("Unsupported platform");
}
@@ -1289,7 +1344,6 @@ void Darwin::addProfileRTLibs(const ArgList &Args,
addExportedSymbol(CmdArgs, "___llvm_profile_filename");
addExportedSymbol(CmdArgs, "___llvm_profile_raw_version");
}
- addExportedSymbol(CmdArgs, "_lprofDirMode");
}
// Align __llvm_prf_{cnts,data} sections to the maximum expected page
@@ -1385,9 +1439,15 @@ void DarwinClang::AddLinkRuntimeLibArgs(const ArgList &Args,
AddLinkRuntimeLib(Args, CmdArgs, "xray-fdr");
}
+ if (isTargetDriverKit() && !Args.hasArg(options::OPT_nodriverkitlib)) {
+ CmdArgs.push_back("-framework");
+ CmdArgs.push_back("DriverKit");
+ }
+
// Otherwise link libSystem, then the dynamic runtime library, and finally any
// target specific static runtime library.
- CmdArgs.push_back("-lSystem");
+ if (!isTargetDriverKit())
+ CmdArgs.push_back("-lSystem");
// Select the dynamic runtime library and the target specific static library.
if (isTargetIOSBased()) {
@@ -1478,6 +1538,10 @@ struct DarwinPlatform {
/// Returns true if the simulator environment can be inferred from the arch.
bool canInferSimulatorFromArch() const { return InferSimulatorFromArch; }
+ const Optional<llvm::Triple> &getTargetVariantTriple() const {
+ return TargetVariantTriple;
+ }
+
/// Adds the -m<os>-version-min argument to the compiler invocation.
void addOSVersionMinArgument(DerivedArgList &Args, const OptTable &Opts) {
if (Argument)
@@ -1498,6 +1562,9 @@ struct DarwinPlatform {
case DarwinPlatformKind::WatchOS:
Opt = options::OPT_mwatchos_version_min_EQ;
break;
+ case DarwinPlatformKind::DriverKit:
+ // DriverKit always explicitly provides a version in the triple.
+ return;
}
Argument = Args.MakeJoinedArg(nullptr, Opts.getOption(Opt), OSVersion);
Args.append(Argument);
@@ -1540,6 +1607,16 @@ struct DarwinPlatform {
}
}
}
+ // In a zippered build, we could be building for a macOS target that's
+ // lower than the version that's implied by the OS version. In that case
+ // we need to use the minimum version as the native target version.
+ if (TargetVariantTriple) {
+ auto TargetVariantVersion = TargetVariantTriple->getOSVersion();
+ if (TargetVariantVersion.getMajor()) {
+ if (TargetVariantVersion < NativeTargetVersion)
+ NativeTargetVersion = TargetVariantVersion;
+ }
+ }
break;
}
default:
@@ -1549,12 +1626,14 @@ struct DarwinPlatform {
static DarwinPlatform
createFromTarget(const llvm::Triple &TT, StringRef OSVersion, Arg *A,
+ Optional<llvm::Triple> TargetVariantTriple,
const Optional<DarwinSDKInfo> &SDKInfo) {
DarwinPlatform Result(TargetArg, getPlatformFromOS(TT.getOS()), OSVersion,
A);
VersionTuple OsVersion = TT.getOSVersion();
if (OsVersion.getMajor() == 0)
Result.HasOSVersion = false;
+ Result.TargetVariantTriple = TargetVariantTriple;
Result.setEnvironment(TT.getEnvironment(), OsVersion, SDKInfo);
return Result;
}
@@ -1625,6 +1704,8 @@ private:
return DarwinPlatformKind::TvOS;
case llvm::Triple::WatchOS:
return DarwinPlatformKind::WatchOS;
+ case llvm::Triple::DriverKit:
+ return DarwinPlatformKind::DriverKit;
default:
llvm_unreachable("Unable to infer Darwin variant");
}
@@ -1638,6 +1719,7 @@ private:
bool HasOSVersion = true, InferSimulatorFromArch = true;
Arg *Argument;
StringRef EnvVarName;
+ Optional<llvm::Triple> TargetVariantTriple;
};
/// Returns the deployment target that's specified using the -m<os>-version-min
@@ -1693,6 +1775,7 @@ getDeploymentTargetFromEnvironmentVariables(const Driver &TheDriver,
"IPHONEOS_DEPLOYMENT_TARGET",
"TVOS_DEPLOYMENT_TARGET",
"WATCHOS_DEPLOYMENT_TARGET",
+ "DRIVERKIT_DEPLOYMENT_TARGET",
};
static_assert(llvm::array_lengthof(EnvVars) == Darwin::LastDarwinPlatform + 1,
"Missing platform");
@@ -1791,6 +1874,8 @@ inferDeploymentTargetFromSDK(DerivedArgList &Args,
return DarwinPlatform::createFromSDK(
Darwin::TvOS, Version,
/*IsSimulator=*/SDK.startswith("AppleTVSimulator"));
+ else if (SDK.startswith("DriverKit"))
+ return DarwinPlatform::createFromSDK(Darwin::DriverKit, Version);
return None;
};
if (auto Result = CreatePlatformFromSDKName(SDK))
@@ -1827,6 +1912,9 @@ std::string getOSVersion(llvm::Triple::OSType OS, const llvm::Triple &Triple,
case llvm::Triple::WatchOS:
OsVersion = Triple.getWatchOSVersion();
break;
+ case llvm::Triple::DriverKit:
+ OsVersion = Triple.getDriverKitVersion();
+ break;
default:
llvm_unreachable("Unexpected OS type");
break;
@@ -1834,8 +1922,8 @@ std::string getOSVersion(llvm::Triple::OSType OS, const llvm::Triple &Triple,
std::string OSVersion;
llvm::raw_string_ostream(OSVersion)
- << OsVersion.getMajor() << '.' << OsVersion.getMinor().getValueOr(0)
- << '.' << OsVersion.getSubminor().getValueOr(0);
+ << OsVersion.getMajor() << '.' << OsVersion.getMinor().value_or(0) << '.'
+ << OsVersion.getSubminor().value_or(0);
return OSVersion;
}
@@ -1847,23 +1935,15 @@ inferDeploymentTargetFromArch(DerivedArgList &Args, const Darwin &Toolchain,
llvm::Triple::OSType OSTy = llvm::Triple::UnknownOS;
StringRef MachOArchName = Toolchain.getMachOArchName(Args);
- if (MachOArchName == "arm64" || MachOArchName == "arm64e") {
-#if __arm64__
- // A clang running on an Apple Silicon mac defaults
- // to building for mac when building for arm64 rather than
- // defaulting to iOS.
+ if (MachOArchName == "arm64" || MachOArchName == "arm64e")
OSTy = llvm::Triple::MacOSX;
-#else
- OSTy = llvm::Triple::IOS;
-#endif
- } else if (MachOArchName == "armv7" || MachOArchName == "armv7s")
+ else if (MachOArchName == "armv7" || MachOArchName == "armv7s")
OSTy = llvm::Triple::IOS;
else if (MachOArchName == "armv7k" || MachOArchName == "arm64_32")
OSTy = llvm::Triple::WatchOS;
else if (MachOArchName != "armv6m" && MachOArchName != "armv7m" &&
MachOArchName != "armv7em")
OSTy = llvm::Triple::MacOSX;
-
if (OSTy == llvm::Triple::UnknownOS)
return None;
return DarwinPlatform::createFromArch(OSTy,
@@ -1880,8 +1960,34 @@ Optional<DarwinPlatform> getDeploymentTargetFromTargetArg(
Triple.getOS() == llvm::Triple::UnknownOS)
return None;
std::string OSVersion = getOSVersion(Triple.getOS(), Triple, TheDriver);
- return DarwinPlatform::createFromTarget(
- Triple, OSVersion, Args.getLastArg(options::OPT_target), SDKInfo);
+ Optional<llvm::Triple> TargetVariantTriple;
+ for (const Arg *A : Args.filtered(options::OPT_darwin_target_variant)) {
+ llvm::Triple TVT(A->getValue());
+ // Find a matching <arch>-<vendor> target variant triple that can be used.
+ if ((Triple.getArch() == llvm::Triple::aarch64 ||
+ TVT.getArchName() == Triple.getArchName()) &&
+ TVT.getArch() == Triple.getArch() &&
+ TVT.getSubArch() == Triple.getSubArch() &&
+ TVT.getVendor() == Triple.getVendor()) {
+ if (TargetVariantTriple)
+ continue;
+ A->claim();
+ // Accept a -target-variant triple when compiling code that may run on
+ // macOS or Mac Catalust.
+ if ((Triple.isMacOSX() && TVT.getOS() == llvm::Triple::IOS &&
+ TVT.isMacCatalystEnvironment()) ||
+ (TVT.isMacOSX() && Triple.getOS() == llvm::Triple::IOS &&
+ Triple.isMacCatalystEnvironment())) {
+ TargetVariantTriple = TVT;
+ continue;
+ }
+ TheDriver.Diag(diag::err_drv_target_variant_invalid)
+ << A->getSpelling() << A->getValue();
+ }
+ }
+ return DarwinPlatform::createFromTarget(Triple, OSVersion,
+ Args.getLastArg(options::OPT_target),
+ TargetVariantTriple, SDKInfo);
}
/// Returns the deployment target that's specified using the -mtargetos option.
@@ -2103,19 +2209,27 @@ void Darwin::AddDeploymentTarget(DerivedArgList &Args) const {
HadExtra || Major >= 10 || Minor >= 100 || Micro >= 100)
getDriver().Diag(diag::err_drv_invalid_version_number)
<< OSTarget->getAsString(Args, Opts);
+ } else if (Platform == DriverKit) {
+ if (!Driver::GetReleaseVersion(OSTarget->getOSVersion(), Major, Minor,
+ Micro, HadExtra) ||
+ HadExtra || Major < 19 || Major >= 100 || Minor >= 100 || Micro >= 100)
+ getDriver().Diag(diag::err_drv_invalid_version_number)
+ << OSTarget->getAsString(Args, Opts);
} else
llvm_unreachable("unknown kind of Darwin platform");
DarwinEnvironmentKind Environment = OSTarget->getEnvironment();
// Recognize iOS targets with an x86 architecture as the iOS simulator.
if (Environment == NativeEnvironment && Platform != MacOS &&
- OSTarget->canInferSimulatorFromArch() && getTriple().isX86())
+ Platform != DriverKit && OSTarget->canInferSimulatorFromArch() &&
+ getTriple().isX86())
Environment = Simulator;
VersionTuple NativeTargetVersion;
if (Environment == MacCatalyst)
NativeTargetVersion = OSTarget->getNativeTargetVersion();
setTarget(Platform, Environment, Major, Minor, Micro, NativeTargetVersion);
+ TargetVariantTriple = OSTarget->getTargetVariantTriple();
if (const Arg *A = Args.getLastArg(options::OPT_isysroot)) {
StringRef SDK = getSDKName(A->getValue());
@@ -2395,6 +2509,8 @@ void DarwinClang::AddCCKextLibArgs(const ArgList &Args,
llvm::sys::path::append(P, "libclang_rt.cc_kext_tvos.a");
} else if (isTargetIPhoneOS()) {
llvm::sys::path::append(P, "libclang_rt.cc_kext_ios.a");
+ } else if (isTargetDriverKit()) {
+ // DriverKit doesn't want extra runtime support.
} else {
llvm::sys::path::append(P, "libclang_rt.cc_kext.a");
}
@@ -2422,12 +2538,9 @@ DerivedArgList *MachO::TranslateArgs(const DerivedArgList &Args,
if (A->getOption().matches(options::OPT_Xarch__)) {
// Skip this argument unless the architecture matches either the toolchain
// triple arch, or the arch being bound.
- llvm::Triple::ArchType XarchArch =
- tools::darwin::getArchTypeForMachOArchName(A->getValue(0));
- if (!(XarchArch == getArch() ||
- (!BoundArch.empty() &&
- XarchArch ==
- tools::darwin::getArchTypeForMachOArchName(BoundArch))))
+ StringRef XarchArch = A->getValue(0);
+ if (!(XarchArch == getArchName() ||
+ (!BoundArch.empty() && XarchArch == BoundArch)))
continue;
Arg *OriginalArg = A;
@@ -2497,14 +2610,6 @@ DerivedArgList *MachO::TranslateArgs(const DerivedArgList &Args,
DAL->AddFlagArg(
A, Opts.getOption(options::OPT_mno_warn_nonportable_cfstrings));
break;
-
- case options::OPT_fpascal_strings:
- DAL->AddFlagArg(A, Opts.getOption(options::OPT_mpascal_strings));
- break;
-
- case options::OPT_fno_pascal_strings:
- DAL->AddFlagArg(A, Opts.getOption(options::OPT_mno_pascal_strings));
- break;
}
}
@@ -2620,6 +2725,8 @@ bool Darwin::isAlignedAllocationUnavailable() const {
case WatchOS: // Earlier than 4.0.
OS = llvm::Triple::WatchOS;
break;
+ case DriverKit: // Always available.
+ return false;
}
return TargetVersion < alignedAllocMinVersion(OS);
@@ -2635,6 +2742,12 @@ void Darwin::addClangTargetOptions(const llvm::opt::ArgList &DriverArgs,
isAlignedAllocationUnavailable())
CC1Args.push_back("-faligned-alloc-unavailable");
+ if (TargetVariantTriple) {
+ CC1Args.push_back("-darwin-target-variant-triple");
+ CC1Args.push_back(
+ DriverArgs.MakeArgString(TargetVariantTriple->getTriple()));
+ }
+
if (SDKInfo) {
/// Pass the SDK version to the compiler when the SDK information is
/// available.
@@ -2656,6 +2769,28 @@ void Darwin::addClangTargetOptions(const llvm::opt::ArgList &DriverArgs,
} else {
EmitTargetSDKVersionArg(SDKInfo->getVersion());
}
+
+ /// Pass the target variant SDK version to the compiler when the SDK
+ /// information is available and is required for target variant.
+ if (TargetVariantTriple) {
+ if (isTargetMacCatalyst()) {
+ std::string Arg;
+ llvm::raw_string_ostream OS(Arg);
+ OS << "-darwin-target-variant-sdk-version=" << SDKInfo->getVersion();
+ CC1Args.push_back(DriverArgs.MakeArgString(OS.str()));
+ } else if (const auto *MacOStoMacCatalystMapping =
+ SDKInfo->getVersionMapping(
+ DarwinSDKInfo::OSEnvPair::macOStoMacCatalystPair())) {
+ if (Optional<VersionTuple> SDKVersion = MacOStoMacCatalystMapping->map(
+ SDKInfo->getVersion(), minimumMacCatalystDeploymentTarget(),
+ None)) {
+ std::string Arg;
+ llvm::raw_string_ostream OS(Arg);
+ OS << "-darwin-target-variant-sdk-version=" << *SDKVersion;
+ CC1Args.push_back(DriverArgs.MakeArgString(OS.str()));
+ }
+ }
+ }
}
// Enable compatibility mode for NSItemProviderCompletionHandler in
@@ -2691,7 +2826,7 @@ Darwin::TranslateArgs(const DerivedArgList &Args, StringRef BoundArch,
// FIXME: It would be far better to avoid inserting those -static arguments,
// but we can't check the deployment target in the translation code until
// it is set here.
- if (isTargetWatchOSBased() ||
+ if (isTargetWatchOSBased() || isTargetDriverKit() ||
(isTargetIOSBased() && !isIPhoneOSVersionLT(6, 0))) {
for (ArgList::iterator it = DAL->begin(), ie = DAL->end(); it != ie; ) {
Arg *A = *it;
@@ -2754,6 +2889,12 @@ bool MachO::UseDwarfDebugFlags() const {
return false;
}
+std::string MachO::GetGlobalDebugPathRemapping() const {
+ if (const char *S = ::getenv("RC_DEBUG_PREFIX_MAP"))
+ return S;
+ return {};
+}
+
llvm::ExceptionHandling Darwin::GetExceptionModel(const ArgList &Args) const {
// Darwin uses SjLj exceptions on ARM.
if (getTriple().getArch() != llvm::Triple::arm &&
@@ -2801,6 +2942,8 @@ void Darwin::addMinVersionArgs(const ArgList &Args,
CmdArgs.push_back("-tvos_version_min");
else if (isTargetTvOSSimulator())
CmdArgs.push_back("-tvos_simulator_version_min");
+ else if (isTargetDriverKit())
+ CmdArgs.push_back("-driverkit_version_min");
else if (isTargetIOSSimulator())
CmdArgs.push_back("-ios_simulator_version_min");
else if (isTargetIOSBased())
@@ -2816,6 +2959,25 @@ void Darwin::addMinVersionArgs(const ArgList &Args,
if (!MinTgtVers.empty() && MinTgtVers > TargetVersion)
TargetVersion = MinTgtVers;
CmdArgs.push_back(Args.MakeArgString(TargetVersion.getAsString()));
+ if (TargetVariantTriple) {
+ assert(isTargetMacOSBased() && "unexpected target");
+ VersionTuple VariantTargetVersion;
+ if (TargetVariantTriple->isMacOSX()) {
+ CmdArgs.push_back("-macosx_version_min");
+ TargetVariantTriple->getMacOSXVersion(VariantTargetVersion);
+ } else {
+ assert(TargetVariantTriple->isiOS() &&
+ TargetVariantTriple->isMacCatalystEnvironment() &&
+ "unexpected target variant triple");
+ CmdArgs.push_back("-maccatalyst_version_min");
+ VariantTargetVersion = TargetVariantTriple->getiOSVersion();
+ }
+ VersionTuple MinTgtVers =
+ TargetVariantTriple->getMinimumSupportedOSVersion();
+ if (MinTgtVers.getMajor() && MinTgtVers > VariantTargetVersion)
+ VariantTargetVersion = MinTgtVers;
+ CmdArgs.push_back(Args.MakeArgString(VariantTargetVersion.getAsString()));
+ }
}
static const char *getPlatformName(Darwin::DarwinPlatformKind Platform,
@@ -2831,58 +2993,96 @@ static const char *getPlatformName(Darwin::DarwinPlatformKind Platform,
return "tvos";
case Darwin::WatchOS:
return "watchos";
+ case Darwin::DriverKit:
+ return "driverkit";
}
llvm_unreachable("invalid platform");
}
void Darwin::addPlatformVersionArgs(const llvm::opt::ArgList &Args,
llvm::opt::ArgStringList &CmdArgs) const {
- // -platform_version <platform> <target_version> <sdk_version>
- // Both the target and SDK version support only up to 3 components.
- CmdArgs.push_back("-platform_version");
- std::string PlatformName = getPlatformName(TargetPlatform, TargetEnvironment);
- if (TargetEnvironment == Darwin::Simulator)
- PlatformName += "-simulator";
- CmdArgs.push_back(Args.MakeArgString(PlatformName));
- VersionTuple TargetVersion = getTripleTargetVersion().withoutBuild();
- VersionTuple MinTgtVers = getEffectiveTriple().getMinimumSupportedOSVersion();
- if (!MinTgtVers.empty() && MinTgtVers > TargetVersion)
- TargetVersion = MinTgtVers;
- CmdArgs.push_back(Args.MakeArgString(TargetVersion.getAsString()));
+ auto EmitPlatformVersionArg =
+ [&](const VersionTuple &TV, Darwin::DarwinPlatformKind TargetPlatform,
+ Darwin::DarwinEnvironmentKind TargetEnvironment,
+ const llvm::Triple &TT) {
+ // -platform_version <platform> <target_version> <sdk_version>
+ // Both the target and SDK version support only up to 3 components.
+ CmdArgs.push_back("-platform_version");
+ std::string PlatformName =
+ getPlatformName(TargetPlatform, TargetEnvironment);
+ if (TargetEnvironment == Darwin::Simulator)
+ PlatformName += "-simulator";
+ CmdArgs.push_back(Args.MakeArgString(PlatformName));
+ VersionTuple TargetVersion = TV.withoutBuild();
+ if ((TargetPlatform == Darwin::IPhoneOS ||
+ TargetPlatform == Darwin::TvOS) &&
+ getTriple().getArchName() == "arm64e" &&
+ TargetVersion.getMajor() < 14) {
+ // arm64e slice is supported on iOS/tvOS 14+ only.
+ TargetVersion = VersionTuple(14, 0);
+ }
+ VersionTuple MinTgtVers = TT.getMinimumSupportedOSVersion();
+ if (!MinTgtVers.empty() && MinTgtVers > TargetVersion)
+ TargetVersion = MinTgtVers;
+ CmdArgs.push_back(Args.MakeArgString(TargetVersion.getAsString()));
- if (isTargetMacCatalyst()) {
- // Mac Catalyst programs must use the appropriate iOS SDK version
- // that corresponds to the macOS SDK version used for the compilation.
- Optional<VersionTuple> iOSSDKVersion;
- if (SDKInfo) {
- if (const auto *MacOStoMacCatalystMapping = SDKInfo->getVersionMapping(
- DarwinSDKInfo::OSEnvPair::macOStoMacCatalystPair())) {
- iOSSDKVersion = MacOStoMacCatalystMapping->map(
- SDKInfo->getVersion().withoutBuild(),
- minimumMacCatalystDeploymentTarget(), None);
- }
- }
- CmdArgs.push_back(Args.MakeArgString(
- (iOSSDKVersion ? *iOSSDKVersion : minimumMacCatalystDeploymentTarget())
- .getAsString()));
- return;
- }
+ if (TargetPlatform == IPhoneOS && TargetEnvironment == MacCatalyst) {
+ // Mac Catalyst programs must use the appropriate iOS SDK version
+ // that corresponds to the macOS SDK version used for the compilation.
+ Optional<VersionTuple> iOSSDKVersion;
+ if (SDKInfo) {
+ if (const auto *MacOStoMacCatalystMapping =
+ SDKInfo->getVersionMapping(
+ DarwinSDKInfo::OSEnvPair::macOStoMacCatalystPair())) {
+ iOSSDKVersion = MacOStoMacCatalystMapping->map(
+ SDKInfo->getVersion().withoutBuild(),
+ minimumMacCatalystDeploymentTarget(), None);
+ }
+ }
+ CmdArgs.push_back(Args.MakeArgString(
+ (iOSSDKVersion ? *iOSSDKVersion
+ : minimumMacCatalystDeploymentTarget())
+ .getAsString()));
+ return;
+ }
- if (SDKInfo) {
- VersionTuple SDKVersion = SDKInfo->getVersion().withoutBuild();
- CmdArgs.push_back(Args.MakeArgString(SDKVersion.getAsString()));
+ if (SDKInfo) {
+ VersionTuple SDKVersion = SDKInfo->getVersion().withoutBuild();
+ CmdArgs.push_back(Args.MakeArgString(SDKVersion.getAsString()));
+ } else {
+ // Use an SDK version that's matching the deployment target if the SDK
+ // version is missing. This is preferred over an empty SDK version
+ // (0.0.0) as the system's runtime might expect the linked binary to
+ // contain a valid SDK version in order for the binary to work
+ // correctly. It's reasonable to use the deployment target version as
+ // a proxy for the SDK version because older SDKs don't guarantee
+ // support for deployment targets newer than the SDK versions, so that
+ // rules out using some predetermined older SDK version, which leaves
+ // the deployment target version as the only reasonable choice.
+ CmdArgs.push_back(Args.MakeArgString(TargetVersion.getAsString()));
+ }
+ };
+ EmitPlatformVersionArg(getTripleTargetVersion(), TargetPlatform,
+ TargetEnvironment, getEffectiveTriple());
+ if (!TargetVariantTriple)
+ return;
+ Darwin::DarwinPlatformKind Platform;
+ Darwin::DarwinEnvironmentKind Environment;
+ VersionTuple TargetVariantVersion;
+ if (TargetVariantTriple->isMacOSX()) {
+ TargetVariantTriple->getMacOSXVersion(TargetVariantVersion);
+ Platform = Darwin::MacOS;
+ Environment = Darwin::NativeEnvironment;
} else {
- // Use an SDK version that's matching the deployment target if the SDK
- // version is missing. This is preferred over an empty SDK version (0.0.0)
- // as the system's runtime might expect the linked binary to contain a
- // valid SDK version in order for the binary to work correctly. It's
- // reasonable to use the deployment target version as a proxy for the
- // SDK version because older SDKs don't guarantee support for deployment
- // targets newer than the SDK versions, so that rules out using some
- // predetermined older SDK version, which leaves the deployment target
- // version as the only reasonable choice.
- CmdArgs.push_back(Args.MakeArgString(TargetVersion.getAsString()));
+ assert(TargetVariantTriple->isiOS() &&
+ TargetVariantTriple->isMacCatalystEnvironment() &&
+ "unexpected target variant triple");
+ TargetVariantVersion = TargetVariantTriple->getiOSVersion();
+ Platform = Darwin::IPhoneOS;
+ Environment = Darwin::MacCatalyst;
}
+ EmitPlatformVersionArg(TargetVariantVersion, Platform, Environment,
+ *TargetVariantTriple);
}
// Add additional link args for the -dynamiclib option.
diff --git a/clang/lib/Driver/ToolChains/Darwin.h b/clang/lib/Driver/ToolChains/Darwin.h
index 5e23047a5512..4535d021262e 100644
--- a/clang/lib/Driver/ToolChains/Darwin.h
+++ b/clang/lib/Driver/ToolChains/Darwin.h
@@ -63,7 +63,7 @@ class LLVM_LIBRARY_VISIBILITY Linker : public MachOTool {
bool NeedsTempPath(const InputInfoList &Inputs) const;
void AddLinkArgs(Compilation &C, const llvm::opt::ArgList &Args,
llvm::opt::ArgStringList &CmdArgs,
- const InputInfoList &Inputs, unsigned Version[5],
+ const InputInfoList &Inputs, VersionTuple Version,
bool LinkerIsLLD) const;
public:
@@ -147,6 +147,9 @@ private:
mutable std::unique_ptr<tools::darwin::Dsymutil> Dsymutil;
mutable std::unique_ptr<tools::darwin::VerifyDebug> VerifyDebug;
+ /// The version of the linker known to be available in the tool chain.
+ mutable Optional<VersionTuple> LinkerVersion;
+
public:
MachO(const Driver &D, const llvm::Triple &Triple,
const llvm::opt::ArgList &Args);
@@ -159,6 +162,10 @@ public:
/// example, Apple treats different ARM variations as distinct architectures.
StringRef getMachOArchName(const llvm::opt::ArgList &Args) const;
+ /// Get the version of the linker known to be available for a particular
+ /// compiler invocation (via the `-mlinker-version=` arg).
+ VersionTuple getLinkerVersion(const llvm::opt::ArgList &Args) const;
+
/// Add the linker arguments to link the ARC runtime library.
virtual void AddLinkARCArgs(const llvm::opt::ArgList &Args,
llvm::opt::ArgStringList &CmdArgs) const {}
@@ -260,6 +267,7 @@ public:
bool SupportsProfiling() const override;
bool UseDwarfDebugFlags() const override;
+ std::string GetGlobalDebugPathRemapping() const override;
llvm::ExceptionHandling
GetExceptionModel(const llvm::opt::ArgList &Args) const override {
@@ -291,7 +299,8 @@ public:
IPhoneOS,
TvOS,
WatchOS,
- LastDarwinPlatform = WatchOS
+ DriverKit,
+ LastDarwinPlatform = DriverKit
};
enum DarwinEnvironmentKind {
NativeEnvironment,
@@ -310,6 +319,9 @@ public:
/// The information about the darwin SDK that was used.
mutable Optional<DarwinSDKInfo> SDKInfo;
+ /// The target variant triple that was specified (if any).
+ mutable Optional<llvm::Triple> TargetVariantTriple;
+
CudaInstallationDetector CudaInstallation;
RocmInstallationDetector RocmInstallation;
@@ -338,7 +350,7 @@ public:
bool isKernelStatic() const override {
return (!(isTargetIPhoneOS() && !isIPhoneOSVersionLT(6, 0)) &&
- !isTargetWatchOS());
+ !isTargetWatchOS() && !isTargetDriverKit());
}
void addProfileRTLibs(const llvm::opt::ArgList &Args,
@@ -424,6 +436,11 @@ public:
return TargetPlatform == WatchOS;
}
+ bool isTargetDriverKit() const {
+ assert(TargetInitialized && "Target not initialized!");
+ return TargetPlatform == DriverKit;
+ }
+
bool isTargetMacCatalyst() const {
return TargetPlatform == IPhoneOS && TargetEnvironment == MacCatalyst;
}
@@ -478,6 +495,12 @@ public:
: TargetVersion) < VersionTuple(V0, V1, V2);
}
+ /// Returns the darwin target variant triple, the variant of the deployment
+ /// target for which the code is being compiled.
+ Optional<llvm::Triple> getTargetVariantTriple() const override {
+ return TargetVariantTriple;
+ }
+
protected:
/// Return true if c++17 aligned allocation/deallocation functions are not
/// implemented in the c++ standard library of the deployment target we are
@@ -527,7 +550,7 @@ public:
GetDefaultStackProtectorLevel(bool KernelOrKext) const override {
// Stack protectors default to on for user code on 10.5,
// and for everything in 10.6 and beyond
- if (isTargetIOSBased() || isTargetWatchOSBased())
+ if (isTargetIOSBased() || isTargetWatchOSBased() || isTargetDriverKit())
return LangOptions::SSPOn;
else if (isTargetMacOSBased() && !isMacosxVersionLT(10, 6))
return LangOptions::SSPOn;
diff --git a/clang/lib/Driver/ToolChains/DragonFly.cpp b/clang/lib/Driver/ToolChains/DragonFly.cpp
index 9568b47e89e6..8cfec6a6c4e0 100644
--- a/clang/lib/Driver/ToolChains/DragonFly.cpp
+++ b/clang/lib/Driver/ToolChains/DragonFly.cpp
@@ -91,7 +91,8 @@ void dragonfly::Linker::ConstructJob(Compilation &C, const JobAction &JA,
assert(Output.isNothing() && "Invalid output.");
}
- if (!Args.hasArg(options::OPT_nostdlib, options::OPT_nostartfiles)) {
+ if (!Args.hasArg(options::OPT_nostdlib, options::OPT_nostartfiles,
+ options::OPT_r)) {
if (!Args.hasArg(options::OPT_shared)) {
if (Args.hasArg(options::OPT_pg))
CmdArgs.push_back(
@@ -119,7 +120,8 @@ void dragonfly::Linker::ConstructJob(Compilation &C, const JobAction &JA,
AddLinkerInputs(getToolChain(), Inputs, Args, CmdArgs, JA);
- if (!Args.hasArg(options::OPT_nostdlib, options::OPT_nodefaultlibs)) {
+ if (!Args.hasArg(options::OPT_nostdlib, options::OPT_nodefaultlibs,
+ options::OPT_r)) {
CmdArgs.push_back("-L/usr/lib/gcc80");
if (!Args.hasArg(options::OPT_static)) {
@@ -158,7 +160,8 @@ void dragonfly::Linker::ConstructJob(Compilation &C, const JobAction &JA,
}
}
- if (!Args.hasArg(options::OPT_nostdlib, options::OPT_nostartfiles)) {
+ if (!Args.hasArg(options::OPT_nostdlib, options::OPT_nostartfiles,
+ options::OPT_r)) {
if (Args.hasArg(options::OPT_shared) || Args.hasArg(options::OPT_pie))
CmdArgs.push_back(
Args.MakeArgString(getToolChain().GetFilePath("crtendS.o")));
diff --git a/clang/lib/Driver/ToolChains/Flang.cpp b/clang/lib/Driver/ToolChains/Flang.cpp
index c169e3d45793..3368f6785718 100644
--- a/clang/lib/Driver/ToolChains/Flang.cpp
+++ b/clang/lib/Driver/ToolChains/Flang.cpp
@@ -19,6 +19,14 @@ using namespace clang::driver::tools;
using namespace clang;
using namespace llvm::opt;
+/// Add -x lang to \p CmdArgs for \p Input.
+static void addDashXForInput(const ArgList &Args, const InputInfo &Input,
+ ArgStringList &CmdArgs) {
+ CmdArgs.push_back("-x");
+ // Map the driver type to the frontend type.
+ CmdArgs.push_back(types::getTypeName(Input.getType()));
+}
+
void Flang::AddFortranDialectOptions(const ArgList &Args,
ArgStringList &CmdArgs) const {
Args.AddAllArgs(
@@ -54,21 +62,18 @@ void Flang::ConstructJob(Compilation &C, const JobAction &JA,
const InputInfo &Output, const InputInfoList &Inputs,
const ArgList &Args, const char *LinkingOutput) const {
const auto &TC = getToolChain();
- // TODO: Once code-generation is available, this will need to be commented
- // out.
- // const llvm::Triple &Triple = TC.getEffectiveTriple();
- // const std::string &TripleStr = Triple.getTriple();
+ const llvm::Triple &Triple = TC.getEffectiveTriple();
+ const std::string &TripleStr = Triple.getTriple();
+ const Driver &D = TC.getDriver();
ArgStringList CmdArgs;
// Invoke ourselves in -fc1 mode.
CmdArgs.push_back("-fc1");
- // TODO: Once code-generation is available, this will need to be commented
- // out.
// Add the "effective" target triple.
- // CmdArgs.push_back("-triple");
- // CmdArgs.push_back(Args.MakeArgString(TripleStr));
+ CmdArgs.push_back("-triple");
+ CmdArgs.push_back(Args.MakeArgString(TripleStr));
if (isa<PreprocessJobAction>(JA)) {
CmdArgs.push_back("-E");
@@ -104,12 +109,42 @@ void Flang::ConstructJob(Compilation &C, const JobAction &JA,
AddFortranDialectOptions(Args, CmdArgs);
+ // Color diagnostics are parsed by the driver directly from argv and later
+ // re-parsed to construct this job; claim any possible color diagnostic here
+ // to avoid warn_drv_unused_argument.
+ Args.getLastArg(options::OPT_fcolor_diagnostics,
+ options::OPT_fno_color_diagnostics);
+ if (D.getDiags().getDiagnosticOptions().ShowColors)
+ CmdArgs.push_back("-fcolor-diagnostics");
+
// Add other compile options
AddOtherOptions(Args, CmdArgs);
// Forward -Xflang arguments to -fc1
Args.AddAllArgValues(CmdArgs, options::OPT_Xflang);
+ // Forward -mllvm options to the LLVM option parser. In practice, this means
+ // forwarding to `-fc1` as that's where the LLVM parser is run.
+ for (const Arg *A : Args.filtered(options::OPT_mllvm)) {
+ A->claim();
+ A->render(Args, CmdArgs);
+ }
+
+ for (const Arg *A : Args.filtered(options::OPT_mmlir)) {
+ A->claim();
+ A->render(Args, CmdArgs);
+ }
+
+ // Optimization level for CodeGen.
+ if (const Arg *A = Args.getLastArg(options::OPT_O_Group)) {
+ if (A->getOption().matches(options::OPT_O4)) {
+ CmdArgs.push_back("-O3");
+ D.Diag(diag::warn_O4_is_O3);
+ } else {
+ A->render(Args, CmdArgs);
+ }
+ }
+
if (Output.isFilename()) {
CmdArgs.push_back("-o");
CmdArgs.push_back(Output.getFilename());
@@ -118,9 +153,11 @@ void Flang::ConstructJob(Compilation &C, const JobAction &JA,
}
assert(Input.isFilename() && "Invalid input.");
+
+ addDashXForInput(Args, Input, CmdArgs);
+
CmdArgs.push_back(Input.getFilename());
- const auto& D = C.getDriver();
// TODO: Replace flang-new with flang once the new driver replaces the
// throwaway driver
const char *Exec = Args.MakeArgString(D.GetProgramPath("flang-new", TC));
diff --git a/clang/lib/Driver/ToolChains/FreeBSD.cpp b/clang/lib/Driver/ToolChains/FreeBSD.cpp
index 05c58a8f43a8..79e3c5cbca5f 100644
--- a/clang/lib/Driver/ToolChains/FreeBSD.cpp
+++ b/clang/lib/Driver/ToolChains/FreeBSD.cpp
@@ -223,10 +223,12 @@ void freebsd::Linker::ConstructJob(Compilation &C, const JobAction &JA,
case llvm::Triple::riscv32:
CmdArgs.push_back("-m");
CmdArgs.push_back("elf32lriscv");
+ CmdArgs.push_back("-X");
break;
case llvm::Triple::riscv64:
CmdArgs.push_back("-m");
CmdArgs.push_back("elf64lriscv");
+ CmdArgs.push_back("-X");
break;
default:
break;
diff --git a/clang/lib/Driver/ToolChains/Fuchsia.cpp b/clang/lib/Driver/ToolChains/Fuchsia.cpp
index bd1600d060c8..03ff9fe894c8 100644
--- a/clang/lib/Driver/ToolChains/Fuchsia.cpp
+++ b/clang/lib/Driver/ToolChains/Fuchsia.cpp
@@ -37,6 +37,8 @@ void fuchsia::Linker::ConstructJob(Compilation &C, const JobAction &JA,
static_cast<const toolchains::Fuchsia &>(getToolChain());
const Driver &D = ToolChain.getDriver();
+ const llvm::Triple &Triple = ToolChain.getEffectiveTriple();
+
ArgStringList CmdArgs;
// Silence warning for "clang -g foo.o -o foo"
@@ -84,6 +86,12 @@ void fuchsia::Linker::ConstructJob(Compilation &C, const JobAction &JA,
CmdArgs.push_back("--hash-style=gnu");
}
+ if (ToolChain.getArch() == llvm::Triple::aarch64) {
+ std::string CPU = getCPUName(D, Args, Triple);
+ if (CPU.empty() || CPU == "generic" || CPU == "cortex-a53")
+ CmdArgs.push_back("--fix-cortex-a53-843419");
+ }
+
CmdArgs.push_back("--eh-frame-hdr");
if (Args.hasArg(options::OPT_static))
@@ -106,6 +114,9 @@ void fuchsia::Linker::ConstructJob(Compilation &C, const JobAction &JA,
CmdArgs.push_back(Args.MakeArgString(Dyld));
}
+ if (ToolChain.getArch() == llvm::Triple::riscv64)
+ CmdArgs.push_back("-X");
+
CmdArgs.push_back("-o");
CmdArgs.push_back(Output.getFilename());
@@ -127,10 +138,8 @@ void fuchsia::Linker::ConstructJob(Compilation &C, const JobAction &JA,
D.getLTOMode() == LTOK_Thin);
}
- bool NeedsSanitizerDeps = addSanitizerRuntimes(ToolChain, Args, CmdArgs);
- bool NeedsXRayDeps = addXRayRuntime(ToolChain, Args, CmdArgs);
+ addLinkerCompressDebugSectionsOption(ToolChain, Args, CmdArgs);
AddLinkerInputs(ToolChain, Inputs, Args, CmdArgs, JA);
- ToolChain.addProfileRTLibs(Args, CmdArgs);
if (!Args.hasArg(options::OPT_nostdlib, options::OPT_nodefaultlibs,
options::OPT_r)) {
@@ -153,11 +162,14 @@ void fuchsia::Linker::ConstructJob(Compilation &C, const JobAction &JA,
}
}
- if (NeedsSanitizerDeps)
- linkSanitizerRuntimeDeps(ToolChain, CmdArgs);
+ // Note that Fuchsia never needs to link in sanitizer runtime deps. Any
+ // sanitizer runtimes with system dependencies use the `.deplibs` feature
+ // instead.
+ addSanitizerRuntimes(ToolChain, Args, CmdArgs);
+
+ addXRayRuntime(ToolChain, Args, CmdArgs);
- if (NeedsXRayDeps)
- linkXRayRuntimeDeps(ToolChain, CmdArgs);
+ ToolChain.addProfileRTLibs(Args, CmdArgs);
AddRunTimeLibs(ToolChain, D, CmdArgs, Args);
diff --git a/clang/lib/Driver/ToolChains/Fuchsia.h b/clang/lib/Driver/ToolChains/Fuchsia.h
index c0e69df22821..f9f3bbfa9fbf 100644
--- a/clang/lib/Driver/ToolChains/Fuchsia.h
+++ b/clang/lib/Driver/ToolChains/Fuchsia.h
@@ -75,24 +75,27 @@ public:
RuntimeLibType
GetRuntimeLibType(const llvm::opt::ArgList &Args) const override;
- CXXStdlibType
- GetCXXStdlibType(const llvm::opt::ArgList &Args) const override;
+ CXXStdlibType GetCXXStdlibType(const llvm::opt::ArgList &Args) const override;
+
+ bool IsAArch64OutlineAtomicsDefault(
+ const llvm::opt::ArgList &Args) const override {
+ return true;
+ }
- void addClangTargetOptions(const llvm::opt::ArgList &DriverArgs,
- llvm::opt::ArgStringList &CC1Args,
- Action::OffloadKind DeviceOffloadKind) const override;
+ void
+ addClangTargetOptions(const llvm::opt::ArgList &DriverArgs,
+ llvm::opt::ArgStringList &CC1Args,
+ Action::OffloadKind DeviceOffloadKind) const override;
void
AddClangSystemIncludeArgs(const llvm::opt::ArgList &DriverArgs,
llvm::opt::ArgStringList &CC1Args) const override;
- void
- AddClangCXXStdlibIncludeArgs(const llvm::opt::ArgList &DriverArgs,
- llvm::opt::ArgStringList &CC1Args) const override;
+ void AddClangCXXStdlibIncludeArgs(
+ const llvm::opt::ArgList &DriverArgs,
+ llvm::opt::ArgStringList &CC1Args) const override;
void AddCXXStdlibLibArgs(const llvm::opt::ArgList &Args,
llvm::opt::ArgStringList &CmdArgs) const override;
- const char *getDefaultLinker() const override {
- return "ld.lld";
- }
+ const char *getDefaultLinker() const override { return "ld.lld"; }
protected:
Tool *buildLinker() const override;
diff --git a/clang/lib/Driver/ToolChains/Gnu.cpp b/clang/lib/Driver/ToolChains/Gnu.cpp
index 7a9570a686f4..f52bb8af5ec9 100644
--- a/clang/lib/Driver/ToolChains/Gnu.cpp
+++ b/clang/lib/Driver/ToolChains/Gnu.cpp
@@ -8,6 +8,7 @@
#include "Gnu.h"
#include "Arch/ARM.h"
+#include "Arch/CSKY.h"
#include "Arch/Mips.h"
#include "Arch/PPC.h"
#include "Arch/RISCV.h"
@@ -299,6 +300,8 @@ static const char *getLDMOption(const llvm::Triple &T, const ArgList &Args) {
return "elf_x86_64";
case llvm::Triple::ve:
return "elf64ve";
+ case llvm::Triple::csky:
+ return "cskyelf_linux";
default:
return nullptr;
}
@@ -451,11 +454,6 @@ void tools::gnutools::Linker::ConstructJob(Compilation &C, const JobAction &JA,
CmdArgs.push_back("--fix-cortex-a53-843419");
}
- // Android does not allow shared text relocations. Emit a warning if the
- // user's code contains any.
- if (isAndroid)
- CmdArgs.push_back("--warn-shared-textrel");
-
ToolChain.addExtraOpts(CmdArgs);
CmdArgs.push_back("--eh-frame-hdr");
@@ -467,6 +465,8 @@ void tools::gnutools::Linker::ConstructJob(Compilation &C, const JobAction &JA,
D.Diag(diag::err_target_unknown_triple) << Triple.str();
return;
}
+ if (Triple.isRISCV())
+ CmdArgs.push_back("-X");
if (Args.hasArg(options::OPT_shared))
CmdArgs.push_back("-shared");
@@ -477,7 +477,8 @@ void tools::gnutools::Linker::ConstructJob(Compilation &C, const JobAction &JA,
if (Args.hasArg(options::OPT_rdynamic))
CmdArgs.push_back("-export-dynamic");
- if (!Args.hasArg(options::OPT_shared) && !IsStaticPIE) {
+ if (!Args.hasArg(options::OPT_shared) && !IsStaticPIE &&
+ !Args.hasArg(options::OPT_r)) {
CmdArgs.push_back("-dynamic-linker");
CmdArgs.push_back(Args.MakeArgString(Twine(D.DyldPrefix) +
ToolChain.getDynamicLinker(Args)));
@@ -560,6 +561,9 @@ void tools::gnutools::Linker::ConstructJob(Compilation &C, const JobAction &JA,
bool NeedsXRayDeps = addXRayRuntime(ToolChain, Args, CmdArgs);
addLinkerCompressDebugSectionsOption(ToolChain, Args, CmdArgs);
AddLinkerInputs(ToolChain, Inputs, Args, CmdArgs, JA);
+
+ addHIPRuntimeLibArgs(ToolChain, Args, CmdArgs);
+
// The profile runtime also needs access to system libraries.
getToolChain().addProfileRTLibs(Args, CmdArgs);
@@ -577,9 +581,27 @@ void tools::gnutools::Linker::ConstructJob(Compilation &C, const JobAction &JA,
}
CmdArgs.push_back("-lm");
}
+
+ // If we are linking for the device all symbols should be bound locally. The
+ // symbols are already protected which makes this redundant. This is only
+ // necessary to work around a problem in bfd.
+ // TODO: Remove this once 'lld' becomes the only linker for offloading.
+ if (JA.isDeviceOffloading(Action::OFK_OpenMP))
+ CmdArgs.push_back("-Bsymbolic");
+
// Silence warnings when linking C code with a C++ '-stdlib' argument.
Args.ClaimAllArgs(options::OPT_stdlib_EQ);
+ // Additional linker set-up and flags for Fortran. This is required in order
+ // to generate executables. As Fortran runtime depends on the C runtime,
+ // these dependencies need to be listed before the C runtime below (i.e.
+ // AddRuntTimeLibs).
+ if (D.IsFlangMode()) {
+ addFortranRuntimeLibraryPath(ToolChain, Args, CmdArgs);
+ addFortranRuntimeLibs(ToolChain, CmdArgs);
+ CmdArgs.push_back("-lm");
+ }
+
if (!Args.hasArg(options::OPT_nostdlib, options::OPT_r)) {
if (!Args.hasArg(options::OPT_nodefaultlibs)) {
if (IsStatic || IsStaticPIE)
@@ -758,6 +780,8 @@ void tools::gnutools::Assembler::ConstructJob(Compilation &C,
StringRef MArchName = riscv::getRISCVArch(Args, getToolChain().getTriple());
CmdArgs.push_back("-march");
CmdArgs.push_back(MArchName.data());
+ if (!Args.hasFlag(options::OPT_mrelax, options::OPT_mno_relax, true))
+ Args.addOptOutFlag(CmdArgs, options::OPT_mrelax, options::OPT_mno_relax);
break;
}
case llvm::Triple::sparc:
@@ -1574,6 +1598,68 @@ static bool findMSP430Multilibs(const Driver &D,
return false;
}
+static void findCSKYMultilibs(const Driver &D, const llvm::Triple &TargetTriple,
+ StringRef Path, const ArgList &Args,
+ DetectedMultilibs &Result) {
+ FilterNonExistent NonExistent(Path, "/crtbegin.o", D.getVFS());
+
+ tools::csky::FloatABI TheFloatABI = tools::csky::getCSKYFloatABI(D, Args);
+ llvm::Optional<llvm::StringRef> Res = tools::csky::getCSKYArchName(D, Args, TargetTriple);
+
+ if (!Res)
+ return;
+ auto ARCHName = *Res;
+
+ Multilib::flags_list Flags;
+ addMultilibFlag(TheFloatABI == tools::csky::FloatABI::Hard, "hard-fp", Flags);
+ addMultilibFlag(TheFloatABI == tools::csky::FloatABI::SoftFP, "soft-fp",
+ Flags);
+ addMultilibFlag(TheFloatABI == tools::csky::FloatABI::Soft, "soft", Flags);
+ addMultilibFlag(ARCHName == "ck801", "march=ck801", Flags);
+ addMultilibFlag(ARCHName == "ck802", "march=ck802", Flags);
+ addMultilibFlag(ARCHName == "ck803", "march=ck803", Flags);
+ addMultilibFlag(ARCHName == "ck804", "march=ck804", Flags);
+ addMultilibFlag(ARCHName == "ck805", "march=ck805", Flags);
+ addMultilibFlag(ARCHName == "ck807", "march=ck807", Flags);
+ addMultilibFlag(ARCHName == "ck810", "march=ck810", Flags);
+ addMultilibFlag(ARCHName == "ck810v", "march=ck810v", Flags);
+ addMultilibFlag(ARCHName == "ck860", "march=ck860", Flags);
+ addMultilibFlag(ARCHName == "ck860v", "march=ck860v", Flags);
+
+ bool isBigEndian = false;
+ if (Arg *A = Args.getLastArg(options::OPT_mlittle_endian,
+ options::OPT_mbig_endian))
+ isBigEndian = !A->getOption().matches(options::OPT_mlittle_endian);
+ addMultilibFlag(isBigEndian, "EB", Flags);
+
+ auto HardFloat = makeMultilib("/hard-fp").flag("+hard-fp");
+ auto SoftFpFloat = makeMultilib("/soft-fp").flag("+soft-fp");
+ auto SoftFloat = makeMultilib("").flag("+soft");
+ auto Arch801 = makeMultilib("/ck801").flag("+march=ck801");
+ auto Arch802 = makeMultilib("/ck802").flag("+march=ck802");
+ auto Arch803 = makeMultilib("/ck803").flag("+march=ck803");
+ // CK804 use the same library as CK803
+ auto Arch804 = makeMultilib("/ck803").flag("+march=ck804");
+ auto Arch805 = makeMultilib("/ck805").flag("+march=ck805");
+ auto Arch807 = makeMultilib("/ck807").flag("+march=ck807");
+ auto Arch810 = makeMultilib("").flag("+march=ck810");
+ auto Arch810v = makeMultilib("/ck810v").flag("+march=ck810v");
+ auto Arch860 = makeMultilib("/ck860").flag("+march=ck860");
+ auto Arch860v = makeMultilib("/ck860v").flag("+march=ck860v");
+ auto BigEndian = makeMultilib("/big").flag("+EB");
+
+ MultilibSet CSKYMultilibs =
+ MultilibSet()
+ .Maybe(BigEndian)
+ .Either({Arch801, Arch802, Arch803, Arch804, Arch805, Arch807,
+ Arch810, Arch810v, Arch860, Arch860v})
+ .Either(HardFloat, SoftFpFloat, SoftFloat)
+ .FilterOut(NonExistent);
+
+ if (CSKYMultilibs.select(Flags, Result.SelectedMultilib))
+ Result.Multilibs = CSKYMultilibs;
+}
+
static void findRISCVBareMetalMultilibs(const Driver &D,
const llvm::Triple &TargetTriple,
StringRef Path, const ArgList &Args,
@@ -1951,7 +2037,7 @@ void Generic_GCC::GCCInstallationDetector::init(
if (!VFS.exists(Prefix))
continue;
for (StringRef Suffix : CandidateLibDirs) {
- const std::string LibDir = Prefix + Suffix.str();
+ const std::string LibDir = concat(Prefix, Suffix);
if (!VFS.exists(LibDir))
continue;
// Maybe filter out <libdir>/gcc and <libdir>/gcc-cross.
@@ -2000,7 +2086,7 @@ void Generic_GCC::GCCInstallationDetector::print(raw_ostream &OS) const {
}
bool Generic_GCC::GCCInstallationDetector::getBiarchSibling(Multilib &M) const {
- if (BiarchSibling.hasValue()) {
+ if (BiarchSibling) {
M = BiarchSibling.getValue();
return true;
}
@@ -2017,7 +2103,7 @@ void Generic_GCC::GCCInstallationDetector::AddDefaultGCCPrefixes(
// so we need to find those /usr/gcc/*/lib/gcc libdirs and go with
// /usr/gcc/<version> as a prefix.
- std::string PrefixDir = SysRoot.str() + "/usr/gcc";
+ std::string PrefixDir = concat(SysRoot, "/usr/gcc");
std::error_code EC;
for (llvm::vfs::directory_iterator LI = D.getVFS().dir_begin(PrefixDir, EC),
LE;
@@ -2039,20 +2125,39 @@ void Generic_GCC::GCCInstallationDetector::AddDefaultGCCPrefixes(
return;
}
- // Non-Solaris is much simpler - most systems just go with "/usr".
- if (SysRoot.empty() && TargetTriple.getOS() == llvm::Triple::Linux) {
- // Yet, still look for RHEL/CentOS devtoolsets and gcc-toolsets.
- Prefixes.push_back("/opt/rh/gcc-toolset-10/root/usr");
- Prefixes.push_back("/opt/rh/devtoolset-10/root/usr");
- Prefixes.push_back("/opt/rh/devtoolset-9/root/usr");
- Prefixes.push_back("/opt/rh/devtoolset-8/root/usr");
- Prefixes.push_back("/opt/rh/devtoolset-7/root/usr");
- Prefixes.push_back("/opt/rh/devtoolset-6/root/usr");
- Prefixes.push_back("/opt/rh/devtoolset-4/root/usr");
- Prefixes.push_back("/opt/rh/devtoolset-3/root/usr");
- Prefixes.push_back("/opt/rh/devtoolset-2/root/usr");
+ // For Linux, if --sysroot is not specified, look for RHEL/CentOS devtoolsets
+ // and gcc-toolsets.
+ if (SysRoot.empty() && TargetTriple.getOS() == llvm::Triple::Linux &&
+ D.getVFS().exists("/opt/rh")) {
+ // Find the directory in /opt/rh/ starting with gcc-toolset-* or
+ // devtoolset-* with the highest version number and add that
+ // one to our prefixes.
+ std::string ChosenToolsetDir;
+ unsigned ChosenToolsetVersion = 0;
+ std::error_code EC;
+ for (llvm::vfs::directory_iterator LI = D.getVFS().dir_begin("/opt/rh", EC),
+ LE;
+ !EC && LI != LE; LI = LI.increment(EC)) {
+ StringRef ToolsetDir = llvm::sys::path::filename(LI->path());
+ unsigned ToolsetVersion;
+ if ((!ToolsetDir.startswith("gcc-toolset-") &&
+ !ToolsetDir.startswith("devtoolset-")) ||
+ ToolsetDir.substr(ToolsetDir.rfind('-') + 1)
+ .getAsInteger(10, ToolsetVersion))
+ continue;
+
+ if (ToolsetVersion > ChosenToolsetVersion) {
+ ChosenToolsetVersion = ToolsetVersion;
+ ChosenToolsetDir = "/opt/rh/" + ToolsetDir.str();
+ }
+ }
+
+ if (ChosenToolsetVersion > 0)
+ Prefixes.push_back(ChosenToolsetDir + "/root/usr");
}
- Prefixes.push_back(SysRoot.str() + "/usr");
+
+ // Fall back to /usr which is used by most non-Solaris systems.
+ Prefixes.push_back(concat(SysRoot, "/usr"));
}
/*static*/ void Generic_GCC::GCCInstallationDetector::CollectLibDirsAndTriples(
@@ -2092,6 +2197,10 @@ void Generic_GCC::GCCInstallationDetector::AddDefaultGCCPrefixes(
static const char *const AVRLibDirs[] = {"/lib"};
static const char *const AVRTriples[] = {"avr"};
+ static const char *const CSKYLibDirs[] = {"/lib"};
+ static const char *const CSKYTriples[] = {
+ "csky-linux-gnuabiv2", "csky-linux-uclibcabiv2", "csky-elf-noneabiv2"};
+
static const char *const X86_64LibDirs[] = {"/lib64", "/lib"};
static const char *const X86_64Triples[] = {
"x86_64-linux-gnu", "x86_64-unknown-linux-gnu",
@@ -2326,6 +2435,10 @@ void Generic_GCC::GCCInstallationDetector::AddDefaultGCCPrefixes(
LibDirs.append(begin(AVRLibDirs), end(AVRLibDirs));
TripleAliases.append(begin(AVRTriples), end(AVRTriples));
break;
+ case llvm::Triple::csky:
+ LibDirs.append(begin(CSKYLibDirs), end(CSKYLibDirs));
+ TripleAliases.append(begin(CSKYTriples), end(CSKYTriples));
+ break;
case llvm::Triple::x86_64:
if (TargetTriple.isX32()) {
LibDirs.append(begin(X32LibDirs), end(X32LibDirs));
@@ -2475,6 +2588,8 @@ bool Generic_GCC::GCCInstallationDetector::ScanGCCForMultilibs(
if (isArmOrThumbArch(TargetArch) && TargetTriple.isAndroid()) {
// It should also work without multilibs in a simplified toolchain.
findAndroidArmMultilibs(D, TargetTriple, Path, Args, Detected);
+ } else if (TargetTriple.isCSKY()) {
+ findCSKYMultilibs(D, TargetTriple, Path, Args, Detected);
} else if (TargetTriple.isMIPS()) {
if (!findMIPSMultilibs(D, TargetTriple, Path, Args, Detected))
return false;
@@ -2565,7 +2680,7 @@ bool Generic_GCC::GCCInstallationDetector::ScanGentooConfigs(
const llvm::Triple &TargetTriple, const ArgList &Args,
const SmallVectorImpl<StringRef> &CandidateTriples,
const SmallVectorImpl<StringRef> &CandidateBiarchTriples) {
- if (!D.getVFS().exists(D.SysRoot + GentooConfigDir))
+ if (!D.getVFS().exists(concat(D.SysRoot, GentooConfigDir)))
return false;
for (StringRef CandidateTriple : CandidateTriples) {
@@ -2584,8 +2699,8 @@ bool Generic_GCC::GCCInstallationDetector::ScanGentooGccConfig(
const llvm::Triple &TargetTriple, const ArgList &Args,
StringRef CandidateTriple, bool NeedsBiarchSuffix) {
llvm::ErrorOr<std::unique_ptr<llvm::MemoryBuffer>> File =
- D.getVFS().getBufferForFile(D.SysRoot + GentooConfigDir + "/config-" +
- CandidateTriple.str());
+ D.getVFS().getBufferForFile(concat(D.SysRoot, GentooConfigDir,
+ "/config-" + CandidateTriple.str()));
if (File) {
SmallVector<StringRef, 2> Lines;
File.get()->getBuffer().split(Lines, "\n");
@@ -2596,8 +2711,8 @@ bool Generic_GCC::GCCInstallationDetector::ScanGentooGccConfig(
continue;
// Process the config file pointed to by CURRENT.
llvm::ErrorOr<std::unique_ptr<llvm::MemoryBuffer>> ConfigFile =
- D.getVFS().getBufferForFile(D.SysRoot + GentooConfigDir + "/" +
- Line.str());
+ D.getVFS().getBufferForFile(
+ concat(D.SysRoot, GentooConfigDir, "/" + Line));
std::pair<StringRef, StringRef> ActiveVersion = Line.rsplit('-');
// List of paths to scan for libraries.
SmallVector<StringRef, 4> GentooScanPaths;
@@ -2630,7 +2745,7 @@ bool Generic_GCC::GCCInstallationDetector::ScanGentooGccConfig(
// Scan all paths for GCC libraries.
for (const auto &GentooScanPath : GentooScanPaths) {
- std::string GentooPath = D.SysRoot + std::string(GentooScanPath);
+ std::string GentooPath = concat(D.SysRoot, GentooScanPath);
if (D.getVFS().exists(GentooPath + "/crtbegin.o")) {
if (!ScanGCCForMultilibs(TargetTriple, Args, GentooPath,
NeedsBiarchSuffix))
@@ -2726,8 +2841,6 @@ bool Generic_GCC::isPICDefaultForced() const {
bool Generic_GCC::IsIntegratedAssemblerDefault() const {
switch (getTriple().getArch()) {
- case llvm::Triple::x86:
- case llvm::Triple::x86_64:
case llvm::Triple::aarch64:
case llvm::Triple::aarch64_be:
case llvm::Triple::arm:
@@ -2735,29 +2848,31 @@ bool Generic_GCC::IsIntegratedAssemblerDefault() const {
case llvm::Triple::avr:
case llvm::Triple::bpfel:
case llvm::Triple::bpfeb:
- case llvm::Triple::thumb:
- case llvm::Triple::thumbeb:
+ case llvm::Triple::csky:
+ case llvm::Triple::hexagon:
+ case llvm::Triple::lanai:
+ case llvm::Triple::m68k:
+ case llvm::Triple::mips:
+ case llvm::Triple::mipsel:
+ case llvm::Triple::mips64:
+ case llvm::Triple::mips64el:
+ case llvm::Triple::msp430:
case llvm::Triple::ppc:
case llvm::Triple::ppcle:
case llvm::Triple::ppc64:
case llvm::Triple::ppc64le:
case llvm::Triple::riscv32:
case llvm::Triple::riscv64:
- case llvm::Triple::systemz:
- case llvm::Triple::mips:
- case llvm::Triple::mipsel:
- case llvm::Triple::mips64:
- case llvm::Triple::mips64el:
- case llvm::Triple::msp430:
- case llvm::Triple::m68k:
- return true;
case llvm::Triple::sparc:
case llvm::Triple::sparcel:
case llvm::Triple::sparcv9:
- if (getTriple().isOSFreeBSD() || getTriple().isOSOpenBSD() ||
- getTriple().isOSSolaris())
- return true;
- return false;
+ case llvm::Triple::systemz:
+ case llvm::Triple::thumb:
+ case llvm::Triple::thumbeb:
+ case llvm::Triple::ve:
+ case llvm::Triple::x86:
+ case llvm::Triple::x86_64:
+ return true;
default:
return false;
}
@@ -2800,6 +2915,11 @@ void Generic_GCC::AddMultilibPaths(const Driver &D,
D, GCCInstallation.getInstallPath() + SelectedMultilib.gccSuffix(),
Paths);
+ // Add lib/gcc/$triple/$libdir
+ // For GCC built with --enable-version-specific-runtime-libs.
+ addPathIfExists(D, GCCInstallation.getInstallPath() + "/../" + OSLibDir,
+ Paths);
+
// GCC cross compiling toolchains will install target libraries which ship
// as part of the toolchain under <prefix>/<triple>/<libdir> rather than as
// any part of the GCC installation in
@@ -2918,9 +3038,9 @@ Generic_GCC::addLibCxxIncludePaths(const llvm::opt::ArgList &DriverArgs,
// If this is a development, non-installed, clang, libcxx will
// not be found at ../include/c++ but it likely to be found at
// one of the following two locations:
- if (AddIncludePath(SysRoot + "/usr/local/include"))
+ if (AddIncludePath(concat(SysRoot, "/usr/local/include")))
return;
- if (AddIncludePath(SysRoot + "/usr/include"))
+ if (AddIncludePath(concat(SysRoot, "/usr/include")))
return;
}
@@ -2978,6 +3098,15 @@ bool Generic_GCC::addGCCLibStdCxxIncludePaths(
TripleStr, Multilib.includeSuffix(), DriverArgs, CC1Args))
return true;
+ // Try /gcc/$triple/$version/include/c++/ (gcc --print-multiarch is not
+ // empty). Like above but for GCC built with
+ // --enable-version-specific-runtime-libs.
+ if (addLibStdCXXIncludePaths(LibDir.str() + "/gcc/" + TripleStr + "/" +
+ Version.Text + "/include/c++/",
+ TripleStr, Multilib.includeSuffix(), DriverArgs,
+ CC1Args))
+ return true;
+
// Detect Debian g++-multiarch-incdir.diff.
if (addLibStdCXXIncludePaths(LibDir.str() + "/../include/c++/" + Version.Text,
DebianMultiarch, Multilib.includeSuffix(),
diff --git a/clang/lib/Driver/ToolChains/HIPAMD.cpp b/clang/lib/Driver/ToolChains/HIPAMD.cpp
index 6d553791b394..b31077c1fd3b 100644
--- a/clang/lib/Driver/ToolChains/HIPAMD.cpp
+++ b/clang/lib/Driver/ToolChains/HIPAMD.cpp
@@ -47,7 +47,7 @@ static bool shouldSkipSanitizeOption(const ToolChain &TC,
return false;
if (!DriverArgs.hasFlag(options::OPT_fgpu_sanitize,
- -options::OPT_fno_gpu_sanitize))
+ options::OPT_fno_gpu_sanitize, true))
return true;
auto &Diags = TC.getDriver().getDiags();
@@ -72,6 +72,36 @@ static bool shouldSkipSanitizeOption(const ToolChain &TC,
return false;
}
+void AMDGCN::Linker::constructLlvmLinkCommand(Compilation &C,
+ const JobAction &JA,
+ const InputInfoList &Inputs,
+ const InputInfo &Output,
+ const llvm::opt::ArgList &Args) const {
+ // Construct llvm-link command.
+ // The output from llvm-link is a bitcode file.
+ ArgStringList LlvmLinkArgs;
+
+ assert(!Inputs.empty() && "Must have at least one input.");
+
+ LlvmLinkArgs.append({"-o", Output.getFilename()});
+ for (auto Input : Inputs)
+ LlvmLinkArgs.push_back(Input.getFilename());
+
+ // Look for archive of bundled bitcode in arguments, and add temporary files
+ // for the extracted archive of bitcode to inputs.
+ auto TargetID = Args.getLastArgValue(options::OPT_mcpu_EQ);
+ AddStaticDeviceLibsLinking(C, *this, JA, Inputs, Args, LlvmLinkArgs, "amdgcn",
+ TargetID,
+ /*IsBitCodeSDL=*/true,
+ /*PostClangLink=*/false);
+
+ const char *LlvmLink =
+ Args.MakeArgString(getToolChain().GetProgramPath("llvm-link"));
+ C.addCommand(std::make_unique<Command>(JA, *this, ResponseFileSupport::None(),
+ LlvmLink, LlvmLinkArgs, Inputs,
+ Output));
+}
+
void AMDGCN::Linker::constructLldCommand(Compilation &C, const JobAction &JA,
const InputInfoList &Inputs,
const InputInfo &Output,
@@ -117,17 +147,29 @@ void AMDGCN::Linker::constructLldCommand(Compilation &C, const JobAction &JA,
addLinkerCompressDebugSectionsOption(TC, Args, LldArgs);
+ for (auto *Arg : Args.filtered(options::OPT_Xoffload_linker))
+ LldArgs.push_back(Arg->getValue(1));
+
LldArgs.append({"-o", Output.getFilename()});
for (auto Input : Inputs)
LldArgs.push_back(Input.getFilename());
+ // Look for archive of bundled bitcode in arguments, and add temporary files
+ // for the extracted archive of bitcode to inputs.
+ auto TargetID = Args.getLastArgValue(options::OPT_mcpu_EQ);
+ AddStaticDeviceLibsLinking(C, *this, JA, Inputs, Args, LldArgs, "amdgcn",
+ TargetID,
+ /*IsBitCodeSDL=*/true,
+ /*PostClangLink=*/false);
+
const char *Lld = Args.MakeArgString(getToolChain().GetProgramPath("lld"));
C.addCommand(std::make_unique<Command>(JA, *this, ResponseFileSupport::None(),
Lld, LldArgs, Inputs, Output));
}
// For amdgcn the inputs of the linker job are device bitcode and output is
-// object file. It calls llvm-link, opt, llc, then lld steps.
+// either an object file or bitcode (-emit-llvm). It calls llvm-link, opt,
+// llc, then lld steps.
void AMDGCN::Linker::ConstructJob(Compilation &C, const JobAction &JA,
const InputInfo &Output,
const InputInfoList &Inputs,
@@ -143,6 +185,9 @@ void AMDGCN::Linker::ConstructJob(Compilation &C, const JobAction &JA,
return HIP::constructHIPFatbinCommand(C, JA, Output.getFilename(), Inputs,
Args, *this);
+ if (JA.getType() == types::TY_LLVM_BC)
+ return constructLlvmLinkCommand(C, JA, Inputs, Output, Args);
+
return constructLldCommand(C, JA, Inputs, Output, Args);
}
@@ -154,6 +199,9 @@ HIPAMDToolChain::HIPAMDToolChain(const Driver &D, const llvm::Triple &Triple,
getProgramPaths().push_back(getDriver().Dir);
// Diagnose unsupported sanitizer options only once.
+ if (!Args.hasFlag(options::OPT_fgpu_sanitize, options::OPT_fno_gpu_sanitize,
+ true))
+ return;
for (auto A : Args.filtered(options::OPT_fsanitize_EQ)) {
SanitizerMask K = parseSanitizerValue(A->getValue(), /*AllowGroups=*/false);
if (K != SanitizerKind::Address)
@@ -198,11 +246,11 @@ void HIPAMDToolChain::addClangTargetOptions(
CC1Args.push_back("-fapply-global-visibility-to-externs");
}
- llvm::for_each(getHIPDeviceLibs(DriverArgs), [&](auto BCFile) {
+ for (auto BCFile : getHIPDeviceLibs(DriverArgs)) {
CC1Args.push_back(BCFile.ShouldInternalize ? "-mlink-builtin-bitcode"
: "-mlink-bitcode-file");
CC1Args.push_back(DriverArgs.MakeArgString(BCFile.Path));
- });
+ }
}
llvm::opt::DerivedArgList *
@@ -322,7 +370,7 @@ HIPAMDToolChain::getHIPDeviceLibs(const llvm::opt::ArgList &DriverArgs) const {
// If --hip-device-lib is not set, add the default bitcode libraries.
if (DriverArgs.hasFlag(options::OPT_fgpu_sanitize,
- options::OPT_fno_gpu_sanitize) &&
+ options::OPT_fno_gpu_sanitize, true) &&
getSanitizerArgs(DriverArgs).needsAsanRt()) {
auto AsanRTL = RocmInstallation.getAsanRTLPath();
if (AsanRTL.empty()) {
@@ -363,6 +411,6 @@ void HIPAMDToolChain::checkTargetID(
auto PTID = getParsedTargetID(DriverArgs);
if (PTID.OptionalTargetID && !PTID.OptionalGPUArch) {
getDriver().Diag(clang::diag::err_drv_bad_target_id)
- << PTID.OptionalTargetID.getValue();
+ << *PTID.OptionalTargetID;
}
}
diff --git a/clang/lib/Driver/ToolChains/HIPAMD.h b/clang/lib/Driver/ToolChains/HIPAMD.h
index cc472a595db9..25d4a998e500 100644
--- a/clang/lib/Driver/ToolChains/HIPAMD.h
+++ b/clang/lib/Driver/ToolChains/HIPAMD.h
@@ -36,6 +36,10 @@ private:
void constructLldCommand(Compilation &C, const JobAction &JA,
const InputInfoList &Inputs, const InputInfo &Output,
const llvm::opt::ArgList &Args) const;
+ void constructLlvmLinkCommand(Compilation &C, const JobAction &JA,
+ const InputInfoList &Inputs,
+ const InputInfo &Output,
+ const llvm::opt::ArgList &Args) const;
};
} // end namespace AMDGCN
diff --git a/clang/lib/Driver/ToolChains/HIPUtility.cpp b/clang/lib/Driver/ToolChains/HIPUtility.cpp
index 1b04a20bacbf..6f8c563c22aa 100644
--- a/clang/lib/Driver/ToolChains/HIPUtility.cpp
+++ b/clang/lib/Driver/ToolChains/HIPUtility.cpp
@@ -53,8 +53,6 @@ void HIP::constructHIPFatbinCommand(Compilation &C, const JobAction &JA,
// ToDo: Remove the dummy host binary entry which is required by
// clang-offload-bundler.
std::string BundlerTargetArg = "-targets=host-x86_64-unknown-linux";
- std::string BundlerInputArg = "-inputs=" NULL_FILE;
-
// AMDGCN:
// For code object version 2 and 3, the offload kind in bundle ID is 'hip'
// for backward compatibility. For code object version 4 and greater, the
@@ -70,14 +68,20 @@ void HIP::constructHIPFatbinCommand(Compilation &C, const JobAction &JA,
"," + OffloadKind + "-" + normalizeForBundler(TT, !ArchStr.empty());
if (!ArchStr.empty())
BundlerTargetArg += "-" + ArchStr.str();
- BundlerInputArg = BundlerInputArg + "," + II.getFilename();
}
BundlerArgs.push_back(Args.MakeArgString(BundlerTargetArg));
+
+ // Use a NULL file as input for the dummy host binary entry
+ std::string BundlerInputArg = "-input=" NULL_FILE;
BundlerArgs.push_back(Args.MakeArgString(BundlerInputArg));
+ for (const auto &II : Inputs) {
+ BundlerInputArg = std::string("-input=") + II.getFilename();
+ BundlerArgs.push_back(Args.MakeArgString(BundlerInputArg));
+ }
std::string Output = std::string(OutputFileName);
auto *BundlerOutputArg =
- Args.MakeArgString(std::string("-outputs=").append(Output));
+ Args.MakeArgString(std::string("-output=").append(Output));
BundlerArgs.push_back(BundlerOutputArg);
const char *Bundler = Args.MakeArgString(
diff --git a/clang/lib/Driver/ToolChains/HLSL.cpp b/clang/lib/Driver/ToolChains/HLSL.cpp
new file mode 100644
index 000000000000..584e00bb7f05
--- /dev/null
+++ b/clang/lib/Driver/ToolChains/HLSL.cpp
@@ -0,0 +1,183 @@
+//===--- HLSL.cpp - HLSL ToolChain Implementations --------------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#include "HLSL.h"
+#include "CommonArgs.h"
+#include "clang/Driver/DriverDiagnostic.h"
+#include "llvm/ADT/StringSwitch.h"
+#include "llvm/ADT/Triple.h"
+
+using namespace clang::driver;
+using namespace clang::driver::tools;
+using namespace clang::driver::toolchains;
+using namespace clang;
+using namespace llvm::opt;
+using namespace llvm;
+
+namespace {
+
+const unsigned OfflineLibMinor = 0xF;
+
+bool isLegalShaderModel(Triple &T) {
+ if (T.getOS() != Triple::OSType::ShaderModel)
+ return false;
+
+ auto Version = T.getOSVersion();
+ if (Version.getBuild())
+ return false;
+ if (Version.getSubminor())
+ return false;
+
+ auto Kind = T.getEnvironment();
+
+ switch (Kind) {
+ default:
+ return false;
+ case Triple::EnvironmentType::Vertex:
+ case Triple::EnvironmentType::Hull:
+ case Triple::EnvironmentType::Domain:
+ case Triple::EnvironmentType::Geometry:
+ case Triple::EnvironmentType::Pixel:
+ case Triple::EnvironmentType::Compute: {
+ VersionTuple MinVer(4, 0);
+ return MinVer <= Version;
+ } break;
+ case Triple::EnvironmentType::Library: {
+ VersionTuple SM6x(6, OfflineLibMinor);
+ if (Version == SM6x)
+ return true;
+
+ VersionTuple MinVer(6, 3);
+ return MinVer <= Version;
+ } break;
+ case Triple::EnvironmentType::Amplification:
+ case Triple::EnvironmentType::Mesh: {
+ VersionTuple MinVer(6, 5);
+ return MinVer <= Version;
+ } break;
+ }
+ return false;
+}
+
+llvm::Optional<std::string> tryParseProfile(StringRef Profile) {
+ // [ps|vs|gs|hs|ds|cs|ms|as]_[major]_[minor]
+ SmallVector<StringRef, 3> Parts;
+ Profile.split(Parts, "_");
+ if (Parts.size() != 3)
+ return NoneType();
+
+ Triple::EnvironmentType Kind =
+ StringSwitch<Triple::EnvironmentType>(Parts[0])
+ .Case("ps", Triple::EnvironmentType::Pixel)
+ .Case("vs", Triple::EnvironmentType::Vertex)
+ .Case("gs", Triple::EnvironmentType::Geometry)
+ .Case("hs", Triple::EnvironmentType::Hull)
+ .Case("ds", Triple::EnvironmentType::Domain)
+ .Case("cs", Triple::EnvironmentType::Compute)
+ .Case("lib", Triple::EnvironmentType::Library)
+ .Case("ms", Triple::EnvironmentType::Mesh)
+ .Case("as", Triple::EnvironmentType::Amplification)
+ .Default(Triple::EnvironmentType::UnknownEnvironment);
+ if (Kind == Triple::EnvironmentType::UnknownEnvironment)
+ return NoneType();
+
+ unsigned long long Major = 0;
+ if (llvm::getAsUnsignedInteger(Parts[1], 0, Major))
+ return NoneType();
+
+ unsigned long long Minor = 0;
+ if (Parts[2] == "x" && Kind == Triple::EnvironmentType::Library)
+ Minor = OfflineLibMinor;
+ else if (llvm::getAsUnsignedInteger(Parts[2], 0, Minor))
+ return NoneType();
+
+ // dxil-unknown-shadermodel-hull
+ llvm::Triple T;
+ T.setArch(Triple::ArchType::dxil);
+ T.setOSName(Triple::getOSTypeName(Triple::OSType::ShaderModel).str() +
+ VersionTuple(Major, Minor).getAsString());
+ T.setEnvironment(Kind);
+ if (isLegalShaderModel(T))
+ return T.getTriple();
+ else
+ return NoneType();
+}
+
+bool isLegalValidatorVersion(StringRef ValVersionStr, const Driver &D) {
+ VersionTuple Version;
+ if (Version.tryParse(ValVersionStr) || Version.getBuild() ||
+ Version.getSubminor() || !Version.getMinor()) {
+ D.Diag(diag::err_drv_invalid_format_dxil_validator_version)
+ << ValVersionStr;
+ return false;
+ }
+
+ uint64_t Major = Version.getMajor();
+ uint64_t Minor = *Version.getMinor();
+ if (Major == 0 && Minor != 0) {
+ D.Diag(diag::err_drv_invalid_empty_dxil_validator_version) << ValVersionStr;
+ return false;
+ }
+ VersionTuple MinVer(1, 0);
+ if (Version < MinVer) {
+ D.Diag(diag::err_drv_invalid_range_dxil_validator_version) << ValVersionStr;
+ return false;
+ }
+ return true;
+}
+
+} // namespace
+
+/// DirectX Toolchain
+HLSLToolChain::HLSLToolChain(const Driver &D, const llvm::Triple &Triple,
+ const ArgList &Args)
+ : ToolChain(D, Triple, Args) {}
+
+llvm::Optional<std::string>
+clang::driver::toolchains::HLSLToolChain::parseTargetProfile(
+ StringRef TargetProfile) {
+ return tryParseProfile(TargetProfile);
+}
+
+DerivedArgList *
+HLSLToolChain::TranslateArgs(const DerivedArgList &Args, StringRef BoundArch,
+ Action::OffloadKind DeviceOffloadKind) const {
+ DerivedArgList *DAL = new DerivedArgList(Args.getBaseArgs());
+
+ const OptTable &Opts = getDriver().getOpts();
+
+ for (Arg *A : Args) {
+ if (A->getOption().getID() == options::OPT_dxil_validator_version) {
+ StringRef ValVerStr = A->getValue();
+ std::string ErrorMsg;
+ if (!isLegalValidatorVersion(ValVerStr, getDriver()))
+ continue;
+ }
+ if (A->getOption().getID() == options::OPT_emit_pristine_llvm) {
+ // Translate fcgl into -S -emit-llvm and -disable-llvm-passes.
+ DAL->AddFlagArg(nullptr, Opts.getOption(options::OPT_S));
+ DAL->AddFlagArg(nullptr, Opts.getOption(options::OPT_emit_llvm));
+ DAL->AddFlagArg(nullptr,
+ Opts.getOption(options::OPT_disable_llvm_passes));
+ A->claim();
+ continue;
+ }
+ DAL->append(A);
+ }
+ // Add default validator version if not set.
+ // TODO: remove this once read validator version from validator.
+ if (!DAL->hasArg(options::OPT_dxil_validator_version)) {
+ const StringRef DefaultValidatorVer = "1.7";
+ DAL->AddSeparateArg(nullptr,
+ Opts.getOption(options::OPT_dxil_validator_version),
+ DefaultValidatorVer);
+ }
+ // FIXME: add validation for enable_16bit_types should be after HLSL 2018 and
+ // shader model 6.2.
+ return DAL;
+}
diff --git a/clang/lib/Driver/ToolChains/HLSL.h b/clang/lib/Driver/ToolChains/HLSL.h
new file mode 100644
index 000000000000..5573b0cc69e2
--- /dev/null
+++ b/clang/lib/Driver/ToolChains/HLSL.h
@@ -0,0 +1,40 @@
+//===--- HLSL.h - HLSL ToolChain Implementations ----------------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_LIB_DRIVER_TOOLCHAINS_HLSL_H
+#define LLVM_CLANG_LIB_DRIVER_TOOLCHAINS_HLSL_H
+
+#include "clang/Driver/ToolChain.h"
+
+namespace clang {
+namespace driver {
+
+namespace toolchains {
+
+class LLVM_LIBRARY_VISIBILITY HLSLToolChain : public ToolChain {
+public:
+ HLSLToolChain(const Driver &D, const llvm::Triple &Triple,
+ const llvm::opt::ArgList &Args);
+ bool isPICDefault() const override { return false; }
+ bool isPIEDefault(const llvm::opt::ArgList &Args) const override {
+ return false;
+ }
+ bool isPICDefaultForced() const override { return false; }
+
+ llvm::opt::DerivedArgList *
+ TranslateArgs(const llvm::opt::DerivedArgList &Args, StringRef BoundArch,
+ Action::OffloadKind DeviceOffloadKind) const override;
+ static llvm::Optional<std::string>
+ parseTargetProfile(StringRef TargetProfile);
+};
+
+} // end namespace toolchains
+} // end namespace driver
+} // end namespace clang
+
+#endif // LLVM_CLANG_LIB_DRIVER_TOOLCHAINS_HLSL_H
diff --git a/clang/lib/Driver/ToolChains/Hexagon.cpp b/clang/lib/Driver/ToolChains/Hexagon.cpp
index ba3040636604..9142dba81d54 100644
--- a/clang/lib/Driver/ToolChains/Hexagon.cpp
+++ b/clang/lib/Driver/ToolChains/Hexagon.cpp
@@ -72,23 +72,25 @@ static void handleHVXTargetFeatures(const Driver &D, const ArgList &Args,
(Cpu.back() == 'T' || Cpu.back() == 't' ? Cpu.drop_back(1) : Cpu).str();
HasHVX = false;
- // Handle -mhvx, -mhvx=, -mno-hvx. If both present, -mhvx= wins over -mhvx.
- auto argOrNull = [&Args](auto FlagOn, auto FlagOff) -> Arg* {
- if (Arg *A = Args.getLastArg(FlagOn, FlagOff)) {
- if (A->getOption().matches(FlagOn))
- return A;
- }
- return nullptr;
- };
-
- Arg *HvxBareA =
- argOrNull(options::OPT_mhexagon_hvx, options::OPT_mno_hexagon_hvx);
- Arg *HvxVerA =
- argOrNull(options::OPT_mhexagon_hvx_EQ, options::OPT_mno_hexagon_hvx);
+ // Handle -mhvx, -mhvx=, -mno-hvx. If versioned and versionless flags
+ // are both present, the last one wins.
+ Arg *HvxEnablingArg =
+ Args.getLastArg(options::OPT_mhexagon_hvx, options::OPT_mhexagon_hvx_EQ,
+ options::OPT_mno_hexagon_hvx);
+ if (HvxEnablingArg) {
+ if (HvxEnablingArg->getOption().matches(options::OPT_mno_hexagon_hvx))
+ HvxEnablingArg = nullptr;
+ }
- if (Arg *A = HvxVerA ? HvxVerA : HvxBareA) {
- if (A->getOption().matches(options::OPT_mhexagon_hvx_EQ))
- HvxVer = StringRef(A->getValue()).lower(); // lower produces std:string
+ if (HvxEnablingArg) {
+ // If -mhvx[=] was given, it takes precedence.
+ if (Arg *A = Args.getLastArg(options::OPT_mhexagon_hvx,
+ options::OPT_mhexagon_hvx_EQ)) {
+ // If the version was given, set HvxVer. Otherwise HvxVer
+ // will remain equal to the CPU version.
+ if (A->getOption().matches(options::OPT_mhexagon_hvx_EQ))
+ HvxVer = StringRef(A->getValue()).lower();
+ }
HasHVX = true;
Features.push_back(makeFeature(Twine("hvx") + HvxVer, true));
} else if (Arg *A = Args.getLastArg(options::OPT_mno_hexagon_hvx)) {
@@ -228,7 +230,7 @@ void hexagon::Assembler::ConstructJob(Compilation &C, const JobAction &JA,
}
if (auto G = toolchains::HexagonToolChain::getSmallDataThreshold(Args)) {
- CmdArgs.push_back(Args.MakeArgString("-gpsize=" + Twine(G.getValue())));
+ CmdArgs.push_back(Args.MakeArgString("-gpsize=" + Twine(*G)));
}
Args.AddAllArgValues(CmdArgs, options::OPT_Wa_COMMA, options::OPT_Xassembler);
@@ -549,8 +551,7 @@ void HexagonToolChain::getHexagonLibraryPaths(const ArgList &Args,
// -L Args
//----------------------------------------------------------------------------
for (Arg *A : Args.filtered(options::OPT_L))
- for (const char *Value : A->getValues())
- LibPaths.push_back(Value);
+ llvm::append_range(LibPaths, A->getValues());
//----------------------------------------------------------------------------
// Other standard paths
@@ -568,7 +569,7 @@ void HexagonToolChain::getHexagonLibraryPaths(const ArgList &Args,
// Assume G0 with -shared.
bool HasG0 = Args.hasArg(options::OPT_shared);
if (auto G = getSmallDataThreshold(Args))
- HasG0 = G.getValue() == 0;
+ HasG0 = *G == 0;
const std::string CpuVer = GetTargetCPUVersion(Args).str();
for (auto &Dir : RootDirs) {
diff --git a/clang/lib/Driver/ToolChains/Hexagon.h b/clang/lib/Driver/ToolChains/Hexagon.h
index 899630555352..c742012444b4 100644
--- a/clang/lib/Driver/ToolChains/Hexagon.h
+++ b/clang/lib/Driver/ToolChains/Hexagon.h
@@ -94,9 +94,6 @@ public:
llvm::opt::ArgStringList &CmdArgs) const override;
StringRef GetGCCLibAndIncVersion() const { return GCCLibAndIncVersion.Text; }
- bool IsIntegratedAssemblerDefault() const override {
- return true;
- }
std::string getHexagonTargetDir(
const std::string &InstalledDir,
diff --git a/clang/lib/Driver/ToolChains/Lanai.h b/clang/lib/Driver/ToolChains/Lanai.h
index dc04b0cfe2ee..33701f7cc045 100644
--- a/clang/lib/Driver/ToolChains/Lanai.h
+++ b/clang/lib/Driver/ToolChains/Lanai.h
@@ -29,8 +29,6 @@ public:
void addLibStdCxxIncludePaths(
const llvm::opt::ArgList &DriverArgs,
llvm::opt::ArgStringList &CC1Args) const override {}
-
- bool IsIntegratedAssemblerDefault() const override { return true; }
};
} // end namespace toolchains
diff --git a/clang/lib/Driver/ToolChains/Linux.cpp b/clang/lib/Driver/ToolChains/Linux.cpp
index af74b108e04e..ceb1a982c3a4 100644
--- a/clang/lib/Driver/ToolChains/Linux.cpp
+++ b/clang/lib/Driver/ToolChains/Linux.cpp
@@ -97,9 +97,9 @@ std::string Linux::getMultiarchTriple(const Driver &D,
case llvm::Triple::mips64: {
std::string MT = std::string(IsMipsR6 ? "mipsisa64r6" : "mips64") +
"-linux-" + (IsMipsN32Abi ? "gnuabin32" : "gnuabi64");
- if (D.getVFS().exists(SysRoot + "/lib/" + MT))
+ if (D.getVFS().exists(concat(SysRoot, "/lib", MT)))
return MT;
- if (D.getVFS().exists(SysRoot + "/lib/mips64-linux-gnu"))
+ if (D.getVFS().exists(concat(SysRoot, "/lib/mips64-linux-gnu")))
return "mips64-linux-gnu";
break;
}
@@ -108,14 +108,14 @@ std::string Linux::getMultiarchTriple(const Driver &D,
return "mips64el-linux-android";
std::string MT = std::string(IsMipsR6 ? "mipsisa64r6el" : "mips64el") +
"-linux-" + (IsMipsN32Abi ? "gnuabin32" : "gnuabi64");
- if (D.getVFS().exists(SysRoot + "/lib/" + MT))
+ if (D.getVFS().exists(concat(SysRoot, "/lib", MT)))
return MT;
- if (D.getVFS().exists(SysRoot + "/lib/mips64el-linux-gnu"))
+ if (D.getVFS().exists(concat(SysRoot, "/lib/mips64el-linux-gnu")))
return "mips64el-linux-gnu";
break;
}
case llvm::Triple::ppc:
- if (D.getVFS().exists(SysRoot + "/lib/powerpc-linux-gnuspe"))
+ if (D.getVFS().exists(concat(SysRoot, "/lib/powerpc-linux-gnuspe")))
return "powerpc-linux-gnuspe";
return "powerpc-linux-gnu";
case llvm::Triple::ppcle:
@@ -124,6 +124,8 @@ std::string Linux::getMultiarchTriple(const Driver &D,
return "powerpc64-linux-gnu";
case llvm::Triple::ppc64le:
return "powerpc64le-linux-gnu";
+ case llvm::Triple::riscv64:
+ return "riscv64-linux-gnu";
case llvm::Triple::sparc:
return "sparc-linux-gnu";
case llvm::Triple::sparcv9:
@@ -221,8 +223,12 @@ Linux::Linux(const Driver &D, const llvm::Triple &Triple, const ArgList &Args)
const bool IsMips = Triple.isMIPS();
const bool IsHexagon = Arch == llvm::Triple::hexagon;
const bool IsRISCV = Triple.isRISCV();
+ const bool IsCSKY = Triple.isCSKY();
- if (IsMips && !SysRoot.empty())
+ if (IsCSKY)
+ SysRoot = SysRoot + SelectedMultilib.osSuffix();
+
+ if ((IsMips || IsCSKY) && !SysRoot.empty())
ExtraOpts.push_back("--sysroot=" + SysRoot);
// Do not use 'gnu' hash style for Mips targets because .gnu.hash
@@ -265,13 +271,13 @@ Linux::Linux(const Driver &D, const llvm::Triple &Triple, const ArgList &Args)
// used. We need add both libo32 and /lib.
if (Arch == llvm::Triple::mips || Arch == llvm::Triple::mipsel) {
Generic_GCC::AddMultilibPaths(D, SysRoot, "libo32", MultiarchTriple, Paths);
- addPathIfExists(D, SysRoot + "/libo32", Paths);
- addPathIfExists(D, SysRoot + "/usr/libo32", Paths);
+ addPathIfExists(D, concat(SysRoot, "/libo32"), Paths);
+ addPathIfExists(D, concat(SysRoot, "/usr/libo32"), Paths);
}
Generic_GCC::AddMultilibPaths(D, SysRoot, OSLibDir, MultiarchTriple, Paths);
- addPathIfExists(D, SysRoot + "/lib/" + MultiarchTriple, Paths);
- addPathIfExists(D, SysRoot + "/lib/../" + OSLibDir, Paths);
+ addPathIfExists(D, concat(SysRoot, "/lib", MultiarchTriple), Paths);
+ addPathIfExists(D, concat(SysRoot, "/lib/..", OSLibDir), Paths);
if (IsAndroid) {
// Android sysroots contain a library directory for each supported OS
@@ -279,43 +285,37 @@ Linux::Linux(const Driver &D, const llvm::Triple &Triple, const ArgList &Args)
// directory.
addPathIfExists(
D,
- SysRoot + "/usr/lib/" + MultiarchTriple + "/" +
- llvm::to_string(Triple.getEnvironmentVersion().getMajor()),
+ concat(SysRoot, "/usr/lib", MultiarchTriple,
+ llvm::to_string(Triple.getEnvironmentVersion().getMajor())),
Paths);
}
- addPathIfExists(D, SysRoot + "/usr/lib/" + MultiarchTriple, Paths);
+ addPathIfExists(D, concat(SysRoot, "/usr/lib", MultiarchTriple), Paths);
// 64-bit OpenEmbedded sysroots may not have a /usr/lib dir. So they cannot
// find /usr/lib64 as it is referenced as /usr/lib/../lib64. So we handle
// this here.
if (Triple.getVendor() == llvm::Triple::OpenEmbedded &&
Triple.isArch64Bit())
- addPathIfExists(D, SysRoot + "/usr/" + OSLibDir, Paths);
+ addPathIfExists(D, concat(SysRoot, "/usr", OSLibDir), Paths);
else
- addPathIfExists(D, SysRoot + "/usr/lib/../" + OSLibDir, Paths);
+ addPathIfExists(D, concat(SysRoot, "/usr/lib/..", OSLibDir), Paths);
if (IsRISCV) {
StringRef ABIName = tools::riscv::getRISCVABI(Args, Triple);
- addPathIfExists(D, SysRoot + "/" + OSLibDir + "/" + ABIName, Paths);
- addPathIfExists(D, SysRoot + "/usr/" + OSLibDir + "/" + ABIName, Paths);
+ addPathIfExists(D, concat(SysRoot, "/", OSLibDir, ABIName), Paths);
+ addPathIfExists(D, concat(SysRoot, "/usr", OSLibDir, ABIName), Paths);
}
Generic_GCC::AddMultiarchPaths(D, SysRoot, OSLibDir, Paths);
- // Similar to the logic for GCC above, if we are currently running Clang
- // inside of the requested system root, add its parent library path to those
- // searched.
- // FIXME: It's not clear whether we should use the driver's installed
- // directory ('Dir' below) or the ResourceDir.
- if (StringRef(D.Dir).startswith(SysRoot)) {
- // Even if OSLibDir != "lib", this is needed for Clang in the build
- // directory (not installed) to find libc++.
+ // The deprecated -DLLVM_ENABLE_PROJECTS=libcxx configuration installs
+ // libc++.so in D.Dir+"/../lib/". Detect this path.
+ // TODO Remove once LLVM_ENABLE_PROJECTS=libcxx is unsupported.
+ if (StringRef(D.Dir).startswith(SysRoot) &&
+ D.getVFS().exists(D.Dir + "/../lib/libc++.so"))
addPathIfExists(D, D.Dir + "/../lib", Paths);
- if (OSLibDir != "lib")
- addPathIfExists(D, D.Dir + "/../" + OSLibDir, Paths);
- }
- addPathIfExists(D, SysRoot + "/lib", Paths);
- addPathIfExists(D, SysRoot + "/usr/lib", Paths);
+ addPathIfExists(D, concat(SysRoot, "/lib"), Paths);
+ addPathIfExists(D, concat(SysRoot, "/usr/lib"), Paths);
}
ToolChain::RuntimeLibType Linux::GetDefaultRuntimeLibType() const {
@@ -361,6 +361,21 @@ std::string Linux::computeSysRoot() const {
return AndroidSysRootPath;
}
+ if (getTriple().isCSKY()) {
+ // CSKY toolchains use different names for sysroot folder.
+ if (!GCCInstallation.isValid())
+ return std::string();
+ // GCCInstallation.getInstallPath() =
+ // $GCCToolchainPath/lib/gcc/csky-linux-gnuabiv2/6.3.0
+ // Path = $GCCToolchainPath/csky-linux-gnuabiv2/libc
+ std::string Path = (GCCInstallation.getInstallPath() + "/../../../../" +
+ GCCInstallation.getTriple().str() + "/libc")
+ .str();
+ if (getVFS().exists(Path))
+ return Path;
+ return std::string();
+ }
+
if (!GCCInstallation.isValid() || !getTriple().isMIPS())
return std::string();
@@ -537,6 +552,11 @@ std::string Linux::getDynamicLinker(const ArgList &Args) const {
}
case llvm::Triple::ve:
return "/opt/nec/ve/lib/ld-linux-ve.so.1";
+ case llvm::Triple::csky: {
+ LibDir = "lib";
+ Loader = "ld.so.1";
+ break;
+ }
}
if (Distro == Distro::Exherbo &&
@@ -568,7 +588,7 @@ void Linux::AddClangSystemIncludeArgs(const ArgList &DriverArgs,
return;
// LOCAL_INCLUDE_DIR
- addSystemInclude(DriverArgs, CC1Args, SysRoot + "/usr/local/include");
+ addSystemInclude(DriverArgs, CC1Args, concat(SysRoot, "/usr/local/include"));
// TOOL_INCLUDE_DIR
AddMultilibIncludeArgs(DriverArgs, CC1Args);
@@ -589,9 +609,10 @@ void Linux::AddClangSystemIncludeArgs(const ArgList &DriverArgs,
// /usr/include.
std::string MultiarchIncludeDir = getMultiarchTriple(D, getTriple(), SysRoot);
if (!MultiarchIncludeDir.empty() &&
- D.getVFS().exists(SysRoot + "/usr/include/" + MultiarchIncludeDir))
- addExternCSystemInclude(DriverArgs, CC1Args,
- SysRoot + "/usr/include/" + MultiarchIncludeDir);
+ D.getVFS().exists(concat(SysRoot, "/usr/include", MultiarchIncludeDir)))
+ addExternCSystemInclude(
+ DriverArgs, CC1Args,
+ concat(SysRoot, "/usr/include", MultiarchIncludeDir));
if (getTriple().getOS() == llvm::Triple::RTEMS)
return;
@@ -599,9 +620,9 @@ void Linux::AddClangSystemIncludeArgs(const ArgList &DriverArgs,
// Add an include of '/include' directly. This isn't provided by default by
// system GCCs, but is often used with cross-compiling GCCs, and harmless to
// add even when Clang is acting as-if it were a system compiler.
- addExternCSystemInclude(DriverArgs, CC1Args, SysRoot + "/include");
+ addExternCSystemInclude(DriverArgs, CC1Args, concat(SysRoot, "/include"));
- addExternCSystemInclude(DriverArgs, CC1Args, SysRoot + "/usr/include");
+ addExternCSystemInclude(DriverArgs, CC1Args, concat(SysRoot, "/usr/include"));
if (!DriverArgs.hasArg(options::OPT_nobuiltininc) && getTriple().isMusl())
addSystemInclude(DriverArgs, CC1Args, ResourceDirInclude);
@@ -658,6 +679,15 @@ void Linux::AddHIPIncludeArgs(const ArgList &DriverArgs,
RocmInstallation.AddHIPIncludeArgs(DriverArgs, CC1Args);
}
+void Linux::AddHIPRuntimeLibArgs(const ArgList &Args,
+ ArgStringList &CmdArgs) const {
+ CmdArgs.append(
+ {Args.MakeArgString(StringRef("-L") + RocmInstallation.getLibPath()),
+ "-rpath", Args.MakeArgString(RocmInstallation.getLibPath())});
+
+ CmdArgs.push_back("-lamdhip64");
+}
+
void Linux::AddIAMCUIncludeArgs(const ArgList &DriverArgs,
ArgStringList &CC1Args) const {
if (GCCInstallation.isValid()) {
@@ -669,8 +699,11 @@ void Linux::AddIAMCUIncludeArgs(const ArgList &DriverArgs,
}
bool Linux::isPIEDefault(const llvm::opt::ArgList &Args) const {
- return CLANG_DEFAULT_PIE_ON_LINUX || getTriple().isAndroid() ||
- getTriple().isMusl() || getSanitizerArgs(Args).requiresPIE();
+ // TODO: Remove the special treatment for Flang once its frontend driver can
+ // generate position independent code.
+ return !getDriver().IsFlangMode() &&
+ (CLANG_DEFAULT_PIE_ON_LINUX || getTriple().isAndroid() ||
+ getTriple().isMusl() || getSanitizerArgs(Args).requiresPIE());
}
bool Linux::IsAArch64OutlineAtomicsDefault(const ArgList &Args) const {
@@ -687,7 +720,7 @@ bool Linux::IsAArch64OutlineAtomicsDefault(const ArgList &Args) const {
}
bool Linux::IsMathErrnoDefault() const {
- if (getTriple().isAndroid())
+ if (getTriple().isAndroid() || getTriple().isMusl())
return false;
return Generic_ELF::IsMathErrnoDefault();
}
diff --git a/clang/lib/Driver/ToolChains/Linux.h b/clang/lib/Driver/ToolChains/Linux.h
index a5648d79d655..188cb1f09788 100644
--- a/clang/lib/Driver/ToolChains/Linux.h
+++ b/clang/lib/Driver/ToolChains/Linux.h
@@ -37,6 +37,8 @@ public:
llvm::opt::ArgStringList &CC1Args) const override;
void AddHIPIncludeArgs(const llvm::opt::ArgList &DriverArgs,
llvm::opt::ArgStringList &CC1Args) const override;
+ void AddHIPRuntimeLibArgs(const llvm::opt::ArgList &Args,
+ llvm::opt::ArgStringList &CmdArgs) const override;
void AddIAMCUIncludeArgs(const llvm::opt::ArgList &DriverArgs,
llvm::opt::ArgStringList &CC1Args) const override;
RuntimeLibType GetDefaultRuntimeLibType() const override;
diff --git a/clang/lib/Driver/ToolChains/MSP430.cpp b/clang/lib/Driver/ToolChains/MSP430.cpp
index 96994ba77fac..bc789853049a 100644
--- a/clang/lib/Driver/ToolChains/MSP430.cpp
+++ b/clang/lib/Driver/ToolChains/MSP430.cpp
@@ -101,7 +101,7 @@ void msp430::getMSP430TargetFeatures(const Driver &D, const ArgList &Args,
Features.push_back("+hwmultf5");
} else {
D.Diag(clang::diag::err_drv_unsupported_option_argument)
- << HWMultArg->getAsString(Args) << HWMult;
+ << HWMultArg->getOption().getName() << HWMult;
}
}
diff --git a/clang/lib/Driver/ToolChains/MSVC.cpp b/clang/lib/Driver/ToolChains/MSVC.cpp
index 18cef288f018..14ebe38ee191 100644
--- a/clang/lib/Driver/ToolChains/MSVC.cpp
+++ b/clang/lib/Driver/ToolChains/MSVC.cpp
@@ -40,91 +40,12 @@
#include <windows.h>
#endif
-#ifdef _MSC_VER
-// Don't support SetupApi on MinGW.
-#define USE_MSVC_SETUP_API
-
-// Make sure this comes before MSVCSetupApi.h
-#include <comdef.h>
-
-#ifdef __clang__
-#pragma clang diagnostic push
-#pragma clang diagnostic ignored "-Wnon-virtual-dtor"
-#endif
-#include "MSVCSetupApi.h"
-#ifdef __clang__
-#pragma clang diagnostic pop
-#endif
-#include "llvm/Support/COM.h"
-_COM_SMARTPTR_TYPEDEF(ISetupConfiguration, __uuidof(ISetupConfiguration));
-_COM_SMARTPTR_TYPEDEF(ISetupConfiguration2, __uuidof(ISetupConfiguration2));
-_COM_SMARTPTR_TYPEDEF(ISetupHelper, __uuidof(ISetupHelper));
-_COM_SMARTPTR_TYPEDEF(IEnumSetupInstances, __uuidof(IEnumSetupInstances));
-_COM_SMARTPTR_TYPEDEF(ISetupInstance, __uuidof(ISetupInstance));
-_COM_SMARTPTR_TYPEDEF(ISetupInstance2, __uuidof(ISetupInstance2));
-#endif
-
using namespace clang::driver;
using namespace clang::driver::toolchains;
using namespace clang::driver::tools;
using namespace clang;
using namespace llvm::opt;
-// Windows SDKs and VC Toolchains group their contents into subdirectories based
-// on the target architecture. This function converts an llvm::Triple::ArchType
-// to the corresponding subdirectory name.
-static const char *llvmArchToWindowsSDKArch(llvm::Triple::ArchType Arch) {
- using ArchType = llvm::Triple::ArchType;
- switch (Arch) {
- case ArchType::x86:
- return "x86";
- case ArchType::x86_64:
- return "x64";
- case ArchType::arm:
- return "arm";
- case ArchType::aarch64:
- return "arm64";
- default:
- return "";
- }
-}
-
-// Similar to the above function, but for Visual Studios before VS2017.
-static const char *llvmArchToLegacyVCArch(llvm::Triple::ArchType Arch) {
- using ArchType = llvm::Triple::ArchType;
- switch (Arch) {
- case ArchType::x86:
- // x86 is default in legacy VC toolchains.
- // e.g. x86 libs are directly in /lib as opposed to /lib/x86.
- return "";
- case ArchType::x86_64:
- return "amd64";
- case ArchType::arm:
- return "arm";
- case ArchType::aarch64:
- return "arm64";
- default:
- return "";
- }
-}
-
-// Similar to the above function, but for DevDiv internal builds.
-static const char *llvmArchToDevDivInternalArch(llvm::Triple::ArchType Arch) {
- using ArchType = llvm::Triple::ArchType;
- switch (Arch) {
- case ArchType::x86:
- return "i386";
- case ArchType::x86_64:
- return "amd64";
- case ArchType::arm:
- return "arm";
- case ArchType::aarch64:
- return "arm64";
- default:
- return "";
- }
-}
-
static bool canExecute(llvm::vfs::FileSystem &VFS, StringRef Path) {
auto Status = VFS.status(Path);
if (!Status)
@@ -132,294 +53,6 @@ static bool canExecute(llvm::vfs::FileSystem &VFS, StringRef Path) {
return (Status->getPermissions() & llvm::sys::fs::perms::all_exe) != 0;
}
-// Defined below.
-// Forward declare this so there aren't too many things above the constructor.
-static bool getSystemRegistryString(const char *keyPath, const char *valueName,
- std::string &value, std::string *phValue);
-
-static std::string getHighestNumericTupleInDirectory(llvm::vfs::FileSystem &VFS,
- StringRef Directory) {
- std::string Highest;
- llvm::VersionTuple HighestTuple;
-
- std::error_code EC;
- for (llvm::vfs::directory_iterator DirIt = VFS.dir_begin(Directory, EC),
- DirEnd;
- !EC && DirIt != DirEnd; DirIt.increment(EC)) {
- auto Status = VFS.status(DirIt->path());
- if (!Status || !Status->isDirectory())
- continue;
- StringRef CandidateName = llvm::sys::path::filename(DirIt->path());
- llvm::VersionTuple Tuple;
- if (Tuple.tryParse(CandidateName)) // tryParse() returns true on error.
- continue;
- if (Tuple > HighestTuple) {
- HighestTuple = Tuple;
- Highest = CandidateName.str();
- }
- }
-
- return Highest;
-}
-
-// Check command line arguments to try and find a toolchain.
-static bool
-findVCToolChainViaCommandLine(llvm::vfs::FileSystem &VFS, const ArgList &Args,
- std::string &Path,
- MSVCToolChain::ToolsetLayout &VSLayout) {
- // Don't validate the input; trust the value supplied by the user.
- // The primary motivation is to prevent unnecessary file and registry access.
- if (Arg *A = Args.getLastArg(options::OPT__SLASH_vctoolsdir,
- options::OPT__SLASH_winsysroot)) {
- if (A->getOption().getID() == options::OPT__SLASH_winsysroot) {
- llvm::SmallString<128> ToolsPath(A->getValue());
- llvm::sys::path::append(ToolsPath, "VC", "Tools", "MSVC");
- std::string VCToolsVersion;
- if (Arg *A = Args.getLastArg(options::OPT__SLASH_vctoolsversion))
- VCToolsVersion = A->getValue();
- else
- VCToolsVersion = getHighestNumericTupleInDirectory(VFS, ToolsPath);
- llvm::sys::path::append(ToolsPath, VCToolsVersion);
- Path = std::string(ToolsPath.str());
- } else {
- Path = A->getValue();
- }
- VSLayout = MSVCToolChain::ToolsetLayout::VS2017OrNewer;
- return true;
- }
- return false;
-}
-
-// Check various environment variables to try and find a toolchain.
-static bool
-findVCToolChainViaEnvironment(llvm::vfs::FileSystem &VFS, std::string &Path,
- MSVCToolChain::ToolsetLayout &VSLayout) {
- // These variables are typically set by vcvarsall.bat
- // when launching a developer command prompt.
- if (llvm::Optional<std::string> VCToolsInstallDir =
- llvm::sys::Process::GetEnv("VCToolsInstallDir")) {
- // This is only set by newer Visual Studios, and it leads straight to
- // the toolchain directory.
- Path = std::move(*VCToolsInstallDir);
- VSLayout = MSVCToolChain::ToolsetLayout::VS2017OrNewer;
- return true;
- }
- if (llvm::Optional<std::string> VCInstallDir =
- llvm::sys::Process::GetEnv("VCINSTALLDIR")) {
- // If the previous variable isn't set but this one is, then we've found
- // an older Visual Studio. This variable is set by newer Visual Studios too,
- // so this check has to appear second.
- // In older Visual Studios, the VC directory is the toolchain.
- Path = std::move(*VCInstallDir);
- VSLayout = MSVCToolChain::ToolsetLayout::OlderVS;
- return true;
- }
-
- // We couldn't find any VC environment variables. Let's walk through PATH and
- // see if it leads us to a VC toolchain bin directory. If it does, pick the
- // first one that we find.
- if (llvm::Optional<std::string> PathEnv =
- llvm::sys::Process::GetEnv("PATH")) {
- llvm::SmallVector<llvm::StringRef, 8> PathEntries;
- llvm::StringRef(*PathEnv).split(PathEntries, llvm::sys::EnvPathSeparator);
- for (llvm::StringRef PathEntry : PathEntries) {
- if (PathEntry.empty())
- continue;
-
- llvm::SmallString<256> ExeTestPath;
-
- // If cl.exe doesn't exist, then this definitely isn't a VC toolchain.
- ExeTestPath = PathEntry;
- llvm::sys::path::append(ExeTestPath, "cl.exe");
- if (!VFS.exists(ExeTestPath))
- continue;
-
- // cl.exe existing isn't a conclusive test for a VC toolchain; clang also
- // has a cl.exe. So let's check for link.exe too.
- ExeTestPath = PathEntry;
- llvm::sys::path::append(ExeTestPath, "link.exe");
- if (!VFS.exists(ExeTestPath))
- continue;
-
- // whatever/VC/bin --> old toolchain, VC dir is toolchain dir.
- llvm::StringRef TestPath = PathEntry;
- bool IsBin =
- llvm::sys::path::filename(TestPath).equals_insensitive("bin");
- if (!IsBin) {
- // Strip any architecture subdir like "amd64".
- TestPath = llvm::sys::path::parent_path(TestPath);
- IsBin = llvm::sys::path::filename(TestPath).equals_insensitive("bin");
- }
- if (IsBin) {
- llvm::StringRef ParentPath = llvm::sys::path::parent_path(TestPath);
- llvm::StringRef ParentFilename = llvm::sys::path::filename(ParentPath);
- if (ParentFilename.equals_insensitive("VC")) {
- Path = std::string(ParentPath);
- VSLayout = MSVCToolChain::ToolsetLayout::OlderVS;
- return true;
- }
- if (ParentFilename.equals_insensitive("x86ret") ||
- ParentFilename.equals_insensitive("x86chk") ||
- ParentFilename.equals_insensitive("amd64ret") ||
- ParentFilename.equals_insensitive("amd64chk")) {
- Path = std::string(ParentPath);
- VSLayout = MSVCToolChain::ToolsetLayout::DevDivInternal;
- return true;
- }
-
- } else {
- // This could be a new (>=VS2017) toolchain. If it is, we should find
- // path components with these prefixes when walking backwards through
- // the path.
- // Note: empty strings match anything.
- llvm::StringRef ExpectedPrefixes[] = {"", "Host", "bin", "",
- "MSVC", "Tools", "VC"};
-
- auto It = llvm::sys::path::rbegin(PathEntry);
- auto End = llvm::sys::path::rend(PathEntry);
- for (llvm::StringRef Prefix : ExpectedPrefixes) {
- if (It == End)
- goto NotAToolChain;
- if (!It->startswith_insensitive(Prefix))
- goto NotAToolChain;
- ++It;
- }
-
- // We've found a new toolchain!
- // Back up 3 times (/bin/Host/arch) to get the root path.
- llvm::StringRef ToolChainPath(PathEntry);
- for (int i = 0; i < 3; ++i)
- ToolChainPath = llvm::sys::path::parent_path(ToolChainPath);
-
- Path = std::string(ToolChainPath);
- VSLayout = MSVCToolChain::ToolsetLayout::VS2017OrNewer;
- return true;
- }
-
- NotAToolChain:
- continue;
- }
- }
- return false;
-}
-
-// Query the Setup Config server for installs, then pick the newest version
-// and find its default VC toolchain.
-// This is the preferred way to discover new Visual Studios, as they're no
-// longer listed in the registry.
-static bool
-findVCToolChainViaSetupConfig(llvm::vfs::FileSystem &VFS, std::string &Path,
- MSVCToolChain::ToolsetLayout &VSLayout) {
-#if !defined(USE_MSVC_SETUP_API)
- return false;
-#else
- // FIXME: This really should be done once in the top-level program's main
- // function, as it may have already been initialized with a different
- // threading model otherwise.
- llvm::sys::InitializeCOMRAII COM(llvm::sys::COMThreadingMode::SingleThreaded);
- HRESULT HR;
-
- // _com_ptr_t will throw a _com_error if a COM calls fail.
- // The LLVM coding standards forbid exception handling, so we'll have to
- // stop them from being thrown in the first place.
- // The destructor will put the regular error handler back when we leave
- // this scope.
- struct SuppressCOMErrorsRAII {
- static void __stdcall handler(HRESULT hr, IErrorInfo *perrinfo) {}
-
- SuppressCOMErrorsRAII() { _set_com_error_handler(handler); }
-
- ~SuppressCOMErrorsRAII() { _set_com_error_handler(_com_raise_error); }
-
- } COMErrorSuppressor;
-
- ISetupConfigurationPtr Query;
- HR = Query.CreateInstance(__uuidof(SetupConfiguration));
- if (FAILED(HR))
- return false;
-
- IEnumSetupInstancesPtr EnumInstances;
- HR = ISetupConfiguration2Ptr(Query)->EnumAllInstances(&EnumInstances);
- if (FAILED(HR))
- return false;
-
- ISetupInstancePtr Instance;
- HR = EnumInstances->Next(1, &Instance, nullptr);
- if (HR != S_OK)
- return false;
-
- ISetupInstancePtr NewestInstance;
- Optional<uint64_t> NewestVersionNum;
- do {
- bstr_t VersionString;
- uint64_t VersionNum;
- HR = Instance->GetInstallationVersion(VersionString.GetAddress());
- if (FAILED(HR))
- continue;
- HR = ISetupHelperPtr(Query)->ParseVersion(VersionString, &VersionNum);
- if (FAILED(HR))
- continue;
- if (!NewestVersionNum || (VersionNum > NewestVersionNum)) {
- NewestInstance = Instance;
- NewestVersionNum = VersionNum;
- }
- } while ((HR = EnumInstances->Next(1, &Instance, nullptr)) == S_OK);
-
- if (!NewestInstance)
- return false;
-
- bstr_t VCPathWide;
- HR = NewestInstance->ResolvePath(L"VC", VCPathWide.GetAddress());
- if (FAILED(HR))
- return false;
-
- std::string VCRootPath;
- llvm::convertWideToUTF8(std::wstring(VCPathWide), VCRootPath);
-
- llvm::SmallString<256> ToolsVersionFilePath(VCRootPath);
- llvm::sys::path::append(ToolsVersionFilePath, "Auxiliary", "Build",
- "Microsoft.VCToolsVersion.default.txt");
-
- auto ToolsVersionFile = llvm::MemoryBuffer::getFile(ToolsVersionFilePath);
- if (!ToolsVersionFile)
- return false;
-
- llvm::SmallString<256> ToolchainPath(VCRootPath);
- llvm::sys::path::append(ToolchainPath, "Tools", "MSVC",
- ToolsVersionFile->get()->getBuffer().rtrim());
- auto Status = VFS.status(ToolchainPath);
- if (!Status || !Status->isDirectory())
- return false;
-
- Path = std::string(ToolchainPath.str());
- VSLayout = MSVCToolChain::ToolsetLayout::VS2017OrNewer;
- return true;
-#endif
-}
-
-// Look in the registry for Visual Studio installs, and use that to get
-// a toolchain path. VS2017 and newer don't get added to the registry.
-// So if we find something here, we know that it's an older version.
-static bool findVCToolChainViaRegistry(std::string &Path,
- MSVCToolChain::ToolsetLayout &VSLayout) {
- std::string VSInstallPath;
- if (getSystemRegistryString(R"(SOFTWARE\Microsoft\VisualStudio\$VERSION)",
- "InstallDir", VSInstallPath, nullptr) ||
- getSystemRegistryString(R"(SOFTWARE\Microsoft\VCExpress\$VERSION)",
- "InstallDir", VSInstallPath, nullptr)) {
- if (!VSInstallPath.empty()) {
- llvm::SmallString<256> VCPath(llvm::StringRef(
- VSInstallPath.c_str(), VSInstallPath.find(R"(\Common7\IDE)")));
- llvm::sys::path::append(VCPath, "VC");
-
- Path = std::string(VCPath.str());
- VSLayout = MSVCToolChain::ToolsetLayout::OlderVS;
- return true;
- }
- }
- return false;
-}
-
// Try to find Exe from a Visual Studio distribution. This first tries to find
// an installed copy of Visual Studio and, failing that, looks in the PATH,
// making sure that whatever executable that's found is not a same-named exe
@@ -427,8 +60,8 @@ static bool findVCToolChainViaRegistry(std::string &Path,
static std::string FindVisualStudioExecutable(const ToolChain &TC,
const char *Exe) {
const auto &MSVC = static_cast<const toolchains::MSVCToolChain &>(TC);
- SmallString<128> FilePath(MSVC.getSubDirectoryPath(
- toolchains::MSVCToolChain::SubDirectoryType::Bin));
+ SmallString<128> FilePath(
+ MSVC.getSubDirectoryPath(llvm::SubDirectoryType::Bin));
llvm::sys::path::append(FilePath, Exe);
return std::string(canExecute(TC.getVFS(), FilePath) ? FilePath.str() : Exe);
}
@@ -448,7 +81,7 @@ void visualstudio::Linker::ConstructJob(Compilation &C, const JobAction &JA,
Args.MakeArgString(std::string("-out:") + Output.getFilename()));
if (!Args.hasArg(options::OPT_nostdlib, options::OPT_nostartfiles) &&
- !C.getDriver().IsCLMode()) {
+ !C.getDriver().IsCLMode() && !C.getDriver().IsFlangMode()) {
CmdArgs.push_back("-defaultlib:libcmt");
CmdArgs.push_back("-defaultlib:oldnames");
}
@@ -469,7 +102,7 @@ void visualstudio::Linker::ConstructJob(Compilation &C, const JobAction &JA,
// The DIA SDK always uses the legacy vc arch, even in new MSVC versions.
llvm::sys::path::append(DIAPath, "lib",
- llvmArchToLegacyVCArch(TC.getArch()));
+ llvm::archToLegacyVCArch(TC.getArch()));
CmdArgs.push_back(Args.MakeArgString(Twine("-libpath:") + DIAPath));
}
if (!llvm::sys::Process::GetEnv("LIB") ||
@@ -477,12 +110,10 @@ void visualstudio::Linker::ConstructJob(Compilation &C, const JobAction &JA,
options::OPT__SLASH_winsysroot)) {
CmdArgs.push_back(Args.MakeArgString(
Twine("-libpath:") +
- TC.getSubDirectoryPath(
- toolchains::MSVCToolChain::SubDirectoryType::Lib)));
+ TC.getSubDirectoryPath(llvm::SubDirectoryType::Lib)));
CmdArgs.push_back(Args.MakeArgString(
Twine("-libpath:") +
- TC.getSubDirectoryPath(toolchains::MSVCToolChain::SubDirectoryType::Lib,
- "atlmfc")));
+ TC.getSubDirectoryPath(llvm::SubDirectoryType::Lib, "atlmfc")));
}
if (!llvm::sys::Process::GetEnv("LIB") ||
Args.getLastArg(options::OPT__SLASH_winsdkdir,
@@ -499,6 +130,16 @@ void visualstudio::Linker::ConstructJob(Compilation &C, const JobAction &JA,
Args.MakeArgString(std::string("-libpath:") + WindowsSdkLibPath));
}
+ if (C.getDriver().IsFlangMode()) {
+ addFortranRuntimeLibraryPath(TC, Args, CmdArgs);
+ addFortranRuntimeLibs(TC, CmdArgs);
+
+ // Inform the MSVC linker that we're generating a console application, i.e.
+ // one with `main` as the "user-defined" entry point. The `main` function is
+ // defined in flang's runtime libraries.
+ CmdArgs.push_back("/subsystem:console");
+ }
+
// Add the compiler-rt library directories to libpath if they exist to help
// the linker find the various sanitizer, builtin, and profiling runtimes.
for (const auto &LibPath : TC.getLibraryPaths()) {
@@ -655,6 +296,8 @@ void visualstudio::Linker::ConstructJob(Compilation &C, const JobAction &JA,
A.renderAsInput(Args, CmdArgs);
}
+ addHIPRuntimeLibArgs(TC, Args, CmdArgs);
+
TC.addProfileRTLibs(Args, CmdArgs);
std::vector<const char *> Environment;
@@ -695,7 +338,7 @@ void visualstudio::Linker::ConstructJob(Compilation &C, const JobAction &JA,
// native target bin directory.
// e.g. when compiling for x86 on an x64 host, PATH should start with:
// /bin/Hostx64/x86;/bin/Hostx64/x64
- // This doesn't attempt to handle ToolsetLayout::DevDivInternal.
+ // This doesn't attempt to handle llvm::ToolsetLayout::DevDivInternal.
if (TC.getIsVS2017OrNewer() &&
llvm::Triple(llvm::sys::getProcessTriple()).getArch() != TC.getArch()) {
auto HostArch = llvm::Triple(llvm::sys::getProcessTriple()).getArch();
@@ -730,13 +373,12 @@ void visualstudio::Linker::ConstructJob(Compilation &C, const JobAction &JA,
for (const char *Cursor = EnvBlock.data(); *Cursor != '\0';) {
llvm::StringRef EnvVar(Cursor);
if (EnvVar.startswith_insensitive("path=")) {
- using SubDirectoryType = toolchains::MSVCToolChain::SubDirectoryType;
constexpr size_t PrefixLen = 5; // strlen("path=")
Environment.push_back(Args.MakeArgString(
EnvVar.substr(0, PrefixLen) +
- TC.getSubDirectoryPath(SubDirectoryType::Bin) +
+ TC.getSubDirectoryPath(llvm::SubDirectoryType::Bin) +
llvm::Twine(llvm::sys::EnvPathSeparator) +
- TC.getSubDirectoryPath(SubDirectoryType::Bin, "", HostArch) +
+ TC.getSubDirectoryPath(llvm::SubDirectoryType::Bin, HostArch) +
(EnvVar.size() > PrefixLen
? llvm::Twine(llvm::sys::EnvPathSeparator) +
EnvVar.substr(PrefixLen)
@@ -769,14 +411,29 @@ MSVCToolChain::MSVCToolChain(const Driver &D, const llvm::Triple &Triple,
if (getDriver().getInstalledDir() != getDriver().Dir)
getProgramPaths().push_back(getDriver().Dir);
+ Optional<llvm::StringRef> VCToolsDir, VCToolsVersion;
+ if (Arg *A = Args.getLastArg(options::OPT__SLASH_vctoolsdir))
+ VCToolsDir = A->getValue();
+ if (Arg *A = Args.getLastArg(options::OPT__SLASH_vctoolsversion))
+ VCToolsVersion = A->getValue();
+ if (Arg *A = Args.getLastArg(options::OPT__SLASH_winsdkdir))
+ WinSdkDir = A->getValue();
+ if (Arg *A = Args.getLastArg(options::OPT__SLASH_winsdkversion))
+ WinSdkVersion = A->getValue();
+ if (Arg *A = Args.getLastArg(options::OPT__SLASH_winsysroot))
+ WinSysRoot = A->getValue();
+
// Check the command line first, that's the user explicitly telling us what to
// use. Check the environment next, in case we're being invoked from a VS
// command prompt. Failing that, just try to find the newest Visual Studio
// version we can and use its default VC toolchain.
- findVCToolChainViaCommandLine(getVFS(), Args, VCToolChainPath, VSLayout) ||
- findVCToolChainViaEnvironment(getVFS(), VCToolChainPath, VSLayout) ||
- findVCToolChainViaSetupConfig(getVFS(), VCToolChainPath, VSLayout) ||
- findVCToolChainViaRegistry(VCToolChainPath, VSLayout);
+ llvm::findVCToolChainViaCommandLine(getVFS(), VCToolsDir, VCToolsVersion,
+ WinSysRoot, VCToolChainPath, VSLayout) ||
+ llvm::findVCToolChainViaEnvironment(getVFS(), VCToolChainPath,
+ VSLayout) ||
+ llvm::findVCToolChainViaSetupConfig(getVFS(), VCToolChainPath,
+ VSLayout) ||
+ llvm::findVCToolChainViaRegistry(VCToolChainPath, VSLayout);
}
Tool *MSVCToolChain::buildLinker() const {
@@ -802,8 +459,8 @@ bool MSVCToolChain::IsUnwindTablesDefault(const ArgList &Args) const {
// All non-x86_32 Windows targets require unwind tables. However, LLVM
// doesn't know how to generate them for all targets, so only enable
// the ones that are actually implemented.
- return getArch() == llvm::Triple::x86_64 ||
- getArch() == llvm::Triple::aarch64;
+ return getArch() == llvm::Triple::x86_64 || getArch() == llvm::Triple::arm ||
+ getArch() == llvm::Triple::thumb || getArch() == llvm::Triple::aarch64;
}
bool MSVCToolChain::isPICDefault() const {
@@ -830,360 +487,60 @@ void MSVCToolChain::AddHIPIncludeArgs(const ArgList &DriverArgs,
RocmInstallation.AddHIPIncludeArgs(DriverArgs, CC1Args);
}
+void MSVCToolChain::AddHIPRuntimeLibArgs(const ArgList &Args,
+ ArgStringList &CmdArgs) const {
+ CmdArgs.append({Args.MakeArgString(StringRef("-libpath:") +
+ RocmInstallation.getLibPath()),
+ "amdhip64.lib"});
+}
+
void MSVCToolChain::printVerboseInfo(raw_ostream &OS) const {
CudaInstallation.print(OS);
RocmInstallation.print(OS);
}
-// Get the path to a specific subdirectory in the current toolchain for
-// a given target architecture.
-// VS2017 changed the VC toolchain layout, so this should be used instead
-// of hardcoding paths.
std::string
-MSVCToolChain::getSubDirectoryPath(SubDirectoryType Type,
- llvm::StringRef SubdirParent,
- llvm::Triple::ArchType TargetArch) const {
- const char *SubdirName;
- const char *IncludeName;
- switch (VSLayout) {
- case ToolsetLayout::OlderVS:
- SubdirName = llvmArchToLegacyVCArch(TargetArch);
- IncludeName = "include";
- break;
- case ToolsetLayout::VS2017OrNewer:
- SubdirName = llvmArchToWindowsSDKArch(TargetArch);
- IncludeName = "include";
- break;
- case ToolsetLayout::DevDivInternal:
- SubdirName = llvmArchToDevDivInternalArch(TargetArch);
- IncludeName = "inc";
- break;
- }
-
- llvm::SmallString<256> Path(VCToolChainPath);
- if (!SubdirParent.empty())
- llvm::sys::path::append(Path, SubdirParent);
-
- switch (Type) {
- case SubDirectoryType::Bin:
- if (VSLayout == ToolsetLayout::VS2017OrNewer) {
- const bool HostIsX64 =
- llvm::Triple(llvm::sys::getProcessTriple()).isArch64Bit();
- const char *const HostName = HostIsX64 ? "Hostx64" : "Hostx86";
- llvm::sys::path::append(Path, "bin", HostName, SubdirName);
- } else { // OlderVS or DevDivInternal
- llvm::sys::path::append(Path, "bin", SubdirName);
- }
- break;
- case SubDirectoryType::Include:
- llvm::sys::path::append(Path, IncludeName);
- break;
- case SubDirectoryType::Lib:
- llvm::sys::path::append(Path, "lib", SubdirName);
- break;
- }
- return std::string(Path.str());
+MSVCToolChain::getSubDirectoryPath(llvm::SubDirectoryType Type,
+ llvm::StringRef SubdirParent) const {
+ return llvm::getSubDirectoryPath(Type, VSLayout, VCToolChainPath, getArch(),
+ SubdirParent);
}
-#ifdef _WIN32
-static bool readFullStringValue(HKEY hkey, const char *valueName,
- std::string &value) {
- std::wstring WideValueName;
- if (!llvm::ConvertUTF8toWide(valueName, WideValueName))
- return false;
-
- DWORD result = 0;
- DWORD valueSize = 0;
- DWORD type = 0;
- // First just query for the required size.
- result = RegQueryValueExW(hkey, WideValueName.c_str(), NULL, &type, NULL,
- &valueSize);
- if (result != ERROR_SUCCESS || type != REG_SZ || !valueSize)
- return false;
- std::vector<BYTE> buffer(valueSize);
- result = RegQueryValueExW(hkey, WideValueName.c_str(), NULL, NULL, &buffer[0],
- &valueSize);
- if (result == ERROR_SUCCESS) {
- std::wstring WideValue(reinterpret_cast<const wchar_t *>(buffer.data()),
- valueSize / sizeof(wchar_t));
- if (valueSize && WideValue.back() == L'\0') {
- WideValue.pop_back();
- }
- // The destination buffer must be empty as an invariant of the conversion
- // function; but this function is sometimes called in a loop that passes in
- // the same buffer, however. Simply clear it out so we can overwrite it.
- value.clear();
- return llvm::convertWideToUTF8(WideValue, value);
- }
- return false;
-}
-#endif
-
-/// Read registry string.
-/// This also supports a means to look for high-versioned keys by use
-/// of a $VERSION placeholder in the key path.
-/// $VERSION in the key path is a placeholder for the version number,
-/// causing the highest value path to be searched for and used.
-/// I.e. "SOFTWARE\\Microsoft\\VisualStudio\\$VERSION".
-/// There can be additional characters in the component. Only the numeric
-/// characters are compared. This function only searches HKLM.
-static bool getSystemRegistryString(const char *keyPath, const char *valueName,
- std::string &value, std::string *phValue) {
-#ifndef _WIN32
- return false;
-#else
- HKEY hRootKey = HKEY_LOCAL_MACHINE;
- HKEY hKey = NULL;
- long lResult;
- bool returnValue = false;
-
- const char *placeHolder = strstr(keyPath, "$VERSION");
- std::string bestName;
- // If we have a $VERSION placeholder, do the highest-version search.
- if (placeHolder) {
- const char *keyEnd = placeHolder - 1;
- const char *nextKey = placeHolder;
- // Find end of previous key.
- while ((keyEnd > keyPath) && (*keyEnd != '\\'))
- keyEnd--;
- // Find end of key containing $VERSION.
- while (*nextKey && (*nextKey != '\\'))
- nextKey++;
- size_t partialKeyLength = keyEnd - keyPath;
- char partialKey[256];
- if (partialKeyLength >= sizeof(partialKey))
- partialKeyLength = sizeof(partialKey) - 1;
- strncpy(partialKey, keyPath, partialKeyLength);
- partialKey[partialKeyLength] = '\0';
- HKEY hTopKey = NULL;
- lResult = RegOpenKeyExA(hRootKey, partialKey, 0, KEY_READ | KEY_WOW64_32KEY,
- &hTopKey);
- if (lResult == ERROR_SUCCESS) {
- char keyName[256];
- double bestValue = 0.0;
- DWORD index, size = sizeof(keyName) - 1;
- for (index = 0; RegEnumKeyExA(hTopKey, index, keyName, &size, NULL, NULL,
- NULL, NULL) == ERROR_SUCCESS;
- index++) {
- const char *sp = keyName;
- while (*sp && !isDigit(*sp))
- sp++;
- if (!*sp)
- continue;
- const char *ep = sp + 1;
- while (*ep && (isDigit(*ep) || (*ep == '.')))
- ep++;
- char numBuf[32];
- strncpy(numBuf, sp, sizeof(numBuf) - 1);
- numBuf[sizeof(numBuf) - 1] = '\0';
- double dvalue = strtod(numBuf, NULL);
- if (dvalue > bestValue) {
- // Test that InstallDir is indeed there before keeping this index.
- // Open the chosen key path remainder.
- bestName = keyName;
- // Append rest of key.
- bestName.append(nextKey);
- lResult = RegOpenKeyExA(hTopKey, bestName.c_str(), 0,
- KEY_READ | KEY_WOW64_32KEY, &hKey);
- if (lResult == ERROR_SUCCESS) {
- if (readFullStringValue(hKey, valueName, value)) {
- bestValue = dvalue;
- if (phValue)
- *phValue = bestName;
- returnValue = true;
- }
- RegCloseKey(hKey);
- }
- }
- size = sizeof(keyName) - 1;
- }
- RegCloseKey(hTopKey);
- }
- } else {
- lResult =
- RegOpenKeyExA(hRootKey, keyPath, 0, KEY_READ | KEY_WOW64_32KEY, &hKey);
- if (lResult == ERROR_SUCCESS) {
- if (readFullStringValue(hKey, valueName, value))
- returnValue = true;
- if (phValue)
- phValue->clear();
- RegCloseKey(hKey);
- }
- }
- return returnValue;
-#endif // _WIN32
+std::string
+MSVCToolChain::getSubDirectoryPath(llvm::SubDirectoryType Type,
+ llvm::Triple::ArchType TargetArch) const {
+ return llvm::getSubDirectoryPath(Type, VSLayout, VCToolChainPath, TargetArch,
+ "");
}
// Find the most recent version of Universal CRT or Windows 10 SDK.
// vcvarsqueryregistry.bat from Visual Studio 2015 sorts entries in the include
// directory by name and uses the last one of the list.
// So we compare entry names lexicographically to find the greatest one.
-static bool getWindows10SDKVersionFromPath(llvm::vfs::FileSystem &VFS,
- const std::string &SDKPath,
- std::string &SDKVersion) {
- llvm::SmallString<128> IncludePath(SDKPath);
- llvm::sys::path::append(IncludePath, "Include");
- SDKVersion = getHighestNumericTupleInDirectory(VFS, IncludePath);
- return !SDKVersion.empty();
-}
-
-static bool getWindowsSDKDirViaCommandLine(llvm::vfs::FileSystem &VFS,
- const ArgList &Args,
- std::string &Path, int &Major,
- std::string &Version) {
- if (Arg *A = Args.getLastArg(options::OPT__SLASH_winsdkdir,
- options::OPT__SLASH_winsysroot)) {
- // Don't validate the input; trust the value supplied by the user.
- // The motivation is to prevent unnecessary file and registry access.
- llvm::VersionTuple SDKVersion;
- if (Arg *A = Args.getLastArg(options::OPT__SLASH_winsdkversion))
- SDKVersion.tryParse(A->getValue());
-
- if (A->getOption().getID() == options::OPT__SLASH_winsysroot) {
- llvm::SmallString<128> SDKPath(A->getValue());
- llvm::sys::path::append(SDKPath, "Windows Kits");
- if (!SDKVersion.empty())
- llvm::sys::path::append(SDKPath, Twine(SDKVersion.getMajor()));
- else
- llvm::sys::path::append(
- SDKPath, getHighestNumericTupleInDirectory(VFS, SDKPath));
- Path = std::string(SDKPath.str());
- } else {
- Path = A->getValue();
- }
-
- if (!SDKVersion.empty()) {
- Major = SDKVersion.getMajor();
- Version = SDKVersion.getAsString();
- } else if (getWindows10SDKVersionFromPath(VFS, Path, Version)) {
- Major = 10;
- }
- return true;
- }
- return false;
-}
-
-/// Get Windows SDK installation directory.
-static bool getWindowsSDKDir(llvm::vfs::FileSystem &VFS, const ArgList &Args,
- std::string &Path, int &Major,
- std::string &WindowsSDKIncludeVersion,
- std::string &WindowsSDKLibVersion) {
- // Trust /winsdkdir and /winsdkversion if present.
- if (getWindowsSDKDirViaCommandLine(VFS, Args, Path, Major,
- WindowsSDKIncludeVersion)) {
- WindowsSDKLibVersion = WindowsSDKIncludeVersion;
- return true;
- }
-
- // FIXME: Try env vars (%WindowsSdkDir%, %UCRTVersion%) before going to registry.
-
- // Try the Windows registry.
- std::string RegistrySDKVersion;
- if (!getSystemRegistryString(
- "SOFTWARE\\Microsoft\\Microsoft SDKs\\Windows\\$VERSION",
- "InstallationFolder", Path, &RegistrySDKVersion))
- return false;
- if (Path.empty() || RegistrySDKVersion.empty())
- return false;
-
- WindowsSDKIncludeVersion.clear();
- WindowsSDKLibVersion.clear();
- Major = 0;
- std::sscanf(RegistrySDKVersion.c_str(), "v%d.", &Major);
- if (Major <= 7)
- return true;
- if (Major == 8) {
- // Windows SDK 8.x installs libraries in a folder whose names depend on the
- // version of the OS you're targeting. By default choose the newest, which
- // usually corresponds to the version of the OS you've installed the SDK on.
- const char *Tests[] = {"winv6.3", "win8", "win7"};
- for (const char *Test : Tests) {
- llvm::SmallString<128> TestPath(Path);
- llvm::sys::path::append(TestPath, "Lib", Test);
- if (VFS.exists(TestPath)) {
- WindowsSDKLibVersion = Test;
- break;
- }
- }
- return !WindowsSDKLibVersion.empty();
- }
- if (Major == 10) {
- if (!getWindows10SDKVersionFromPath(VFS, Path, WindowsSDKIncludeVersion))
- return false;
- WindowsSDKLibVersion = WindowsSDKIncludeVersion;
- return true;
- }
- // Unsupported SDK version
- return false;
-}
-
// Gets the library path required to link against the Windows SDK.
-bool MSVCToolChain::getWindowsSDKLibraryPath(
- const ArgList &Args, std::string &path) const {
+bool MSVCToolChain::getWindowsSDKLibraryPath(const ArgList &Args,
+ std::string &path) const {
std::string sdkPath;
int sdkMajor = 0;
std::string windowsSDKIncludeVersion;
std::string windowsSDKLibVersion;
path.clear();
- if (!getWindowsSDKDir(getVFS(), Args, sdkPath, sdkMajor,
- windowsSDKIncludeVersion, windowsSDKLibVersion))
+ if (!llvm::getWindowsSDKDir(getVFS(), WinSdkDir, WinSdkVersion, WinSysRoot,
+ sdkPath, sdkMajor, windowsSDKIncludeVersion,
+ windowsSDKLibVersion))
return false;
llvm::SmallString<128> libPath(sdkPath);
llvm::sys::path::append(libPath, "Lib");
- if (sdkMajor >= 8) {
- llvm::sys::path::append(libPath, windowsSDKLibVersion, "um",
- llvmArchToWindowsSDKArch(getArch()));
- } else {
- switch (getArch()) {
- // In Windows SDK 7.x, x86 libraries are directly in the Lib folder.
- case llvm::Triple::x86:
- break;
- case llvm::Triple::x86_64:
- llvm::sys::path::append(libPath, "x64");
- break;
- case llvm::Triple::arm:
- // It is not necessary to link against Windows SDK 7.x when targeting ARM.
- return false;
- default:
- return false;
- }
- }
-
- path = std::string(libPath.str());
- return true;
+ if (sdkMajor >= 8)
+ llvm::sys::path::append(libPath, windowsSDKLibVersion, "um");
+ return llvm::appendArchToWindowsSDKLibPath(sdkMajor, libPath, getArch(),
+ path);
}
-// Check if the Include path of a specified version of Visual Studio contains
-// specific header files. If not, they are probably shipped with Universal CRT.
bool MSVCToolChain::useUniversalCRT() const {
- llvm::SmallString<128> TestPath(
- getSubDirectoryPath(SubDirectoryType::Include));
- llvm::sys::path::append(TestPath, "stdlib.h");
- return !getVFS().exists(TestPath);
-}
-
-static bool getUniversalCRTSdkDir(llvm::vfs::FileSystem &VFS,
- const ArgList &Args, std::string &Path,
- std::string &UCRTVersion) {
- // If /winsdkdir is passed, use it as location for the UCRT too.
- // FIXME: Should there be a dedicated /ucrtdir to override /winsdkdir?
- int Major;
- if (getWindowsSDKDirViaCommandLine(VFS, Args, Path, Major, UCRTVersion))
- return true;
-
- // FIXME: Try env vars (%UniversalCRTSdkDir%, %UCRTVersion%) before going to
- // registry.
-
- // vcvarsqueryregistry.bat for Visual Studio 2015 queries the registry
- // for the specific key "KitsRoot10". So do we.
- if (!getSystemRegistryString(
- "SOFTWARE\\Microsoft\\Windows Kits\\Installed Roots", "KitsRoot10",
- Path, nullptr))
- return false;
-
- return getWindows10SDKVersionFromPath(VFS, Path, UCRTVersion);
+ return llvm::useUniversalCRT(VSLayout, VCToolChainPath, getArch(), getVFS());
}
bool MSVCToolChain::getUniversalCRTLibraryPath(const ArgList &Args,
@@ -1192,10 +549,12 @@ bool MSVCToolChain::getUniversalCRTLibraryPath(const ArgList &Args,
std::string UCRTVersion;
Path.clear();
- if (!getUniversalCRTSdkDir(getVFS(), Args, UniversalCRTSdkPath, UCRTVersion))
+ if (!llvm::getUniversalCRTSdkDir(getVFS(), WinSdkDir, WinSdkVersion,
+ WinSysRoot, UniversalCRTSdkPath,
+ UCRTVersion))
return false;
- StringRef ArchName = llvmArchToWindowsSDKArch(getArch());
+ StringRef ArchName = llvm::archToWindowsSDKArch(getArch());
if (ArchName.empty())
return false;
@@ -1313,15 +672,17 @@ void MSVCToolChain::AddClangSystemIncludeArgs(const ArgList &DriverArgs,
// the correct include paths first.
if (!VCToolChainPath.empty()) {
addSystemInclude(DriverArgs, CC1Args,
- getSubDirectoryPath(SubDirectoryType::Include));
- addSystemInclude(DriverArgs, CC1Args,
- getSubDirectoryPath(SubDirectoryType::Include, "atlmfc"));
+ getSubDirectoryPath(llvm::SubDirectoryType::Include));
+ addSystemInclude(
+ DriverArgs, CC1Args,
+ getSubDirectoryPath(llvm::SubDirectoryType::Include, "atlmfc"));
if (useUniversalCRT()) {
std::string UniversalCRTSdkPath;
std::string UCRTVersion;
- if (getUniversalCRTSdkDir(getVFS(), DriverArgs, UniversalCRTSdkPath,
- UCRTVersion)) {
+ if (llvm::getUniversalCRTSdkDir(getVFS(), WinSdkDir, WinSdkVersion,
+ WinSysRoot, UniversalCRTSdkPath,
+ UCRTVersion)) {
AddSystemIncludeWithSubfolder(DriverArgs, CC1Args, UniversalCRTSdkPath,
"Include", UCRTVersion, "ucrt");
}
@@ -1331,8 +692,9 @@ void MSVCToolChain::AddClangSystemIncludeArgs(const ArgList &DriverArgs,
int major = 0;
std::string windowsSDKIncludeVersion;
std::string windowsSDKLibVersion;
- if (getWindowsSDKDir(getVFS(), DriverArgs, WindowsSDKDir, major,
- windowsSDKIncludeVersion, windowsSDKLibVersion)) {
+ if (llvm::getWindowsSDKDir(getVFS(), WinSdkDir, WinSdkVersion, WinSysRoot,
+ WindowsSDKDir, major, windowsSDKIncludeVersion,
+ windowsSDKLibVersion)) {
if (major >= 8) {
// Note: windowsSDKIncludeVersion is empty for SDKs prior to v10.
// Anyway, llvm::sys::path::append is able to manage it.
@@ -1348,7 +710,7 @@ void MSVCToolChain::AddClangSystemIncludeArgs(const ArgList &DriverArgs,
if (major >= 10) {
llvm::VersionTuple Tuple;
if (!Tuple.tryParse(windowsSDKIncludeVersion) &&
- Tuple.getSubminor().getValueOr(0) >= 17134) {
+ Tuple.getSubminor().value_or(0) >= 17134) {
AddSystemIncludeWithSubfolder(DriverArgs, CC1Args, WindowsSDKDir,
"Include", windowsSDKIncludeVersion,
"cppwinrt");
@@ -1389,12 +751,13 @@ VersionTuple MSVCToolChain::computeMSVCVersion(const Driver *D,
if (MSVT.empty())
MSVT = getTriple().getEnvironmentVersion();
if (MSVT.empty() && IsWindowsMSVC)
- MSVT = getMSVCVersionFromExe(getSubDirectoryPath(SubDirectoryType::Bin));
+ MSVT =
+ getMSVCVersionFromExe(getSubDirectoryPath(llvm::SubDirectoryType::Bin));
if (MSVT.empty() &&
Args.hasFlag(options::OPT_fms_extensions, options::OPT_fno_ms_extensions,
IsWindowsMSVC)) {
- // -fms-compatibility-version=19.14 is default, aka 2017, 15.7
- MSVT = VersionTuple(19, 14);
+ // -fms-compatibility-version=19.20 is default, aka 2019, 16.x
+ MSVT = VersionTuple(19, 20);
}
return MSVT;
}
@@ -1405,8 +768,8 @@ MSVCToolChain::ComputeEffectiveClangTriple(const ArgList &Args,
// The MSVC version doesn't care about the architecture, even though it
// may look at the triple internally.
VersionTuple MSVT = computeMSVCVersion(/*D=*/nullptr, Args);
- MSVT = VersionTuple(MSVT.getMajor(), MSVT.getMinor().getValueOr(0),
- MSVT.getSubminor().getValueOr(0));
+ MSVT = VersionTuple(MSVT.getMajor(), MSVT.getMinor().value_or(0),
+ MSVT.getSubminor().value_or(0));
// For the rest of the triple, however, a computed architecture name may
// be needed.
@@ -1619,7 +982,7 @@ void MSVCToolChain::addClangTargetOptions(
Action::OffloadKind DeviceOffloadKind) const {
// MSVC STL kindly allows removing all usages of typeid by defining
// _HAS_STATIC_RTTI to 0. Do so, when compiling with -fno-rtti
- if (DriverArgs.hasArg(options::OPT_fno_rtti, options::OPT_frtti,
- /*Default=*/false))
+ if (DriverArgs.hasFlag(options::OPT_fno_rtti, options::OPT_frtti,
+ /*Default=*/false))
CC1Args.push_back("-D_HAS_STATIC_RTTI=0");
}
diff --git a/clang/lib/Driver/ToolChains/MSVC.h b/clang/lib/Driver/ToolChains/MSVC.h
index c842773996ed..f09256ba124e 100644
--- a/clang/lib/Driver/ToolChains/MSVC.h
+++ b/clang/lib/Driver/ToolChains/MSVC.h
@@ -15,6 +15,7 @@
#include "clang/Driver/Compilation.h"
#include "clang/Driver/Tool.h"
#include "clang/Driver/ToolChain.h"
+#include "llvm/WindowsDriver/MSVCPaths.h"
namespace clang {
namespace driver {
@@ -73,29 +74,15 @@ public:
return 4;
}
- enum class SubDirectoryType {
- Bin,
- Include,
- Lib,
- };
- std::string getSubDirectoryPath(SubDirectoryType Type,
- llvm::StringRef SubdirParent,
+ std::string getSubDirectoryPath(llvm::SubDirectoryType Type,
+ llvm::StringRef SubdirParent = "") const;
+ std::string getSubDirectoryPath(llvm::SubDirectoryType Type,
llvm::Triple::ArchType TargetArch) const;
- // Convenience overload.
- // Uses the current target arch.
- std::string getSubDirectoryPath(SubDirectoryType Type,
- llvm::StringRef SubdirParent = "") const {
- return getSubDirectoryPath(Type, SubdirParent, getArch());
+ bool getIsVS2017OrNewer() const {
+ return VSLayout == llvm::ToolsetLayout::VS2017OrNewer;
}
- enum class ToolsetLayout {
- OlderVS,
- VS2017OrNewer,
- DevDivInternal,
- };
- bool getIsVS2017OrNewer() const { return VSLayout == ToolsetLayout::VS2017OrNewer; }
-
void
AddClangSystemIncludeArgs(const llvm::opt::ArgList &DriverArgs,
llvm::opt::ArgStringList &CC1Args) const override;
@@ -109,6 +96,9 @@ public:
void AddHIPIncludeArgs(const llvm::opt::ArgList &DriverArgs,
llvm::opt::ArgStringList &CC1Args) const override;
+ void AddHIPRuntimeLibArgs(const llvm::opt::ArgList &Args,
+ llvm::opt::ArgStringList &CmdArgs) const override;
+
bool getWindowsSDKLibraryPath(
const llvm::opt::ArgList &Args, std::string &path) const;
bool getUniversalCRTLibraryPath(const llvm::opt::ArgList &Args,
@@ -142,8 +132,9 @@ protected:
Tool *buildLinker() const override;
Tool *buildAssembler() const override;
private:
+ llvm::Optional<llvm::StringRef> WinSdkDir, WinSdkVersion, WinSysRoot;
std::string VCToolChainPath;
- ToolsetLayout VSLayout = ToolsetLayout::OlderVS;
+ llvm::ToolsetLayout VSLayout = llvm::ToolsetLayout::OlderVS;
CudaInstallationDetector CudaInstallation;
RocmInstallationDetector RocmInstallation;
};
diff --git a/clang/lib/Driver/ToolChains/MSVCSetupApi.h b/clang/lib/Driver/ToolChains/MSVCSetupApi.h
deleted file mode 100644
index 28e6e3e08e37..000000000000
--- a/clang/lib/Driver/ToolChains/MSVCSetupApi.h
+++ /dev/null
@@ -1,523 +0,0 @@
-// <copyright file="Program.cpp" company="Microsoft Corporation">
-// Copyright (C) Microsoft Corporation. All rights reserved.
-// Licensed under the MIT license.
-// </copyright>
-// <license>
-// The MIT License (MIT)
-//
-// Copyright (C) Microsoft Corporation. All rights reserved.
-//
-// Permission is hereby granted, free of charge, to any person obtaining
-// a copy of this software and associated documentation files (the "Software"),
-// to deal in the Software without restriction, including without limitation the
-// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
-// sell copies of the Software, and to permit persons to whom the Software is
-// furnished to do so, subject to the following conditions:
-//
-// The above copyright notice and this permission notice shall be included in
-// all copies or substantial portions of the Software.
-//
-// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
-// SOFTWARE.
-// </license>
-
-#pragma once
-
-#ifdef __clang__
-#pragma clang diagnostic push
-#pragma clang diagnostic ignored "-Wnon-virtual-dtor"
-#endif
-
-// Constants
-//
-#ifndef E_NOTFOUND
-#define E_NOTFOUND HRESULT_FROM_WIN32(ERROR_NOT_FOUND)
-#endif
-
-#ifndef E_FILENOTFOUND
-#define E_FILENOTFOUND HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND)
-#endif
-
-// Enumerations
-//
-/// <summary>
-/// The state of an instance.
-/// </summary>
-enum InstanceState : unsigned {
- /// <summary>
- /// The instance state has not been determined.
- /// </summary>
- eNone = 0,
-
- /// <summary>
- /// The instance installation path exists.
- /// </summary>
- eLocal = 1,
-
- /// <summary>
- /// A product is registered to the instance.
- /// </summary>
- eRegistered = 2,
-
- /// <summary>
- /// No reboot is required for the instance.
- /// </summary>
- eNoRebootRequired = 4,
-
- /// <summary>
- /// The instance represents a complete install.
- /// </summary>
- eComplete = MAXUINT,
-};
-
-// Forward interface declarations
-//
-#ifndef __ISetupInstance_FWD_DEFINED__
-#define __ISetupInstance_FWD_DEFINED__
-typedef struct ISetupInstance ISetupInstance;
-#endif
-
-#ifndef __ISetupInstance2_FWD_DEFINED__
-#define __ISetupInstance2_FWD_DEFINED__
-typedef struct ISetupInstance2 ISetupInstance2;
-#endif
-
-#ifndef __IEnumSetupInstances_FWD_DEFINED__
-#define __IEnumSetupInstances_FWD_DEFINED__
-typedef struct IEnumSetupInstances IEnumSetupInstances;
-#endif
-
-#ifndef __ISetupConfiguration_FWD_DEFINED__
-#define __ISetupConfiguration_FWD_DEFINED__
-typedef struct ISetupConfiguration ISetupConfiguration;
-#endif
-
-#ifndef __ISetupConfiguration2_FWD_DEFINED__
-#define __ISetupConfiguration2_FWD_DEFINED__
-typedef struct ISetupConfiguration2 ISetupConfiguration2;
-#endif
-
-#ifndef __ISetupPackageReference_FWD_DEFINED__
-#define __ISetupPackageReference_FWD_DEFINED__
-typedef struct ISetupPackageReference ISetupPackageReference;
-#endif
-
-#ifndef __ISetupHelper_FWD_DEFINED__
-#define __ISetupHelper_FWD_DEFINED__
-typedef struct ISetupHelper ISetupHelper;
-#endif
-
-// Forward class declarations
-//
-#ifndef __SetupConfiguration_FWD_DEFINED__
-#define __SetupConfiguration_FWD_DEFINED__
-
-#ifdef __cplusplus
-typedef class SetupConfiguration SetupConfiguration;
-#endif
-
-#endif
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-// Interface definitions
-//
-EXTERN_C const IID IID_ISetupInstance;
-
-#if defined(__cplusplus) && !defined(CINTERFACE)
-/// <summary>
-/// Information about an instance of a product.
-/// </summary>
-struct DECLSPEC_UUID("B41463C3-8866-43B5-BC33-2B0676F7F42E")
- DECLSPEC_NOVTABLE ISetupInstance : public IUnknown {
- /// <summary>
- /// Gets the instance identifier (should match the name of the parent instance
- /// directory).
- /// </summary>
- /// <param name="pbstrInstanceId">The instance identifier.</param>
- /// <returns>Standard HRESULT indicating success or failure, including
- /// E_FILENOTFOUND if the instance state does not exist.</returns>
- STDMETHOD(GetInstanceId)(_Out_ BSTR *pbstrInstanceId) = 0;
-
- /// <summary>
- /// Gets the local date and time when the installation was originally
- /// installed.
- /// </summary>
- /// <param name="pInstallDate">The local date and time when the installation
- /// was originally installed.</param>
- /// <returns>Standard HRESULT indicating success or failure, including
- /// E_FILENOTFOUND if the instance state does not exist and E_NOTFOUND if the
- /// property is not defined.</returns>
- STDMETHOD(GetInstallDate)(_Out_ LPFILETIME pInstallDate) = 0;
-
- /// <summary>
- /// Gets the unique name of the installation, often indicating the branch and
- /// other information used for telemetry.
- /// </summary>
- /// <param name="pbstrInstallationName">The unique name of the installation,
- /// often indicating the branch and other information used for
- /// telemetry.</param>
- /// <returns>Standard HRESULT indicating success or failure, including
- /// E_FILENOTFOUND if the instance state does not exist and E_NOTFOUND if the
- /// property is not defined.</returns>
- STDMETHOD(GetInstallationName)(_Out_ BSTR *pbstrInstallationName) = 0;
-
- /// <summary>
- /// Gets the path to the installation root of the product.
- /// </summary>
- /// <param name="pbstrInstallationPath">The path to the installation root of
- /// the product.</param>
- /// <returns>Standard HRESULT indicating success or failure, including
- /// E_FILENOTFOUND if the instance state does not exist and E_NOTFOUND if the
- /// property is not defined.</returns>
- STDMETHOD(GetInstallationPath)(_Out_ BSTR *pbstrInstallationPath) = 0;
-
- /// <summary>
- /// Gets the version of the product installed in this instance.
- /// </summary>
- /// <param name="pbstrInstallationVersion">The version of the product
- /// installed in this instance.</param>
- /// <returns>Standard HRESULT indicating success or failure, including
- /// E_FILENOTFOUND if the instance state does not exist and E_NOTFOUND if the
- /// property is not defined.</returns>
- STDMETHOD(GetInstallationVersion)(_Out_ BSTR *pbstrInstallationVersion) = 0;
-
- /// <summary>
- /// Gets the display name (title) of the product installed in this instance.
- /// </summary>
- /// <param name="lcid">The LCID for the display name.</param>
- /// <param name="pbstrDisplayName">The display name (title) of the product
- /// installed in this instance.</param>
- /// <returns>Standard HRESULT indicating success or failure, including
- /// E_FILENOTFOUND if the instance state does not exist and E_NOTFOUND if the
- /// property is not defined.</returns>
- STDMETHOD(GetDisplayName)(_In_ LCID lcid, _Out_ BSTR *pbstrDisplayName) = 0;
-
- /// <summary>
- /// Gets the description of the product installed in this instance.
- /// </summary>
- /// <param name="lcid">The LCID for the description.</param>
- /// <param name="pbstrDescription">The description of the product installed in
- /// this instance.</param>
- /// <returns>Standard HRESULT indicating success or failure, including
- /// E_FILENOTFOUND if the instance state does not exist and E_NOTFOUND if the
- /// property is not defined.</returns>
- STDMETHOD(GetDescription)(_In_ LCID lcid, _Out_ BSTR *pbstrDescription) = 0;
-
- /// <summary>
- /// Resolves the optional relative path to the root path of the instance.
- /// </summary>
- /// <param name="pwszRelativePath">A relative path within the instance to
- /// resolve, or NULL to get the root path.</param>
- /// <param name="pbstrAbsolutePath">The full path to the optional relative
- /// path within the instance. If the relative path is NULL, the root path will
- /// always terminate in a backslash.</param>
- /// <returns>Standard HRESULT indicating success or failure, including
- /// E_FILENOTFOUND if the instance state does not exist and E_NOTFOUND if the
- /// property is not defined.</returns>
- STDMETHOD(ResolvePath)
- (_In_opt_z_ LPCOLESTR pwszRelativePath, _Out_ BSTR *pbstrAbsolutePath) = 0;
-};
-#endif
-
-EXTERN_C const IID IID_ISetupInstance2;
-
-#if defined(__cplusplus) && !defined(CINTERFACE)
-/// <summary>
-/// Information about an instance of a product.
-/// </summary>
-struct DECLSPEC_UUID("89143C9A-05AF-49B0-B717-72E218A2185C")
- DECLSPEC_NOVTABLE ISetupInstance2 : public ISetupInstance {
- /// <summary>
- /// Gets the state of the instance.
- /// </summary>
- /// <param name="pState">The state of the instance.</param>
- /// <returns>Standard HRESULT indicating success or failure, including
- /// E_FILENOTFOUND if the instance state does not exist.</returns>
- STDMETHOD(GetState)(_Out_ InstanceState *pState) = 0;
-
- /// <summary>
- /// Gets an array of package references registered to the instance.
- /// </summary>
- /// <param name="ppsaPackages">Pointer to an array of <see
- /// cref="ISetupPackageReference"/>.</param>
- /// <returns>Standard HRESULT indicating success or failure, including
- /// E_FILENOTFOUND if the instance state does not exist and E_NOTFOUND if the
- /// packages property is not defined.</returns>
- STDMETHOD(GetPackages)(_Out_ LPSAFEARRAY *ppsaPackages) = 0;
-
- /// <summary>
- /// Gets a pointer to the <see cref="ISetupPackageReference"/> that represents
- /// the registered product.
- /// </summary>
- /// <param name="ppPackage">Pointer to an instance of <see
- /// cref="ISetupPackageReference"/>. This may be NULL if <see
- /// cref="GetState"/> does not return <see cref="eComplete"/>.</param>
- /// <returns>Standard HRESULT indicating success or failure, including
- /// E_FILENOTFOUND if the instance state does not exist and E_NOTFOUND if the
- /// packages property is not defined.</returns>
- STDMETHOD(GetProduct)
- (_Outptr_result_maybenull_ ISetupPackageReference **ppPackage) = 0;
-
- /// <summary>
- /// Gets the relative path to the product application, if available.
- /// </summary>
- /// <param name="pbstrProductPath">The relative path to the product
- /// application, if available.</param>
- /// <returns>Standard HRESULT indicating success or failure, including
- /// E_FILENOTFOUND if the instance state does not exist.</returns>
- STDMETHOD(GetProductPath)
- (_Outptr_result_maybenull_ BSTR *pbstrProductPath) = 0;
-};
-#endif
-
-EXTERN_C const IID IID_IEnumSetupInstances;
-
-#if defined(__cplusplus) && !defined(CINTERFACE)
-/// <summary>
-/// A enumerator of installed <see cref="ISetupInstance"/> objects.
-/// </summary>
-struct DECLSPEC_UUID("6380BCFF-41D3-4B2E-8B2E-BF8A6810C848")
- DECLSPEC_NOVTABLE IEnumSetupInstances : public IUnknown {
- /// <summary>
- /// Retrieves the next set of product instances in the enumeration sequence.
- /// </summary>
- /// <param name="celt">The number of product instances to retrieve.</param>
- /// <param name="rgelt">A pointer to an array of <see
- /// cref="ISetupInstance"/>.</param>
- /// <param name="pceltFetched">A pointer to the number of product instances
- /// retrieved. If celt is 1 this parameter may be NULL.</param>
- /// <returns>S_OK if the number of elements were fetched, S_FALSE if nothing
- /// was fetched (at end of enumeration), E_INVALIDARG if celt is greater than
- /// 1 and pceltFetched is NULL, or E_OUTOFMEMORY if an <see
- /// cref="ISetupInstance"/> could not be allocated.</returns>
- STDMETHOD(Next)
- (_In_ ULONG celt, _Out_writes_to_(celt, *pceltFetched) ISetupInstance **rgelt,
- _Out_opt_ _Deref_out_range_(0, celt) ULONG *pceltFetched) = 0;
-
- /// <summary>
- /// Skips the next set of product instances in the enumeration sequence.
- /// </summary>
- /// <param name="celt">The number of product instances to skip.</param>
- /// <returns>S_OK if the number of elements could be skipped; otherwise,
- /// S_FALSE;</returns>
- STDMETHOD(Skip)(_In_ ULONG celt) = 0;
-
- /// <summary>
- /// Resets the enumeration sequence to the beginning.
- /// </summary>
- /// <returns>Always returns S_OK;</returns>
- STDMETHOD(Reset)(void) = 0;
-
- /// <summary>
- /// Creates a new enumeration object in the same state as the current
- /// enumeration object: the new object points to the same place in the
- /// enumeration sequence.
- /// </summary>
- /// <param name="ppenum">A pointer to a pointer to a new <see
- /// cref="IEnumSetupInstances"/> interface. If the method fails, this
- /// parameter is undefined.</param>
- /// <returns>S_OK if a clone was returned; otherwise, E_OUTOFMEMORY.</returns>
- STDMETHOD(Clone)(_Deref_out_opt_ IEnumSetupInstances **ppenum) = 0;
-};
-#endif
-
-EXTERN_C const IID IID_ISetupConfiguration;
-
-#if defined(__cplusplus) && !defined(CINTERFACE)
-/// <summary>
-/// Gets information about product instances set up on the machine.
-/// </summary>
-struct DECLSPEC_UUID("42843719-DB4C-46C2-8E7C-64F1816EFD5B")
- DECLSPEC_NOVTABLE ISetupConfiguration : public IUnknown {
- /// <summary>
- /// Enumerates all completed product instances installed.
- /// </summary>
- /// <param name="ppEnumInstances">An enumeration of completed, installed
- /// product instances.</param>
- /// <returns>Standard HRESULT indicating success or failure.</returns>
- STDMETHOD(EnumInstances)(_Out_ IEnumSetupInstances **ppEnumInstances) = 0;
-
- /// <summary>
- /// Gets the instance for the current process path.
- /// </summary>
- /// <param name="ppInstance">The instance for the current process
- /// path.</param>
- /// <returns>The instance for the current process path, or E_NOTFOUND if not
- /// found.</returns>
- STDMETHOD(GetInstanceForCurrentProcess)
- (_Out_ ISetupInstance **ppInstance) = 0;
-
- /// <summary>
- /// Gets the instance for the given path.
- /// </summary>
- /// <param name="ppInstance">The instance for the given path.</param>
- /// <returns>The instance for the given path, or E_NOTFOUND if not
- /// found.</returns>
- STDMETHOD(GetInstanceForPath)
- (_In_z_ LPCWSTR wzPath, _Out_ ISetupInstance **ppInstance) = 0;
-};
-#endif
-
-EXTERN_C const IID IID_ISetupConfiguration2;
-
-#if defined(__cplusplus) && !defined(CINTERFACE)
-/// <summary>
-/// Gets information about product instances.
-/// </summary>
-struct DECLSPEC_UUID("26AAB78C-4A60-49D6-AF3B-3C35BC93365D")
- DECLSPEC_NOVTABLE ISetupConfiguration2 : public ISetupConfiguration {
- /// <summary>
- /// Enumerates all product instances.
- /// </summary>
- /// <param name="ppEnumInstances">An enumeration of all product
- /// instances.</param>
- /// <returns>Standard HRESULT indicating success or failure.</returns>
- STDMETHOD(EnumAllInstances)(_Out_ IEnumSetupInstances **ppEnumInstances) = 0;
-};
-#endif
-
-EXTERN_C const IID IID_ISetupPackageReference;
-
-#if defined(__cplusplus) && !defined(CINTERFACE)
-/// <summary>
-/// A reference to a package.
-/// </summary>
-struct DECLSPEC_UUID("da8d8a16-b2b6-4487-a2f1-594ccccd6bf5")
- DECLSPEC_NOVTABLE ISetupPackageReference : public IUnknown {
- /// <summary>
- /// Gets the general package identifier.
- /// </summary>
- /// <param name="pbstrId">The general package identifier.</param>
- /// <returns>Standard HRESULT indicating success or failure.</returns>
- STDMETHOD(GetId)(_Out_ BSTR *pbstrId) = 0;
-
- /// <summary>
- /// Gets the version of the package.
- /// </summary>
- /// <param name="pbstrVersion">The version of the package.</param>
- /// <returns>Standard HRESULT indicating success or failure.</returns>
- STDMETHOD(GetVersion)(_Out_ BSTR *pbstrVersion) = 0;
-
- /// <summary>
- /// Gets the target process architecture of the package.
- /// </summary>
- /// <param name="pbstrChip">The target process architecture of the
- /// package.</param>
- /// <returns>Standard HRESULT indicating success or failure.</returns>
- STDMETHOD(GetChip)(_Out_ BSTR *pbstrChip) = 0;
-
- /// <summary>
- /// Gets the language and optional region identifier.
- /// </summary>
- /// <param name="pbstrLanguage">The language and optional region
- /// identifier.</param>
- /// <returns>Standard HRESULT indicating success or failure.</returns>
- STDMETHOD(GetLanguage)(_Out_ BSTR *pbstrLanguage) = 0;
-
- /// <summary>
- /// Gets the build branch of the package.
- /// </summary>
- /// <param name="pbstrBranch">The build branch of the package.</param>
- /// <returns>Standard HRESULT indicating success or failure.</returns>
- STDMETHOD(GetBranch)(_Out_ BSTR *pbstrBranch) = 0;
-
- /// <summary>
- /// Gets the type of the package.
- /// </summary>
- /// <param name="pbstrType">The type of the package.</param>
- /// <returns>Standard HRESULT indicating success or failure.</returns>
- STDMETHOD(GetType)(_Out_ BSTR *pbstrType) = 0;
-
- /// <summary>
- /// Gets the unique identifier consisting of all defined tokens.
- /// </summary>
- /// <param name="pbstrUniqueId">The unique identifier consisting of all
- /// defined tokens.</param>
- /// <returns>Standard HRESULT indicating success or failure, including
- /// E_UNEXPECTED if no Id was defined (required).</returns>
- STDMETHOD(GetUniqueId)(_Out_ BSTR *pbstrUniqueId) = 0;
-};
-#endif
-
-EXTERN_C const IID IID_ISetupHelper;
-
-#if defined(__cplusplus) && !defined(CINTERFACE)
-/// <summary>
-/// Helper functions.
-/// </summary>
-/// <remarks>
-/// You can query for this interface from the <see cref="SetupConfiguration"/>
-/// class.
-/// </remarks>
-struct DECLSPEC_UUID("42b21b78-6192-463e-87bf-d577838f1d5c")
- DECLSPEC_NOVTABLE ISetupHelper : public IUnknown {
- /// <summary>
- /// Parses a dotted quad version string into a 64-bit unsigned integer.
- /// </summary>
- /// <param name="pwszVersion">The dotted quad version string to parse, e.g.
- /// 1.2.3.4.</param>
- /// <param name="pullVersion">A 64-bit unsigned integer representing the
- /// version. You can compare this to other versions.</param>
- /// <returns>Standard HRESULT indicating success or failure.</returns>
- STDMETHOD(ParseVersion)
- (_In_ LPCOLESTR pwszVersion, _Out_ PULONGLONG pullVersion) = 0;
-
- /// <summary>
- /// Parses a dotted quad version string into a 64-bit unsigned integer.
- /// </summary>
- /// <param name="pwszVersionRange">The string containing 1 or 2 dotted quad
- /// version strings to parse, e.g. [1.0,) that means 1.0.0.0 or newer.</param>
- /// <param name="pullMinVersion">A 64-bit unsigned integer representing the
- /// minimum version, which may be 0. You can compare this to other
- /// versions.</param>
- /// <param name="pullMaxVersion">A 64-bit unsigned integer representing the
- /// maximum version, which may be MAXULONGLONG. You can compare this to other
- /// versions.</param>
- /// <returns>Standard HRESULT indicating success or failure.</returns>
- STDMETHOD(ParseVersionRange)
- (_In_ LPCOLESTR pwszVersionRange, _Out_ PULONGLONG pullMinVersion,
- _Out_ PULONGLONG pullMaxVersion) = 0;
-};
-#endif
-
-// Class declarations
-//
-EXTERN_C const CLSID CLSID_SetupConfiguration;
-
-#ifdef __cplusplus
-/// <summary>
-/// This class implements <see cref="ISetupConfiguration"/>, <see
-/// cref="ISetupConfiguration2"/>, and <see cref="ISetupHelper"/>.
-/// </summary>
-class DECLSPEC_UUID("177F0C4A-1CD3-4DE7-A32C-71DBBB9FA36D") SetupConfiguration;
-#endif
-
-// Function declarations
-//
-/// <summary>
-/// Gets an <see cref="ISetupConfiguration"/> that provides information about
-/// product instances installed on the machine.
-/// </summary>
-/// <param name="ppConfiguration">The <see cref="ISetupConfiguration"/> that
-/// provides information about product instances installed on the
-/// machine.</param>
-/// <param name="pReserved">Reserved for future use.</param>
-/// <returns>Standard HRESULT indicating success or failure.</returns>
-STDMETHODIMP GetSetupConfiguration(_Out_ ISetupConfiguration **ppConfiguration,
- _Reserved_ LPVOID pReserved);
-
-#ifdef __cplusplus
-}
-#endif
-
-#ifdef __clang__
-#pragma clang diagnostic pop
-#endif
diff --git a/clang/lib/Driver/ToolChains/MinGW.cpp b/clang/lib/Driver/ToolChains/MinGW.cpp
index 0501f9737404..c4b4f8e9b89b 100644
--- a/clang/lib/Driver/ToolChains/MinGW.cpp
+++ b/clang/lib/Driver/ToolChains/MinGW.cpp
@@ -86,7 +86,9 @@ void tools::MinGW::Linker::AddLibGCC(const ArgList &Args,
CmdArgs.push_back("-lmoldname");
CmdArgs.push_back("-lmingwex");
for (auto Lib : Args.getAllArgValues(options::OPT_l))
- if (StringRef(Lib).startswith("msvcr") || StringRef(Lib).startswith("ucrt"))
+ if (StringRef(Lib).startswith("msvcr") ||
+ StringRef(Lib).startswith("ucrt") ||
+ StringRef(Lib).startswith("crtdll"))
return;
CmdArgs.push_back("-lmsvcrt");
}
@@ -216,6 +218,11 @@ void tools::MinGW::Linker::ConstructJob(Compilation &C, const JobAction &JA,
AddLinkerInputs(TC, Inputs, Args, CmdArgs, JA);
+ if (C.getDriver().IsFlangMode()) {
+ addFortranRuntimeLibraryPath(TC, Args, CmdArgs);
+ addFortranRuntimeLibs(TC, CmdArgs);
+ }
+
// TODO: Add profile stuff here
if (TC.ShouldLinkCXXStdlib(Args)) {
@@ -476,8 +483,8 @@ bool toolchains::MinGW::IsUnwindTablesDefault(const ArgList &Args) const {
if (ExceptionArg &&
ExceptionArg->getOption().matches(options::OPT_fseh_exceptions))
return true;
- return getArch() == llvm::Triple::x86_64 ||
- getArch() == llvm::Triple::aarch64;
+ return getArch() == llvm::Triple::x86_64 || getArch() == llvm::Triple::arm ||
+ getArch() == llvm::Triple::thumb || getArch() == llvm::Triple::aarch64;
}
bool toolchains::MinGW::isPICDefault() const {
@@ -493,7 +500,8 @@ bool toolchains::MinGW::isPICDefaultForced() const { return true; }
llvm::ExceptionHandling
toolchains::MinGW::GetExceptionModel(const ArgList &Args) const {
- if (getArch() == llvm::Triple::x86_64 || getArch() == llvm::Triple::aarch64)
+ if (getArch() == llvm::Triple::x86_64 || getArch() == llvm::Triple::aarch64 ||
+ getArch() == llvm::Triple::arm || getArch() == llvm::Triple::thumb)
return llvm::ExceptionHandling::WinEH;
return llvm::ExceptionHandling::DwarfCFI;
}
diff --git a/clang/lib/Driver/ToolChains/MinGW.h b/clang/lib/Driver/ToolChains/MinGW.h
index c3de19b97724..c9553b4f4652 100644
--- a/clang/lib/Driver/ToolChains/MinGW.h
+++ b/clang/lib/Driver/ToolChains/MinGW.h
@@ -90,6 +90,8 @@ public:
void printVerboseInfo(raw_ostream &OS) const override;
+ unsigned GetDefaultDwarfVersion() const override { return 4; }
+
protected:
Tool *getTool(Action::ActionClass AC) const override;
Tool *buildLinker() const override;
diff --git a/clang/lib/Driver/ToolChains/Minix.cpp b/clang/lib/Driver/ToolChains/Minix.cpp
index 5bceb9aba3e9..4b8670a79012 100644
--- a/clang/lib/Driver/ToolChains/Minix.cpp
+++ b/clang/lib/Driver/ToolChains/Minix.cpp
@@ -56,7 +56,8 @@ void tools::minix::Linker::ConstructJob(Compilation &C, const JobAction &JA,
assert(Output.isNothing() && "Invalid output.");
}
- if (!Args.hasArg(options::OPT_nostdlib, options::OPT_nostartfiles)) {
+ if (!Args.hasArg(options::OPT_nostdlib, options::OPT_nostartfiles,
+ options::OPT_r)) {
CmdArgs.push_back(Args.MakeArgString(getToolChain().GetFilePath("crt1.o")));
CmdArgs.push_back(Args.MakeArgString(getToolChain().GetFilePath("crti.o")));
CmdArgs.push_back(
@@ -71,7 +72,8 @@ void tools::minix::Linker::ConstructJob(Compilation &C, const JobAction &JA,
getToolChain().addProfileRTLibs(Args, CmdArgs);
- if (!Args.hasArg(options::OPT_nostdlib, options::OPT_nodefaultlibs)) {
+ if (!Args.hasArg(options::OPT_nostdlib, options::OPT_nodefaultlibs,
+ options::OPT_r)) {
if (D.CCCIsCXX()) {
if (getToolChain().ShouldLinkCXXStdlib(Args))
getToolChain().AddCXXStdlibLibArgs(Args, CmdArgs);
@@ -79,7 +81,8 @@ void tools::minix::Linker::ConstructJob(Compilation &C, const JobAction &JA,
}
}
- if (!Args.hasArg(options::OPT_nostdlib, options::OPT_nostartfiles)) {
+ if (!Args.hasArg(options::OPT_nostdlib, options::OPT_nostartfiles,
+ options::OPT_r)) {
if (Args.hasArg(options::OPT_pthread))
CmdArgs.push_back("-lpthread");
CmdArgs.push_back("-lc");
diff --git a/clang/lib/Driver/ToolChains/NetBSD.cpp b/clang/lib/Driver/ToolChains/NetBSD.cpp
index 37b1fc5215ff..d1eda14a51f0 100644
--- a/clang/lib/Driver/ToolChains/NetBSD.cpp
+++ b/clang/lib/Driver/ToolChains/NetBSD.cpp
@@ -236,7 +236,8 @@ void netbsd::Linker::ConstructJob(Compilation &C, const JobAction &JA,
assert(Output.isNothing() && "Invalid output.");
}
- if (!Args.hasArg(options::OPT_nostdlib, options::OPT_nostartfiles)) {
+ if (!Args.hasArg(options::OPT_nostdlib, options::OPT_nostartfiles,
+ options::OPT_r)) {
if (!Args.hasArg(options::OPT_shared)) {
CmdArgs.push_back(
Args.MakeArgString(ToolChain.GetFilePath("crt0.o")));
@@ -294,7 +295,8 @@ void netbsd::Linker::ConstructJob(Compilation &C, const JobAction &JA,
}
}
- if (!Args.hasArg(options::OPT_nostdlib, options::OPT_nodefaultlibs)) {
+ if (!Args.hasArg(options::OPT_nostdlib, options::OPT_nodefaultlibs,
+ options::OPT_r)) {
// Use the static OpenMP runtime with -static-openmp
bool StaticOpenMP = Args.hasArg(options::OPT_static_openmp) &&
!Args.hasArg(options::OPT_static);
@@ -330,7 +332,8 @@ void netbsd::Linker::ConstructJob(Compilation &C, const JobAction &JA,
}
}
- if (!Args.hasArg(options::OPT_nostdlib, options::OPT_nostartfiles)) {
+ if (!Args.hasArg(options::OPT_nostdlib, options::OPT_nostartfiles,
+ options::OPT_r)) {
if (Args.hasArg(options::OPT_shared) || Args.hasArg(options::OPT_pie))
CmdArgs.push_back(
Args.MakeArgString(ToolChain.GetFilePath("crtendS.o")));
diff --git a/clang/lib/Driver/ToolChains/OpenBSD.cpp b/clang/lib/Driver/ToolChains/OpenBSD.cpp
index 96abac57764f..54cf3cc89caf 100644
--- a/clang/lib/Driver/ToolChains/OpenBSD.cpp
+++ b/clang/lib/Driver/ToolChains/OpenBSD.cpp
@@ -17,6 +17,7 @@
#include "clang/Driver/SanitizerArgs.h"
#include "llvm/Option/ArgList.h"
#include "llvm/Support/Path.h"
+#include "llvm/Support/VirtualFileSystem.h"
using namespace clang::driver;
using namespace clang::driver::tools;
@@ -113,6 +114,7 @@ void openbsd::Linker::ConstructJob(Compilation &C, const JobAction &JA,
const toolchains::OpenBSD &ToolChain =
static_cast<const toolchains::OpenBSD &>(getToolChain());
const Driver &D = ToolChain.getDriver();
+ const llvm::Triple::ArchType Arch = ToolChain.getArch();
ArgStringList CmdArgs;
// Silence warning for "clang -g foo.o -o foo"
@@ -123,9 +125,12 @@ void openbsd::Linker::ConstructJob(Compilation &C, const JobAction &JA,
// handled somewhere else.
Args.ClaimAllArgs(options::OPT_w);
- if (ToolChain.getArch() == llvm::Triple::mips64)
+ if (!D.SysRoot.empty())
+ CmdArgs.push_back(Args.MakeArgString("--sysroot=" + D.SysRoot));
+
+ if (Arch == llvm::Triple::mips64)
CmdArgs.push_back("-EB");
- else if (ToolChain.getArch() == llvm::Triple::mips64el)
+ else if (Arch == llvm::Triple::mips64el)
CmdArgs.push_back("-EL");
if (!Args.hasArg(options::OPT_nostdlib, options::OPT_shared)) {
@@ -153,6 +158,9 @@ void openbsd::Linker::ConstructJob(Compilation &C, const JobAction &JA,
if (Args.hasArg(options::OPT_nopie) || Args.hasArg(options::OPT_pg))
CmdArgs.push_back("-nopie");
+ if (Arch == llvm::Triple::riscv64)
+ CmdArgs.push_back("-X");
+
if (Output.isFilename()) {
CmdArgs.push_back("-o");
CmdArgs.push_back(Output.getFilename());
@@ -160,7 +168,8 @@ void openbsd::Linker::ConstructJob(Compilation &C, const JobAction &JA,
assert(Output.isNothing() && "Invalid output.");
}
- if (!Args.hasArg(options::OPT_nostdlib, options::OPT_nostartfiles)) {
+ if (!Args.hasArg(options::OPT_nostdlib, options::OPT_nostartfiles,
+ options::OPT_r)) {
const char *crt0 = nullptr;
const char *crtbegin = nullptr;
if (!Args.hasArg(options::OPT_shared)) {
@@ -191,7 +200,8 @@ void openbsd::Linker::ConstructJob(Compilation &C, const JobAction &JA,
bool NeedsXRayDeps = addXRayRuntime(ToolChain, Args, CmdArgs);
AddLinkerInputs(ToolChain, Inputs, Args, CmdArgs, JA);
- if (!Args.hasArg(options::OPT_nostdlib, options::OPT_nodefaultlibs)) {
+ if (!Args.hasArg(options::OPT_nostdlib, options::OPT_nodefaultlibs,
+ options::OPT_r)) {
// Use the static OpenMP runtime with -static-openmp
bool StaticOpenMP = Args.hasArg(options::OPT_static_openmp) &&
!Args.hasArg(options::OPT_static);
@@ -234,7 +244,8 @@ void openbsd::Linker::ConstructJob(Compilation &C, const JobAction &JA,
CmdArgs.push_back("-lcompiler_rt");
}
- if (!Args.hasArg(options::OPT_nostdlib, options::OPT_nostartfiles)) {
+ if (!Args.hasArg(options::OPT_nostdlib, options::OPT_nostartfiles,
+ options::OPT_r)) {
const char *crtend = nullptr;
if (!Args.hasArg(options::OPT_shared))
crtend = "crtend.o";
@@ -324,12 +335,21 @@ void OpenBSD::AddCXXStdlibLibArgs(const ArgList &Args,
CmdArgs.push_back(Profiling ? "-lpthread_p" : "-lpthread");
}
-std::string OpenBSD::getCompilerRT(const ArgList &Args,
- StringRef Component,
+std::string OpenBSD::getCompilerRT(const ArgList &Args, StringRef Component,
FileType Type) const {
- SmallString<128> Path(getDriver().SysRoot);
- llvm::sys::path::append(Path, "/usr/lib/libcompiler_rt.a");
- return std::string(Path.str());
+ if (Component == "builtins") {
+ SmallString<128> Path(getDriver().SysRoot);
+ llvm::sys::path::append(Path, "/usr/lib/libcompiler_rt.a");
+ return std::string(Path.str());
+ }
+ SmallString<128> P(getDriver().ResourceDir);
+ std::string CRTBasename =
+ buildCompilerRTBasename(Args, Component, Type, /*AddArch=*/false);
+ llvm::sys::path::append(P, "lib", CRTBasename);
+ // Checks if this is the base system case which uses a different location.
+ if (getVFS().exists(P))
+ return std::string(P.str());
+ return ToolChain::getCompilerRT(Args, Component, Type);
}
Tool *OpenBSD::buildAssembler() const {
@@ -339,3 +359,12 @@ Tool *OpenBSD::buildAssembler() const {
Tool *OpenBSD::buildLinker() const { return new tools::openbsd::Linker(*this); }
bool OpenBSD::HasNativeLLVMSupport() const { return true; }
+
+bool OpenBSD::IsUnwindTablesDefault(const ArgList &Args) const {
+ switch (getArch()) {
+ case llvm::Triple::arm:
+ return false;
+ default:
+ return true;
+ }
+}
diff --git a/clang/lib/Driver/ToolChains/OpenBSD.h b/clang/lib/Driver/ToolChains/OpenBSD.h
index 95c10cc62316..2d4c4e34520b 100644
--- a/clang/lib/Driver/ToolChains/OpenBSD.h
+++ b/clang/lib/Driver/ToolChains/OpenBSD.h
@@ -82,6 +82,8 @@ public:
std::string getCompilerRT(const llvm::opt::ArgList &Args, StringRef Component,
FileType Type = ToolChain::FT_Static) const override;
+ bool IsUnwindTablesDefault(const llvm::opt::ArgList &Args) const override;
+
LangOptions::StackProtectorMode
GetDefaultStackProtectorLevel(bool KernelOrKext) const override {
return LangOptions::SSPStrong;
diff --git a/clang/lib/Driver/ToolChains/PPCLinux.cpp b/clang/lib/Driver/ToolChains/PPCLinux.cpp
index e480d8bd8703..2fea262fd109 100644
--- a/clang/lib/Driver/ToolChains/PPCLinux.cpp
+++ b/clang/lib/Driver/ToolChains/PPCLinux.cpp
@@ -76,9 +76,11 @@ bool PPCLinuxToolChain::SupportIEEEFloat128(
if (Args.hasArg(options::OPT_nostdlib, options::OPT_nostdlibxx))
return true;
+ CXXStdlibType StdLib = ToolChain::GetCXXStdlibType(Args);
bool HasUnsupportedCXXLib =
- ToolChain::GetCXXStdlibType(Args) == CST_Libcxx &&
- GCCInstallation.getVersion().isOlderThan(12, 1, 0);
+ StdLib == CST_Libcxx ||
+ (StdLib == CST_Libstdcxx &&
+ GCCInstallation.getVersion().isOlderThan(12, 1, 0));
return GlibcSupportsFloat128(Linux::getDynamicLinker(Args)) &&
!(D.CCCIsCXX() && HasUnsupportedCXXLib);
diff --git a/clang/lib/Driver/ToolChains/PS4CPU.cpp b/clang/lib/Driver/ToolChains/PS4CPU.cpp
index bcf9147833dd..35a83d79abfd 100644
--- a/clang/lib/Driver/ToolChains/PS4CPU.cpp
+++ b/clang/lib/Driver/ToolChains/PS4CPU.cpp
@@ -7,7 +7,6 @@
//===----------------------------------------------------------------------===//
#include "PS4CPU.h"
-#include "FreeBSD.h"
#include "CommonArgs.h"
#include "clang/Driver/Compilation.h"
#include "clang/Driver/Driver.h"
@@ -23,8 +22,18 @@ using namespace clang::driver;
using namespace clang;
using namespace llvm::opt;
-void tools::PS4cpu::addProfileRTArgs(const ToolChain &TC, const ArgList &Args,
- ArgStringList &CmdArgs) {
+// Helper to paste bits of an option together and return a saved string.
+static const char *makeArgString(const ArgList &Args, const char *Prefix,
+ const char *Base, const char *Suffix) {
+ // Basically "Prefix + Base + Suffix" all converted to Twine then saved.
+ return Args.MakeArgString(Twine(StringRef(Prefix), Base) + Suffix);
+}
+
+void tools::PScpu::addProfileRTArgs(const ToolChain &TC, const ArgList &Args,
+ ArgStringList &CmdArgs) {
+ assert(TC.getTriple().isPS());
+ auto &PSTC = static_cast<const toolchains::PS4PS5Base &>(TC);
+
if ((Args.hasFlag(options::OPT_fprofile_arcs, options::OPT_fno_profile_arcs,
false) ||
Args.hasFlag(options::OPT_fprofile_generate,
@@ -41,14 +50,16 @@ void tools::PS4cpu::addProfileRTArgs(const ToolChain &TC, const ArgList &Args,
options::OPT_fno_profile_generate, false) ||
Args.hasArg(options::OPT_fcreate_profile) ||
Args.hasArg(options::OPT_coverage)))
- CmdArgs.push_back("--dependent-lib=libclang_rt.profile-x86_64.a");
+ CmdArgs.push_back(makeArgString(
+ Args, "--dependent-lib=", PSTC.getProfileRTLibName(), ""));
}
-void tools::PS4cpu::Assemble::ConstructJob(Compilation &C, const JobAction &JA,
+void tools::PScpu::Assembler::ConstructJob(Compilation &C, const JobAction &JA,
const InputInfo &Output,
const InputInfoList &Inputs,
const ArgList &Args,
const char *LinkingOutput) const {
+ auto &TC = static_cast<const toolchains::PS4PS5Base &>(getToolChain());
claimNoWarnArgs(Args);
ArgStringList CmdArgs;
@@ -62,41 +73,57 @@ void tools::PS4cpu::Assemble::ConstructJob(Compilation &C, const JobAction &JA,
assert(Input.isFilename() && "Invalid input.");
CmdArgs.push_back(Input.getFilename());
- const char *Exec =
- Args.MakeArgString(getToolChain().GetProgramPath("orbis-as"));
+ std::string AsName = TC.qualifyPSCmdName("as");
+ const char *Exec = Args.MakeArgString(TC.GetProgramPath(AsName.c_str()));
C.addCommand(std::make_unique<Command>(JA, *this,
ResponseFileSupport::AtFileUTF8(),
Exec, CmdArgs, Inputs, Output));
}
-static void AddPS4SanitizerArgs(const ToolChain &TC, const ArgList &Args,
- ArgStringList &CmdArgs) {
- const SanitizerArgs &SanArgs = TC.getSanitizerArgs(Args);
- if (SanArgs.needsUbsanRt()) {
- CmdArgs.push_back("-lSceDbgUBSanitizer_stub_weak");
- }
- if (SanArgs.needsAsanRt()) {
- CmdArgs.push_back("-lSceDbgAddressSanitizer_stub_weak");
- }
+void tools::PScpu::addSanitizerArgs(const ToolChain &TC, const ArgList &Args,
+ ArgStringList &CmdArgs) {
+ assert(TC.getTriple().isPS());
+ auto &PSTC = static_cast<const toolchains::PS4PS5Base &>(TC);
+ PSTC.addSanitizerArgs(Args, CmdArgs, "--dependent-lib=lib", ".a");
+}
+
+void toolchains::PS4CPU::addSanitizerArgs(const ArgList &Args,
+ ArgStringList &CmdArgs,
+ const char *Prefix,
+ const char *Suffix) const {
+ auto arg = [&](const char *Name) -> const char * {
+ return makeArgString(Args, Prefix, Name, Suffix);
+ };
+ const SanitizerArgs &SanArgs = getSanitizerArgs(Args);
+ if (SanArgs.needsUbsanRt())
+ CmdArgs.push_back(arg("SceDbgUBSanitizer_stub_weak"));
+ if (SanArgs.needsAsanRt())
+ CmdArgs.push_back(arg("SceDbgAddressSanitizer_stub_weak"));
}
-void tools::PS4cpu::addSanitizerArgs(const ToolChain &TC, const ArgList &Args,
- ArgStringList &CmdArgs) {
- const SanitizerArgs &SanArgs = TC.getSanitizerArgs(Args);
+void toolchains::PS5CPU::addSanitizerArgs(const ArgList &Args,
+ ArgStringList &CmdArgs,
+ const char *Prefix,
+ const char *Suffix) const {
+ auto arg = [&](const char *Name) -> const char * {
+ return makeArgString(Args, Prefix, Name, Suffix);
+ };
+ const SanitizerArgs &SanArgs = getSanitizerArgs(Args);
if (SanArgs.needsUbsanRt())
- CmdArgs.push_back("--dependent-lib=libSceDbgUBSanitizer_stub_weak.a");
+ CmdArgs.push_back(arg("SceUBSanitizer_nosubmission_stub_weak"));
if (SanArgs.needsAsanRt())
- CmdArgs.push_back("--dependent-lib=libSceDbgAddressSanitizer_stub_weak.a");
+ CmdArgs.push_back(arg("SceAddressSanitizer_nosubmission_stub_weak"));
+ if (SanArgs.needsTsanRt())
+ CmdArgs.push_back(arg("SceThreadSanitizer_nosubmission_stub_weak"));
}
-void tools::PS4cpu::Link::ConstructJob(Compilation &C, const JobAction &JA,
- const InputInfo &Output,
- const InputInfoList &Inputs,
- const ArgList &Args,
- const char *LinkingOutput) const {
- const toolchains::FreeBSD &ToolChain =
- static_cast<const toolchains::FreeBSD &>(getToolChain());
- const Driver &D = ToolChain.getDriver();
+void tools::PScpu::Linker::ConstructJob(Compilation &C, const JobAction &JA,
+ const InputInfo &Output,
+ const InputInfoList &Inputs,
+ const ArgList &Args,
+ const char *LinkingOutput) const {
+ auto &TC = static_cast<const toolchains::PS4PS5Base &>(getToolChain());
+ const Driver &D = TC.getDriver();
ArgStringList CmdArgs;
// Silence warning for "clang -g foo.o -o foo"
@@ -116,7 +143,7 @@ void tools::PS4cpu::Link::ConstructJob(Compilation &C, const JobAction &JA,
if (Args.hasArg(options::OPT_rdynamic))
CmdArgs.push_back("-export-dynamic");
if (Args.hasArg(options::OPT_shared))
- CmdArgs.push_back("--oformat=so");
+ CmdArgs.push_back("--shared");
if (Output.isFilename()) {
CmdArgs.push_back("-o");
@@ -125,8 +152,8 @@ void tools::PS4cpu::Link::ConstructJob(Compilation &C, const JobAction &JA,
assert(Output.isNothing() && "Invalid output.");
}
- if(!Args.hasArg(options::OPT_nostdlib, options::OPT_nodefaultlibs))
- AddPS4SanitizerArgs(ToolChain, Args, CmdArgs);
+ if (!Args.hasArg(options::OPT_nostdlib, options::OPT_nodefaultlibs))
+ TC.addSanitizerArgs(Args, CmdArgs, "-l", "");
Args.AddAllArgs(CmdArgs, options::OPT_L);
Args.AddAllArgs(CmdArgs, options::OPT_T_Group);
@@ -138,7 +165,7 @@ void tools::PS4cpu::Link::ConstructJob(Compilation &C, const JobAction &JA,
if (Args.hasArg(options::OPT_Z_Xlinker__no_demangle))
CmdArgs.push_back("--no-demangle");
- AddLinkerInputs(ToolChain, Inputs, Args, CmdArgs, JA);
+ AddLinkerInputs(TC, Inputs, Args, CmdArgs, JA);
if (Args.hasArg(options::OPT_pthread)) {
CmdArgs.push_back("-lpthread");
@@ -146,89 +173,92 @@ void tools::PS4cpu::Link::ConstructJob(Compilation &C, const JobAction &JA,
if (Args.hasArg(options::OPT_fuse_ld_EQ)) {
D.Diag(diag::err_drv_unsupported_opt_for_target)
- << "-fuse-ld" << getToolChain().getTriple().str();
+ << "-fuse-ld" << TC.getTriple().str();
}
- const char *Exec =
- Args.MakeArgString(ToolChain.GetProgramPath("orbis-ld"));
+ std::string LdName = TC.qualifyPSCmdName(TC.getLinkerBaseName());
+ const char *Exec = Args.MakeArgString(TC.GetProgramPath(LdName.c_str()));
C.addCommand(std::make_unique<Command>(JA, *this,
ResponseFileSupport::AtFileUTF8(),
Exec, CmdArgs, Inputs, Output));
}
-toolchains::PS4CPU::PS4CPU(const Driver &D, const llvm::Triple &Triple,
- const ArgList &Args)
+toolchains::PS4PS5Base::PS4PS5Base(const Driver &D, const llvm::Triple &Triple,
+ const ArgList &Args, StringRef Platform,
+ const char *EnvVar)
: Generic_ELF(D, Triple, Args) {
if (Args.hasArg(clang::driver::options::OPT_static))
- D.Diag(clang::diag::err_drv_unsupported_opt_for_target) << "-static"
- << "PS4";
+ D.Diag(clang::diag::err_drv_unsupported_opt_for_target)
+ << "-static" << Platform;
- // Determine where to find the PS4 libraries. We use SCE_ORBIS_SDK_DIR
+ // Determine where to find the PS4/PS5 libraries. We use the EnvVar
// if it exists; otherwise use the driver's installation path, which
// should be <SDK_DIR>/host_tools/bin.
- SmallString<512> PS4SDKDir;
- if (const char *EnvValue = getenv("SCE_ORBIS_SDK_DIR")) {
+ SmallString<512> SDKDir;
+ if (const char *EnvValue = getenv(EnvVar)) {
if (!llvm::sys::fs::exists(EnvValue))
- getDriver().Diag(clang::diag::warn_drv_ps4_sdk_dir) << EnvValue;
- PS4SDKDir = EnvValue;
+ D.Diag(clang::diag::warn_drv_ps_sdk_dir) << EnvVar << EnvValue;
+ SDKDir = EnvValue;
} else {
- PS4SDKDir = getDriver().Dir;
- llvm::sys::path::append(PS4SDKDir, "/../../");
+ SDKDir = D.Dir;
+ llvm::sys::path::append(SDKDir, "/../../");
}
- // By default, the driver won't report a warning if it can't find
- // PS4's include or lib directories. This behavior could be changed if
+ // By default, the driver won't report a warning if it can't find the
+ // SDK include or lib directories. This behavior could be changed if
// -Weverything or -Winvalid-or-nonexistent-directory options are passed.
// If -isysroot was passed, use that as the SDK base path.
std::string PrefixDir;
if (const Arg *A = Args.getLastArg(options::OPT_isysroot)) {
PrefixDir = A->getValue();
if (!llvm::sys::fs::exists(PrefixDir))
- getDriver().Diag(clang::diag::warn_missing_sysroot) << PrefixDir;
+ D.Diag(clang::diag::warn_missing_sysroot) << PrefixDir;
} else
- PrefixDir = std::string(PS4SDKDir.str());
+ PrefixDir = std::string(SDKDir.str());
- SmallString<512> PS4SDKIncludeDir(PrefixDir);
- llvm::sys::path::append(PS4SDKIncludeDir, "target/include");
+ SmallString<512> SDKIncludeDir(PrefixDir);
+ llvm::sys::path::append(SDKIncludeDir, "target/include");
if (!Args.hasArg(options::OPT_nostdinc) &&
!Args.hasArg(options::OPT_nostdlibinc) &&
!Args.hasArg(options::OPT_isysroot) &&
!Args.hasArg(options::OPT__sysroot_EQ) &&
- !llvm::sys::fs::exists(PS4SDKIncludeDir)) {
- getDriver().Diag(clang::diag::warn_drv_unable_to_find_directory_expected)
- << "PS4 system headers" << PS4SDKIncludeDir;
+ !llvm::sys::fs::exists(SDKIncludeDir)) {
+ D.Diag(clang::diag::warn_drv_unable_to_find_directory_expected)
+ << Twine(Platform, " system headers").str() << SDKIncludeDir;
}
- SmallString<512> PS4SDKLibDir(PS4SDKDir);
- llvm::sys::path::append(PS4SDKLibDir, "target/lib");
+ SmallString<512> SDKLibDir(SDKDir);
+ llvm::sys::path::append(SDKLibDir, "target/lib");
if (!Args.hasArg(options::OPT_nostdlib) &&
!Args.hasArg(options::OPT_nodefaultlibs) &&
!Args.hasArg(options::OPT__sysroot_EQ) && !Args.hasArg(options::OPT_E) &&
!Args.hasArg(options::OPT_c) && !Args.hasArg(options::OPT_S) &&
!Args.hasArg(options::OPT_emit_ast) &&
- !llvm::sys::fs::exists(PS4SDKLibDir)) {
- getDriver().Diag(clang::diag::warn_drv_unable_to_find_directory_expected)
- << "PS4 system libraries" << PS4SDKLibDir;
+ !llvm::sys::fs::exists(SDKLibDir)) {
+ D.Diag(clang::diag::warn_drv_unable_to_find_directory_expected)
+ << Twine(Platform, " system libraries").str() << SDKLibDir;
return;
}
- getFilePaths().push_back(std::string(PS4SDKLibDir.str()));
+ getFilePaths().push_back(std::string(SDKLibDir.str()));
}
Tool *toolchains::PS4CPU::buildAssembler() const {
- return new tools::PS4cpu::Assemble(*this);
+ return new tools::PScpu::Assembler(*this);
}
-Tool *toolchains::PS4CPU::buildLinker() const {
- return new tools::PS4cpu::Link(*this);
+Tool *toolchains::PS5CPU::buildAssembler() const {
+ // PS5 does not support an external assembler.
+ getDriver().Diag(clang::diag::err_no_external_assembler);
+ return nullptr;
}
-bool toolchains::PS4CPU::isPICDefault() const { return true; }
-
-bool toolchains::PS4CPU::HasNativeLLVMSupport() const { return true; }
+Tool *toolchains::PS4PS5Base::buildLinker() const {
+ return new tools::PScpu::Linker(*this);
+}
-SanitizerMask toolchains::PS4CPU::getSupportedSanitizers() const {
+SanitizerMask toolchains::PS4PS5Base::getSupportedSanitizers() const {
SanitizerMask Res = ToolChain::getSupportedSanitizers();
Res |= SanitizerKind::Address;
Res |= SanitizerKind::PointerCompare;
@@ -237,10 +267,16 @@ SanitizerMask toolchains::PS4CPU::getSupportedSanitizers() const {
return Res;
}
-void toolchains::PS4CPU::addClangTargetOptions(
+SanitizerMask toolchains::PS5CPU::getSupportedSanitizers() const {
+ SanitizerMask Res = PS4PS5Base::getSupportedSanitizers();
+ Res |= SanitizerKind::Thread;
+ return Res;
+}
+
+void toolchains::PS4PS5Base::addClangTargetOptions(
const ArgList &DriverArgs, ArgStringList &CC1Args,
Action::OffloadKind DeviceOffloadingKind) const {
- // PS4 does not use init arrays.
+ // PS4/PS5 do not use init arrays.
if (DriverArgs.hasArg(options::OPT_fuse_init_array)) {
Arg *A = DriverArgs.getLastArg(options::OPT_fuse_init_array);
getDriver().Diag(clang::diag::err_drv_unsupported_opt_for_target)
@@ -281,3 +317,13 @@ void toolchains::PS4CPU::addClangTargetOptions(
CC1Args.push_back("-fvisibility-externs-nodllstorageclass=default");
}
}
+
+// PS4 toolchain.
+toolchains::PS4CPU::PS4CPU(const Driver &D, const llvm::Triple &Triple,
+ const llvm::opt::ArgList &Args)
+ : PS4PS5Base(D, Triple, Args, "PS4", "SCE_ORBIS_SDK_DIR") {}
+
+// PS5 toolchain.
+toolchains::PS5CPU::PS5CPU(const Driver &D, const llvm::Triple &Triple,
+ const llvm::opt::ArgList &Args)
+ : PS4PS5Base(D, Triple, Args, "PS5", "SCE_PROSPERO_SDK_DIR") {}
diff --git a/clang/lib/Driver/ToolChains/PS4CPU.h b/clang/lib/Driver/ToolChains/PS4CPU.h
index 4bedabaf267c..954e7d8d8d68 100644
--- a/clang/lib/Driver/ToolChains/PS4CPU.h
+++ b/clang/lib/Driver/ToolChains/PS4CPU.h
@@ -18,7 +18,8 @@ namespace clang {
namespace driver {
namespace tools {
-namespace PS4cpu {
+namespace PScpu {
+// Functions/classes in this namespace support both PS4 and PS5.
void addProfileRTArgs(const ToolChain &TC, const llvm::opt::ArgList &Args,
llvm::opt::ArgStringList &CmdArgs);
@@ -26,75 +27,69 @@ void addProfileRTArgs(const ToolChain &TC, const llvm::opt::ArgList &Args,
void addSanitizerArgs(const ToolChain &TC, const llvm::opt::ArgList &Args,
llvm::opt::ArgStringList &CmdArgs);
-class LLVM_LIBRARY_VISIBILITY Assemble : public Tool {
+class LLVM_LIBRARY_VISIBILITY Assembler : public Tool {
public:
- Assemble(const ToolChain &TC) : Tool("PS4cpu::Assemble", "assembler", TC) {}
+ Assembler(const ToolChain &TC) : Tool("PScpu::Assembler", "assembler", TC) {}
bool hasIntegratedCPP() const override { return false; }
void ConstructJob(Compilation &C, const JobAction &JA,
- const InputInfo &Output,
- const InputInfoList &Inputs,
+ const InputInfo &Output, const InputInfoList &Inputs,
const llvm::opt::ArgList &TCArgs,
const char *LinkingOutput) const override;
};
-class LLVM_LIBRARY_VISIBILITY Link : public Tool {
+class LLVM_LIBRARY_VISIBILITY Linker : public Tool {
public:
- Link(const ToolChain &TC) : Tool("PS4cpu::Link", "linker", TC) {}
+ Linker(const ToolChain &TC) : Tool("PScpu::Linker", "linker", TC) {}
bool hasIntegratedCPP() const override { return false; }
bool isLinkJob() const override { return true; }
void ConstructJob(Compilation &C, const JobAction &JA,
- const InputInfo &Output,
- const InputInfoList &Inputs,
+ const InputInfo &Output, const InputInfoList &Inputs,
const llvm::opt::ArgList &TCArgs,
const char *LinkingOutput) const override;
};
-} // end namespace PS4cpu
+} // namespace PScpu
} // namespace tools
namespace toolchains {
-class LLVM_LIBRARY_VISIBILITY PS4CPU : public Generic_ELF {
+// Common Toolchain base class for PS4 and PS5.
+class LLVM_LIBRARY_VISIBILITY PS4PS5Base : public Generic_ELF {
public:
- PS4CPU(const Driver &D, const llvm::Triple &Triple,
- const llvm::opt::ArgList &Args);
+ PS4PS5Base(const Driver &D, const llvm::Triple &Triple,
+ const llvm::opt::ArgList &Args, StringRef Platform,
+ const char *EnvVar);
// No support for finding a C++ standard library yet.
- void addLibCxxIncludePaths(
- const llvm::opt::ArgList &DriverArgs,
- llvm::opt::ArgStringList &CC1Args) const override {}
- void addLibStdCxxIncludePaths(
- const llvm::opt::ArgList &DriverArgs,
- llvm::opt::ArgStringList &CC1Args) const override {}
+ void addLibCxxIncludePaths(const llvm::opt::ArgList &DriverArgs,
+ llvm::opt::ArgStringList &CC1Args) const override {
+ }
+ void
+ addLibStdCxxIncludePaths(const llvm::opt::ArgList &DriverArgs,
+ llvm::opt::ArgStringList &CC1Args) const override {}
bool IsMathErrnoDefault() const override { return false; }
bool IsObjCNonFragileABIDefault() const override { return true; }
- bool HasNativeLLVMSupport() const override;
- bool isPICDefault() const override;
+ bool HasNativeLLVMSupport() const override { return true; }
+ bool isPICDefault() const override { return true; }
LangOptions::StackProtectorMode
GetDefaultStackProtectorLevel(bool KernelOrKext) const override {
return LangOptions::SSPStrong;
}
- unsigned GetDefaultDwarfVersion() const override { return 4; }
llvm::DebuggerKind getDefaultDebuggerTuning() const override {
return llvm::DebuggerKind::SCE;
}
SanitizerMask getSupportedSanitizers() const override;
- // PS4 toolchain uses legacy thin LTO API, which is not
- // capable of unit splitting.
- bool canSplitThinLTOUnit() const override { return false; }
-
void addClangTargetOptions(
- const llvm::opt::ArgList &DriverArgs,
- llvm::opt::ArgStringList &CC1Args,
- Action::OffloadKind DeviceOffloadingKind) const override;
+ const llvm::opt::ArgList &DriverArgs, llvm::opt::ArgStringList &CC1Args,
+ Action::OffloadKind DeviceOffloadingKind) const override;
llvm::DenormalMode getDefaultDenormalModeForType(
const llvm::opt::ArgList &DriverArgs, const JobAction &JA,
@@ -105,11 +100,71 @@ public:
bool useRelaxRelocations() const override { return true; }
+ // Helper methods for PS4/PS5.
+ virtual const char *getLinkerBaseName() const = 0;
+ virtual std::string qualifyPSCmdName(StringRef CmdName) const = 0;
+ virtual void addSanitizerArgs(const llvm::opt::ArgList &Args,
+ llvm::opt::ArgStringList &CmdArgs,
+ const char *Prefix,
+ const char *Suffix) const = 0;
+ virtual const char *getProfileRTLibName() const = 0;
+
protected:
- Tool *buildAssembler() const override;
Tool *buildLinker() const override;
};
+// PS4-specific Toolchain class.
+class LLVM_LIBRARY_VISIBILITY PS4CPU : public PS4PS5Base {
+public:
+ PS4CPU(const Driver &D, const llvm::Triple &Triple,
+ const llvm::opt::ArgList &Args);
+
+ unsigned GetDefaultDwarfVersion() const override { return 4; }
+
+ // PS4 toolchain uses legacy thin LTO API, which is not
+ // capable of unit splitting.
+ bool canSplitThinLTOUnit() const override { return false; }
+
+ const char *getLinkerBaseName() const override { return "ld"; }
+ std::string qualifyPSCmdName(StringRef CmdName) const override {
+ return Twine("orbis-", CmdName).str();
+ }
+ void addSanitizerArgs(const llvm::opt::ArgList &Args,
+ llvm::opt::ArgStringList &CmdArgs, const char *Prefix,
+ const char *Suffix) const override;
+ const char *getProfileRTLibName() const override {
+ return "libclang_rt.profile-x86_64.a";
+ }
+
+protected:
+ Tool *buildAssembler() const override;
+};
+
+// PS5-specific Toolchain class.
+class LLVM_LIBRARY_VISIBILITY PS5CPU : public PS4PS5Base {
+public:
+ PS5CPU(const Driver &D, const llvm::Triple &Triple,
+ const llvm::opt::ArgList &Args);
+
+ unsigned GetDefaultDwarfVersion() const override { return 5; }
+
+ SanitizerMask getSupportedSanitizers() const override;
+
+ const char *getLinkerBaseName() const override { return "lld"; }
+ std::string qualifyPSCmdName(StringRef CmdName) const override {
+ return Twine("prospero-", CmdName).str();
+ }
+ void addSanitizerArgs(const llvm::opt::ArgList &Args,
+ llvm::opt::ArgStringList &CmdArgs, const char *Prefix,
+ const char *Suffix) const override;
+ const char *getProfileRTLibName() const override {
+ return "libclang_rt.profile-x86_64_nosubmission.a";
+ }
+
+protected:
+ Tool *buildAssembler() const override;
+};
+
} // end namespace toolchains
} // end namespace driver
} // end namespace clang
diff --git a/clang/lib/Driver/ToolChains/RISCVToolchain.cpp b/clang/lib/Driver/ToolChains/RISCVToolchain.cpp
index 714325a2db39..a048765bc6d3 100644
--- a/clang/lib/Driver/ToolChains/RISCVToolchain.cpp
+++ b/clang/lib/Driver/ToolChains/RISCVToolchain.cpp
@@ -98,6 +98,12 @@ void RISCVToolChain::AddClangSystemIncludeArgs(const ArgList &DriverArgs,
if (DriverArgs.hasArg(options::OPT_nostdinc))
return;
+ if (!DriverArgs.hasArg(options::OPT_nobuiltininc)) {
+ SmallString<128> Dir(getDriver().ResourceDir);
+ llvm::sys::path::append(Dir, "include");
+ addSystemInclude(DriverArgs, CC1Args, Dir.str());
+ }
+
if (!DriverArgs.hasArg(options::OPT_nostdlibinc)) {
SmallString<128> Dir(computeSysRoot());
llvm::sys::path::append(Dir, "include");
@@ -157,6 +163,7 @@ void RISCV::Linker::ConstructJob(Compilation &C, const JobAction &JA,
} else {
CmdArgs.push_back("elf32lriscv");
}
+ CmdArgs.push_back("-X");
std::string Linker = getToolChain().GetLinkerPath();
diff --git a/clang/lib/Driver/ToolChains/RISCVToolchain.h b/clang/lib/Driver/ToolChains/RISCVToolchain.h
index 62099bee0404..46b94bdb54e0 100644
--- a/clang/lib/Driver/ToolChains/RISCVToolchain.h
+++ b/clang/lib/Driver/ToolChains/RISCVToolchain.h
@@ -22,7 +22,6 @@ public:
const llvm::opt::ArgList &Args);
static bool hasGCCToolchain(const Driver &D, const llvm::opt::ArgList &Args);
- bool IsIntegratedAssemblerDefault() const override { return true; }
void addClangTargetOptions(const llvm::opt::ArgList &DriverArgs,
llvm::opt::ArgStringList &CC1Args,
Action::OffloadKind) const override;
diff --git a/clang/lib/Driver/ToolChains/ROCm.h b/clang/lib/Driver/ToolChains/ROCm.h
index bb482be68260..33baaa887043 100644
--- a/clang/lib/Driver/ToolChains/ROCm.h
+++ b/clang/lib/Driver/ToolChains/ROCm.h
@@ -22,6 +22,26 @@
namespace clang {
namespace driver {
+/// ABI version of device library.
+struct DeviceLibABIVersion {
+ unsigned ABIVersion = 0;
+ DeviceLibABIVersion(unsigned V) : ABIVersion(V) {}
+ static DeviceLibABIVersion fromCodeObjectVersion(unsigned CodeObjectVersion) {
+ if (CodeObjectVersion < 4)
+ CodeObjectVersion = 4;
+ return DeviceLibABIVersion(CodeObjectVersion * 100);
+ }
+ /// Whether ABI version bc file is requested.
+ /// ABIVersion is code object version multiplied by 100. Code object v4
+ /// and below works with ROCm 5.0 and below which does not have
+ /// abi_version_*.bc. Code object v5 requires abi_version_500.bc.
+ bool requiresLibrary() { return ABIVersion >= 500; }
+ std::string toString() {
+ assert(ABIVersion % 100 == 0 && "Not supported");
+ return Twine(ABIVersion / 100).str();
+ }
+};
+
/// A class to find a viable ROCM installation
/// TODO: Generalize to handle libclc.
class RocmInstallationDetector {
@@ -107,6 +127,10 @@ private:
ConditionalLibrary DenormalsAreZero;
ConditionalLibrary CorrectlyRoundedSqrt;
+ // Maps ABI version to library path. The version number is in the format of
+ // three digits as used in the ABI version library name.
+ std::map<unsigned, std::string> ABIVersionMap;
+
// Cache ROCm installation search paths.
SmallVector<Candidate, 4> ROCmSearchDirs;
bool PrintROCmSearchDirs;
@@ -142,7 +166,12 @@ public:
getCommonBitcodeLibs(const llvm::opt::ArgList &DriverArgs,
StringRef LibDeviceFile, bool Wave64, bool DAZ,
bool FiniteOnly, bool UnsafeMathOpt,
- bool FastRelaxedMath, bool CorrectSqrt) const;
+ bool FastRelaxedMath, bool CorrectSqrt,
+ DeviceLibABIVersion ABIVer, bool isOpenMP) const;
+ /// Check file paths of default bitcode libraries common to AMDGPU based
+ /// toolchains. \returns false if there are invalid or missing files.
+ bool checkCommonBitcodeLibs(StringRef GPUArch, StringRef LibDeviceFile,
+ DeviceLibABIVersion ABIVer) const;
/// Check whether we detected a valid HIP runtime.
bool hasHIPRuntime() const { return HasHIPRuntime; }
@@ -214,6 +243,13 @@ public:
return CorrectlyRoundedSqrt.get(Enabled);
}
+ StringRef getABIVersionPath(DeviceLibABIVersion ABIVer) const {
+ auto Loc = ABIVersionMap.find(ABIVer.ABIVersion);
+ if (Loc == ABIVersionMap.end())
+ return StringRef();
+ return Loc->second;
+ }
+
/// Get libdevice file for given architecture
std::string getLibDeviceFile(StringRef Gpu) const {
return LibDeviceMap.lookup(Gpu);
diff --git a/clang/lib/Driver/ToolChains/SPIRV.h b/clang/lib/Driver/ToolChains/SPIRV.h
index a16ae3ca51fa..bb2904f76128 100644
--- a/clang/lib/Driver/ToolChains/SPIRV.h
+++ b/clang/lib/Driver/ToolChains/SPIRV.h
@@ -64,8 +64,9 @@ public:
: ToolChain(D, Triple, Args) {}
bool useIntegratedAs() const override { return true; }
- bool useIntegratedBackend() const override { return false; }
+ bool IsIntegratedBackendDefault() const override { return false; }
+ bool IsNonIntegratedBackendSupported() const override { return true; }
bool IsMathErrnoDefault() const override { return false; }
bool isCrossCompiling() const override { return true; }
bool isPICDefault() const override { return false; }
diff --git a/clang/lib/Driver/ToolChains/Solaris.cpp b/clang/lib/Driver/ToolChains/Solaris.cpp
index 4d1af094f481..c75375ac95f7 100644
--- a/clang/lib/Driver/ToolChains/Solaris.cpp
+++ b/clang/lib/Driver/ToolChains/Solaris.cpp
@@ -14,6 +14,8 @@
#include "clang/Driver/Driver.h"
#include "clang/Driver/DriverDiagnostic.h"
#include "clang/Driver/Options.h"
+#include "clang/Driver/SanitizerArgs.h"
+#include "clang/Driver/ToolChain.h"
#include "llvm/Option/ArgList.h"
#include "llvm/Support/FileSystem.h"
#include "llvm/Support/Path.h"
@@ -82,7 +84,8 @@ void solaris::Linker::ConstructJob(Compilation &C, const JobAction &JA,
assert(Output.isNothing() && "Invalid output.");
}
- if (!Args.hasArg(options::OPT_nostdlib, options::OPT_nostartfiles)) {
+ if (!Args.hasArg(options::OPT_nostdlib, options::OPT_nostartfiles,
+ options::OPT_r)) {
if (!Args.hasArg(options::OPT_shared))
CmdArgs.push_back(
Args.MakeArgString(getToolChain().GetFilePath("crt1.o")));
@@ -122,7 +125,8 @@ void solaris::Linker::ConstructJob(Compilation &C, const JobAction &JA,
bool NeedsSanitizerDeps = addSanitizerRuntimes(getToolChain(), Args, CmdArgs);
AddLinkerInputs(getToolChain(), Inputs, Args, CmdArgs, JA);
- if (!Args.hasArg(options::OPT_nostdlib, options::OPT_nodefaultlibs)) {
+ if (!Args.hasArg(options::OPT_nostdlib, options::OPT_nodefaultlibs,
+ options::OPT_r)) {
if (getToolChain().ShouldLinkCXXStdlib(Args))
getToolChain().AddCXXStdlibLibArgs(Args, CmdArgs);
if (Args.hasArg(options::OPT_fstack_protector) ||
@@ -132,21 +136,40 @@ void solaris::Linker::ConstructJob(Compilation &C, const JobAction &JA,
CmdArgs.push_back("-lssp_nonshared");
CmdArgs.push_back("-lssp");
}
+ // LLVM support for atomics on 32-bit SPARC V8+ is incomplete, so
+ // forcibly link with libatomic as a workaround.
+ if (getToolChain().getTriple().getArch() == llvm::Triple::sparc) {
+ CmdArgs.push_back(getAsNeededOption(getToolChain(), true));
+ CmdArgs.push_back("-latomic");
+ CmdArgs.push_back(getAsNeededOption(getToolChain(), false));
+ }
CmdArgs.push_back("-lgcc_s");
CmdArgs.push_back("-lc");
if (!Args.hasArg(options::OPT_shared)) {
CmdArgs.push_back("-lgcc");
CmdArgs.push_back("-lm");
}
- if (NeedsSanitizerDeps)
+ if (NeedsSanitizerDeps) {
linkSanitizerRuntimeDeps(getToolChain(), CmdArgs);
+
+ // Work around Solaris/amd64 ld bug when calling __tls_get_addr directly.
+ // However, ld -z relax=transtls is available since Solaris 11.2, but not
+ // in Illumos.
+ const SanitizerArgs &SA = getToolChain().getSanitizerArgs(Args);
+ if (getToolChain().getTriple().getArch() == llvm::Triple::x86_64 &&
+ (SA.needsAsanRt() || SA.needsStatsRt() ||
+ (SA.needsUbsanRt() && !SA.requiresMinimalRuntime())))
+ CmdArgs.push_back("-zrelax=transtls");
+ }
}
- if (!Args.hasArg(options::OPT_nostdlib, options::OPT_nostartfiles)) {
+ if (!Args.hasArg(options::OPT_nostdlib, options::OPT_nostartfiles,
+ options::OPT_r)) {
CmdArgs.push_back(
Args.MakeArgString(getToolChain().GetFilePath("crtend.o")));
+ CmdArgs.push_back(
+ Args.MakeArgString(getToolChain().GetFilePath("crtn.o")));
}
- CmdArgs.push_back(Args.MakeArgString(getToolChain().GetFilePath("crtn.o")));
getToolChain().addProfileRTLibs(Args, CmdArgs);
diff --git a/clang/lib/Driver/ToolChains/VEToolchain.h b/clang/lib/Driver/ToolChains/VEToolchain.h
index 964b0d0dd8d4..8b9ccaa7fada 100644
--- a/clang/lib/Driver/ToolChains/VEToolchain.h
+++ b/clang/lib/Driver/ToolChains/VEToolchain.h
@@ -26,7 +26,6 @@ protected:
Tool *buildLinker() const override;
public:
- bool IsIntegratedAssemblerDefault() const override { return true; }
bool isPICDefault() const override;
bool isPIEDefault(const llvm::opt::ArgList &Args) const override;
bool isPICDefaultForced() const override;
diff --git a/clang/lib/Driver/ToolChains/WebAssembly.cpp b/clang/lib/Driver/ToolChains/WebAssembly.cpp
index 3614272a5f74..c5e4d569793c 100644
--- a/clang/lib/Driver/ToolChains/WebAssembly.cpp
+++ b/clang/lib/Driver/ToolChains/WebAssembly.cpp
@@ -8,15 +8,17 @@
#include "WebAssembly.h"
#include "CommonArgs.h"
+#include "Gnu.h"
#include "clang/Basic/Version.h"
#include "clang/Config/config.h"
#include "clang/Driver/Compilation.h"
#include "clang/Driver/Driver.h"
#include "clang/Driver/DriverDiagnostic.h"
#include "clang/Driver/Options.h"
+#include "llvm/Option/ArgList.h"
#include "llvm/Support/FileSystem.h"
#include "llvm/Support/Path.h"
-#include "llvm/Option/ArgList.h"
+#include "llvm/Support/VirtualFileSystem.h"
using namespace clang::driver;
using namespace clang::driver::tools;
@@ -371,7 +373,11 @@ ToolChain::CXXStdlibType
WebAssembly::GetCXXStdlibType(const ArgList &Args) const {
if (Arg *A = Args.getLastArg(options::OPT_stdlib_EQ)) {
StringRef Value = A->getValue();
- if (Value != "libc++")
+ if (Value == "libc++")
+ return ToolChain::CST_Libcxx;
+ else if (Value == "libstdc++")
+ return ToolChain::CST_Libstdcxx;
+ else
getDriver().Diag(diag::err_drv_invalid_stdlib_name)
<< A->getAsString(Args);
}
@@ -417,17 +423,18 @@ void WebAssembly::AddClangSystemIncludeArgs(const ArgList &DriverArgs,
void WebAssembly::AddClangCXXStdlibIncludeArgs(const ArgList &DriverArgs,
ArgStringList &CC1Args) const {
- if (!DriverArgs.hasArg(options::OPT_nostdlibinc) &&
- !DriverArgs.hasArg(options::OPT_nostdincxx)) {
- if (getTriple().getOS() != llvm::Triple::UnknownOS) {
- const std::string MultiarchTriple =
- getMultiarchTriple(getDriver(), getTriple(), getDriver().SysRoot);
- addSystemInclude(DriverArgs, CC1Args,
- getDriver().SysRoot + "/include/" + MultiarchTriple +
- "/c++/v1");
- }
- addSystemInclude(DriverArgs, CC1Args,
- getDriver().SysRoot + "/include/c++/v1");
+
+ if (DriverArgs.hasArg(options::OPT_nostdlibinc) ||
+ DriverArgs.hasArg(options::OPT_nostdincxx))
+ return;
+
+ switch (GetCXXStdlibType(DriverArgs)) {
+ case ToolChain::CST_Libcxx:
+ addLibCxxIncludePaths(DriverArgs, CC1Args);
+ break;
+ case ToolChain::CST_Libstdcxx:
+ addLibStdCXXIncludePaths(DriverArgs, CC1Args);
+ break;
}
}
@@ -440,7 +447,8 @@ void WebAssembly::AddCXXStdlibLibArgs(const llvm::opt::ArgList &Args,
CmdArgs.push_back("-lc++abi");
break;
case ToolChain::CST_Libstdcxx:
- llvm_unreachable("invalid stdlib name");
+ CmdArgs.push_back("-lstdc++");
+ break;
}
}
@@ -455,3 +463,77 @@ SanitizerMask WebAssembly::getSupportedSanitizers() const {
Tool *WebAssembly::buildLinker() const {
return new tools::wasm::Linker(*this);
}
+
+void WebAssembly::addLibCxxIncludePaths(
+ const llvm::opt::ArgList &DriverArgs,
+ llvm::opt::ArgStringList &CC1Args) const {
+ const Driver &D = getDriver();
+ std::string SysRoot = computeSysRoot();
+ std::string LibPath = SysRoot + "/include";
+ const std::string MultiarchTriple =
+ getMultiarchTriple(D, getTriple(), SysRoot);
+ bool IsKnownOs = (getTriple().getOS() != llvm::Triple::UnknownOS);
+
+ std::string Version = detectLibcxxVersion(LibPath);
+ if (Version.empty())
+ return;
+
+ // First add the per-target include path if the OS is known.
+ if (IsKnownOs) {
+ std::string TargetDir = LibPath + "/" + MultiarchTriple + "/c++/" + Version;
+ addSystemInclude(DriverArgs, CC1Args, TargetDir);
+ }
+
+ // Second add the generic one.
+ addSystemInclude(DriverArgs, CC1Args, LibPath + "/c++/" + Version);
+}
+
+void WebAssembly::addLibStdCXXIncludePaths(
+ const llvm::opt::ArgList &DriverArgs,
+ llvm::opt::ArgStringList &CC1Args) const {
+ // We cannot use GCCInstallationDetector here as the sysroot usually does
+ // not contain a full GCC installation.
+ // Instead, we search the given sysroot for /usr/include/xx, similar
+ // to how we do it for libc++.
+ const Driver &D = getDriver();
+ std::string SysRoot = computeSysRoot();
+ std::string LibPath = SysRoot + "/include";
+ const std::string MultiarchTriple =
+ getMultiarchTriple(D, getTriple(), SysRoot);
+ bool IsKnownOs = (getTriple().getOS() != llvm::Triple::UnknownOS);
+
+ // This is similar to detectLibcxxVersion()
+ std::string Version;
+ {
+ std::error_code EC;
+ Generic_GCC::GCCVersion MaxVersion =
+ Generic_GCC::GCCVersion::Parse("0.0.0");
+ SmallString<128> Path(LibPath);
+ llvm::sys::path::append(Path, "c++");
+ for (llvm::vfs::directory_iterator LI = getVFS().dir_begin(Path, EC), LE;
+ !EC && LI != LE; LI = LI.increment(EC)) {
+ StringRef VersionText = llvm::sys::path::filename(LI->path());
+ if (VersionText[0] != 'v') {
+ auto Version = Generic_GCC::GCCVersion::Parse(VersionText);
+ if (Version > MaxVersion)
+ MaxVersion = Version;
+ }
+ }
+ if (MaxVersion.Major > 0)
+ Version = MaxVersion.Text;
+ }
+
+ if (Version.empty())
+ return;
+
+ // First add the per-target include path if the OS is known.
+ if (IsKnownOs) {
+ std::string TargetDir = LibPath + "/c++/" + Version + "/" + MultiarchTriple;
+ addSystemInclude(DriverArgs, CC1Args, TargetDir);
+ }
+
+ // Second add the generic one.
+ addSystemInclude(DriverArgs, CC1Args, LibPath + "/c++/" + Version);
+ // Third the backward one.
+ addSystemInclude(DriverArgs, CC1Args, LibPath + "/c++/" + Version + "/backward");
+}
diff --git a/clang/lib/Driver/ToolChains/WebAssembly.h b/clang/lib/Driver/ToolChains/WebAssembly.h
index b4c3082a089a..5b9b8a0fe4e6 100644
--- a/clang/lib/Driver/ToolChains/WebAssembly.h
+++ b/clang/lib/Driver/ToolChains/WebAssembly.h
@@ -70,11 +70,20 @@ private:
const char *getDefaultLinker() const override { return "wasm-ld"; }
+ CXXStdlibType GetDefaultCXXStdlibType() const override {
+ return ToolChain::CST_Libcxx;
+ }
+
Tool *buildLinker() const override;
std::string getMultiarchTriple(const Driver &D,
const llvm::Triple &TargetTriple,
StringRef SysRoot) const override;
+
+ void addLibCxxIncludePaths(const llvm::opt::ArgList &DriverArgs,
+ llvm::opt::ArgStringList &CC1Args) const;
+ void addLibStdCXXIncludePaths(const llvm::opt::ArgList &DriverArgs,
+ llvm::opt::ArgStringList &CC1Args) const;
};
} // end namespace toolchains
diff --git a/clang/lib/Driver/ToolChains/ZOS.h b/clang/lib/Driver/ToolChains/ZOS.h
index 50bff0993561..53138306fd41 100644
--- a/clang/lib/Driver/ToolChains/ZOS.h
+++ b/clang/lib/Driver/ToolChains/ZOS.h
@@ -30,6 +30,8 @@ public:
bool IsIntegratedAssemblerDefault() const override { return true; }
+ unsigned GetDefaultDwarfVersion() const override { return 4; }
+
void addClangTargetOptions(
const llvm::opt::ArgList &DriverArgs, llvm::opt::ArgStringList &CC1Args,
Action::OffloadKind DeviceOffloadingKind) const override;
diff --git a/clang/lib/Driver/Types.cpp b/clang/lib/Driver/Types.cpp
index 8f6adc6c2ad1..66da6fe97059 100644
--- a/clang/lib/Driver/Types.cpp
+++ b/clang/lib/Driver/Types.cpp
@@ -65,9 +65,16 @@ static bool isPreprocessedModuleType(ID Id) {
return Id == TY_CXXModule || Id == TY_PP_CXXModule;
}
+static bool isPreprocessedHeaderUnitType(ID Id) {
+ return Id == TY_CXXSHeader || Id == TY_CXXUHeader || Id == TY_CXXHUHeader ||
+ Id == TY_PP_CXXHeaderUnit;
+}
+
types::ID types::getPrecompiledType(ID Id) {
if (isPreprocessedModuleType(Id))
return TY_ModuleFile;
+ if (isPreprocessedHeaderUnitType(Id))
+ return TY_HeaderUnit;
if (onlyPrecompileType(Id))
return TY_PCH;
return TY_INVALID;
@@ -139,6 +146,10 @@ bool types::isAcceptedByClang(ID Id) {
case TY_CLHeader:
case TY_ObjCHeader: case TY_PP_ObjCHeader:
case TY_CXXHeader: case TY_PP_CXXHeader:
+ case TY_CXXSHeader:
+ case TY_CXXUHeader:
+ case TY_CXXHUHeader:
+ case TY_PP_CXXHeaderUnit:
case TY_ObjCXXHeader: case TY_PP_ObjCXXHeader:
case TY_CXXModule: case TY_PP_CXXModule:
case TY_AST: case TY_ModuleFile: case TY_PCH:
@@ -148,6 +159,20 @@ bool types::isAcceptedByClang(ID Id) {
}
}
+bool types::isAcceptedByFlang(ID Id) {
+ switch (Id) {
+ default:
+ return false;
+
+ case TY_Fortran:
+ case TY_PP_Fortran:
+ return true;
+ case TY_LLVM_IR:
+ case TY_LLVM_BC:
+ return true;
+ }
+}
+
bool types::isDerivedFromC(ID Id) {
switch (Id) {
default:
@@ -210,6 +235,10 @@ bool types::isCXX(ID Id) {
case TY_CXX: case TY_PP_CXX:
case TY_ObjCXX: case TY_PP_ObjCXX: case TY_PP_ObjCXX_Alias:
case TY_CXXHeader: case TY_PP_CXXHeader:
+ case TY_CXXSHeader:
+ case TY_CXXUHeader:
+ case TY_CXXHUHeader:
+ case TY_PP_CXXHeaderUnit:
case TY_ObjCXXHeader: case TY_PP_ObjCXXHeader:
case TY_CXXModule: case TY_PP_CXXModule:
case TY_CUDA: case TY_PP_CUDA: case TY_CUDA_DEVICE:
@@ -257,16 +286,6 @@ bool types::isHIP(ID Id) {
}
}
-bool types::isFortran(ID Id) {
- switch (Id) {
- default:
- return false;
-
- case TY_Fortran: case TY_PP_Fortran:
- return true;
- }
-}
-
bool types::isSrcFile(ID Id) {
return Id != TY_Object && getPreprocessedType(Id) != TY_INVALID;
}
@@ -323,6 +342,7 @@ types::ID types::lookupTypeForExtension(llvm::StringRef Ext) {
.Case("hpp", TY_CXXHeader)
.Case("hxx", TY_CXXHeader)
.Case("iim", TY_PP_CXXModule)
+ .Case("iih", TY_PP_CXXHeaderUnit)
.Case("lib", TY_Object)
.Case("mii", TY_PP_ObjCXX)
.Case("obj", TY_Object)
@@ -332,6 +352,7 @@ types::ID types::lookupTypeForExtension(llvm::StringRef Ext) {
.Case("c++m", TY_CXXModule)
.Case("cppm", TY_CXXModule)
.Case("cxxm", TY_CXXModule)
+ .Case("hlsl", TY_HLSL)
.Default(TY_INVALID);
}