aboutsummaryrefslogtreecommitdiff
path: root/clang/lib/Driver/ToolChains
diff options
context:
space:
mode:
authorDimitry Andric <dim@FreeBSD.org>2021-11-19 20:06:13 +0000
committerDimitry Andric <dim@FreeBSD.org>2021-11-19 20:06:13 +0000
commitc0981da47d5696fe36474fcf86b4ce03ae3ff818 (patch)
treef42add1021b9f2ac6a69ac7cf6c4499962739a45 /clang/lib/Driver/ToolChains
parent344a3780b2e33f6ca763666c380202b18aab72a3 (diff)
downloadsrc-c0981da47d5696fe36474fcf86b4ce03ae3ff818.tar.gz
src-c0981da47d5696fe36474fcf86b4ce03ae3ff818.zip
Vendor import of llvm-project main llvmorg-14-init-10186-gff7f2cfa959b.vendor/llvm-project/llvmorg-14-init-10186-gff7f2cfa959b
Diffstat (limited to 'clang/lib/Driver/ToolChains')
-rw-r--r--clang/lib/Driver/ToolChains/AIX.cpp53
-rw-r--r--clang/lib/Driver/ToolChains/AIX.h8
-rw-r--r--clang/lib/Driver/ToolChains/AMDGPU.cpp43
-rw-r--r--clang/lib/Driver/ToolChains/AMDGPU.h13
-rw-r--r--clang/lib/Driver/ToolChains/AMDGPUOpenMP.cpp54
-rw-r--r--clang/lib/Driver/ToolChains/AMDGPUOpenMP.h14
-rw-r--r--clang/lib/Driver/ToolChains/AVR.cpp43
-rw-r--r--clang/lib/Driver/ToolChains/AVR.h7
-rw-r--r--clang/lib/Driver/ToolChains/Arch/AArch64.cpp60
-rw-r--r--clang/lib/Driver/ToolChains/Arch/ARM.cpp36
-rw-r--r--clang/lib/Driver/ToolChains/Arch/ARM.h5
-rw-r--r--clang/lib/Driver/ToolChains/Arch/Mips.cpp5
-rw-r--r--clang/lib/Driver/ToolChains/Arch/Mips.h3
-rw-r--r--clang/lib/Driver/ToolChains/Arch/RISCV.cpp488
-rw-r--r--clang/lib/Driver/ToolChains/Arch/X86.cpp49
-rw-r--r--clang/lib/Driver/ToolChains/Arch/X86.h2
-rw-r--r--clang/lib/Driver/ToolChains/BareMetal.cpp17
-rw-r--r--clang/lib/Driver/ToolChains/BareMetal.h4
-rw-r--r--clang/lib/Driver/ToolChains/Clang.cpp436
-rw-r--r--clang/lib/Driver/ToolChains/CloudABI.cpp4
-rw-r--r--clang/lib/Driver/ToolChains/CloudABI.h2
-rw-r--r--clang/lib/Driver/ToolChains/CommonArgs.cpp360
-rw-r--r--clang/lib/Driver/ToolChains/CommonArgs.h37
-rw-r--r--clang/lib/Driver/ToolChains/CrossWindows.cpp4
-rw-r--r--clang/lib/Driver/ToolChains/CrossWindows.h2
-rw-r--r--clang/lib/Driver/ToolChains/Cuda.cpp121
-rw-r--r--clang/lib/Driver/ToolChains/Cuda.h11
-rw-r--r--clang/lib/Driver/ToolChains/Darwin.cpp179
-rw-r--r--clang/lib/Driver/ToolChains/Darwin.h17
-rw-r--r--clang/lib/Driver/ToolChains/Flang.cpp5
-rw-r--r--clang/lib/Driver/ToolChains/FreeBSD.cpp10
-rw-r--r--clang/lib/Driver/ToolChains/FreeBSD.h2
-rw-r--r--clang/lib/Driver/ToolChains/Fuchsia.cpp23
-rw-r--r--clang/lib/Driver/ToolChains/Fuchsia.h7
-rw-r--r--clang/lib/Driver/ToolChains/Gnu.cpp105
-rw-r--r--clang/lib/Driver/ToolChains/Gnu.h2
-rw-r--r--clang/lib/Driver/ToolChains/HIP.cpp129
-rw-r--r--clang/lib/Driver/ToolChains/HIP.h4
-rw-r--r--clang/lib/Driver/ToolChains/Haiku.h2
-rw-r--r--clang/lib/Driver/ToolChains/Hexagon.cpp55
-rw-r--r--clang/lib/Driver/ToolChains/Hexagon.h6
-rw-r--r--clang/lib/Driver/ToolChains/Linux.cpp34
-rw-r--r--clang/lib/Driver/ToolChains/Linux.h3
-rw-r--r--clang/lib/Driver/ToolChains/MSP430.h4
-rw-r--r--clang/lib/Driver/ToolChains/MSVC.cpp151
-rw-r--r--clang/lib/Driver/ToolChains/MSVC.h2
-rw-r--r--clang/lib/Driver/ToolChains/MinGW.cpp142
-rw-r--r--clang/lib/Driver/ToolChains/MinGW.h9
-rw-r--r--clang/lib/Driver/ToolChains/NetBSD.cpp53
-rw-r--r--clang/lib/Driver/ToolChains/OpenBSD.cpp43
-rw-r--r--clang/lib/Driver/ToolChains/OpenBSD.h4
-rw-r--r--clang/lib/Driver/ToolChains/PS4CPU.cpp11
-rw-r--r--clang/lib/Driver/ToolChains/PS4CPU.h3
-rw-r--r--clang/lib/Driver/ToolChains/SPIRV.cpp49
-rw-r--r--clang/lib/Driver/ToolChains/SPIRV.h46
-rw-r--r--clang/lib/Driver/ToolChains/TCE.cpp4
-rw-r--r--clang/lib/Driver/ToolChains/TCE.h2
-rw-r--r--clang/lib/Driver/ToolChains/VEToolchain.cpp4
-rw-r--r--clang/lib/Driver/ToolChains/VEToolchain.h2
-rw-r--r--clang/lib/Driver/ToolChains/WebAssembly.cpp49
-rw-r--r--clang/lib/Driver/ToolChains/WebAssembly.h2
-rw-r--r--clang/lib/Driver/ToolChains/XCore.cpp4
-rw-r--r--clang/lib/Driver/ToolChains/XCore.h2
-rw-r--r--clang/lib/Driver/ToolChains/ZOS.h4
64 files changed, 1932 insertions, 1122 deletions
diff --git a/clang/lib/Driver/ToolChains/AIX.cpp b/clang/lib/Driver/ToolChains/AIX.cpp
index 3000b8416adf..e4bbf498b9cd 100644
--- a/clang/lib/Driver/ToolChains/AIX.cpp
+++ b/clang/lib/Driver/ToolChains/AIX.cpp
@@ -98,6 +98,26 @@ 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,
+ false) ||
+ Args.hasFlag(options::OPT_fprofile_generate,
+ options::OPT_fno_profile_generate, false) ||
+ Args.hasFlag(options::OPT_fprofile_generate_EQ,
+ options::OPT_fno_profile_generate, false) ||
+ Args.hasFlag(options::OPT_fprofile_instr_generate,
+ options::OPT_fno_profile_instr_generate, false) ||
+ Args.hasFlag(options::OPT_fprofile_instr_generate_EQ,
+ options::OPT_fno_profile_instr_generate, false) ||
+ Args.hasFlag(options::OPT_fcs_profile_generate,
+ options::OPT_fno_profile_generate, false) ||
+ 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");
+
// Specify linker output file.
assert((Output.isFilename() || Output.isNothing()) && "Invalid output.");
if (Output.isFilename()) {
@@ -218,15 +238,44 @@ void AIX::AddClangSystemIncludeArgs(const ArgList &DriverArgs,
addSystemInclude(DriverArgs, CC1Args, UP.str());
}
+void AIX::AddClangCXXStdlibIncludeArgs(
+ const llvm::opt::ArgList &DriverArgs,
+ llvm::opt::ArgStringList &CC1Args) const {
+
+ if (DriverArgs.hasArg(options::OPT_nostdinc) ||
+ DriverArgs.hasArg(options::OPT_nostdincxx) ||
+ DriverArgs.hasArg(options::OPT_nostdlibinc))
+ return;
+
+ switch (GetCXXStdlibType(DriverArgs)) {
+ case ToolChain::CST_Libstdcxx:
+ llvm::report_fatal_error(
+ "picking up libstdc++ headers is unimplemented on AIX");
+ case ToolChain::CST_Libcxx: {
+ llvm::StringRef Sysroot = GetHeaderSysroot(DriverArgs);
+ SmallString<128> PathCPP(Sysroot);
+ llvm::sys::path::append(PathCPP, "opt/IBM/openxlCSDK", "include", "c++",
+ "v1");
+ addSystemInclude(DriverArgs, CC1Args, PathCPP.str());
+ // Required in order to suppress conflicting C++ overloads in the system
+ // libc headers that were used by XL C++.
+ CC1Args.push_back("-D__LIBC_NO_CPP_MATH_OVERLOADS__");
+ return;
+ }
+ }
+
+ llvm_unreachable("Unexpected C++ library type; only libc++ is supported.");
+}
+
void AIX::AddCXXStdlibLibArgs(const llvm::opt::ArgList &Args,
llvm::opt::ArgStringList &CmdArgs) const {
switch (GetCXXStdlibType(Args)) {
+ case ToolChain::CST_Libstdcxx:
+ llvm::report_fatal_error("linking libstdc++ unimplemented on AIX");
case ToolChain::CST_Libcxx:
CmdArgs.push_back("-lc++");
CmdArgs.push_back("-lc++abi");
return;
- case ToolChain::CST_Libstdcxx:
- llvm::report_fatal_error("linking libstdc++ unimplemented on AIX");
}
llvm_unreachable("Unexpected C++ library type; only libc++ is supported.");
diff --git a/clang/lib/Driver/ToolChains/AIX.h b/clang/lib/Driver/ToolChains/AIX.h
index d1ec6d10fb3a..e7ec3a5ece4d 100644
--- a/clang/lib/Driver/ToolChains/AIX.h
+++ b/clang/lib/Driver/ToolChains/AIX.h
@@ -63,13 +63,19 @@ public:
return ParseInlineAsmUsingAsmParser;
}
bool isPICDefault() const override { return true; }
- bool isPIEDefault() const override { return false; }
+ bool isPIEDefault(const llvm::opt::ArgList &Args) const override {
+ return false;
+ }
bool isPICDefaultForced() const override { return true; }
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 AddCXXStdlibLibArgs(const llvm::opt::ArgList &Args,
llvm::opt::ArgStringList &CmdArgs) const override;
diff --git a/clang/lib/Driver/ToolChains/AMDGPU.cpp b/clang/lib/Driver/ToolChains/AMDGPU.cpp
index d63c5e12c4af..b5eaf1adca6b 100644
--- a/clang/lib/Driver/ToolChains/AMDGPU.cpp
+++ b/clang/lib/Driver/ToolChains/AMDGPU.cpp
@@ -754,7 +754,7 @@ AMDGPUToolChain::detectSystemGPUs(const ArgList &Args,
std::string ErrorMessage;
if (int Result = llvm::sys::ExecuteAndWait(
- Program.c_str(), {}, {}, Redirects, /* SecondsToWait */ 0,
+ Program, {}, {}, Redirects, /* SecondsToWait */ 0,
/*MemoryLimit*/ 0, &ErrorMessage)) {
if (Result > 0) {
ErrorMessage = "Exited with error code " + std::to_string(Result);
@@ -796,9 +796,9 @@ llvm::Error AMDGPUToolChain::getSystemGPUArch(const ArgList &Args,
}
GPUArch = GPUArchs[0];
if (GPUArchs.size() > 1) {
- bool AllSame = std::all_of(
- GPUArchs.begin(), GPUArchs.end(),
- [&](const StringRef &GPUArch) { return GPUArch == GPUArchs.front(); });
+ bool AllSame = llvm::all_of(GPUArchs, [&](const StringRef &GPUArch) {
+ return GPUArch == GPUArchs.front();
+ });
if (!AllSame)
return llvm::createStringError(
std::error_code(), "Multiple AMD GPUs found with different archs");
@@ -893,3 +893,38 @@ bool AMDGPUToolChain::shouldSkipArgument(const llvm::opt::Arg *A) const {
return true;
return false;
}
+
+llvm::SmallVector<std::string, 12>
+ROCMToolChain::getCommonDeviceLibNames(const llvm::opt::ArgList &DriverArgs,
+ const std::string &GPUArch) 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;
+ 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
+ // them all?
+ bool DAZ = DriverArgs.hasFlag(options::OPT_fgpu_flush_denormals_to_zero,
+ options::OPT_fno_gpu_flush_denormals_to_zero,
+ getDefaultDenormsAreZeroForTarget(Kind));
+ bool FiniteOnly = DriverArgs.hasFlag(
+ options::OPT_ffinite_math_only, options::OPT_fno_finite_math_only, false);
+ bool UnsafeMathOpt =
+ DriverArgs.hasFlag(options::OPT_funsafe_math_optimizations,
+ options::OPT_fno_unsafe_math_optimizations, false);
+ bool FastRelaxedMath = DriverArgs.hasFlag(options::OPT_ffast_math,
+ 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);
+ bool Wave64 = isWave64(DriverArgs, Kind);
+
+ return RocmInstallation.getCommonBitcodeLibs(
+ DriverArgs, LibDeviceFile, Wave64, DAZ, FiniteOnly, UnsafeMathOpt,
+ FastRelaxedMath, CorrectSqrt);
+}
diff --git a/clang/lib/Driver/ToolChains/AMDGPU.h b/clang/lib/Driver/ToolChains/AMDGPU.h
index 50ed3b3ded9a..156bfd1fbdb2 100644
--- a/clang/lib/Driver/ToolChains/AMDGPU.h
+++ b/clang/lib/Driver/ToolChains/AMDGPU.h
@@ -51,7 +51,7 @@ protected:
const std::map<options::ID, const StringRef> OptionsDefault;
Tool *buildLinker() const override;
- const StringRef getOptionDefault(options::ID OptID) const {
+ StringRef getOptionDefault(options::ID OptID) const {
auto opt = OptionsDefault.find(OptID);
assert(opt != OptionsDefault.end() && "No Default for Option");
return opt->second;
@@ -60,14 +60,16 @@ protected:
public:
AMDGPUToolChain(const Driver &D, const llvm::Triple &Triple,
const llvm::opt::ArgList &Args);
- unsigned GetDefaultDwarfVersion() const override { return 4; }
+ unsigned GetDefaultDwarfVersion() const override { return 5; }
bool IsIntegratedAssemblerDefault() const override { return true; }
bool IsMathErrnoDefault() const override { return false; }
bool useIntegratedAs() const override { return true; }
bool isCrossCompiling() const override { return true; }
bool isPICDefault() const override { return false; }
- bool isPIEDefault() const override { return false; }
+ bool isPIEDefault(const llvm::opt::ArgList &Args) const override {
+ return false;
+ }
bool isPICDefaultForced() const override { return false; }
bool SupportsProfiling() const override { return false; }
@@ -136,6 +138,11 @@ public:
addClangTargetOptions(const llvm::opt::ArgList &DriverArgs,
llvm::opt::ArgStringList &CC1Args,
Action::OffloadKind DeviceOffloadKind) const override;
+
+ // 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;
};
} // end namespace toolchains
diff --git a/clang/lib/Driver/ToolChains/AMDGPUOpenMP.cpp b/clang/lib/Driver/ToolChains/AMDGPUOpenMP.cpp
index fe1d19c2dd67..863e2c597d53 100644
--- a/clang/lib/Driver/ToolChains/AMDGPUOpenMP.cpp
+++ b/clang/lib/Driver/ToolChains/AMDGPUOpenMP.cpp
@@ -9,12 +9,14 @@
#include "AMDGPUOpenMP.h"
#include "AMDGPU.h"
#include "CommonArgs.h"
+#include "ToolChains/ROCm.h"
#include "clang/Basic/DiagnosticDriver.h"
#include "clang/Driver/Compilation.h"
#include "clang/Driver/Driver.h"
#include "clang/Driver/DriverDiagnostic.h"
#include "clang/Driver/InputInfo.h"
#include "clang/Driver/Options.h"
+#include "llvm/ADT/STLExtras.h"
#include "llvm/Support/FileSystem.h"
#include "llvm/Support/FormatAdapters.h"
#include "llvm/Support/FormatVariadic.h"
@@ -84,14 +86,54 @@ static bool checkSystemForAMDGPU(const ArgList &Args, const AMDGPUToolChain &TC,
} // namespace
const char *AMDGCN::OpenMPLinker::constructLLVMLinkCommand(
- Compilation &C, const JobAction &JA, const InputInfoList &Inputs,
- const ArgList &Args, StringRef SubArchName,
- StringRef OutputFilePrefix) const {
+ const toolchains::AMDGPUOpenMPToolChain &AMDGPUOpenMPTC, Compilation &C,
+ const JobAction &JA, const InputInfoList &Inputs, const ArgList &Args,
+ StringRef SubArchName, StringRef OutputFilePrefix) const {
ArgStringList CmdArgs;
for (const auto &II : Inputs)
if (II.isFilename())
CmdArgs.push_back(II.getFilename());
+
+ if (Args.hasArg(options::OPT_l)) {
+ auto Lm = Args.getAllArgValues(options::OPT_l);
+ bool HasLibm = false;
+ for (auto &Lib : Lm) {
+ if (Lib == "m") {
+ HasLibm = true;
+ break;
+ }
+ }
+
+ if (HasLibm) {
+ // This is not certain to work. The device libs added here, and passed to
+ // llvm-link, are missing attributes that they expect to be inserted when
+ // passed to mlink-builtin-bitcode. The amdgpu backend does not generate
+ // conservatively correct code when attributes are missing, so this may
+ // be the root cause of miscompilations. Passing via mlink-builtin-bitcode
+ // ultimately hits CodeGenModule::addDefaultFunctionDefinitionAttributes
+ // on each function, see D28538 for context.
+ // Potential workarounds:
+ // - unconditionally link all of the device libs to every translation
+ // unit in clang via mlink-builtin-bitcode
+ // - build a libm bitcode file as part of the DeviceRTL and explictly
+ // mlink-builtin-bitcode the rocm device libs components at build time
+ // - drop this llvm-link fork in favour or some calls into LLVM, chosen
+ // to do basically the same work as llvm-link but with that call first
+ // - write an opt pass that sets that on every function it sees and pipe
+ // 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) {
+ CmdArgs.push_back(Args.MakeArgString(BCFile));
+ });
+ }
+ }
+
+ AddStaticDeviceLibsLinking(C, *this, JA, Inputs, Args, CmdArgs, "amdgcn",
+ SubArchName,
+ /* bitcode SDL?*/ true,
+ /* PostClang Link? */ false);
// Add an intermediate output file.
CmdArgs.push_back("-o");
const char *OutputFileName =
@@ -180,8 +222,8 @@ void AMDGCN::OpenMPLinker::ConstructJob(Compilation &C, const JobAction &JA,
assert(Prefix.length() && "no linker inputs are files ");
// Each command outputs different files.
- const char *LLVMLinkCommand =
- constructLLVMLinkCommand(C, JA, Inputs, Args, GPUArch, Prefix);
+ const char *LLVMLinkCommand = constructLLVMLinkCommand(
+ AMDGPUOpenMPTC, C, JA, Inputs, Args, GPUArch, Prefix);
// Produce readable assembly if save-temps is enabled.
if (C.getDriver().isSaveTempsEnabled())
@@ -226,7 +268,7 @@ void AMDGPUOpenMPToolChain::addClangTargetOptions(
std::string BitcodeSuffix;
if (DriverArgs.hasFlag(options::OPT_fopenmp_target_new_runtime,
options::OPT_fno_openmp_target_new_runtime, false))
- BitcodeSuffix = "new-amdgcn-" + GPUArch;
+ BitcodeSuffix = "new-amdgpu-" + GPUArch;
else
BitcodeSuffix = "amdgcn-" + GPUArch;
diff --git a/clang/lib/Driver/ToolChains/AMDGPUOpenMP.h b/clang/lib/Driver/ToolChains/AMDGPUOpenMP.h
index effca7e212cc..233256bf7378 100644
--- a/clang/lib/Driver/ToolChains/AMDGPUOpenMP.h
+++ b/clang/lib/Driver/ToolChains/AMDGPUOpenMP.h
@@ -16,6 +16,10 @@
namespace clang {
namespace driver {
+namespace toolchains {
+class AMDGPUOpenMPToolChain;
+}
+
namespace tools {
namespace AMDGCN {
@@ -35,11 +39,11 @@ public:
private:
/// \return llvm-link output file name.
- const char *constructLLVMLinkCommand(Compilation &C, const JobAction &JA,
- const InputInfoList &Inputs,
- const llvm::opt::ArgList &Args,
- llvm::StringRef SubArchName,
- llvm::StringRef OutputFilePrefix) const;
+ const char *constructLLVMLinkCommand(
+ const toolchains::AMDGPUOpenMPToolChain &AMDGPUOpenMPTC, Compilation &C,
+ const JobAction &JA, const InputInfoList &Inputs,
+ const llvm::opt::ArgList &Args, llvm::StringRef SubArchName,
+ llvm::StringRef OutputFilePrefix) const;
/// \return llc output file name.
const char *constructLlcCommand(Compilation &C, const JobAction &JA,
diff --git a/clang/lib/Driver/ToolChains/AVR.cpp b/clang/lib/Driver/ToolChains/AVR.cpp
index f147292038a8..a66cae8b4d6b 100644
--- a/clang/lib/Driver/ToolChains/AVR.cpp
+++ b/clang/lib/Driver/ToolChains/AVR.cpp
@@ -28,9 +28,9 @@ using namespace llvm::opt;
namespace {
-const struct {
+constexpr struct {
StringRef Name;
- std::string SubPath;
+ StringRef SubPath;
StringRef Family;
unsigned DataAddr;
} MCUInfo[] = {
@@ -298,6 +298,7 @@ llvm::Optional<unsigned> GetMCUSectionAddressData(StringRef MCUName) {
}
const StringRef PossibleAVRLibcLocations[] = {
+ "/avr",
"/usr/avr",
"/usr/lib/avr",
};
@@ -314,7 +315,7 @@ AVRToolChain::AVRToolChain(const Driver &D, const llvm::Triple &Triple,
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(Args, Triple);
+ std::string CPU = getCPUName(D, Args, Triple);
if (CPU.empty()) {
// We cannot link any standard libraries without an MCU specified.
@@ -370,6 +371,16 @@ void AVRToolChain::AddClangSystemIncludeArgs(const ArgList &DriverArgs,
addSystemInclude(DriverArgs, CC1Args, AVRInc);
}
+void AVRToolChain::addClangTargetOptions(
+ const llvm::opt::ArgList &DriverArgs, llvm::opt::ArgStringList &CC1Args,
+ Action::OffloadKind DeviceOffloadKind) const {
+ // By default, use `.ctors` (not `.init_array`), as required by libgcc, which
+ // runs constructors/destructors on AVR.
+ if (!DriverArgs.hasFlag(options::OPT_fuse_init_array,
+ options::OPT_fno_use_init_array, false))
+ CC1Args.push_back("-fno-use-init-array");
+}
+
Tool *AVRToolChain::buildLinker() const {
return new tools::AVR::Linker(getTriple(), *this, LinkStdlib);
}
@@ -378,8 +389,10 @@ void AVR::Linker::ConstructJob(Compilation &C, const JobAction &JA,
const InputInfo &Output,
const InputInfoList &Inputs, const ArgList &Args,
const char *LinkingOutput) const {
+ const Driver &D = getToolChain().getDriver();
+
// Compute information about the target AVR.
- std::string CPU = getCPUName(Args, getToolChain().getTriple());
+ std::string CPU = getCPUName(D, Args, getToolChain().getTriple());
llvm::Optional<StringRef> FamilyName = GetMCUFamilyName(CPU);
llvm::Optional<unsigned> SectionAddressData = GetMCUSectionAddressData(CPU);
@@ -403,9 +416,7 @@ void AVR::Linker::ConstructJob(Compilation &C, const JobAction &JA,
CmdArgs.push_back(Args.MakeArgString(DataSectionArg));
} else {
// We do not have an entry for this CPU in the address mapping table yet.
- getToolChain().getDriver().Diag(
- diag::warn_drv_avr_linker_section_addresses_not_implemented)
- << CPU;
+ D.Diag(diag::warn_drv_avr_linker_section_addresses_not_implemented) << CPU;
}
// If the family name is known, we can link with the device-specific libgcc.
@@ -414,6 +425,8 @@ void AVR::Linker::ConstructJob(Compilation &C, const JobAction &JA,
if (LinkStdlib) {
assert(!CPU.empty() && "CPU name must be known in order to link stdlibs");
+ CmdArgs.push_back("--start-group");
+
// Add the object file for the CRT.
std::string CrtFileName = std::string("-l:crt") + CPU + std::string(".o");
CmdArgs.push_back(Args.MakeArgString(CrtFileName));
@@ -425,6 +438,8 @@ void AVR::Linker::ConstructJob(Compilation &C, const JobAction &JA,
// Add the link library specific to the MCU.
CmdArgs.push_back(Args.MakeArgString(std::string("-l") + CPU));
+ CmdArgs.push_back("--end-group");
+
// 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
@@ -438,11 +453,21 @@ void AVR::Linker::ConstructJob(Compilation &C, const JobAction &JA,
}
llvm::Optional<std::string> AVRToolChain::findAVRLibcInstallation() const {
+ // Search avr-libc installation according to avr-gcc installation.
+ std::string GCCParent(GCCInstallation.getParentLibPath());
+ std::string Path(GCCParent + "/avr");
+ if (llvm::sys::fs::is_directory(Path))
+ return Path;
+ Path = GCCParent + "/../avr";
+ if (llvm::sys::fs::is_directory(Path))
+ return Path;
+
+ // Search avr-libc installation from possible locations, and return the first
+ // one that exists, if there is no avr-gcc installed.
for (StringRef PossiblePath : PossibleAVRLibcLocations) {
std::string Path = getDriver().SysRoot + PossiblePath.str();
- // Return the first avr-libc installation that exists.
if (llvm::sys::fs::is_directory(Path))
- return Optional<std::string>(Path);
+ return Path;
}
return llvm::None;
diff --git a/clang/lib/Driver/ToolChains/AVR.h b/clang/lib/Driver/ToolChains/AVR.h
index f612aa691182..2d027957ed76 100644
--- a/clang/lib/Driver/ToolChains/AVR.h
+++ b/clang/lib/Driver/ToolChains/AVR.h
@@ -11,8 +11,8 @@
#include "Gnu.h"
#include "clang/Driver/InputInfo.h"
-#include "clang/Driver/ToolChain.h"
#include "clang/Driver/Tool.h"
+#include "clang/Driver/ToolChain.h"
namespace clang {
namespace driver {
@@ -26,6 +26,11 @@ public:
AddClangSystemIncludeArgs(const llvm::opt::ArgList &DriverArgs,
llvm::opt::ArgStringList &CC1Args) const override;
+ void
+ addClangTargetOptions(const llvm::opt::ArgList &DriverArgs,
+ llvm::opt::ArgStringList &CC1Args,
+ Action::OffloadKind DeviceOffloadKind) const override;
+
protected:
Tool *buildLinker() const override;
diff --git a/clang/lib/Driver/ToolChains/Arch/AArch64.cpp b/clang/lib/Driver/ToolChains/Arch/AArch64.cpp
index ed8c7e94b013..0b60d097b9ca 100644
--- a/clang/lib/Driver/ToolChains/Arch/AArch64.cpp
+++ b/clang/lib/Driver/ToolChains/Arch/AArch64.cpp
@@ -79,10 +79,32 @@ static bool DecodeAArch64Features(const Driver &D, StringRef text,
else
return false;
- // +sve implies +f32mm if the base architecture is v8.6A or v8.7A
- // it isn't the case in general that sve implies both f64mm and f32mm
+ if (Feature == "sve2")
+ Features.push_back("+sve");
+ else if (Feature == "sve2-bitperm" || Feature == "sve2-sha3" ||
+ Feature == "sve2-aes" || Feature == "sve2-sm4") {
+ Features.push_back("+sve");
+ Features.push_back("+sve2");
+ } else if (Feature == "nosve") {
+ Features.push_back("-sve2");
+ Features.push_back("-sve2-bitperm");
+ Features.push_back("-sve2-sha3");
+ Features.push_back("-sve2-aes");
+ Features.push_back("-sve2-sm4");
+ } else if (Feature == "nosve2") {
+ Features.push_back("-sve2-bitperm");
+ Features.push_back("-sve2-sha3");
+ Features.push_back("-sve2-aes");
+ Features.push_back("-sve2-sm4");
+ }
+
+ // +sve implies +f32mm if the base architecture is v8.6A, v8.7A, v9.1A or
+ // v9.2A. It isn't the case in general that sve implies both f64mm and f32mm
if ((ArchKind == llvm::AArch64::ArchKind::ARMV8_6A ||
- ArchKind == llvm::AArch64::ArchKind::ARMV8_7A) && Feature == "sve")
+ ArchKind == llvm::AArch64::ArchKind::ARMV8_7A ||
+ ArchKind == llvm::AArch64::ArchKind::ARMV9_1A ||
+ ArchKind == llvm::AArch64::ArchKind::ARMV9_2A) &&
+ Feature == "sve")
Features.push_back("+f32mm");
}
return true;
@@ -127,8 +149,20 @@ getAArch64ArchFeaturesFromMarch(const Driver &D, StringRef March,
llvm::AArch64::ArchKind ArchKind = llvm::AArch64::parseArch(Split.first);
if (ArchKind == llvm::AArch64::ArchKind::INVALID ||
- !llvm::AArch64::getArchFeatures(ArchKind, Features) ||
- (Split.second.size() &&
+ !llvm::AArch64::getArchFeatures(ArchKind, Features))
+ return false;
+
+ // Enable SVE2 by default on Armv9-A.
+ // It can still be disabled if +nosve2 is present.
+ // We must do this early so that DecodeAArch64Features has the correct state
+ if ((ArchKind == llvm::AArch64::ArchKind::ARMV9A ||
+ ArchKind == llvm::AArch64::ArchKind::ARMV9_1A ||
+ ArchKind == llvm::AArch64::ArchKind::ARMV9_2A)) {
+ Features.push_back("+sve");
+ Features.push_back("+sve2");
+ }
+
+ if ((Split.second.size() &&
!DecodeAArch64Features(D, Split.second, Features, ArchKind)))
return false;
@@ -210,6 +244,9 @@ void aarch64::getAArch64TargetFeatures(const Driver &D,
else if (Args.hasArg(options::OPT_arch) || isCPUDeterminedByTriple(Triple))
success = getAArch64ArchFeaturesFromMcpu(
D, getAArch64TargetCPU(Args, Triple, A), Args, Features);
+ else
+ // Default to 'A' profile if the architecture is not specified.
+ success = getAArch64ArchFeaturesFromMarch(D, "armv8-a", Args, Features);
if (success && (A = Args.getLastArg(clang::driver::options::OPT_mtune_EQ)))
success =
@@ -345,7 +382,10 @@ fp16_fml_fallthrough:
NoCrypto = true;
}
- if (std::find(ItBegin, ItEnd, "+v8.4a") != ItEnd) {
+ if (std::find(ItBegin, ItEnd, "+v8.4a") != ItEnd ||
+ std::find(ItBegin, ItEnd, "+v9a") != ItEnd ||
+ std::find(ItBegin, ItEnd, "+v9.1a") != ItEnd ||
+ std::find(ItBegin, ItEnd, "+v9.2a") != ItEnd) {
if (HasCrypto && !NoCrypto) {
// Check if we have NOT disabled an algorithm with something like:
// +crypto, -algorithm
@@ -404,9 +444,11 @@ fp16_fml_fallthrough:
}
}
- auto V8_6Pos = llvm::find(Features, "+v8.6a");
- if (V8_6Pos != std::end(Features))
- V8_6Pos = Features.insert(std::next(V8_6Pos), {"+i8mm", "+bf16"});
+ const char *Archs[] = {"+v8.6a", "+v8.7a", "+v9.1a", "+v9.2a"};
+ 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"});
if (Arg *A = Args.getLastArg(options::OPT_mno_unaligned_access,
options::OPT_munaligned_access)) {
diff --git a/clang/lib/Driver/ToolChains/Arch/ARM.cpp b/clang/lib/Driver/ToolChains/Arch/ARM.cpp
index 4ab547fabe43..21c091e1a0ba 100644
--- a/clang/lib/Driver/ToolChains/Arch/ARM.cpp
+++ b/clang/lib/Driver/ToolChains/Arch/ARM.cpp
@@ -148,13 +148,21 @@ bool arm::useAAPCSForMachO(const llvm::Triple &T) {
}
// Select mode for reading thread pointer (-mtp=soft/cp15).
-arm::ReadTPMode arm::getReadTPMode(const Driver &D, const ArgList &Args) {
+arm::ReadTPMode arm::getReadTPMode(const Driver &D, const ArgList &Args,
+ const llvm::Triple &Triple) {
if (Arg *A = Args.getLastArg(options::OPT_mtp_mode_EQ)) {
arm::ReadTPMode ThreadPointer =
llvm::StringSwitch<arm::ReadTPMode>(A->getValue())
.Case("cp15", ReadTPMode::Cp15)
.Case("soft", ReadTPMode::Soft)
.Default(ReadTPMode::Invalid);
+ if (ThreadPointer == ReadTPMode::Cp15 &&
+ getARMSubArchVersionNumber(Triple) < 7 &&
+ llvm::ARM::parseArch(Triple.getArchName()) !=
+ llvm::ARM::ArchKind::ARMV6T2) {
+ D.Diag(diag::err_target_unsupported_tp_hard) << Triple.getArchName();
+ return ReadTPMode::Invalid;
+ }
if (ThreadPointer != ReadTPMode::Invalid)
return ThreadPointer;
if (StringRef(A->getValue()).empty())
@@ -314,6 +322,10 @@ arm::FloatABI arm::getDefaultFloatABI(const llvm::Triple &Triple) {
// FIXME: this is invalid for WindowsCE
case llvm::Triple::Win32:
+ // It is incorrect to select hard float ABI on MachO platforms if the ABI is
+ // "apcs-gnu".
+ if (Triple.isOSBinFormatMachO() && !useAAPCSForMachO(Triple))
+ return FloatABI::Soft;
return FloatABI::Hard;
case llvm::Triple::NetBSD:
@@ -418,7 +430,7 @@ void arm::getARMTargetFeatures(const Driver &D, const llvm::Triple &Triple,
bool KernelOrKext =
Args.hasArg(options::OPT_mkernel, options::OPT_fapple_kext);
arm::FloatABI ABI = arm::getARMFloatABI(D, Triple, Args);
- arm::ReadTPMode ThreadPointer = arm::getReadTPMode(D, Args);
+ arm::ReadTPMode ThreadPointer = arm::getReadTPMode(D, Args, Triple);
llvm::Optional<std::pair<const Arg *, StringRef>> WaCPU, WaFPU, WaHDiv,
WaArch;
@@ -701,6 +713,18 @@ fp16_fml_fallthrough:
if (Args.getLastArg(options::OPT_mcmse))
Features.push_back("+8msecext");
+ if (Arg *A = Args.getLastArg(options::OPT_mfix_cmse_cve_2021_35465,
+ options::OPT_mno_fix_cmse_cve_2021_35465)) {
+ if (!Args.getLastArg(options::OPT_mcmse))
+ D.Diag(diag::err_opt_not_valid_without_opt)
+ << A->getOption().getName() << "-mcmse";
+
+ if (A->getOption().matches(options::OPT_mfix_cmse_cve_2021_35465))
+ Features.push_back("+fix-cmse-cve-2021-35465");
+ else
+ Features.push_back("-fix-cmse-cve-2021-35465");
+ }
+
// 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.
@@ -763,7 +787,8 @@ fp16_fml_fallthrough:
// which raises an alignment fault on unaligned accesses. Linux
// defaults this bit to 0 and handles it as a system-wide (not
// per-process) setting. It is therefore safe to assume that ARMv7+
- // Linux targets support unaligned accesses. The same goes for NaCl.
+ // Linux targets support unaligned accesses. The same goes for NaCl
+ // and Windows.
//
// The above behavior is consistent with GCC.
int VersionNum = getARMSubArchVersionNumber(Triple);
@@ -771,7 +796,8 @@ fp16_fml_fallthrough:
if (VersionNum < 6 ||
Triple.getSubArch() == llvm::Triple::SubArchType::ARMSubArch_v6m)
Features.push_back("+strict-align");
- } else if (Triple.isOSLinux() || Triple.isOSNaCl()) {
+ } else if (Triple.isOSLinux() || Triple.isOSNaCl() ||
+ Triple.isOSWindows()) {
if (VersionNum < 7)
Features.push_back("+strict-align");
} else
@@ -845,7 +871,7 @@ fp16_fml_fallthrough:
}
-const std::string arm::getARMArch(StringRef Arch, const llvm::Triple &Triple) {
+std::string arm::getARMArch(StringRef Arch, const llvm::Triple &Triple) {
std::string MArch;
if (!Arch.empty())
MArch = std::string(Arch);
diff --git a/clang/lib/Driver/ToolChains/Arch/ARM.h b/clang/lib/Driver/ToolChains/Arch/ARM.h
index 8e7c10ecd5d6..b6fd68fbb9c6 100644
--- a/clang/lib/Driver/ToolChains/Arch/ARM.h
+++ b/clang/lib/Driver/ToolChains/Arch/ARM.h
@@ -24,7 +24,7 @@ namespace arm {
std::string getARMTargetCPU(StringRef CPU, llvm::StringRef Arch,
const llvm::Triple &Triple);
-const std::string getARMArch(llvm::StringRef Arch, const llvm::Triple &Triple);
+std::string getARMArch(llvm::StringRef Arch, const llvm::Triple &Triple);
StringRef getARMCPUForMArch(llvm::StringRef Arch, const llvm::Triple &Triple);
llvm::ARM::ArchKind getLLVMArchKindForARM(StringRef CPU, StringRef Arch,
const llvm::Triple &Triple);
@@ -53,7 +53,8 @@ FloatABI getARMFloatABI(const Driver &D, const llvm::Triple &Triple,
const llvm::opt::ArgList &Args);
void setFloatABIInTriple(const Driver &D, const llvm::opt::ArgList &Args,
llvm::Triple &triple);
-ReadTPMode getReadTPMode(const Driver &D, const llvm::opt::ArgList &Args);
+ReadTPMode getReadTPMode(const Driver &D, const llvm::opt::ArgList &Args,
+ const llvm::Triple &Triple);
void setArchNameInTriple(const Driver &D, const llvm::opt::ArgList &Args,
types::ID InputType, llvm::Triple &Triple);
diff --git a/clang/lib/Driver/ToolChains/Arch/Mips.cpp b/clang/lib/Driver/ToolChains/Arch/Mips.cpp
index 5a509dbb2bd3..c374d745da38 100644
--- a/clang/lib/Driver/ToolChains/Arch/Mips.cpp
+++ b/clang/lib/Driver/ToolChains/Arch/Mips.cpp
@@ -441,7 +441,8 @@ bool mips::isUCLibc(const ArgList &Args) {
return A && A->getOption().matches(options::OPT_muclibc);
}
-bool mips::isNaN2008(const ArgList &Args, const llvm::Triple &Triple) {
+bool mips::isNaN2008(const Driver &D, const ArgList &Args,
+ const llvm::Triple &Triple) {
if (Arg *NaNArg = Args.getLastArg(options::OPT_mnan_EQ))
return llvm::StringSwitch<bool>(NaNArg->getValue())
.Case("2008", true)
@@ -449,7 +450,7 @@ bool mips::isNaN2008(const ArgList &Args, const llvm::Triple &Triple) {
.Default(false);
// NaN2008 is the default for MIPS32r6/MIPS64r6.
- return llvm::StringSwitch<bool>(getCPUName(Args, Triple))
+ return llvm::StringSwitch<bool>(getCPUName(D, Args, Triple))
.Cases("mips32r6", "mips64r6", true)
.Default(false);
}
diff --git a/clang/lib/Driver/ToolChains/Arch/Mips.h b/clang/lib/Driver/ToolChains/Arch/Mips.h
index 074012f40fe5..f4c11a7e3188 100644
--- a/clang/lib/Driver/ToolChains/Arch/Mips.h
+++ b/clang/lib/Driver/ToolChains/Arch/Mips.h
@@ -44,7 +44,8 @@ std::string getMipsABILibSuffix(const llvm::opt::ArgList &Args,
const llvm::Triple &Triple);
bool hasMipsAbiArg(const llvm::opt::ArgList &Args, const char *Value);
bool isUCLibc(const llvm::opt::ArgList &Args);
-bool isNaN2008(const llvm::opt::ArgList &Args, const llvm::Triple &Triple);
+bool isNaN2008(const Driver &D, const llvm::opt::ArgList &Args,
+ const llvm::Triple &Triple);
bool isFP64ADefault(const llvm::Triple &Triple, StringRef CPUName);
bool isFPXXDefault(const llvm::Triple &Triple, StringRef CPUName,
StringRef ABIName, mips::FloatABI FloatABI);
diff --git a/clang/lib/Driver/ToolChains/Arch/RISCV.cpp b/clang/lib/Driver/ToolChains/Arch/RISCV.cpp
index ade93d6881a7..323f588c8269 100644
--- a/clang/lib/Driver/ToolChains/Arch/RISCV.cpp
+++ b/clang/lib/Driver/ToolChains/Arch/RISCV.cpp
@@ -7,462 +7,42 @@
//===----------------------------------------------------------------------===//
#include "RISCV.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/Option/ArgList.h"
#include "llvm/ADT/Optional.h"
+#include "llvm/Option/ArgList.h"
+#include "llvm/Support/Error.h"
+#include "llvm/Support/RISCVISAInfo.h"
#include "llvm/Support/TargetParser.h"
#include "llvm/Support/raw_ostream.h"
-#include "ToolChains/CommonArgs.h"
using namespace clang::driver;
using namespace clang::driver::tools;
using namespace clang;
using namespace llvm::opt;
-namespace {
-// Represents the major and version number components of a RISC-V extension
-struct RISCVExtensionVersion {
- StringRef Major;
- StringRef Minor;
-};
-} // end anonymous namespace
-
-static StringRef getExtensionTypeDesc(StringRef Ext) {
- if (Ext.startswith("sx"))
- return "non-standard supervisor-level extension";
- if (Ext.startswith("s"))
- return "standard supervisor-level extension";
- if (Ext.startswith("x"))
- return "non-standard user-level extension";
- if (Ext.startswith("z"))
- return "standard user-level extension";
- return StringRef();
-}
-
-static StringRef getExtensionType(StringRef Ext) {
- if (Ext.startswith("sx"))
- return "sx";
- if (Ext.startswith("s"))
- return "s";
- if (Ext.startswith("x"))
- return "x";
- if (Ext.startswith("z"))
- return "z";
- return StringRef();
-}
-
-// If the extension is supported as experimental, return the version of that
-// extension that the compiler currently supports.
-static Optional<RISCVExtensionVersion>
-isExperimentalExtension(StringRef Ext) {
- if (Ext == "b" || Ext == "zba" || Ext == "zbb" || Ext == "zbc" ||
- Ext == "zbe" || Ext == "zbf" || Ext == "zbm" || Ext == "zbp" ||
- Ext == "zbr" || Ext == "zbs" || Ext == "zbt" || Ext == "zbproposedc")
- return RISCVExtensionVersion{"0", "93"};
- if (Ext == "v" || Ext == "zvamo" || Ext == "zvlsseg")
- return RISCVExtensionVersion{"0", "10"};
- if (Ext == "zfh")
- return RISCVExtensionVersion{"0", "1"};
- return None;
-}
-
-static bool isSupportedExtension(StringRef Ext) {
- // LLVM supports "z" extensions which are marked as experimental.
- if (isExperimentalExtension(Ext))
- return true;
-
- // LLVM does not support "sx", "s" nor "x" extensions.
- return false;
-}
-
-// Extensions may have a version number, and may be separated by
-// an underscore '_' e.g.: rv32i2_m2.
-// Version number is divided into major and minor version numbers,
-// separated by a 'p'. If the minor version is 0 then 'p0' can be
-// omitted from the version string. E.g., rv32i2p0, rv32i2, rv32i2p1.
-static bool getExtensionVersion(const Driver &D, const ArgList &Args,
- StringRef MArch, StringRef Ext, StringRef In,
- std::string &Major, std::string &Minor) {
- Major = std::string(In.take_while(isDigit));
- In = In.substr(Major.size());
-
- if (Major.size() && In.consume_front("p")) {
- Minor = std::string(In.take_while(isDigit));
- In = In.substr(Major.size() + 1);
-
- // Expected 'p' to be followed by minor version number.
- if (Minor.empty()) {
- std::string Error =
- "minor version number missing after 'p' for extension";
- D.Diag(diag::err_drv_invalid_riscv_ext_arch_name)
- << MArch << Error << Ext;
- return false;
- }
- }
-
- // Expected multi-character extension with version number to have no
- // subsequent characters (i.e. must either end string or be followed by
- // an underscore).
- if (Ext.size() > 1 && In.size()) {
- std::string Error =
- "multi-character extensions must be separated by underscores";
- D.Diag(diag::err_drv_invalid_riscv_ext_arch_name) << MArch << Error << In;
- return false;
- }
-
- // If experimental extension, require use of current version number number
- if (auto ExperimentalExtension = isExperimentalExtension(Ext)) {
- if (!Args.hasArg(options::OPT_menable_experimental_extensions)) {
- std::string Error =
- "requires '-menable-experimental-extensions' for experimental extension";
- D.Diag(diag::err_drv_invalid_riscv_ext_arch_name)
- << MArch << Error << Ext;
- return false;
- } else if (Major.empty() && Minor.empty()) {
- std::string Error =
- "experimental extension requires explicit version number";
- D.Diag(diag::err_drv_invalid_riscv_ext_arch_name)
- << MArch << Error << Ext;
- return false;
- }
- auto SupportedVers = *ExperimentalExtension;
- if (Major != SupportedVers.Major || Minor != SupportedVers.Minor) {
- std::string Error =
- "unsupported version number " + Major;
- if (!Minor.empty())
- Error += "." + Minor;
- Error += " for experimental extension (this compiler supports "
- + SupportedVers.Major.str() + "."
- + SupportedVers.Minor.str() + ")";
-
- D.Diag(diag::err_drv_invalid_riscv_ext_arch_name)
- << MArch << Error << Ext;
- return false;
- }
- return true;
- }
-
- // Allow extensions to declare no version number
- if (Major.empty() && Minor.empty())
- return true;
-
- // TODO: Handle supported extensions with version number.
- std::string Error = "unsupported version number " + Major;
- if (!Minor.empty())
- Error += "." + Minor;
- Error += " for extension";
- D.Diag(diag::err_drv_invalid_riscv_ext_arch_name) << MArch << Error << Ext;
-
- return false;
-}
-
-// Handle other types of extensions other than the standard
-// general purpose and standard user-level extensions.
-// Parse the ISA string containing non-standard user-level
-// extensions, standard supervisor-level extensions and
-// non-standard supervisor-level extensions.
-// These extensions start with 'z', 'x', 's', 'sx' prefixes, follow a
-// canonical order, might have a version number (major, minor)
-// and are separated by a single underscore '_'.
-// Set the hardware features for the extensions that are supported.
-static void getExtensionFeatures(const Driver &D,
- const ArgList &Args,
- std::vector<StringRef> &Features,
- StringRef &MArch, StringRef &Exts) {
- if (Exts.empty())
- return;
-
- // Multi-letter extensions are seperated by a single underscore
- // as described in RISC-V User-Level ISA V2.2.
- SmallVector<StringRef, 8> Split;
- Exts.split(Split, StringRef("_"));
-
- SmallVector<StringRef, 4> Prefix{"z", "x", "s", "sx"};
- auto I = Prefix.begin();
- auto E = Prefix.end();
-
- SmallVector<StringRef, 8> AllExts;
-
- for (StringRef Ext : Split) {
- if (Ext.empty()) {
- D.Diag(diag::err_drv_invalid_riscv_arch_name) << MArch
- << "extension name missing after separator '_'";
- return;
- }
-
- StringRef Type = getExtensionType(Ext);
- StringRef Desc = getExtensionTypeDesc(Ext);
- auto Pos = Ext.find_if(isDigit);
- StringRef Name(Ext.substr(0, Pos));
- StringRef Vers(Ext.substr(Pos));
-
- if (Type.empty()) {
- D.Diag(diag::err_drv_invalid_riscv_ext_arch_name)
- << MArch << "invalid extension prefix" << Ext;
- return;
- }
-
- // Check ISA extensions are specified in the canonical order.
- while (I != E && *I != Type)
- ++I;
-
- if (I == E) {
- std::string Error = std::string(Desc);
- Error += " not given in canonical order";
- D.Diag(diag::err_drv_invalid_riscv_ext_arch_name)
- << MArch << Error << Ext;
- return;
- }
-
- // The order is OK, do not advance I to the next prefix
- // to allow repeated extension type, e.g.: rv32ixabc_xdef.
-
- if (Name.size() == Type.size()) {
- std::string Error = std::string(Desc);
- Error += " name missing after";
- D.Diag(diag::err_drv_invalid_riscv_ext_arch_name)
- << MArch << Error << Type;
- return;
- }
-
- std::string Major, Minor;
- if (!getExtensionVersion(D, Args, MArch, Name, Vers, Major, Minor))
- return;
-
- // Check if duplicated extension.
- if (llvm::is_contained(AllExts, Name)) {
- std::string Error = "duplicated ";
- Error += Desc;
- D.Diag(diag::err_drv_invalid_riscv_ext_arch_name)
- << MArch << Error << Name;
- return;
- }
-
- // Extension format is correct, keep parsing the extensions.
- // TODO: Save Type, Name, Major, Minor to avoid parsing them later.
- AllExts.push_back(Name);
- }
-
- // Set target features.
- // TODO: Hardware features to be handled in Support/TargetParser.cpp.
- // TODO: Use version number when setting target features.
- for (auto Ext : AllExts) {
- if (!isSupportedExtension(Ext)) {
- StringRef Desc = getExtensionTypeDesc(getExtensionType(Ext));
- std::string Error = "unsupported ";
- Error += Desc;
- D.Diag(diag::err_drv_invalid_riscv_ext_arch_name)
- << MArch << Error << Ext;
- return;
- }
- if (Ext == "zvlsseg") {
- Features.push_back("+experimental-v");
- Features.push_back("+experimental-zvlsseg");
- } else if (Ext == "zvamo") {
- Features.push_back("+experimental-v");
- Features.push_back("+experimental-zvlsseg");
- Features.push_back("+experimental-zvamo");
- } else if (isExperimentalExtension(Ext))
- Features.push_back(Args.MakeArgString("+experimental-" + Ext));
- else
- Features.push_back(Args.MakeArgString("+" + Ext));
- }
-}
-
// Returns false if an error is diagnosed.
-static bool getArchFeatures(const Driver &D, StringRef MArch,
+static bool getArchFeatures(const Driver &D, StringRef Arch,
std::vector<StringRef> &Features,
const ArgList &Args) {
- // RISC-V ISA strings must be lowercase.
- if (llvm::any_of(MArch, [](char c) { return isupper(c); })) {
- D.Diag(diag::err_drv_invalid_riscv_arch_name)
- << MArch << "string must be lowercase";
- return false;
- }
-
- // ISA string must begin with rv32 or rv64.
- if (!(MArch.startswith("rv32") || MArch.startswith("rv64")) ||
- (MArch.size() < 5)) {
- D.Diag(diag::err_drv_invalid_riscv_arch_name)
- << MArch << "string must begin with rv32{i,e,g} or rv64{i,g}";
- return false;
- }
-
- bool HasRV64 = MArch.startswith("rv64");
-
- // The canonical order specified in ISA manual.
- // Ref: Table 22.1 in RISC-V User-Level ISA V2.2
- StringRef StdExts = "mafdqlcbjtpvn";
- bool HasF = false, HasD = false;
- char Baseline = MArch[4];
-
- // First letter should be 'e', 'i' or 'g'.
- switch (Baseline) {
- default:
- D.Diag(diag::err_drv_invalid_riscv_arch_name)
- << MArch << "first letter should be 'e', 'i' or 'g'";
- return false;
- case 'e': {
- StringRef Error;
- // Currently LLVM does not support 'e'.
- // Extension 'e' is not allowed in rv64.
- if (HasRV64)
- Error = "standard user-level extension 'e' requires 'rv32'";
- else
- Error = "unsupported standard user-level extension 'e'";
- D.Diag(diag::err_drv_invalid_riscv_arch_name) << MArch << Error;
- return false;
- }
- case 'i':
- break;
- case 'g':
- // g = imafd
- StdExts = StdExts.drop_front(4);
- Features.push_back("+m");
- Features.push_back("+a");
- Features.push_back("+f");
- Features.push_back("+d");
- HasF = true;
- HasD = true;
- break;
- }
-
- // Skip rvxxx
- StringRef Exts = MArch.substr(5);
-
- // Remove multi-letter standard extensions, non-standard extensions and
- // supervisor-level extensions. They have 'z', 'x', 's', 'sx' prefixes.
- // Parse them at the end.
- // Find the very first occurrence of 's', 'x' or 'z'.
- StringRef OtherExts;
- size_t Pos = Exts.find_first_of("zsx");
- if (Pos != StringRef::npos) {
- OtherExts = Exts.substr(Pos);
- Exts = Exts.substr(0, Pos);
- }
+ bool EnableExperimentalExtensions =
+ Args.hasArg(options::OPT_menable_experimental_extensions);
+ auto ISAInfo =
+ llvm::RISCVISAInfo::parseArchString(Arch, EnableExperimentalExtensions);
+ if (!ISAInfo) {
+ handleAllErrors(ISAInfo.takeError(), [&](llvm::StringError &ErrMsg) {
+ D.Diag(diag::err_drv_invalid_riscv_arch_name)
+ << Arch << ErrMsg.getMessage();
+ });
- std::string Major, Minor;
- if (!getExtensionVersion(D, Args, MArch, std::string(1, Baseline), Exts,
- Major, Minor))
return false;
-
- // Consume the base ISA version number and any '_' between rvxxx and the
- // first extension
- Exts = Exts.drop_front(Major.size());
- if (!Minor.empty())
- Exts = Exts.drop_front(Minor.size() + 1 /*'p'*/);
- Exts.consume_front("_");
-
- // TODO: Use version number when setting target features
-
- auto StdExtsItr = StdExts.begin();
- auto StdExtsEnd = StdExts.end();
-
- for (auto I = Exts.begin(), E = Exts.end(); I != E; ) {
- char c = *I;
-
- // Check ISA extensions are specified in the canonical order.
- while (StdExtsItr != StdExtsEnd && *StdExtsItr != c)
- ++StdExtsItr;
-
- if (StdExtsItr == StdExtsEnd) {
- // Either c contains a valid extension but it was not given in
- // canonical order or it is an invalid extension.
- StringRef Error;
- if (StdExts.contains(c))
- Error = "standard user-level extension not given in canonical order";
- else
- Error = "invalid standard user-level extension";
- D.Diag(diag::err_drv_invalid_riscv_ext_arch_name)
- << MArch << Error << std::string(1, c);
- return false;
- }
-
- // Move to next char to prevent repeated letter.
- ++StdExtsItr;
-
- std::string Next, Major, Minor;
- if (std::next(I) != E)
- Next = std::string(std::next(I), E);
- if (!getExtensionVersion(D, Args, MArch, std::string(1, c), Next, Major,
- Minor))
- return false;
-
- // The order is OK, then push it into features.
- // TODO: Use version number when setting target features
- switch (c) {
- default:
- // Currently LLVM supports only "mafdc".
- D.Diag(diag::err_drv_invalid_riscv_ext_arch_name)
- << MArch << "unsupported standard user-level extension"
- << std::string(1, c);
- return false;
- case 'm':
- Features.push_back("+m");
- break;
- case 'a':
- Features.push_back("+a");
- break;
- case 'f':
- Features.push_back("+f");
- HasF = true;
- break;
- case 'd':
- Features.push_back("+d");
- HasD = true;
- break;
- case 'c':
- Features.push_back("+c");
- break;
- case 'b':
- Features.push_back("+experimental-b");
- Features.push_back("+experimental-zba");
- Features.push_back("+experimental-zbb");
- Features.push_back("+experimental-zbc");
- Features.push_back("+experimental-zbe");
- Features.push_back("+experimental-zbf");
- Features.push_back("+experimental-zbm");
- Features.push_back("+experimental-zbp");
- Features.push_back("+experimental-zbr");
- Features.push_back("+experimental-zbs");
- Features.push_back("+experimental-zbt");
- break;
- case 'v':
- Features.push_back("+experimental-v");
- Features.push_back("+experimental-zvlsseg");
- break;
- }
-
- // Consume full extension name and version, including any optional '_'
- // between this extension and the next
- ++I;
- I += Major.size();
- if (Minor.size())
- I += Minor.size() + 1 /*'p'*/;
- if (*I == '_')
- ++I;
}
- // Dependency check.
- // It's illegal to specify the 'd' (double-precision floating point)
- // extension without also specifying the 'f' (single precision
- // floating-point) extension.
- if (HasD && !HasF) {
- D.Diag(diag::err_drv_invalid_riscv_arch_name)
- << MArch << "d requires f extension to also be specified";
- return false;
- }
-
- // Additional dependency checks.
- // TODO: The 'q' extension requires rv64.
- // TODO: It is illegal to specify 'e' extensions with 'f' and 'd'.
-
- // Handle all other types of extensions.
- getExtensionFeatures(D, Args, Features, MArch, OtherExts);
-
+ (*ISAInfo)->toFeatures(
+ Features, [&Args](const Twine &Str) { return Args.MakeArgString(Str); });
return true;
}
@@ -610,24 +190,30 @@ StringRef riscv::getRISCVABI(const ArgList &Args, const llvm::Triple &Triple) {
// rv32* -> ilp32
// rv64g | rv64*d -> lp64d
// rv64* -> lp64
- StringRef MArch = getRISCVArch(Args, Triple);
+ StringRef Arch = getRISCVArch(Args, Triple);
- if (MArch.startswith_insensitive("rv32")) {
- // FIXME: parse `March` to find `D` extension properly
- if (MArch.substr(4).contains_insensitive("d") ||
- MArch.startswith_insensitive("rv32g"))
- return "ilp32d";
- else if (MArch.startswith_insensitive("rv32e"))
- return "ilp32e";
- else
+ auto ParseResult = llvm::RISCVISAInfo::parseArchString(
+ Arch, /* EnableExperimentalExtension */ true);
+ if (!ParseResult) {
+ // Ignore parsing error, just go 3rd step.
+ consumeError(ParseResult.takeError());
+ } else {
+ auto &ISAInfo = *ParseResult;
+ bool HasD = ISAInfo->hasExtension("d");
+ unsigned XLen = ISAInfo->getXLen();
+ if (XLen == 32) {
+ bool HasE = ISAInfo->hasExtension("e");
+ if (HasD)
+ return "ilp32d";
+ if (HasE)
+ return "ilp32e";
return "ilp32";
- } else if (MArch.startswith_insensitive("rv64")) {
- // FIXME: parse `March` to find `D` extension properly
- if (MArch.substr(4).contains_insensitive("d") ||
- MArch.startswith_insensitive("rv64g"))
- return "lp64d";
- else
+ } else if (XLen == 64) {
+ if (HasD)
+ return "lp64d";
return "lp64";
+ }
+ llvm_unreachable("unhandled XLen");
}
// 3. Choose a default based on the triple
diff --git a/clang/lib/Driver/ToolChains/Arch/X86.cpp b/clang/lib/Driver/ToolChains/Arch/X86.cpp
index 12749c7ec871..bfa008f964e1 100644
--- a/clang/lib/Driver/ToolChains/Arch/X86.cpp
+++ b/clang/lib/Driver/ToolChains/Arch/X86.cpp
@@ -11,6 +11,8 @@
#include "clang/Driver/Driver.h"
#include "clang/Driver/DriverDiagnostic.h"
#include "clang/Driver/Options.h"
+#include "llvm/ADT/StringExtras.h"
+#include "llvm/ADT/StringMap.h"
#include "llvm/ADT/StringSwitch.h"
#include "llvm/Option/ArgList.h"
#include "llvm/Support/Host.h"
@@ -20,7 +22,7 @@ using namespace clang::driver::tools;
using namespace clang;
using namespace llvm::opt;
-std::string x86::getX86TargetCPU(const ArgList &Args,
+std::string x86::getX86TargetCPU(const Driver &D, const ArgList &Args,
const llvm::Triple &Triple) {
if (const Arg *A = Args.getLastArg(clang::driver::options::OPT_march_EQ)) {
StringRef CPU = A->getValue();
@@ -37,29 +39,34 @@ std::string x86::getX86TargetCPU(const ArgList &Args,
return std::string(CPU);
}
- if (const Arg *A = Args.getLastArgNoClaim(options::OPT__SLASH_arch)) {
+ if (const Arg *A = Args.getLastArg(options::OPT__SLASH_arch)) {
// Mapping built by looking at lib/Basic's X86TargetInfo::initFeatureMap().
- StringRef Arch = A->getValue();
- StringRef CPU;
- if (Triple.getArch() == llvm::Triple::x86) { // 32-bit-only /arch: flags.
- CPU = llvm::StringSwitch<StringRef>(Arch)
- .Case("IA32", "i386")
- .Case("SSE", "pentium3")
- .Case("SSE2", "pentium4")
- .Default("");
+ // The keys are case-sensitive; this matches link.exe.
+ // 32-bit and 64-bit /arch: flags.
+ llvm::StringMap<StringRef> ArchMap({
+ {"AVX", "sandybridge"},
+ {"AVX2", "haswell"},
+ {"AVX512F", "knl"},
+ {"AVX512", "skylake-avx512"},
+ });
+ if (Triple.getArch() == llvm::Triple::x86) {
+ // 32-bit-only /arch: flags.
+ ArchMap.insert({
+ {"IA32", "i386"},
+ {"SSE", "pentium3"},
+ {"SSE2", "pentium4"},
+ });
}
- if (CPU.empty()) { // 32-bit and 64-bit /arch: flags.
- CPU = llvm::StringSwitch<StringRef>(Arch)
- .Case("AVX", "sandybridge")
- .Case("AVX2", "haswell")
- .Case("AVX512F", "knl")
- .Case("AVX512", "skylake-avx512")
- .Default("");
- }
- if (!CPU.empty()) {
- A->claim();
- return std::string(CPU);
+ StringRef CPU = ArchMap.lookup(A->getValue());
+ if (CPU.empty()) {
+ std::vector<StringRef> ValidArchs{ArchMap.keys().begin(),
+ ArchMap.keys().end()};
+ sort(ValidArchs);
+ D.Diag(diag::warn_drv_invalid_arch_name_with_suggestion)
+ << A->getValue() << (Triple.getArch() == llvm::Triple::x86)
+ << join(ValidArchs, ", ");
}
+ return std::string(CPU);
}
// Select the default CPU if none was given (or detection failed).
diff --git a/clang/lib/Driver/ToolChains/Arch/X86.h b/clang/lib/Driver/ToolChains/Arch/X86.h
index 14f0a26c8be4..36a2ab52899d 100644
--- a/clang/lib/Driver/ToolChains/Arch/X86.h
+++ b/clang/lib/Driver/ToolChains/Arch/X86.h
@@ -21,7 +21,7 @@ namespace driver {
namespace tools {
namespace x86 {
-std::string getX86TargetCPU(const llvm::opt::ArgList &Args,
+std::string getX86TargetCPU(const Driver &D, const llvm::opt::ArgList &Args,
const llvm::Triple &Triple);
void getX86TargetFeatures(const Driver &D, const llvm::Triple &Triple,
diff --git a/clang/lib/Driver/ToolChains/BareMetal.cpp b/clang/lib/Driver/ToolChains/BareMetal.cpp
index ce73e39d1456..cd07692be358 100644
--- a/clang/lib/Driver/ToolChains/BareMetal.cpp
+++ b/clang/lib/Driver/ToolChains/BareMetal.cpp
@@ -125,6 +125,20 @@ static bool isARMBareMetal(const llvm::Triple &Triple) {
return true;
}
+/// Is the triple aarch64-none-elf?
+static bool isAArch64BareMetal(const llvm::Triple &Triple) {
+ if (Triple.getArch() != llvm::Triple::aarch64)
+ return false;
+
+ if (Triple.getVendor() != llvm::Triple::UnknownVendor)
+ return false;
+
+ if (Triple.getOS() != llvm::Triple::UnknownOS)
+ return false;
+
+ return Triple.getEnvironmentName() == "elf";
+}
+
static bool isRISCVBareMetal(const llvm::Triple &Triple) {
if (Triple.getArch() != llvm::Triple::riscv32 &&
Triple.getArch() != llvm::Triple::riscv64)
@@ -151,7 +165,8 @@ void BareMetal::findMultilibs(const Driver &D, const llvm::Triple &Triple,
}
bool BareMetal::handlesTarget(const llvm::Triple &Triple) {
- return isARMBareMetal(Triple) || isRISCVBareMetal(Triple);
+ return isARMBareMetal(Triple) || isAArch64BareMetal(Triple) ||
+ isRISCVBareMetal(Triple);
}
Tool *BareMetal::buildLinker() const {
diff --git a/clang/lib/Driver/ToolChains/BareMetal.h b/clang/lib/Driver/ToolChains/BareMetal.h
index d68c43c64c97..dc718e09ad43 100644
--- a/clang/lib/Driver/ToolChains/BareMetal.h
+++ b/clang/lib/Driver/ToolChains/BareMetal.h
@@ -42,7 +42,9 @@ public:
bool useIntegratedAs() const override { return true; }
bool isCrossCompiling() const override { return true; }
bool isPICDefault() const override { return false; }
- bool isPIEDefault() const override { return false; }
+ bool isPIEDefault(const llvm::opt::ArgList &Args) const override {
+ return false;
+ }
bool isPICDefaultForced() const override { return false; }
bool SupportsProfiling() const override { return false; }
diff --git a/clang/lib/Driver/ToolChains/Clang.cpp b/clang/lib/Driver/ToolChains/Clang.cpp
index a4b53a640ab5..e5476e07a5cc 100644
--- a/clang/lib/Driver/ToolChains/Clang.cpp
+++ b/clang/lib/Driver/ToolChains/Clang.cpp
@@ -22,6 +22,7 @@
#include "Hexagon.h"
#include "MSP430.h"
#include "PS4CPU.h"
+#include "clang/Basic/CLWarnings.h"
#include "clang/Basic/CharInfo.h"
#include "clang/Basic/CodeGenOptions.h"
#include "clang/Basic/LangOptions.h"
@@ -612,7 +613,8 @@ getFramePointerKind(const ArgList &Args, const llvm::Triple &Triple) {
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.isAArch64() || Triple.isPS4CPU() ||
+ Triple.isVE());
if (NoOmitFP || mustUseNonLeafFramePointerForTarget(Triple) ||
(!OmitFP && useFramePointerForTargetByDefault(Args, Triple))) {
if (OmitLeafFP)
@@ -643,7 +645,7 @@ static void addDebugPrefixMapArg(const Driver &D, const ArgList &Args, ArgString
for (const Arg *A : Args.filtered(options::OPT_ffile_prefix_map_EQ,
options::OPT_fdebug_prefix_map_EQ)) {
StringRef Map = A->getValue();
- if (Map.find('=') == StringRef::npos)
+ if (!Map.contains('='))
D.Diag(diag::err_drv_invalid_argument_to_option)
<< Map << A->getOption().getName();
else
@@ -658,7 +660,7 @@ static void addMacroPrefixMapArg(const Driver &D, const ArgList &Args,
for (const Arg *A : Args.filtered(options::OPT_ffile_prefix_map_EQ,
options::OPT_fmacro_prefix_map_EQ)) {
StringRef Map = A->getValue();
- if (Map.find('=') == StringRef::npos)
+ if (!Map.contains('='))
D.Diag(diag::err_drv_invalid_argument_to_option)
<< Map << A->getOption().getName();
else
@@ -673,7 +675,7 @@ static void addCoveragePrefixMapArg(const Driver &D, const ArgList &Args,
for (const Arg *A : Args.filtered(options::OPT_ffile_prefix_map_EQ,
options::OPT_fcoverage_prefix_map_EQ)) {
StringRef Map = A->getValue();
- if (Map.find('=') == StringRef::npos)
+ if (!Map.contains('='))
D.Diag(diag::err_drv_invalid_argument_to_option)
<< Map << A->getOption().getName();
else
@@ -748,7 +750,7 @@ static void addDashXForInput(const ArgList &Args, const InputInfo &Input,
static void addPGOAndCoverageFlags(const ToolChain &TC, Compilation &C,
const Driver &D, const InputInfo &Output,
- const ArgList &Args,
+ const ArgList &Args, SanitizerArgs &SanArgs,
ArgStringList &CmdArgs) {
auto *PGOGenerateArg = Args.getLastArg(options::OPT_fprofile_generate,
@@ -795,11 +797,6 @@ static void addPGOAndCoverageFlags(const ToolChain &TC, Compilation &C,
}
if (TC.getTriple().isOSAIX()) {
- if (PGOGenerateArg)
- if (!D.isUsingLTO(false /*IsDeviceOffloadAction */) ||
- D.getLTOMode() != LTOK_Full)
- D.Diag(clang::diag::err_drv_argument_only_allowed_with)
- << PGOGenerateArg->getSpelling() << "-flto";
if (ProfileGenerateArg)
D.Diag(diag::err_drv_unsupported_opt_for_target)
<< ProfileGenerateArg->getSpelling() << TC.getTriple().str();
@@ -927,7 +924,7 @@ static void addPGOAndCoverageFlags(const ToolChain &TC, Compilation &C,
else if (Val != "single")
D.Diag(diag::err_drv_unsupported_option_argument)
<< A->getOption().getName() << Val;
- } else if (TC.getSanitizerArgs().needsTsanRt()) {
+ } else if (SanArgs.needsTsanRt()) {
CmdArgs.push_back("-fprofile-update=atomic");
}
@@ -1256,7 +1253,8 @@ 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) &&
- getToolChain().getTriple().isNVPTX()){
+ (getToolChain().getTriple().isNVPTX() ||
+ getToolChain().getTriple().isAMDGCN())) {
if (!Args.hasArg(options::OPT_nobuiltininc)) {
// Add openmp_wrappers/* to our system include path. This lets us wrap
// standard library headers.
@@ -1587,8 +1585,8 @@ void AddAAPCSVolatileBitfieldArgs(const ArgList &Args, ArgStringList &CmdArgs) {
}
namespace {
-void RenderARMABI(const llvm::Triple &Triple, const ArgList &Args,
- ArgStringList &CmdArgs) {
+void RenderARMABI(const Driver &D, const llvm::Triple &Triple,
+ const ArgList &Args, ArgStringList &CmdArgs) {
// Select the ABI to use.
// FIXME: Support -meabi.
// FIXME: Parts of this are duplicated in the backend, unify this somehow.
@@ -1596,7 +1594,7 @@ void RenderARMABI(const llvm::Triple &Triple, const ArgList &Args,
if (Arg *A = Args.getLastArg(options::OPT_mabi_EQ)) {
ABIName = A->getValue();
} else {
- std::string CPU = getCPUName(Args, Triple, /*FromAs*/ false);
+ std::string CPU = getCPUName(D, Args, Triple, /*FromAs*/ false);
ABIName = llvm::ARM::computeDefaultTargetABI(Triple, CPU).data();
}
@@ -1607,7 +1605,7 @@ void RenderARMABI(const llvm::Triple &Triple, const ArgList &Args,
void Clang::AddARMTargetArgs(const llvm::Triple &Triple, const ArgList &Args,
ArgStringList &CmdArgs, bool KernelOrKext) const {
- RenderARMABI(Triple, Args, CmdArgs);
+ RenderARMABI(getToolChain().getDriver(), Triple, Args, CmdArgs);
// Determine floating point ABI from the options & target defaults.
arm::FloatABI ABI = arm::getARMFloatABI(getToolChain(), Args);
@@ -1825,17 +1823,46 @@ void Clang::AddAArch64TargetArgs(const ArgList &Args,
StringRef Val = A->getValue();
const Driver &D = getToolChain().getDriver();
if (Val.equals("128") || Val.equals("256") || Val.equals("512") ||
- Val.equals("1024") || Val.equals("2048"))
+ Val.equals("1024") || Val.equals("2048") || Val.equals("128+") ||
+ Val.equals("256+") || Val.equals("512+") || Val.equals("1024+") ||
+ Val.equals("2048+")) {
+ unsigned Bits = 0;
+ if (Val.endswith("+"))
+ Val = Val.substr(0, Val.size() - 1);
+ else {
+ bool Invalid = Val.getAsInteger(10, Bits); (void)Invalid;
+ assert(!Invalid && "Failed to parse value");
+ CmdArgs.push_back(
+ Args.MakeArgString("-mvscale-max=" + llvm::Twine(Bits / 128)));
+ }
+
+ bool Invalid = Val.getAsInteger(10, Bits); (void)Invalid;
+ assert(!Invalid && "Failed to parse value");
CmdArgs.push_back(
- Args.MakeArgString(llvm::Twine("-msve-vector-bits=") + Val));
+ Args.MakeArgString("-mvscale-min=" + llvm::Twine(Bits / 128)));
// Silently drop requests for vector-length agnostic code as it's implied.
- else if (!Val.equals("scalable"))
+ } else if (!Val.equals("scalable"))
// Handle the unsupported values passed to msve-vector-bits.
D.Diag(diag::err_drv_unsupported_option_argument)
<< A->getOption().getName() << Val;
}
AddAAPCSVolatileBitfieldArgs(Args, CmdArgs);
+
+ if (const Arg *A = Args.getLastArg(clang::driver::options::OPT_mtune_EQ)) {
+ StringRef Name = A->getValue();
+
+ std::string TuneCPU;
+ if (Name == "native")
+ TuneCPU = std::string(llvm::sys::getHostCPUName());
+ else
+ TuneCPU = std::string(Name);
+
+ if (!TuneCPU.empty()) {
+ CmdArgs.push_back("-tune-cpu");
+ CmdArgs.push_back(Args.MakeArgString(TuneCPU));
+ }
+ }
}
void Clang::AddMIPSTargetArgs(const ArgList &Args,
@@ -2173,6 +2200,7 @@ void Clang::AddX86TargetArgs(const ArgList &Args,
if (Value == "intel" || Value == "att") {
CmdArgs.push_back("-mllvm");
CmdArgs.push_back(Args.MakeArgString("-x86-asm-syntax=" + Value));
+ CmdArgs.push_back(Args.MakeArgString("-inline-asm=" + Value));
} else {
D.Diag(diag::err_drv_unsupported_option_argument)
<< A->getOption().getName() << Value;
@@ -2182,6 +2210,11 @@ void Clang::AddX86TargetArgs(const ArgList &Args,
CmdArgs.push_back("-x86-asm-syntax=intel");
}
+ if (Arg *A = Args.getLastArg(options::OPT_mskip_rax_setup,
+ options::OPT_mno_skip_rax_setup))
+ if (A->getOption().matches(options::OPT_mskip_rax_setup))
+ CmdArgs.push_back(Args.MakeArgString("-mskip-rax-setup"));
+
// Set flags to support MCU ABI.
if (Args.hasFlag(options::OPT_miamcu, options::OPT_mno_iamcu, false)) {
CmdArgs.push_back("-mfloat-abi");
@@ -2411,7 +2444,7 @@ static void CollectArgsForIntegratedAssembler(Compilation &C,
bool TakeNextArg = false;
bool UseRelaxRelocations = C.getDefaultToolChain().useRelaxRelocations();
- bool UseNoExecStack = C.getDefaultToolChain().isNoExecStackDefault();
+ bool UseNoExecStack = false;
const char *MipsTargetFeature = nullptr;
StringRef ImplicitIt;
for (const Arg *A :
@@ -2617,6 +2650,7 @@ static void RenderFloatingPointOptions(const ToolChain &TC, const Driver &D,
// LLVM flags based on the final state.
bool HonorINFs = true;
bool HonorNaNs = true;
+ bool ApproxFunc = false;
// -fmath-errno is the default on some platforms, e.g. BSD-derived OSes.
bool MathErrno = TC.IsMathErrnoDefault();
bool AssociativeMath = false;
@@ -2638,10 +2672,14 @@ static void RenderFloatingPointOptions(const ToolChain &TC, const Driver &D,
llvm::DenormalMode DenormalFPMath = DefaultDenormalFPMath;
llvm::DenormalMode DenormalFP32Math = DefaultDenormalFP32Math;
- StringRef FPContract = "on";
+ // CUDA and HIP don't rely on the frontend to pass an ffp-contract option.
+ // If one wasn't given by the user, don't pass it here.
+ StringRef FPContract;
+ if (!JA.isDeviceOffloading(Action::OFK_Cuda) &&
+ !JA.isOffloading(Action::OFK_HIP))
+ FPContract = "on";
bool StrictFPModel = false;
-
if (const Arg *A = Args.getLastArg(options::OPT_flimited_precision_EQ)) {
CmdArgs.push_back("-mlimit-float-precision");
CmdArgs.push_back(A->getValue());
@@ -2685,12 +2723,12 @@ static void RenderFloatingPointOptions(const ToolChain &TC, const Driver &D,
// Use the gcc option in the switch below.
if (!FPModel.empty() && !FPModel.equals(Val))
D.Diag(clang::diag::warn_drv_overriding_flag_option)
- << Args.MakeArgString("-ffp-model=" + FPModel)
- << Args.MakeArgString("-ffp-model=" + Val);
+ << Args.MakeArgString("-ffp-model=" + FPModel)
+ << Args.MakeArgString("-ffp-model=" + Val);
if (Val.equals("fast")) {
optID = options::OPT_ffast_math;
FPModel = Val;
- FPContract = Val;
+ FPContract = "fast";
} else if (Val.equals("precise")) {
optID = options::OPT_ffp_contract;
FPModel = Val;
@@ -2719,6 +2757,8 @@ static void RenderFloatingPointOptions(const ToolChain &TC, const Driver &D,
case options::OPT_fno_honor_infinities: HonorINFs = false; break;
case options::OPT_fhonor_nans: HonorNaNs = true; break;
case options::OPT_fno_honor_nans: HonorNaNs = false; break;
+ case options::OPT_fapprox_func: ApproxFunc = true; break;
+ case options::OPT_fno_approx_func: ApproxFunc = false; break;
case options::OPT_fmath_errno: MathErrno = true; break;
case options::OPT_fno_math_errno: MathErrno = false; break;
case options::OPT_fassociative_math: AssociativeMath = true; break;
@@ -2780,11 +2820,9 @@ static void RenderFloatingPointOptions(const ToolChain &TC, const Driver &D,
case options::OPT_ffp_contract: {
StringRef Val = A->getValue();
if (PreciseFPModel) {
- // When -ffp-model=precise is seen on the command line,
- // the boolean PreciseFPModel is set to true which indicates
- // "the current option is actually PreciseFPModel". The optID
- // is changed to OPT_ffp_contract and FPContract is set to "on".
- // the argument Val string is "precise": it shouldn't be checked.
+ // -ffp-model=precise enables ffp-contract=on.
+ // -ffp-model=precise sets PreciseFPModel to on and Val to
+ // "precise". FPContract is set.
;
} else if (Val.equals("fast") || Val.equals("on") || Val.equals("off"))
FPContract = Val;
@@ -2877,12 +2915,17 @@ static void RenderFloatingPointOptions(const ToolChain &TC, const Driver &D,
AssociativeMath = false;
ReciprocalMath = false;
SignedZeros = true;
- TrappingMath = false;
- RoundingFPMath = false;
// -fno_fast_math restores default denormal and fpcontract handling
DenormalFPMath = DefaultDenormalFPMath;
DenormalFP32Math = llvm::DenormalMode::getIEEE();
- FPContract = "on";
+ if (!JA.isDeviceOffloading(Action::OFK_Cuda) &&
+ !JA.isOffloading(Action::OFK_HIP))
+ if (FPContract == "fast") {
+ FPContract = "on";
+ D.Diag(clang::diag::warn_drv_overriding_flag_option)
+ << "-ffp-contract=fast"
+ << "-ffp-contract=on";
+ }
break;
}
if (StrictFPModel) {
@@ -2915,6 +2958,9 @@ static void RenderFloatingPointOptions(const ToolChain &TC, const Driver &D,
if (!HonorNaNs)
CmdArgs.push_back("-menable-no-nans");
+ if (ApproxFunc)
+ CmdArgs.push_back("-fapprox-func");
+
if (MathErrno)
CmdArgs.push_back("-fmath-errno");
@@ -3128,14 +3174,44 @@ static void RenderSSPOptions(const Driver &D, const ToolChain &TC,
const std::string &TripleStr = EffectiveTriple.getTriple();
if (Arg *A = Args.getLastArg(options::OPT_mstack_protector_guard_EQ)) {
StringRef Value = A->getValue();
- if (!EffectiveTriple.isX86() && !EffectiveTriple.isAArch64())
+ if (!EffectiveTriple.isX86() && !EffectiveTriple.isAArch64() &&
+ !EffectiveTriple.isARM() && !EffectiveTriple.isThumb())
D.Diag(diag::err_drv_unsupported_opt_for_target)
<< A->getAsString(Args) << TripleStr;
- if (EffectiveTriple.isX86() && Value != "tls" && Value != "global") {
+ if ((EffectiveTriple.isX86() || EffectiveTriple.isARM() ||
+ EffectiveTriple.isThumb()) &&
+ Value != "tls" && Value != "global") {
D.Diag(diag::err_drv_invalid_value_with_suggestion)
<< A->getOption().getName() << Value << "tls global";
return;
}
+ if ((EffectiveTriple.isARM() || EffectiveTriple.isThumb()) &&
+ Value == "tls") {
+ if (!Args.hasArg(options::OPT_mstack_protector_guard_offset_EQ)) {
+ D.Diag(diag::err_drv_ssp_missing_offset_argument)
+ << A->getAsString(Args);
+ return;
+ }
+ // Check whether the target subarch supports the hardware TLS register
+ if (arm::getARMSubArchVersionNumber(EffectiveTriple) < 7 &&
+ llvm::ARM::parseArch(EffectiveTriple.getArchName()) !=
+ llvm::ARM::ArchKind::ARMV6T2) {
+ D.Diag(diag::err_target_unsupported_tp_hard)
+ << EffectiveTriple.getArchName();
+ return;
+ }
+ // Check whether the user asked for something other than -mtp=cp15
+ if (Arg *A = Args.getLastArg(options::OPT_mtp_mode_EQ)) {
+ StringRef Value = A->getValue();
+ if (Value != "cp15") {
+ D.Diag(diag::err_drv_argument_not_allowed_with)
+ << A->getAsString(Args) << "-mstack-protector-guard=tls";
+ return;
+ }
+ }
+ CmdArgs.push_back("-target-feature");
+ CmdArgs.push_back("+read-tp-hard");
+ }
if (EffectiveTriple.isAArch64() && Value != "sysreg" && Value != "global") {
D.Diag(diag::err_drv_invalid_value_with_suggestion)
<< A->getOption().getName() << Value << "sysreg global";
@@ -3146,7 +3222,8 @@ static void RenderSSPOptions(const Driver &D, const ToolChain &TC,
if (Arg *A = Args.getLastArg(options::OPT_mstack_protector_guard_offset_EQ)) {
StringRef Value = A->getValue();
- if (!EffectiveTriple.isX86() && !EffectiveTriple.isAArch64())
+ if (!EffectiveTriple.isX86() && !EffectiveTriple.isAArch64() &&
+ !EffectiveTriple.isARM() && !EffectiveTriple.isThumb())
D.Diag(diag::err_drv_unsupported_opt_for_target)
<< A->getAsString(Args) << TripleStr;
int Offset;
@@ -3154,6 +3231,12 @@ static void RenderSSPOptions(const Driver &D, const ToolChain &TC,
D.Diag(diag::err_drv_invalid_value) << A->getOption().getName() << Value;
return;
}
+ if ((EffectiveTriple.isARM() || EffectiveTriple.isThumb()) &&
+ (Offset < 0 || Offset > 0xfffff)) {
+ D.Diag(diag::err_drv_invalid_int_value)
+ << A->getOption().getName() << Value;
+ return;
+ }
A->render(Args, CmdArgs);
}
@@ -3179,7 +3262,7 @@ static void RenderSCPOptions(const ToolChain &TC, const ArgList &Args,
ArgStringList &CmdArgs) {
const llvm::Triple &EffectiveTriple = TC.getEffectiveTriple();
- if (!EffectiveTriple.isOSLinux())
+ if (!EffectiveTriple.isOSFreeBSD() && !EffectiveTriple.isOSLinux())
return;
if (!EffectiveTriple.isX86() && !EffectiveTriple.isSystemZ() &&
@@ -3354,7 +3437,7 @@ static void RenderARCMigrateToolOptions(const Driver &D, const ArgList &Args,
Args.AddLastArg(CmdArgs, options::OPT_objcmt_returns_innerpointer_property);
Args.AddLastArg(CmdArgs, options::OPT_objcmt_ns_nonatomic_iosonly);
Args.AddLastArg(CmdArgs, options::OPT_objcmt_migrate_designated_init);
- Args.AddLastArg(CmdArgs, options::OPT_objcmt_whitelist_dir_path);
+ Args.AddLastArg(CmdArgs, options::OPT_objcmt_allowlist_dir_path);
}
}
@@ -3554,11 +3637,11 @@ static void RenderModulesOptions(Compilation &C, const Driver &D,
llvm::sys::fs::file_status Status;
if (llvm::sys::fs::status(A->getValue(), Status))
D.Diag(diag::err_drv_no_such_file) << A->getValue();
- CmdArgs.push_back(
- Args.MakeArgString("-fbuild-session-timestamp=" +
- Twine((uint64_t)Status.getLastModificationTime()
- .time_since_epoch()
- .count())));
+ CmdArgs.push_back(Args.MakeArgString(
+ "-fbuild-session-timestamp=" +
+ Twine((uint64_t)std::chrono::duration_cast<std::chrono::seconds>(
+ Status.getLastModificationTime().time_since_epoch())
+ .count())));
}
if (Args.getLastArg(options::OPT_fmodules_validate_once_per_build_session)) {
@@ -3873,12 +3956,6 @@ static void renderDebugOptions(const ToolChain &TC, const Driver &D,
ArgStringList &CmdArgs,
codegenoptions::DebugInfoKind &DebugInfoKind,
DwarfFissionKind &DwarfFission) {
- // These two forms of profiling info can't be used together.
- if (const Arg *A1 = Args.getLastArg(options::OPT_fpseudo_probe_for_profiling))
- if (const Arg *A2 = Args.getLastArg(options::OPT_fdebug_info_for_profiling))
- D.Diag(diag::err_drv_argument_not_allowed_with)
- << A1->getAsString(Args) << A2->getAsString(Args);
-
if (Args.hasFlag(options::OPT_fdebug_info_for_profiling,
options::OPT_fno_debug_info_for_profiling, false) &&
checkDebugInfoOption(
@@ -4132,6 +4209,29 @@ static void renderDebugOptions(const ToolChain &TC, const Driver &D,
options::OPT_gpubnames)
? "-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);
+ bool ForwardTemplateParams = DebuggerTuning == llvm::DebuggerKind::SCE;
+ if (SimpleTemplateNamesArg &&
+ checkDebugInfoOption(SimpleTemplateNamesArg, Args, D, TC)) {
+ const auto &Opt = SimpleTemplateNamesArg->getOption();
+ 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();
+ }
+ }
+ }
if (Args.hasFlag(options::OPT_fdebug_ranges_base_address,
options::OPT_fno_debug_ranges_base_address, false)) {
@@ -4178,7 +4278,7 @@ static void renderDebugOptions(const ToolChain &TC, const Driver &D,
// Decide how to render forward declarations of template instantiations.
// SCE wants full descriptions, others just get them in the name.
- if (DebuggerTuning == llvm::DebuggerKind::SCE)
+ if (ForwardTemplateParams)
CmdArgs.push_back("-debug-forward-template-params");
// Do we need to explicitly import anonymous namespaces into the parent
@@ -4360,7 +4460,7 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,
TC.addClangWarningOptions(CmdArgs);
// FIXME: Subclass ToolChain for SPIR and move this to addClangWarningOptions.
- if (Triple.isSPIR())
+ if (Triple.isSPIR() || Triple.isSPIRV())
CmdArgs.push_back("-Wspir-compat");
// Select the appropriate action.
@@ -4478,28 +4578,18 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,
CmdArgs.push_back("-emit-llvm-uselists");
if (IsUsingLTO) {
- if (!IsDeviceOffloadAction) {
- if (Args.hasArg(options::OPT_flto))
- CmdArgs.push_back("-flto");
- else {
- if (D.getLTOMode() == LTOK_Thin)
- CmdArgs.push_back("-flto=thin");
- else
- CmdArgs.push_back("-flto=full");
- }
- CmdArgs.push_back("-flto-unit");
- } else if (Triple.isAMDGPU()) {
- // Only AMDGPU supports device-side LTO
- assert(LTOMode == LTOK_Full || LTOMode == LTOK_Thin);
- CmdArgs.push_back(Args.MakeArgString(
- Twine("-flto=") + (LTOMode == LTOK_Thin ? "thin" : "full")));
- CmdArgs.push_back("-flto-unit");
- } else {
+ // Only AMDGPU supports device-side LTO.
+ if (IsDeviceOffloadAction && !Triple.isAMDGPU()) {
D.Diag(diag::err_drv_unsupported_opt_for_target)
<< Args.getLastArg(options::OPT_foffload_lto,
options::OPT_foffload_lto_EQ)
->getAsString(Args)
<< Triple.getTriple();
+ } else {
+ assert(LTOMode == LTOK_Full || LTOMode == LTOK_Thin);
+ CmdArgs.push_back(Args.MakeArgString(
+ Twine("-flto=") + (LTOMode == LTOK_Thin ? "thin" : "full")));
+ CmdArgs.push_back("-flto-unit");
}
}
}
@@ -4537,7 +4627,7 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,
// reject options that shouldn't be supported in bitcode
// also reject kernel/kext
- static const constexpr unsigned kBitcodeOptionBlacklist[] = {
+ static const constexpr unsigned kBitcodeOptionIgnorelist[] = {
options::OPT_mkernel,
options::OPT_fapple_kext,
options::OPT_ffunction_sections,
@@ -4581,8 +4671,7 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,
options::OPT_mllvm,
};
for (const auto &A : Args)
- if (llvm::find(kBitcodeOptionBlacklist, A->getOption().getID()) !=
- std::end(kBitcodeOptionBlacklist))
+ if (llvm::is_contained(kBitcodeOptionIgnorelist, A->getOption().getID()))
D.Diag(diag::err_drv_unsupported_embed_bitcode) << A->getSpelling();
// Render the CodeGen options that need to be passed.
@@ -4599,7 +4688,7 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,
case llvm::Triple::arm:
case llvm::Triple::armeb:
case llvm::Triple::thumbeb:
- RenderARMABI(Triple, Args, CmdArgs);
+ RenderARMABI(D, Triple, Args, CmdArgs);
break;
case llvm::Triple::aarch64:
case llvm::Triple::aarch64_32:
@@ -4650,6 +4739,7 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,
// cleanup.
if (!C.isForDiagnostics())
CmdArgs.push_back("-disable-free");
+ CmdArgs.push_back("-clear-ast-before-backend");
#ifdef NDEBUG
const bool IsAssertBuild = false;
@@ -4665,10 +4755,9 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,
if (Args.hasFlag(options::OPT_fdiscard_value_names,
options::OPT_fno_discard_value_names, !IsAssertBuild)) {
if (Args.hasArg(options::OPT_fdiscard_value_names) &&
- (std::any_of(Inputs.begin(), Inputs.end(),
- [](const clang::driver::InputInfo &II) {
- return types::isLLVMIR(II.getType());
- }))) {
+ llvm::any_of(Inputs, [](const clang::driver::InputInfo &II) {
+ return types::isLLVMIR(II.getType());
+ })) {
D.Diag(diag::warn_ignoring_fdiscard_for_bitcode);
}
CmdArgs.push_back("-discard-value-names");
@@ -4721,6 +4810,22 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,
CmdArgs.push_back(Args.MakeArgString(std::to_string(FunctionAlignment)));
}
+ // We support -falign-loops=N where N is a power of 2. GCC supports more
+ // forms.
+ if (const Arg *A = Args.getLastArg(options::OPT_falign_loops_EQ)) {
+ unsigned Value = 0;
+ if (StringRef(A->getValue()).getAsInteger(10, Value) || Value > 65536)
+ TC.getDriver().Diag(diag::err_drv_invalid_int_value)
+ << A->getAsString(Args) << A->getValue();
+ else if (Value & (Value - 1))
+ TC.getDriver().Diag(diag::err_drv_alignment_not_power_of_two)
+ << A->getAsString(Args) << A->getValue();
+ // Treat =0 as unspecified (use the target preference).
+ if (Value)
+ CmdArgs.push_back(Args.MakeArgString("-falign-loops=" +
+ Twine(std::min(Value, 65536u))));
+ }
+
llvm::Reloc::Model RelocationModel;
unsigned PICLevel;
bool IsPIE;
@@ -5062,9 +5167,9 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,
}
// Enable -mconstructor-aliases except on darwin, where we have to work around
- // a linker bug (see <rdar://problem/7651567>), and CUDA/AMDGPU device code,
- // where aliases aren't supported.
- if (!RawTriple.isOSDarwin() && !RawTriple.isNVPTX() && !RawTriple.isAMDGPU())
+ // a linker bug (see <rdar://problem/7651567>), and CUDA device code, where
+ // aliases aren't supported.
+ if (!RawTriple.isOSDarwin() && !RawTriple.isNVPTX())
CmdArgs.push_back("-mconstructor-aliases");
// Darwin's kernel doesn't support guard variables; just die if we
@@ -5102,16 +5207,18 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,
// This is a coarse approximation of what llvm-gcc actually does, both
// -fasynchronous-unwind-tables and -fnon-call-exceptions interact in more
// complicated ways.
- bool UnwindTables =
- Args.hasFlag(options::OPT_fasynchronous_unwind_tables,
- options::OPT_fno_asynchronous_unwind_tables,
- (TC.IsUnwindTablesDefault(Args) ||
- TC.getSanitizerArgs().needsUnwindTables()) &&
- !Freestanding);
- UnwindTables = Args.hasFlag(options::OPT_funwind_tables,
- options::OPT_fno_unwind_tables, UnwindTables);
- if (UnwindTables)
- CmdArgs.push_back("-munwind-tables");
+ auto SanitizeArgs = TC.getSanitizerArgs(Args);
+ bool AsyncUnwindTables = Args.hasFlag(
+ options::OPT_fasynchronous_unwind_tables,
+ options::OPT_fno_asynchronous_unwind_tables,
+ (TC.IsUnwindTablesDefault(Args) || SanitizeArgs.needsUnwindTables()) &&
+ !Freestanding);
+ bool UnwindTables = Args.hasFlag(options::OPT_funwind_tables,
+ options::OPT_fno_unwind_tables, false);
+ if (AsyncUnwindTables)
+ CmdArgs.push_back("-funwind-tables=2");
+ else if (UnwindTables)
+ CmdArgs.push_back("-funwind-tables=1");
// Prepare `-aux-target-cpu` and `-aux-target-feature` unless
// `--gpu-use-aux-triple-only` is specified.
@@ -5120,7 +5227,7 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,
const ArgList &HostArgs =
C.getArgsForToolChain(nullptr, StringRef(), Action::OFK_None);
std::string HostCPU =
- getCPUName(HostArgs, *TC.getAuxTriple(), /*FromAs*/ false);
+ getCPUName(D, HostArgs, *TC.getAuxTriple(), /*FromAs*/ false);
if (!HostCPU.empty()) {
CmdArgs.push_back("-aux-target-cpu");
CmdArgs.push_back(Args.MakeArgString(HostCPU));
@@ -5162,7 +5269,7 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,
}
// Add the target cpu
- std::string CPU = getCPUName(Args, Triple, /*FromAs*/ false);
+ std::string CPU = getCPUName(D, Args, Triple, /*FromAs*/ false);
if (!CPU.empty()) {
CmdArgs.push_back("-target-cpu");
CmdArgs.push_back(Args.MakeArgString(CPU));
@@ -5346,7 +5453,7 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,
// for sampling, overhead of call arc collection is way too high and there's
// no way to collect the output.
if (!Triple.isNVPTX() && !Triple.isAMDGCN())
- addPGOAndCoverageFlags(TC, C, D, Output, Args, CmdArgs);
+ addPGOAndCoverageFlags(TC, C, D, Output, Args, SanitizeArgs, CmdArgs);
Args.AddLastArg(CmdArgs, options::OPT_fclang_abi_compat_EQ);
@@ -5354,7 +5461,7 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,
if (RawTriple.isPS4CPU() &&
!Args.hasArg(options::OPT_nostdlib, options::OPT_nodefaultlibs)) {
PS4cpu::addProfileRTArgs(TC, Args, CmdArgs);
- PS4cpu::addSanitizerArgs(TC, CmdArgs);
+ PS4cpu::addSanitizerArgs(TC, Args, CmdArgs);
}
// Pass options for controlling the default header search paths.
@@ -5416,7 +5523,26 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,
Args.AddAllArgs(CmdArgs, options::OPT_R_Group);
- Args.AddAllArgs(CmdArgs, options::OPT_W_Group);
+ for (const Arg *A :
+ Args.filtered(options::OPT_W_Group, options::OPT__SLASH_wd)) {
+ A->claim();
+ if (A->getOption().getID() == options::OPT__SLASH_wd) {
+ unsigned WarningNumber;
+ if (StringRef(A->getValue()).getAsInteger(10, WarningNumber)) {
+ D.Diag(diag::err_drv_invalid_int_value)
+ << A->getAsString(Args) << A->getValue();
+ continue;
+ }
+
+ if (auto Group = diagGroupFromCLWarningID(WarningNumber)) {
+ CmdArgs.push_back(Args.MakeArgString(
+ "-Wno-" + DiagnosticIDs::getWarningOptionForGroup(*Group)));
+ }
+ continue;
+ }
+ A->render(Args, CmdArgs);
+ }
+
if (Args.hasFlag(options::OPT_pedantic, options::OPT_no_pedantic, false))
CmdArgs.push_back("-pedantic");
Args.AddLastArg(CmdArgs, options::OPT_pedantic_errors);
@@ -5433,6 +5559,9 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,
Args.AddLastArg(CmdArgs, options::OPT_fexperimental_relative_cxx_abi_vtables,
options::OPT_fno_experimental_relative_cxx_abi_vtables);
+ if (Arg *A = Args.getLastArg(options::OPT_ffuchsia_api_level_EQ))
+ A->render(Args, CmdArgs);
+
// Handle -{std, ansi, trigraphs} -- take the last of -{std, ansi}
// (-ansi is equivalent to -std=c89 or -std=c++98).
//
@@ -5693,7 +5822,7 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,
Args.AddLastArg(CmdArgs, options::OPT_fvisibility_inlines_hidden_static_local_var,
options::OPT_fno_visibility_inlines_hidden_static_local_var);
Args.AddLastArg(CmdArgs, options::OPT_fvisibility_global_new_delete_hidden);
-
+ Args.AddLastArg(CmdArgs, options::OPT_fnew_infallible);
Args.AddLastArg(CmdArgs, options::OPT_ftlsmodel_EQ);
if (Args.hasFlag(options::OPT_fno_operator_names,
@@ -5736,6 +5865,9 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,
options::OPT_fno_openmp_simd);
Args.AddAllArgs(CmdArgs, options::OPT_fopenmp_enable_irbuilder);
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.AddAllArgs(CmdArgs, options::OPT_fopenmp_cuda_number_of_sm_EQ);
Args.AddAllArgs(CmdArgs, options::OPT_fopenmp_cuda_blocks_per_sm_EQ);
Args.AddAllArgs(CmdArgs,
@@ -5751,12 +5883,36 @@ 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=*/false))
+ 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,
+ options::OPT_fno_openmp_target_debug, /*Default=*/false))
+ CmdArgs.push_back("-fopenmp-target-debug");
+
// When in OpenMP offloading mode with NVPTX target, check if full runtime
// is required.
if (Args.hasFlag(options::OPT_fopenmp_cuda_force_full_runtime,
options::OPT_fno_openmp_cuda_force_full_runtime,
/*Default=*/false))
CmdArgs.push_back("-fopenmp-cuda-force-full-runtime");
+
+ // When in OpenMP offloading mode, forward assumptions information about
+ // thread and team counts in the device.
+ if (Args.hasFlag(options::OPT_fopenmp_assume_teams_oversubscription,
+ options::OPT_fno_openmp_assume_teams_oversubscription,
+ /*Default=*/false))
+ CmdArgs.push_back("-fopenmp-assume-teams-oversubscription");
+ if (Args.hasFlag(options::OPT_fopenmp_assume_threads_oversubscription,
+ options::OPT_fno_openmp_assume_threads_oversubscription,
+ /*Default=*/false))
+ CmdArgs.push_back("-fopenmp-assume-threads-oversubscription");
break;
default:
// By default, if Clang doesn't know how to generate useful OpenMP code
@@ -5771,10 +5927,12 @@ 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");
}
- const SanitizerArgs &Sanitize = TC.getSanitizerArgs();
- Sanitize.addArgs(TC, Args, CmdArgs, InputType);
+ SanitizeArgs.addArgs(TC, Args, CmdArgs, InputType);
const XRayArgs &XRay = TC.getXRayArgs();
XRay.addArgs(TC, Args, CmdArgs, InputType);
@@ -5891,6 +6049,8 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,
RenderSCPOptions(TC, Args, CmdArgs);
RenderTrivialAutoVarInitOptions(D, TC, Args, CmdArgs);
+ Args.AddLastArg(CmdArgs, options::OPT_fswift_async_fp_EQ);
+
// Translate -mstackrealign
if (Args.hasFlag(options::OPT_mstackrealign, options::OPT_mno_stackrealign,
false))
@@ -6175,7 +6335,8 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,
// than 19.
if (!Args.hasFlag(options::OPT_fthreadsafe_statics,
options::OPT_fno_threadsafe_statics,
- !IsWindowsMSVC || IsMSVC2015Compatible))
+ !types::isOpenCL(InputType) &&
+ (!IsWindowsMSVC || IsMSVC2015Compatible)))
CmdArgs.push_back("-fno-threadsafe-statics");
// -fno-delayed-template-parsing is default, except when targeting MSVC.
@@ -6715,12 +6876,12 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,
}
bool DefaultsSplitLTOUnit =
- (WholeProgramVTables || Sanitize.needsLTO()) &&
+ (WholeProgramVTables || SanitizeArgs.needsLTO()) &&
(LTOMode == LTOK_Full || TC.canSplitThinLTOUnit());
bool SplitLTOUnit =
Args.hasFlag(options::OPT_fsplit_lto_unit,
options::OPT_fno_split_lto_unit, DefaultsSplitLTOUnit);
- if (Sanitize.needsLTO() && !SplitLTOUnit)
+ if (SanitizeArgs.needsLTO() && !SplitLTOUnit)
D.Diag(diag::err_drv_argument_not_allowed_with) << "-fno-split-lto-unit"
<< "-fsanitize=cfi";
if (SplitLTOUnit)
@@ -6819,7 +6980,8 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,
CmdArgs.push_back("-faddrsig");
if ((Triple.isOSBinFormatELF() || Triple.isOSBinFormatMachO()) &&
- (EH || UnwindTables || DebugInfoKind != codegenoptions::NoDebugInfo))
+ (EH || AsyncUnwindTables || UnwindTables ||
+ DebugInfoKind != codegenoptions::NoDebugInfo))
CmdArgs.push_back("-D__GCC_HAVE_DWARF2_CFI_ASM=1");
if (Arg *A = Args.getLastArg(options::OPT_fsymbol_partition_EQ)) {
@@ -7431,7 +7593,7 @@ void ClangAs::ConstructJob(Compilation &C, const JobAction &JA,
CmdArgs.push_back(Clang::getBaseInputName(Args, Input));
// Add the target cpu
- std::string CPU = getCPUName(Args, Triple, /*FromAs*/ true);
+ std::string CPU = getCPUName(D, Args, Triple, /*FromAs*/ true);
if (!CPU.empty()) {
CmdArgs.push_back("-target-cpu");
CmdArgs.push_back(Args.MakeArgString(CPU));
@@ -7667,18 +7829,30 @@ void OffloadBundler::ConstructJob(Compilation &C, const JobAction &JA,
});
}
Triples += Action::GetOffloadKindName(CurKind);
- Triples += "-";
- std::string NormalizedTriple = CurTC->getTriple().normalize();
- Triples += NormalizedTriple;
-
- if (CurDep->getOffloadingArch() != nullptr) {
- // If OffloadArch is present it can only appear as the 6th hypen
- // sepearated field of Bundle Entry ID. So, pad required number of
- // hyphens in Triple.
- for (int i = 4 - StringRef(NormalizedTriple).count("-"); i > 0; i--)
- Triples += "-";
+ Triples += '-';
+ Triples += CurTC->getTriple().normalize();
+ if ((CurKind == Action::OFK_HIP || CurKind == Action::OFK_Cuda) &&
+ CurDep->getOffloadingArch()) {
+ Triples += '-';
Triples += CurDep->getOffloadingArch();
}
+
+ // TODO: Replace parsing of -march flag. Can be done by storing GPUArch
+ // with each toolchain.
+ StringRef GPUArchName;
+ if (CurKind == Action::OFK_OpenMP) {
+ // Extract GPUArch from -march argument in TC argument list.
+ for (unsigned ArgIndex = 0; ArgIndex < TCArgs.size(); ArgIndex++) {
+ auto ArchStr = StringRef(TCArgs.getArgString(ArgIndex));
+ auto Arch = ArchStr.startswith_insensitive("-march=");
+ if (Arch) {
+ GPUArchName = ArchStr.substr(7);
+ Triples += "-";
+ break;
+ }
+ }
+ Triples += GPUArchName.str();
+ }
}
CmdArgs.push_back(TCArgs.MakeArgString(Triples));
@@ -7701,8 +7875,11 @@ void OffloadBundler::ConstructJob(Compilation &C, const JobAction &JA,
assert(CurTC == nullptr && "Expected one dependence!");
CurTC = TC;
});
+ UB += C.addTempFile(
+ C.getArgs().MakeArgString(CurTC->getInputFilename(Inputs[I])));
+ } else {
+ UB += CurTC->getInputFilename(Inputs[I]);
}
- UB += CurTC->getInputFilename(Inputs[I]);
}
CmdArgs.push_back(TCArgs.MakeArgString(UB));
@@ -7746,19 +7923,30 @@ void OffloadBundler::ConstructJobMultipleOutputs(
auto &Dep = DepInfo[I];
Triples += Action::GetOffloadKindName(Dep.DependentOffloadKind);
- Triples += "-";
- std::string NormalizedTriple =
- Dep.DependentToolChain->getTriple().normalize();
- Triples += NormalizedTriple;
-
- if (!Dep.DependentBoundArch.empty()) {
- // If OffloadArch is present it can only appear as the 6th hypen
- // sepearated field of Bundle Entry ID. So, pad required number of
- // hyphens in Triple.
- for (int i = 4 - StringRef(NormalizedTriple).count("-"); i > 0; i--)
- Triples += "-";
+ Triples += '-';
+ Triples += Dep.DependentToolChain->getTriple().normalize();
+ if ((Dep.DependentOffloadKind == Action::OFK_HIP ||
+ Dep.DependentOffloadKind == Action::OFK_Cuda) &&
+ !Dep.DependentBoundArch.empty()) {
+ Triples += '-';
Triples += Dep.DependentBoundArch;
}
+ // TODO: Replace parsing of -march flag. Can be done by storing GPUArch
+ // with each toolchain.
+ StringRef GPUArchName;
+ if (Dep.DependentOffloadKind == Action::OFK_OpenMP) {
+ // Extract GPUArch from -march argument in TC argument list.
+ for (unsigned ArgIndex = 0; ArgIndex < TCArgs.size(); ArgIndex++) {
+ StringRef ArchStr = StringRef(TCArgs.getArgString(ArgIndex));
+ auto Arch = ArchStr.startswith_insensitive("-march=");
+ if (Arch) {
+ GPUArchName = ArchStr.substr(7);
+ Triples += "-";
+ break;
+ }
+ }
+ Triples += GPUArchName.str();
+ }
}
CmdArgs.push_back(TCArgs.MakeArgString(Triples));
diff --git a/clang/lib/Driver/ToolChains/CloudABI.cpp b/clang/lib/Driver/ToolChains/CloudABI.cpp
index 9ee46ac857f0..501e3a382ec1 100644
--- a/clang/lib/Driver/ToolChains/CloudABI.cpp
+++ b/clang/lib/Driver/ToolChains/CloudABI.cpp
@@ -47,7 +47,7 @@ void cloudabi::Linker::ConstructJob(Compilation &C, const JobAction &JA,
CmdArgs.push_back("--no-dynamic-linker");
// Provide PIE linker flags in case PIE is default for the architecture.
- if (ToolChain.isPIEDefault()) {
+ if (ToolChain.isPIEDefault(Args)) {
CmdArgs.push_back("-pie");
CmdArgs.push_back("-zrelro");
}
@@ -125,7 +125,7 @@ Tool *CloudABI::buildLinker() const {
return new tools::cloudabi::Linker(*this);
}
-bool CloudABI::isPIEDefault() const {
+bool CloudABI::isPIEDefault(const llvm::opt::ArgList &Args) const {
// Only enable PIE on architectures that support PC-relative
// addressing. PC-relative addressing is required, as the process
// startup code must be able to relocate itself.
diff --git a/clang/lib/Driver/ToolChains/CloudABI.h b/clang/lib/Driver/ToolChains/CloudABI.h
index 98bf23127706..8856fe3dde6d 100644
--- a/clang/lib/Driver/ToolChains/CloudABI.h
+++ b/clang/lib/Driver/ToolChains/CloudABI.h
@@ -55,7 +55,7 @@ public:
void AddCXXStdlibLibArgs(const llvm::opt::ArgList &Args,
llvm::opt::ArgStringList &CmdArgs) const override;
- bool isPIEDefault() const override;
+ bool isPIEDefault(const llvm::opt::ArgList &Args) const override;
SanitizerMask getSupportedSanitizers() const override;
SanitizerMask getDefaultSanitizers() const override;
diff --git a/clang/lib/Driver/ToolChains/CommonArgs.cpp b/clang/lib/Driver/ToolChains/CommonArgs.cpp
index 83cab3ac00cb..630baf9d6ae6 100644
--- a/clang/lib/Driver/ToolChains/CommonArgs.cpp
+++ b/clang/lib/Driver/ToolChains/CommonArgs.cpp
@@ -34,6 +34,7 @@
#include "clang/Driver/Util.h"
#include "clang/Driver/XRayArgs.h"
#include "llvm/ADT/STLExtras.h"
+#include "llvm/ADT/SmallSet.h"
#include "llvm/ADT/SmallString.h"
#include "llvm/ADT/StringExtras.h"
#include "llvm/ADT/StringSwitch.h"
@@ -266,6 +267,15 @@ void tools::AddLinkerInputs(const ToolChain &TC, const InputInfoList &Inputs,
// Pass -z prefix for gcc linker compatibility.
A.claim();
A.render(Args, CmdArgs);
+ } else if (A.getOption().matches(options::OPT_b)) {
+ const llvm::Triple &T = TC.getTriple();
+ if (!T.isOSAIX()) {
+ TC.getDriver().Diag(diag::err_drv_unsupported_opt_for_target)
+ << A.getSpelling() << T.str();
+ }
+ // Pass -b prefix for AIX linker.
+ A.claim();
+ A.render(Args, CmdArgs);
} else {
A.renderAsInput(Args, CmdArgs);
}
@@ -346,8 +356,8 @@ static StringRef getWebAssemblyTargetCPU(const ArgList &Args) {
return "generic";
}
-std::string tools::getCPUName(const ArgList &Args, const llvm::Triple &T,
- bool FromAs) {
+std::string tools::getCPUName(const Driver &D, const ArgList &Args,
+ const llvm::Triple &T, bool FromAs) {
Arg *A;
switch (T.getArch()) {
@@ -403,14 +413,9 @@ std::string tools::getCPUName(const ArgList &Args, const llvm::Triple &T,
if (!TargetCPUName.empty())
return TargetCPUName;
- if (T.isOSAIX()) {
- unsigned major, minor, unused_micro;
- T.getOSVersion(major, minor, unused_micro);
- // The minimal arch level moved from pwr4 for AIX7.1 to
- // pwr7 for AIX7.2.
- TargetCPUName =
- (major < 7 || (major == 7 && minor < 2)) ? "pwr4" : "pwr7";
- } else if (T.getArch() == llvm::Triple::ppc64le)
+ if (T.isOSAIX())
+ TargetCPUName = "pwr7";
+ else if (T.getArch() == llvm::Triple::ppc64le)
TargetCPUName = "ppc64le";
else if (T.getArch() == llvm::Triple::ppc64)
TargetCPUName = "ppc64";
@@ -438,7 +443,7 @@ std::string tools::getCPUName(const ArgList &Args, const llvm::Triple &T,
case llvm::Triple::x86:
case llvm::Triple::x86_64:
- return x86::getX86TargetCPU(Args, T);
+ return x86::getX86TargetCPU(D, Args, T);
case llvm::Triple::hexagon:
return "hexagon" +
@@ -506,7 +511,7 @@ void tools::addLTOOptions(const ToolChain &ToolChain, const ArgList &Args,
// the plugin.
// Handle flags for selecting CPU variants.
- std::string CPU = getCPUName(Args, ToolChain.getTriple());
+ std::string CPU = getCPUName(D, Args, ToolChain.getTriple());
if (!CPU.empty())
CmdArgs.push_back(Args.MakeArgString(Twine("-plugin-opt=mcpu=") + CPU));
@@ -616,11 +621,6 @@ void tools::addLTOOptions(const ToolChain &ToolChain, const ArgList &Args,
CmdArgs.push_back("-plugin-opt=new-pass-manager");
}
- // Pass an option to enable pseudo probe emission.
- if (Args.hasFlag(options::OPT_fpseudo_probe_for_profiling,
- options::OPT_fno_pseudo_probe_for_profiling, false))
- CmdArgs.push_back("-plugin-opt=pseudo-probe-for-profiling");
-
// Setup statistics file output.
SmallString<128> StatsFile = getStatsFileName(Args, Output, Input, D);
if (!StatsFile.empty())
@@ -657,7 +657,7 @@ void tools::addArchSpecificRPath(const ToolChain &TC, const ArgList &Args,
std::string CandidateRPath = TC.getArchSpecificLibPath();
if (TC.getVFS().exists(CandidateRPath)) {
CmdArgs.push_back("-rpath");
- CmdArgs.push_back(Args.MakeArgString(CandidateRPath.c_str()));
+ CmdArgs.push_back(Args.MakeArgString(CandidateRPath));
}
}
@@ -775,7 +775,8 @@ void tools::linkSanitizerRuntimeDeps(const ToolChain &TC,
CmdArgs.push_back("-ldl");
// Required for backtrace on some OSes
if (TC.getTriple().isOSFreeBSD() ||
- TC.getTriple().isOSNetBSD())
+ TC.getTriple().isOSNetBSD() ||
+ TC.getTriple().isOSOpenBSD())
CmdArgs.push_back("-lexecinfo");
}
@@ -786,7 +787,7 @@ collectSanitizerRuntimes(const ToolChain &TC, const ArgList &Args,
SmallVectorImpl<StringRef> &NonWholeStaticRuntimes,
SmallVectorImpl<StringRef> &HelperStaticRuntimes,
SmallVectorImpl<StringRef> &RequiredSymbols) {
- const SanitizerArgs &SanArgs = TC.getSanitizerArgs();
+ const SanitizerArgs &SanArgs = TC.getSanitizerArgs(Args);
// Collect shared runtimes.
if (SanArgs.needsSharedRt()) {
if (SanArgs.needsAsanRt() && SanArgs.linkRuntimes()) {
@@ -922,7 +923,7 @@ bool tools::addSanitizerRuntimes(const ToolChain &TC, const ArgList &Args,
NonWholeStaticRuntimes, HelperStaticRuntimes,
RequiredSymbols);
- const SanitizerArgs &SanArgs = TC.getSanitizerArgs();
+ const SanitizerArgs &SanArgs = TC.getSanitizerArgs(Args);
// Inject libfuzzer dependencies.
if (SanArgs.needsFuzzer() && SanArgs.linkRuntimes() &&
!Args.hasArg(options::OPT_shared)) {
@@ -1115,7 +1116,7 @@ tools::ParsePICArgs(const ToolChain &ToolChain, const ArgList &Args) {
const llvm::Triple &EffectiveTriple = ToolChain.getEffectiveTriple();
const llvm::Triple &Triple = ToolChain.getTriple();
- bool PIE = ToolChain.isPIEDefault();
+ bool PIE = ToolChain.isPIEDefault(Args);
bool PIC = PIE || ToolChain.isPICDefault();
// The Darwin/MachO default to use PIC does not apply when using -static.
if (Triple.isOSBinFormatMachO() && Args.hasArg(options::OPT_static))
@@ -1587,6 +1588,292 @@ void tools::addX86AlignBranchArgs(const Driver &D, const ArgList &Args,
}
}
+/// SDLSearch: Search for Static Device Library
+/// The search for SDL bitcode files is consistent with how static host
+/// libraries are discovered. That is, the -l option triggers a search for
+/// files in a set of directories called the LINKPATH. The host library search
+/// procedure looks for a specific filename in the LINKPATH. The filename for
+/// a host library is lib<libname>.a or lib<libname>.so. For SDLs, there is an
+/// ordered-set of filenames that are searched. We call this ordered-set of
+/// filenames as SEARCH-ORDER. Since an SDL can either be device-type specific,
+/// architecture specific, or generic across all architectures, a naming
+/// convention and search order is used where the file name embeds the
+/// architecture name <arch-name> (nvptx or amdgcn) and the GPU device type
+/// <device-name> such as sm_30 and gfx906. <device-name> is absent in case of
+/// device-independent SDLs. To reduce congestion in host library directories,
+/// the search first looks for files in the “libdevice” subdirectory. SDLs that
+/// are bc files begin with the prefix “lib”.
+///
+/// Machine-code SDLs can also be managed as an archive (*.a file). The
+/// convention has been to use the prefix “lib”. To avoid confusion with host
+/// archive libraries, we use prefix "libbc-" for the bitcode SDL archives.
+///
+bool tools::SDLSearch(const Driver &D, const llvm::opt::ArgList &DriverArgs,
+ llvm::opt::ArgStringList &CC1Args,
+ SmallVector<std::string, 8> LibraryPaths, std::string Lib,
+ StringRef Arch, StringRef Target, bool isBitCodeSDL,
+ bool postClangLink) {
+ SmallVector<std::string, 12> SDLs;
+
+ std::string LibDeviceLoc = "/libdevice";
+ std::string LibBcPrefix = "/libbc-";
+ std::string LibPrefix = "/lib";
+
+ if (isBitCodeSDL) {
+ // SEARCH-ORDER for Bitcode SDLs:
+ // libdevice/libbc-<libname>-<arch-name>-<device-type>.a
+ // libbc-<libname>-<arch-name>-<device-type>.a
+ // libdevice/libbc-<libname>-<arch-name>.a
+ // libbc-<libname>-<arch-name>.a
+ // libdevice/libbc-<libname>.a
+ // libbc-<libname>.a
+ // libdevice/lib<libname>-<arch-name>-<device-type>.bc
+ // lib<libname>-<arch-name>-<device-type>.bc
+ // libdevice/lib<libname>-<arch-name>.bc
+ // lib<libname>-<arch-name>.bc
+ // libdevice/lib<libname>.bc
+ // lib<libname>.bc
+
+ for (StringRef Base : {LibBcPrefix, LibPrefix}) {
+ const auto *Ext = Base.contains(LibBcPrefix) ? ".a" : ".bc";
+
+ for (auto Suffix : {Twine(Lib + "-" + Arch + "-" + Target).str(),
+ Twine(Lib + "-" + Arch).str(), Twine(Lib).str()}) {
+ SDLs.push_back(Twine(LibDeviceLoc + Base + Suffix + Ext).str());
+ SDLs.push_back(Twine(Base + Suffix + Ext).str());
+ }
+ }
+ } else {
+ // SEARCH-ORDER for Machine-code SDLs:
+ // libdevice/lib<libname>-<arch-name>-<device-type>.a
+ // lib<libname>-<arch-name>-<device-type>.a
+ // libdevice/lib<libname>-<arch-name>.a
+ // lib<libname>-<arch-name>.a
+
+ const auto *Ext = ".a";
+
+ for (auto Suffix : {Twine(Lib + "-" + Arch + "-" + Target).str(),
+ Twine(Lib + "-" + Arch).str()}) {
+ SDLs.push_back(Twine(LibDeviceLoc + LibPrefix + Suffix + Ext).str());
+ SDLs.push_back(Twine(LibPrefix + Suffix + Ext).str());
+ }
+ }
+
+ // The CUDA toolchain does not use a global device llvm-link before the LLVM
+ // backend generates ptx. So currently, the use of bitcode SDL for nvptx is
+ // only possible with post-clang-cc1 linking. Clang cc1 has a feature that
+ // will link libraries after clang compilation while the LLVM IR is still in
+ // memory. This utilizes a clang cc1 option called “-mlink-builtin-bitcode”.
+ // This is a clang -cc1 option that is generated by the clang driver. The
+ // option value must a full path to an existing file.
+ bool FoundSDL = false;
+ for (auto LPath : LibraryPaths) {
+ for (auto SDL : SDLs) {
+ auto FullName = Twine(LPath + SDL).str();
+ if (llvm::sys::fs::exists(FullName)) {
+ if (postClangLink)
+ CC1Args.push_back("-mlink-builtin-bitcode");
+ CC1Args.push_back(DriverArgs.MakeArgString(FullName));
+ FoundSDL = true;
+ break;
+ }
+ }
+ if (FoundSDL)
+ break;
+ }
+ return FoundSDL;
+}
+
+/// Search if a user provided archive file lib<libname>.a exists in any of
+/// the library paths. If so, add a new command to clang-offload-bundler to
+/// unbundle this archive and create a temporary device specific archive. Name
+/// of this SDL is passed to the llvm-link (for amdgcn) or to the
+/// clang-nvlink-wrapper (for nvptx) commands by the driver.
+bool tools::GetSDLFromOffloadArchive(
+ Compilation &C, const Driver &D, const Tool &T, const JobAction &JA,
+ const InputInfoList &Inputs, const llvm::opt::ArgList &DriverArgs,
+ llvm::opt::ArgStringList &CC1Args, SmallVector<std::string, 8> LibraryPaths,
+ StringRef Lib, StringRef Arch, StringRef Target, bool isBitCodeSDL,
+ bool postClangLink) {
+
+ // We don't support bitcode archive bundles for nvptx
+ if (isBitCodeSDL && Arch.contains("nvptx"))
+ return false;
+
+ bool FoundAOB = false;
+ SmallVector<std::string, 2> AOBFileNames;
+ std::string ArchiveOfBundles;
+ 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());
+
+ for (auto AOB : AOBFileNames) {
+ if (llvm::sys::fs::exists(AOB)) {
+ ArchiveOfBundles = AOB;
+ FoundAOB = true;
+ break;
+ }
+ }
+
+ if (!FoundAOB)
+ continue;
+
+ StringRef Prefix = isBitCodeSDL ? "libbc-" : "lib";
+ std::string OutputLib = D.GetTemporaryPath(
+ Twine(Prefix + Lib + "-" + Arch + "-" + Target).str(), "a");
+
+ C.addTempFile(C.getArgs().MakeArgString(OutputLib.c_str()));
+
+ ArgStringList CmdArgs;
+ SmallString<128> DeviceTriple;
+ DeviceTriple += Action::GetOffloadKindName(JA.getOffloadingDeviceKind());
+ DeviceTriple += '-';
+ std::string NormalizedTriple = T.getToolChain().getTriple().normalize();
+ DeviceTriple += NormalizedTriple;
+ if (!Target.empty()) {
+ DeviceTriple += '-';
+ DeviceTriple += Target;
+ }
+
+ std::string UnbundleArg("-unbundle");
+ std::string TypeArg("-type=a");
+ std::string InputArg("-inputs=" + ArchiveOfBundles);
+ std::string OffloadArg("-targets=" + std::string(DeviceTriple));
+ std::string OutputArg("-outputs=" + OutputLib);
+
+ const char *UBProgram = DriverArgs.MakeArgString(
+ T.getToolChain().GetProgramPath("clang-offload-bundler"));
+
+ ArgStringList UBArgs;
+ UBArgs.push_back(C.getArgs().MakeArgString(UnbundleArg.c_str()));
+ UBArgs.push_back(C.getArgs().MakeArgString(TypeArg.c_str()));
+ UBArgs.push_back(C.getArgs().MakeArgString(InputArg.c_str()));
+ UBArgs.push_back(C.getArgs().MakeArgString(OffloadArg.c_str()));
+ UBArgs.push_back(C.getArgs().MakeArgString(OutputArg.c_str()));
+
+ // Add this flag to not exit from clang-offload-bundler if no compatible
+ // code object is found in heterogenous archive library.
+ std::string AdditionalArgs("-allow-missing-bundles");
+ UBArgs.push_back(C.getArgs().MakeArgString(AdditionalArgs.c_str()));
+
+ C.addCommand(std::make_unique<Command>(
+ JA, T, ResponseFileSupport::AtFileCurCP(), UBProgram, UBArgs, Inputs,
+ InputInfo(&JA, C.getArgs().MakeArgString(OutputLib.c_str()))));
+ if (postClangLink)
+ CC1Args.push_back("-mlink-builtin-bitcode");
+
+ CC1Args.push_back(DriverArgs.MakeArgString(OutputLib));
+ break;
+ }
+
+ return FoundAOB;
+}
+
+// Wrapper function used by driver for adding SDLs during link phase.
+void tools::AddStaticDeviceLibsLinking(Compilation &C, const Tool &T,
+ const JobAction &JA,
+ const InputInfoList &Inputs,
+ const llvm::opt::ArgList &DriverArgs,
+ llvm::opt::ArgStringList &CC1Args,
+ StringRef Arch, StringRef Target,
+ bool isBitCodeSDL, bool postClangLink) {
+ AddStaticDeviceLibs(&C, &T, &JA, &Inputs, C.getDriver(), DriverArgs, CC1Args,
+ Arch, Target, isBitCodeSDL, postClangLink);
+}
+
+// Wrapper function used for post clang linking of bitcode SDLS for nvptx by
+// the CUDA toolchain.
+void tools::AddStaticDeviceLibsPostLinking(const Driver &D,
+ const llvm::opt::ArgList &DriverArgs,
+ llvm::opt::ArgStringList &CC1Args,
+ StringRef Arch, StringRef Target,
+ bool isBitCodeSDL, bool postClangLink) {
+ AddStaticDeviceLibs(nullptr, nullptr, nullptr, nullptr, D, DriverArgs,
+ CC1Args, Arch, Target, isBitCodeSDL, postClangLink);
+}
+
+// User defined Static Device Libraries(SDLs) can be passed to clang for
+// offloading GPU compilers. Like static host libraries, the use of a SDL is
+// specified with the -l command line option. The primary difference between
+// host and SDLs is the filenames for SDLs (refer SEARCH-ORDER for Bitcode SDLs
+// and SEARCH-ORDER for Machine-code SDLs for the naming convention).
+// SDLs are of following types:
+//
+// * Bitcode SDLs: They can either be a *.bc file or an archive of *.bc files.
+// For NVPTX, these libraries are post-clang linked following each
+// compilation. For AMDGPU, these libraries are linked one time
+// during the application link phase.
+//
+// * Machine-code SDLs: They are archive files. For NVPTX, the archive members
+// contain cubin for Nvidia GPUs and are linked one time during the
+// link phase by the CUDA SDK linker called nvlink. For AMDGPU, the
+// process for machine code SDLs is still in development. But they
+// will be linked by the LLVM tool lld.
+//
+// * Bundled objects that contain both host and device codes: Bundled objects
+// may also contain library code compiled from source. For NVPTX, the
+// bundle contains cubin. For AMDGPU, the bundle contains bitcode.
+//
+// For Bitcode and Machine-code SDLs, current compiler toolchains hardcode the
+// inclusion of specific SDLs such as math libraries and the OpenMP device
+// library libomptarget.
+void tools::AddStaticDeviceLibs(Compilation *C, const Tool *T,
+ const JobAction *JA,
+ const InputInfoList *Inputs, const Driver &D,
+ const llvm::opt::ArgList &DriverArgs,
+ llvm::opt::ArgStringList &CC1Args,
+ StringRef Arch, StringRef Target,
+ bool isBitCodeSDL, bool postClangLink) {
+
+ SmallVector<std::string, 8> LibraryPaths;
+ // Add search directories from LIBRARY_PATH env variable
+ llvm::Optional<std::string> LibPath =
+ llvm::sys::Process::GetEnv("LIBRARY_PATH");
+ if (LibPath) {
+ SmallVector<StringRef, 8> Frags;
+ const char EnvPathSeparatorStr[] = {llvm::sys::EnvPathSeparator, '\0'};
+ llvm::SplitString(*LibPath, Frags, EnvPathSeparatorStr);
+ for (StringRef Path : Frags)
+ LibraryPaths.emplace_back(Path.trim());
+ }
+
+ // Add directories from user-specified -L options
+ for (std::string Search_Dir : DriverArgs.getAllArgValues(options::OPT_L))
+ LibraryPaths.emplace_back(Search_Dir);
+
+ // Add path to lib-debug folders
+ SmallString<256> DefaultLibPath = llvm::sys::path::parent_path(D.Dir);
+ llvm::sys::path::append(DefaultLibPath, Twine("lib") + CLANG_LIBDIR_SUFFIX);
+ LibraryPaths.emplace_back(DefaultLibPath.c_str());
+
+ // Build list of Static Device Libraries SDLs specified by -l option
+ llvm::SmallSet<std::string, 16> SDLNames;
+ static const StringRef HostOnlyArchives[] = {
+ "omp", "cudart", "m", "gcc", "gcc_s", "pthread", "hip_hcc"};
+ for (auto SDLName : DriverArgs.getAllArgValues(options::OPT_l)) {
+ if (!HostOnlyArchives->contains(SDLName)) {
+ SDLNames.insert(SDLName);
+ }
+ }
+
+ // The search stops as soon as an SDL file is found. The driver then provides
+ // the full filename of the SDL to the llvm-link or clang-nvlink-wrapper
+ // command. If no SDL is found after searching each LINKPATH with
+ // SEARCH-ORDER, it is possible that an archive file lib<libname>.a exists
+ // and may contain bundled object files.
+ for (auto SDLName : SDLNames) {
+ // This is the only call to SDLSearch
+ if (!SDLSearch(D, DriverArgs, CC1Args, LibraryPaths, SDLName, Arch, Target,
+ isBitCodeSDL, postClangLink)) {
+ GetSDLFromOffloadArchive(*C, D, *T, *JA, *Inputs, DriverArgs, CC1Args,
+ LibraryPaths, SDLName, Arch, Target,
+ isBitCodeSDL, postClangLink);
+ }
+ }
+}
+
static llvm::opt::Arg *
getAMDGPUCodeObjectArgument(const Driver &D, const llvm::opt::ArgList &Args) {
// The last of -mcode-object-v3, -mno-code-object-v3 and
@@ -1684,6 +1971,12 @@ void tools::addOpenMPDeviceRTL(const Driver &D,
StringRef BitcodeSuffix,
const llvm::Triple &Triple) {
SmallVector<StringRef, 8> LibraryPaths;
+
+ // Add path to clang lib / lib64 folder.
+ SmallString<256> DefaultLibPath = llvm::sys::path::parent_path(D.Dir);
+ llvm::sys::path::append(DefaultLibPath, Twine("lib") + CLANG_LIBDIR_SUFFIX);
+ LibraryPaths.emplace_back(DefaultLibPath.c_str());
+
// Add user defined library paths from LIBRARY_PATH.
llvm::Optional<std::string> LibPath =
llvm::sys::Process::GetEnv("LIBRARY_PATH");
@@ -1695,32 +1988,31 @@ void tools::addOpenMPDeviceRTL(const Driver &D,
LibraryPaths.emplace_back(Path.trim());
}
- // Add path to lib / lib64 folder.
- SmallString<256> DefaultLibPath = llvm::sys::path::parent_path(D.Dir);
- llvm::sys::path::append(DefaultLibPath, Twine("lib") + CLANG_LIBDIR_SUFFIX);
- LibraryPaths.emplace_back(DefaultLibPath.c_str());
-
OptSpecifier LibomptargetBCPathOpt =
Triple.isAMDGCN() ? options::OPT_libomptarget_amdgcn_bc_path_EQ
: options::OPT_libomptarget_nvptx_bc_path_EQ;
StringRef ArchPrefix = Triple.isAMDGCN() ? "amdgcn" : "nvptx";
+ std::string LibOmpTargetName = "libomptarget-" + BitcodeSuffix.str() + ".bc";
+
// First check whether user specifies bc library
if (const Arg *A = DriverArgs.getLastArg(LibomptargetBCPathOpt)) {
- std::string LibOmpTargetName(A->getValue());
- if (llvm::sys::fs::exists(LibOmpTargetName)) {
+ SmallString<128> LibOmpTargetFile(A->getValue());
+ if (llvm::sys::fs::exists(LibOmpTargetFile) &&
+ llvm::sys::fs::is_directory(LibOmpTargetFile)) {
+ llvm::sys::path::append(LibOmpTargetFile, LibOmpTargetName);
+ }
+
+ if (llvm::sys::fs::exists(LibOmpTargetFile)) {
CC1Args.push_back("-mlink-builtin-bitcode");
- CC1Args.push_back(DriverArgs.MakeArgString(LibOmpTargetName));
+ CC1Args.push_back(DriverArgs.MakeArgString(LibOmpTargetFile));
} else {
D.Diag(diag::err_drv_omp_offload_target_bcruntime_not_found)
- << LibOmpTargetName;
+ << LibOmpTargetFile;
}
} else {
bool FoundBCLibrary = false;
- std::string LibOmpTargetName =
- "libomptarget-" + BitcodeSuffix.str() + ".bc";
-
for (StringRef LibraryPath : LibraryPaths) {
SmallString<128> LibOmpTargetFile(LibraryPath);
llvm::sys::path::append(LibOmpTargetFile, LibOmpTargetName);
diff --git a/clang/lib/Driver/ToolChains/CommonArgs.h b/clang/lib/Driver/ToolChains/CommonArgs.h
index c94c15864661..00291a3681c8 100644
--- a/clang/lib/Driver/ToolChains/CommonArgs.h
+++ b/clang/lib/Driver/ToolChains/CommonArgs.h
@@ -49,6 +49,39 @@ void AddRunTimeLibs(const ToolChain &TC, const Driver &D,
llvm::opt::ArgStringList &CmdArgs,
const llvm::opt::ArgList &Args);
+void AddStaticDeviceLibsLinking(Compilation &C, const Tool &T,
+ const JobAction &JA,
+ const InputInfoList &Inputs,
+ const llvm::opt::ArgList &DriverArgs,
+ llvm::opt::ArgStringList &CmdArgs,
+ StringRef Arch, StringRef Target,
+ bool isBitCodeSDL, bool postClangLink);
+void AddStaticDeviceLibsPostLinking(const Driver &D,
+ const llvm::opt::ArgList &DriverArgs,
+ llvm::opt::ArgStringList &CmdArgs,
+ StringRef Arch, StringRef Target,
+ bool isBitCodeSDL, bool postClangLink);
+void AddStaticDeviceLibs(Compilation *C, const Tool *T, const JobAction *JA,
+ const InputInfoList *Inputs, const Driver &D,
+ const llvm::opt::ArgList &DriverArgs,
+ llvm::opt::ArgStringList &CmdArgs, StringRef Arch,
+ StringRef Target, bool isBitCodeSDL,
+ bool postClangLink);
+
+bool SDLSearch(const Driver &D, const llvm::opt::ArgList &DriverArgs,
+ llvm::opt::ArgStringList &CmdArgs,
+ SmallVector<std::string, 8> LibraryPaths, std::string Lib,
+ StringRef Arch, StringRef Target, bool isBitCodeSDL,
+ bool postClangLink);
+
+bool GetSDLFromOffloadArchive(Compilation &C, const Driver &D, const Tool &T,
+ const JobAction &JA, const InputInfoList &Inputs,
+ const llvm::opt::ArgList &DriverArgs,
+ llvm::opt::ArgStringList &CC1Args,
+ SmallVector<std::string, 8> LibraryPaths,
+ StringRef Lib, StringRef Arch, StringRef Target,
+ bool isBitCodeSDL, bool postClangLink);
+
const char *SplitDebugName(const JobAction &JA, const llvm::opt::ArgList &Args,
const InputInfo &Input, const InputInfo &Output);
@@ -107,8 +140,8 @@ void AddTargetFeature(const llvm::opt::ArgList &Args,
llvm::opt::OptSpecifier OnOpt,
llvm::opt::OptSpecifier OffOpt, StringRef FeatureName);
-std::string getCPUName(const llvm::opt::ArgList &Args, const llvm::Triple &T,
- bool FromAs = false);
+std::string getCPUName(const Driver &D, const llvm::opt::ArgList &Args,
+ const llvm::Triple &T, bool FromAs = false);
/// Iterate \p Args and convert -mxxx to +xxx and -mno-xxx to -xxx and
/// append it to \p Features.
diff --git a/clang/lib/Driver/ToolChains/CrossWindows.cpp b/clang/lib/Driver/ToolChains/CrossWindows.cpp
index 07abf4f83f7d..2b043fbeecda 100644
--- a/clang/lib/Driver/ToolChains/CrossWindows.cpp
+++ b/clang/lib/Driver/ToolChains/CrossWindows.cpp
@@ -185,7 +185,7 @@ void tools::CrossWindows::Linker::ConstructJob(
}
}
- if (TC.getSanitizerArgs().needsAsanRt()) {
+ if (TC.getSanitizerArgs(Args).needsAsanRt()) {
// TODO handle /MT[d] /MD[d]
if (Args.hasArg(options::OPT_shared)) {
CmdArgs.push_back(TC.getCompilerRTArgString(Args, "asan_dll_thunk"));
@@ -223,7 +223,7 @@ bool CrossWindowsToolChain::isPICDefault() const {
return getArch() == llvm::Triple::x86_64;
}
-bool CrossWindowsToolChain::isPIEDefault() const {
+bool CrossWindowsToolChain::isPIEDefault(const llvm::opt::ArgList &Args) const {
return getArch() == llvm::Triple::x86_64;
}
diff --git a/clang/lib/Driver/ToolChains/CrossWindows.h b/clang/lib/Driver/ToolChains/CrossWindows.h
index ffe75332c2e8..bab690ea34d0 100644
--- a/clang/lib/Driver/ToolChains/CrossWindows.h
+++ b/clang/lib/Driver/ToolChains/CrossWindows.h
@@ -57,7 +57,7 @@ public:
bool IsIntegratedAssemblerDefault() const override { return true; }
bool IsUnwindTablesDefault(const llvm::opt::ArgList &Args) const override;
bool isPICDefault() const override;
- bool isPIEDefault() const override;
+ bool isPIEDefault(const llvm::opt::ArgList &Args) const override;
bool isPICDefaultForced() const override;
LangOptions::StackProtectorMode
diff --git a/clang/lib/Driver/ToolChains/Cuda.cpp b/clang/lib/Driver/ToolChains/Cuda.cpp
index 769eae14df51..5397c7a9a0e6 100644
--- a/clang/lib/Driver/ToolChains/Cuda.cpp
+++ b/clang/lib/Driver/ToolChains/Cuda.cpp
@@ -17,6 +17,7 @@
#include "clang/Driver/InputInfo.h"
#include "clang/Driver/Options.h"
#include "llvm/ADT/Optional.h"
+#include "llvm/ADT/StringExtras.h"
#include "llvm/Option/ArgList.h"
#include "llvm/Support/FileSystem.h"
#include "llvm/Support/Host.h"
@@ -34,25 +35,6 @@ using namespace clang;
using namespace llvm::opt;
namespace {
-struct CudaVersionInfo {
- std::string DetectedVersion;
- CudaVersion Version;
-};
-// Parses the contents of version.txt in an CUDA installation. It should
-// contain one line of the from e.g. "CUDA Version 7.5.2".
-CudaVersionInfo parseCudaVersionFile(llvm::StringRef V) {
- V = V.trim();
- if (!V.startswith("CUDA Version "))
- return {V.str(), CudaVersion::UNKNOWN};
- V = V.substr(strlen("CUDA Version "));
- SmallVector<StringRef,4> VersionParts;
- V.split(VersionParts, '.');
- return {"version.txt: " + V.str() + ".",
- VersionParts.size() < 2
- ? CudaVersion::UNKNOWN
- : CudaStringToVersion(
- join_items(".", VersionParts[0], VersionParts[1]))};
-}
CudaVersion getCudaVersion(uint32_t raw_version) {
if (raw_version < 7050)
@@ -77,10 +59,18 @@ CudaVersion getCudaVersion(uint32_t raw_version) {
return CudaVersion::CUDA_110;
if (raw_version < 11020)
return CudaVersion::CUDA_111;
- return CudaVersion::LATEST;
+ if (raw_version < 11030)
+ return CudaVersion::CUDA_112;
+ if (raw_version < 11040)
+ return CudaVersion::CUDA_113;
+ if (raw_version < 11050)
+ return CudaVersion::CUDA_114;
+ if (raw_version < 11060)
+ return CudaVersion::CUDA_115;
+ return CudaVersion::NEW;
}
-CudaVersionInfo parseCudaHFile(llvm::StringRef Input) {
+CudaVersion parseCudaHFile(llvm::StringRef Input) {
// Helper lambda which skips the words if the line starts with them or returns
// None otherwise.
auto StartsWithWords =
@@ -100,21 +90,27 @@ CudaVersionInfo parseCudaHFile(llvm::StringRef Input) {
StartsWithWords(Input.ltrim(), {"#", "define", "CUDA_VERSION"})) {
uint32_t RawVersion;
Line->consumeInteger(10, RawVersion);
- return {"cuda.h: CUDA_VERSION=" + Twine(RawVersion).str() + ".",
- getCudaVersion(RawVersion)};
+ return getCudaVersion(RawVersion);
}
// Find next non-empty line.
Input = Input.drop_front(Input.find_first_of("\n\r")).ltrim();
}
- return {"cuda.h: CUDA_VERSION not found.", CudaVersion::UNKNOWN};
+ return CudaVersion::UNKNOWN;
}
} // namespace
void CudaInstallationDetector::WarnIfUnsupportedVersion() {
- if (DetectedVersionIsNotSupported)
- D.Diag(diag::warn_drv_unknown_cuda_version)
- << DetectedVersion
- << CudaVersionToString(CudaVersion::LATEST_SUPPORTED);
+ if (Version > CudaVersion::PARTIALLY_SUPPORTED) {
+ std::string VersionString = CudaVersionToString(Version);
+ if (!VersionString.empty())
+ VersionString.insert(0, " ");
+ D.Diag(diag::warn_drv_new_cuda_version)
+ << VersionString
+ << (CudaVersion::PARTIALLY_SUPPORTED != CudaVersion::FULLY_SUPPORTED)
+ << CudaVersionToString(CudaVersion::PARTIALLY_SUPPORTED);
+ } else if (Version > CudaVersion::FULLY_SUPPORTED)
+ D.Diag(diag::warn_drv_partially_supported_cuda_version)
+ << CudaVersionToString(Version);
}
CudaInstallationDetector::CudaInstallationDetector(
@@ -206,31 +202,17 @@ CudaInstallationDetector::CudaInstallationDetector(
else
continue;
- CudaVersionInfo VersionInfo = {"", CudaVersion::UNKNOWN};
- if (auto VersionFile = FS.getBufferForFile(InstallPath + "/version.txt"))
- VersionInfo = parseCudaVersionFile((*VersionFile)->getBuffer());
- // If version file didn't give us the version, try to find it in cuda.h
- if (VersionInfo.Version == CudaVersion::UNKNOWN)
- if (auto CudaHFile = FS.getBufferForFile(InstallPath + "/include/cuda.h"))
- VersionInfo = parseCudaHFile((*CudaHFile)->getBuffer());
- // As the last resort, make an educated guess between CUDA-7.0, (which had
- // no version.txt file and had old-style libdevice bitcode ) and an unknown
- // recent CUDA version (no version.txt, new style bitcode).
- if (VersionInfo.Version == CudaVersion::UNKNOWN) {
- VersionInfo.Version = (FS.exists(LibDevicePath + "/libdevice.10.bc"))
- ? Version = CudaVersion::LATEST
- : Version = CudaVersion::CUDA_70;
- VersionInfo.DetectedVersion =
- "No version found in version.txt or cuda.h.";
+ Version = CudaVersion::UNKNOWN;
+ if (auto CudaHFile = FS.getBufferForFile(InstallPath + "/include/cuda.h"))
+ Version = parseCudaHFile((*CudaHFile)->getBuffer());
+ // As the last resort, make an educated guess between CUDA-7.0, which had
+ // old-style libdevice bitcode, and an unknown recent CUDA version.
+ if (Version == CudaVersion::UNKNOWN) {
+ Version = FS.exists(LibDevicePath + "/libdevice.10.bc")
+ ? CudaVersion::NEW
+ : CudaVersion::CUDA_70;
}
- Version = VersionInfo.Version;
- DetectedVersion = VersionInfo.DetectedVersion;
-
- // TODO(tra): remove the warning once we have all features of 10.2
- // and 11.0 implemented.
- DetectedVersionIsNotSupported = Version > CudaVersion::LATEST_SUPPORTED;
-
if (Version >= CudaVersion::CUDA_90) {
// CUDA-9+ uses single libdevice file for all GPU variants.
std::string FilePath = LibDevicePath + "/libdevice.10.bc";
@@ -319,8 +301,6 @@ void CudaInstallationDetector::AddCudaIncludeArgs(
return;
}
- CC1Args.push_back("-internal-isystem");
- CC1Args.push_back(DriverArgs.MakeArgString(getIncludePath()));
CC1Args.push_back("-include");
CC1Args.push_back("__clang_cuda_runtime_wrapper.h");
}
@@ -632,8 +612,16 @@ void NVPTX::OpenMPLinker::ConstructJob(Compilation &C, const JobAction &JA,
CmdArgs.push_back(CubinF);
}
+ AddStaticDeviceLibsLinking(C, *this, JA, Inputs, Args, CmdArgs, "nvptx", GPUArch,
+ false, false);
+
+ // Find nvlink and pass it as "--nvlink-path=" argument of
+ // clang-nvlink-wrapper.
+ CmdArgs.push_back(Args.MakeArgString(
+ Twine("--nvlink-path=" + getToolChain().GetProgramPath("nvlink"))));
+
const char *Exec =
- Args.MakeArgString(getToolChain().GetProgramPath("nvlink"));
+ Args.MakeArgString(getToolChain().GetProgramPath("clang-nvlink-wrapper"));
C.addCommand(std::make_unique<Command>(
JA, *this,
ResponseFileSupport{ResponseFileSupport::RF_Full, llvm::sys::WEM_UTF8,
@@ -686,7 +674,8 @@ void CudaToolChain::addClangTargetOptions(
"Only OpenMP or CUDA offloading kinds are supported for NVIDIA GPUs.");
if (DeviceOffloadingKind == Action::OFK_Cuda) {
- CC1Args.push_back("-fcuda-is-device");
+ CC1Args.append(
+ {"-fcuda-is-device", "-mllvm", "-enable-memcpyopt-without-libcalls"});
if (DriverArgs.hasFlag(options::OPT_fcuda_approx_transcendentals,
options::OPT_fno_cuda_approx_transcendentals, false))
@@ -720,6 +709,9 @@ void CudaToolChain::addClangTargetOptions(
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);
@@ -760,6 +752,8 @@ void CudaToolChain::addClangTargetOptions(
addOpenMPDeviceRTL(getDriver(), DriverArgs, CC1Args, BitcodeSuffix,
getTriple());
+ AddStaticDeviceLibsPostLinking(getDriver(), DriverArgs, CC1Args, "nvptx", GpuArch,
+ /* bitcode SDL?*/ true, /* PostClang Link? */ true);
}
}
@@ -831,17 +825,9 @@ CudaToolChain::TranslateArgs(const llvm::opt::DerivedArgList &Args,
// flags are not duplicated.
// Also append the compute capability.
if (DeviceOffloadKind == Action::OFK_OpenMP) {
- for (Arg *A : Args) {
- bool IsDuplicate = false;
- for (Arg *DALArg : *DAL) {
- if (A == DALArg) {
- IsDuplicate = true;
- break;
- }
- }
- if (!IsDuplicate)
+ for (Arg *A : Args)
+ if (!llvm::is_contained(*DAL, A))
DAL->append(A);
- }
StringRef Arch = DAL->getLastArgValue(options::OPT_march_EQ);
if (Arch.empty())
@@ -884,6 +870,11 @@ CudaToolChain::GetCXXStdlibType(const ArgList &Args) const {
void CudaToolChain::AddClangSystemIncludeArgs(const ArgList &DriverArgs,
ArgStringList &CC1Args) const {
HostTC.AddClangSystemIncludeArgs(DriverArgs, CC1Args);
+
+ if (!DriverArgs.hasArg(options::OPT_nogpuinc) && CudaInstallation.isValid())
+ CC1Args.append(
+ {"-internal-isystem",
+ DriverArgs.MakeArgString(CudaInstallation.getIncludePath())});
}
void CudaToolChain::AddClangCXXStdlibIncludeArgs(const ArgList &Args,
diff --git a/clang/lib/Driver/ToolChains/Cuda.h b/clang/lib/Driver/ToolChains/Cuda.h
index 6ae4415a563a..a7e6e84f4902 100644
--- a/clang/lib/Driver/ToolChains/Cuda.h
+++ b/clang/lib/Driver/ToolChains/Cuda.h
@@ -30,8 +30,6 @@ private:
const Driver &D;
bool IsValid = false;
CudaVersion Version = CudaVersion::UNKNOWN;
- std::string DetectedVersion;
- bool DetectedVersionIsNotSupported = false;
std::string InstallPath;
std::string BinPath;
std::string LibPath;
@@ -62,7 +60,10 @@ public:
void print(raw_ostream &OS) const;
/// Get the detected Cuda install's version.
- CudaVersion version() const { return Version; }
+ CudaVersion version() const {
+ return Version == CudaVersion::NEW ? CudaVersion::PARTIALLY_SUPPORTED
+ : Version;
+ }
/// Get the detected Cuda installation path.
StringRef getInstallPath() const { return InstallPath; }
/// Get the detected path to Cuda's bin directory.
@@ -156,7 +157,9 @@ public:
bool useIntegratedAs() const override { return false; }
bool isCrossCompiling() const override { return true; }
bool isPICDefault() const override { return false; }
- bool isPIEDefault() const override { return false; }
+ bool isPIEDefault(const llvm::opt::ArgList &Args) const override {
+ return false;
+ }
bool isPICDefaultForced() const override { return false; }
bool SupportsProfiling() const override { return false; }
bool supportsDebugInfoOption(const llvm::opt::Arg *A) const override;
diff --git a/clang/lib/Driver/ToolChains/Darwin.cpp b/clang/lib/Driver/ToolChains/Darwin.cpp
index 261f522f6c49..06d3edc70e45 100644
--- a/clang/lib/Driver/ToolChains/Darwin.cpp
+++ b/clang/lib/Driver/ToolChains/Darwin.cpp
@@ -34,7 +34,7 @@ using namespace clang::driver::toolchains;
using namespace clang;
using namespace llvm::opt;
-static const VersionTuple minimumMacCatalystDeploymentTarget() {
+static VersionTuple minimumMacCatalystDeploymentTarget() {
return VersionTuple(13, 1);
}
@@ -94,6 +94,8 @@ void darwin::Assembler::ConstructJob(Compilation &C, const JobAction &JA,
const InputInfoList &Inputs,
const ArgList &Args,
const char *LinkingOutput) const {
+ const llvm::Triple &T(getToolChain().getTriple());
+
ArgStringList CmdArgs;
assert(Inputs.size() == 1 && "Unexpected number of inputs.");
@@ -112,7 +114,6 @@ void darwin::Assembler::ConstructJob(Compilation &C, const JobAction &JA,
// FIXME: at run-time detect assembler capabilities or rely on version
// information forwarded by -target-assembler-version.
if (Args.hasArg(options::OPT_fno_integrated_as)) {
- const llvm::Triple &T(getToolChain().getTriple());
if (!(T.isMacOSX() && T.isMacOSXVersionLT(10, 7)))
CmdArgs.push_back("-Q");
}
@@ -130,8 +131,7 @@ void darwin::Assembler::ConstructJob(Compilation &C, const JobAction &JA,
AddMachOArch(Args, CmdArgs);
// Use -force_cpusubtype_ALL on x86 by default.
- if (getToolChain().getTriple().isX86() ||
- Args.hasArg(options::OPT_force__cpusubtype__ALL))
+ if (T.isX86() || Args.hasArg(options::OPT_force__cpusubtype__ALL))
CmdArgs.push_back("-force_cpusubtype_ALL");
if (getToolChain().getArch() != llvm::Triple::x86_64 &&
@@ -729,6 +729,54 @@ void darwin::Linker::ConstructJob(Compilation &C, const JobAction &JA,
C.addCommand(std::move(Cmd));
}
+void darwin::StaticLibTool::ConstructJob(Compilation &C, const JobAction &JA,
+ const InputInfo &Output,
+ const InputInfoList &Inputs,
+ const ArgList &Args,
+ const char *LinkingOutput) const {
+ const Driver &D = getToolChain().getDriver();
+
+ // Silence warning for "clang -g foo.o -o foo"
+ Args.ClaimAllArgs(options::OPT_g_Group);
+ // and "clang -emit-llvm foo.o -o foo"
+ Args.ClaimAllArgs(options::OPT_emit_llvm);
+ // and for "clang -w foo.o -o foo". Other warning options are already
+ // handled somewhere else.
+ Args.ClaimAllArgs(options::OPT_w);
+ // Silence warnings when linking C code with a C++ '-stdlib' argument.
+ Args.ClaimAllArgs(options::OPT_stdlib_EQ);
+
+ // libtool <options> <output_file> <input_files>
+ ArgStringList CmdArgs;
+ // Create and insert file members with a deterministic index.
+ CmdArgs.push_back("-static");
+ CmdArgs.push_back("-D");
+ CmdArgs.push_back("-no_warning_for_no_symbols");
+ CmdArgs.push_back("-o");
+ CmdArgs.push_back(Output.getFilename());
+
+ for (const auto &II : Inputs) {
+ if (II.isFilename()) {
+ CmdArgs.push_back(II.getFilename());
+ }
+ }
+
+ // Delete old output archive file if it already exists before generating a new
+ // archive file.
+ const auto *OutputFileName = Output.getFilename();
+ if (Output.isFilename() && llvm::sys::fs::exists(OutputFileName)) {
+ if (std::error_code EC = llvm::sys::fs::remove(OutputFileName)) {
+ D.Diag(diag::err_drv_unable_to_remove_file) << EC.message();
+ return;
+ }
+ }
+
+ const char *Exec = Args.MakeArgString(getToolChain().GetStaticLibToolPath());
+ C.addCommand(std::make_unique<Command>(JA, *this,
+ ResponseFileSupport::AtFileUTF8(),
+ Exec, CmdArgs, Inputs, Output));
+}
+
void darwin::Lipo::ConstructJob(Compilation &C, const JobAction &JA,
const InputInfo &Output,
const InputInfoList &Inputs,
@@ -982,6 +1030,10 @@ Tool *MachO::getTool(Action::ActionClass AC) const {
Tool *MachO::buildLinker() const { return new tools::darwin::Linker(*this); }
+Tool *MachO::buildStaticLibTool() const {
+ return new tools::darwin::StaticLibTool(*this);
+}
+
Tool *MachO::buildAssembler() const {
return new tools::darwin::Assembler(*this);
}
@@ -1305,7 +1357,7 @@ void DarwinClang::AddLinkRuntimeLibArgs(const ArgList &Args,
return;
}
- const SanitizerArgs &Sanitize = getSanitizerArgs();
+ const SanitizerArgs &Sanitize = getSanitizerArgs(Args);
if (Sanitize.needsAsanRt())
AddLinkSanitizerLibArgs(Args, CmdArgs, "asan");
if (Sanitize.needsLsanRt())
@@ -1379,6 +1431,8 @@ struct DarwinPlatform {
enum SourceKind {
/// The OS was specified using the -target argument.
TargetArg,
+ /// The OS was specified using the -mtargetos= argument.
+ MTargetOSArg,
/// The OS was specified using the -m<os>-version-min argument.
OSVersionArg,
/// The OS was specified using the OS_DEPLOYMENT_TARGET environment.
@@ -1430,7 +1484,8 @@ struct DarwinPlatform {
void addOSVersionMinArgument(DerivedArgList &Args, const OptTable &Opts) {
if (Argument)
return;
- assert(Kind != TargetArg && Kind != OSVersionArg && "Invalid kind");
+ assert(Kind != TargetArg && Kind != MTargetOSArg && Kind != OSVersionArg &&
+ "Invalid kind");
options::ID Opt;
switch (Platform) {
case DarwinPlatformKind::MacOS:
@@ -1455,6 +1510,7 @@ struct DarwinPlatform {
std::string getAsString(DerivedArgList &Args, const OptTable &Opts) {
switch (Kind) {
case TargetArg:
+ case MTargetOSArg:
case OSVersionArg:
case InferredFromSDK:
case InferredFromArch:
@@ -1466,40 +1522,54 @@ struct DarwinPlatform {
llvm_unreachable("Unsupported Darwin Source Kind");
}
- static DarwinPlatform
- createFromTarget(const llvm::Triple &TT, StringRef OSVersion, Arg *A,
- const Optional<DarwinSDKInfo> &SDKInfo) {
- DarwinPlatform Result(TargetArg, getPlatformFromOS(TT.getOS()), OSVersion,
- A);
- unsigned Major, Minor, Micro;
- TT.getOSVersion(Major, Minor, Micro);
- if (Major == 0)
- Result.HasOSVersion = false;
-
- switch (TT.getEnvironment()) {
+ void setEnvironment(llvm::Triple::EnvironmentType EnvType,
+ const VersionTuple &OSVersion,
+ const Optional<DarwinSDKInfo> &SDKInfo) {
+ switch (EnvType) {
case llvm::Triple::Simulator:
- Result.Environment = DarwinEnvironmentKind::Simulator;
+ Environment = DarwinEnvironmentKind::Simulator;
break;
case llvm::Triple::MacABI: {
+ Environment = DarwinEnvironmentKind::MacCatalyst;
// The minimum native macOS target for MacCatalyst is macOS 10.15.
- auto NativeTargetVersion = VersionTuple(10, 15);
- if (Result.HasOSVersion && SDKInfo) {
+ NativeTargetVersion = VersionTuple(10, 15);
+ if (HasOSVersion && SDKInfo) {
if (const auto *MacCatalystToMacOSMapping = SDKInfo->getVersionMapping(
DarwinSDKInfo::OSEnvPair::macCatalystToMacOSPair())) {
if (auto MacOSVersion = MacCatalystToMacOSMapping->map(
- VersionTuple(Major, Minor, Micro), NativeTargetVersion,
- None)) {
+ OSVersion, NativeTargetVersion, None)) {
NativeTargetVersion = *MacOSVersion;
}
}
}
- Result.Environment = DarwinEnvironmentKind::MacCatalyst;
- Result.NativeTargetVersion = NativeTargetVersion;
break;
}
default:
break;
}
+ }
+
+ static DarwinPlatform
+ createFromTarget(const llvm::Triple &TT, StringRef OSVersion, Arg *A,
+ const Optional<DarwinSDKInfo> &SDKInfo) {
+ DarwinPlatform Result(TargetArg, getPlatformFromOS(TT.getOS()), OSVersion,
+ A);
+ unsigned Major, Minor, Micro;
+ TT.getOSVersion(Major, Minor, Micro);
+ if (Major == 0)
+ Result.HasOSVersion = false;
+ Result.setEnvironment(TT.getEnvironment(),
+ VersionTuple(Major, Minor, Micro), SDKInfo);
+ return Result;
+ }
+ static DarwinPlatform
+ createFromMTargetOS(llvm::Triple::OSType OS, VersionTuple OSVersion,
+ llvm::Triple::EnvironmentType Environment, Arg *A,
+ const Optional<DarwinSDKInfo> &SDKInfo) {
+ DarwinPlatform Result(MTargetOSArg, getPlatformFromOS(OS),
+ OSVersion.getAsString(), A);
+ Result.InferSimulatorFromArch = false;
+ Result.setEnvironment(Environment, OSVersion, SDKInfo);
return Result;
}
static DarwinPlatform createOSVersionArg(DarwinPlatformKind Platform,
@@ -1750,7 +1820,12 @@ std::string getOSVersion(llvm::Triple::OSType OS, const llvm::Triple &Triple,
<< Triple.getOSName();
break;
case llvm::Triple::IOS:
- Triple.getiOSVersion(Major, Minor, Micro);
+ if (Triple.isMacCatalystEnvironment() && !Triple.getOSMajorVersion()) {
+ Major = 13;
+ Minor = 1;
+ Micro = 0;
+ } else
+ Triple.getiOSVersion(Major, Minor, Micro);
break;
case llvm::Triple::TvOS:
Triple.getOSVersion(Major, Minor, Micro);
@@ -1813,6 +1888,39 @@ Optional<DarwinPlatform> getDeploymentTargetFromTargetArg(
Triple, OSVersion, Args.getLastArg(options::OPT_target), SDKInfo);
}
+/// Returns the deployment target that's specified using the -mtargetos option.
+Optional<DarwinPlatform>
+getDeploymentTargetFromMTargetOSArg(DerivedArgList &Args,
+ const Driver &TheDriver,
+ const Optional<DarwinSDKInfo> &SDKInfo) {
+ auto *A = Args.getLastArg(options::OPT_mtargetos_EQ);
+ if (!A)
+ return None;
+ llvm::Triple TT(llvm::Twine("unknown-apple-") + A->getValue());
+ switch (TT.getOS()) {
+ case llvm::Triple::MacOSX:
+ case llvm::Triple::IOS:
+ case llvm::Triple::TvOS:
+ case llvm::Triple::WatchOS:
+ break;
+ default:
+ TheDriver.Diag(diag::err_drv_invalid_os_in_arg)
+ << TT.getOSName() << A->getAsString(Args);
+ return None;
+ }
+
+ unsigned Major, Minor, Micro;
+ TT.getOSVersion(Major, Minor, Micro);
+ if (!Major) {
+ TheDriver.Diag(diag::err_drv_invalid_version_number)
+ << A->getAsString(Args);
+ return None;
+ }
+ return DarwinPlatform::createFromMTargetOS(TT.getOS(),
+ VersionTuple(Major, Minor, Micro),
+ TT.getEnvironment(), A, SDKInfo);
+}
+
Optional<DarwinSDKInfo> parseSDKSettings(llvm::vfs::FileSystem &VFS,
const ArgList &Args,
const Driver &TheDriver) {
@@ -1861,6 +1969,13 @@ void Darwin::AddDeploymentTarget(DerivedArgList &Args) const {
Optional<DarwinPlatform> OSTarget =
getDeploymentTargetFromTargetArg(Args, getTriple(), getDriver(), SDKInfo);
if (OSTarget) {
+ // Disallow mixing -target and -mtargetos=.
+ if (const auto *MTargetOSArg = Args.getLastArg(options::OPT_mtargetos_EQ)) {
+ std::string TargetArgStr = OSTarget->getAsString(Args, Opts);
+ std::string MTargetOSArgStr = MTargetOSArg->getAsString(Args);
+ getDriver().Diag(diag::err_drv_cannot_mix_options)
+ << TargetArgStr << MTargetOSArgStr;
+ }
Optional<DarwinPlatform> OSVersionArgTarget =
getDeploymentTargetFromOSVersionArg(Args, getDriver());
if (OSVersionArgTarget) {
@@ -1892,6 +2007,18 @@ void Darwin::AddDeploymentTarget(DerivedArgList &Args) const {
}
}
}
+ } else if ((OSTarget = getDeploymentTargetFromMTargetOSArg(Args, getDriver(),
+ SDKInfo))) {
+ // The OS target can be specified using the -mtargetos= argument.
+ // Disallow mixing -mtargetos= and -m<os>version-min=.
+ Optional<DarwinPlatform> OSVersionArgTarget =
+ getDeploymentTargetFromOSVersionArg(Args, getDriver());
+ if (OSVersionArgTarget) {
+ std::string MTargetOSArgStr = OSTarget->getAsString(Args, Opts);
+ std::string OSVersionArgStr = OSVersionArgTarget->getAsString(Args, Opts);
+ getDriver().Diag(diag::err_drv_cannot_mix_options)
+ << MTargetOSArgStr << OSVersionArgStr;
+ }
} else {
// The OS target can be specified using the -m<os>version-min argument.
OSTarget = getDeploymentTargetFromOSVersionArg(Args, getDriver());
@@ -2656,7 +2783,7 @@ bool Darwin::SupportsEmbeddedBitcode() const {
bool MachO::isPICDefault() const { return true; }
-bool MachO::isPIEDefault() const { return false; }
+bool MachO::isPIEDefault(const llvm::opt::ArgList &Args) const { return false; }
bool MachO::isPICDefaultForced() const {
return (getArch() == llvm::Triple::x86_64 ||
diff --git a/clang/lib/Driver/ToolChains/Darwin.h b/clang/lib/Driver/ToolChains/Darwin.h
index 4de122c8d513..a307cd317ac3 100644
--- a/clang/lib/Driver/ToolChains/Darwin.h
+++ b/clang/lib/Driver/ToolChains/Darwin.h
@@ -78,6 +78,20 @@ public:
const char *LinkingOutput) const override;
};
+class LLVM_LIBRARY_VISIBILITY StaticLibTool : public MachOTool {
+public:
+ StaticLibTool(const ToolChain &TC)
+ : MachOTool("darwin::StaticLibTool", "static-lib-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 llvm::opt::ArgList &TCArgs,
+ const char *LinkingOutput) const override;
+};
+
class LLVM_LIBRARY_VISIBILITY Lipo : public MachOTool {
public:
Lipo(const ToolChain &TC) : MachOTool("darwin::Lipo", "lipo", TC) {}
@@ -125,6 +139,7 @@ class LLVM_LIBRARY_VISIBILITY MachO : public ToolChain {
protected:
Tool *buildAssembler() const override;
Tool *buildLinker() const override;
+ Tool *buildStaticLibTool() const override;
Tool *getTool(Action::ActionClass AC) const override;
private:
@@ -239,7 +254,7 @@ public:
}
bool isPICDefault() const override;
- bool isPIEDefault() const override;
+ bool isPIEDefault(const llvm::opt::ArgList &Args) const override;
bool isPICDefaultForced() const override;
bool SupportsProfiling() const override;
diff --git a/clang/lib/Driver/ToolChains/Flang.cpp b/clang/lib/Driver/ToolChains/Flang.cpp
index 1bfad6115d51..b82c5d7600df 100644
--- a/clang/lib/Driver/ToolChains/Flang.cpp
+++ b/clang/lib/Driver/ToolChains/Flang.cpp
@@ -37,8 +37,9 @@ void Flang::AddFortranDialectOptions(const ArgList &Args,
void Flang::AddPreprocessingOptions(const ArgList &Args,
ArgStringList &CmdArgs) const {
- Args.AddAllArgs(CmdArgs, {options::OPT_D, options::OPT_U, options::OPT_I,
- options::OPT_cpp, options::OPT_nocpp});
+ Args.AddAllArgs(CmdArgs,
+ {options::OPT_P, options::OPT_D, options::OPT_U,
+ options::OPT_I, options::OPT_cpp, options::OPT_nocpp});
}
void Flang::AddOtherOptions(const ArgList &Args, ArgStringList &CmdArgs) const {
diff --git a/clang/lib/Driver/ToolChains/FreeBSD.cpp b/clang/lib/Driver/ToolChains/FreeBSD.cpp
index 5dcf74dabf4f..dc05f9893465 100644
--- a/clang/lib/Driver/ToolChains/FreeBSD.cpp
+++ b/clang/lib/Driver/ToolChains/FreeBSD.cpp
@@ -99,7 +99,7 @@ void freebsd::Assembler::ConstructJob(Compilation &C, const JobAction &JA,
case llvm::Triple::sparc:
case llvm::Triple::sparcel:
case llvm::Triple::sparcv9: {
- std::string CPU = getCPUName(Args, getToolChain().getTriple());
+ std::string CPU = getCPUName(D, Args, getToolChain().getTriple());
CmdArgs.push_back(
sparc::getSparcAsmModeForCPU(CPU, getToolChain().getTriple()));
AddAssemblerKPIC(getToolChain(), Args, CmdArgs);
@@ -110,7 +110,7 @@ void freebsd::Assembler::ConstructJob(Compilation &C, const JobAction &JA,
for (const Arg *A : Args.filtered(options::OPT_ffile_prefix_map_EQ,
options::OPT_fdebug_prefix_map_EQ)) {
StringRef Map = A->getValue();
- if (Map.find('=') == StringRef::npos)
+ if (!Map.contains('='))
D.Diag(diag::err_drv_invalid_argument_to_option)
<< Map << A->getOption().getName();
else {
@@ -145,7 +145,7 @@ void freebsd::Linker::ConstructJob(Compilation &C, const JobAction &JA,
const llvm::Triple::ArchType Arch = ToolChain.getArch();
const bool IsPIE =
!Args.hasArg(options::OPT_shared) &&
- (Args.hasArg(options::OPT_pie) || ToolChain.isPIEDefault());
+ (Args.hasArg(options::OPT_pie) || ToolChain.isPIEDefault(Args));
ArgStringList CmdArgs;
// Silence warning for "clang -g foo.o -o foo"
@@ -467,7 +467,9 @@ bool FreeBSD::HasNativeLLVMSupport() const { return true; }
bool FreeBSD::IsUnwindTablesDefault(const ArgList &Args) const { return true; }
-bool FreeBSD::isPIEDefault() const { return getSanitizerArgs().requiresPIE(); }
+bool FreeBSD::isPIEDefault(const llvm::opt::ArgList &Args) const {
+ return getSanitizerArgs(Args).requiresPIE();
+}
SanitizerMask FreeBSD::getSupportedSanitizers() const {
const bool IsAArch64 = getTriple().getArch() == llvm::Triple::aarch64;
diff --git a/clang/lib/Driver/ToolChains/FreeBSD.h b/clang/lib/Driver/ToolChains/FreeBSD.h
index abc0876cef26..2a721c750a64 100644
--- a/clang/lib/Driver/ToolChains/FreeBSD.h
+++ b/clang/lib/Driver/ToolChains/FreeBSD.h
@@ -74,7 +74,7 @@ public:
llvm::ExceptionHandling
GetExceptionModel(const llvm::opt::ArgList &Args) const override;
bool IsUnwindTablesDefault(const llvm::opt::ArgList &Args) const override;
- bool isPIEDefault() const override;
+ bool isPIEDefault(const llvm::opt::ArgList &Args) const override;
SanitizerMask getSupportedSanitizers() const override;
unsigned GetDefaultDwarfVersion() const override;
// Until dtrace (via CTF) and LLDB can deal with distributed debug info,
diff --git a/clang/lib/Driver/ToolChains/Fuchsia.cpp b/clang/lib/Driver/ToolChains/Fuchsia.cpp
index fd9804a7f353..a7afec6963a1 100644
--- a/clang/lib/Driver/ToolChains/Fuchsia.cpp
+++ b/clang/lib/Driver/ToolChains/Fuchsia.cpp
@@ -60,6 +60,8 @@ void fuchsia::Linker::ConstructJob(Compilation &C, const JobAction &JA,
CmdArgs.push_back("rodynamic");
CmdArgs.push_back("-z");
CmdArgs.push_back("separate-loadable-segments");
+ CmdArgs.push_back("-z");
+ CmdArgs.push_back("rel");
CmdArgs.push_back("--pack-dyn-relocs=relr");
}
@@ -89,7 +91,7 @@ void fuchsia::Linker::ConstructJob(Compilation &C, const JobAction &JA,
else if (Args.hasArg(options::OPT_shared))
CmdArgs.push_back("-shared");
- const SanitizerArgs &SanArgs = ToolChain.getSanitizerArgs();
+ const SanitizerArgs &SanArgs = ToolChain.getSanitizerArgs(Args);
if (!Args.hasArg(options::OPT_shared)) {
std::string Dyld = D.DyldPrefix;
@@ -247,17 +249,16 @@ Fuchsia::Fuchsia(const Driver &D, const llvm::Triple &Triple,
Multilibs.FilterOut([&](const Multilib &M) {
std::vector<std::string> RD = FilePaths(M);
- return std::all_of(RD.begin(), RD.end(), [&](std::string P) {
- return !getVFS().exists(P);
- });
+ return llvm::all_of(RD, [&](std::string P) { return !getVFS().exists(P); });
});
Multilib::flags_list Flags;
addMultilibFlag(
Args.hasFlag(options::OPT_fexceptions, options::OPT_fno_exceptions, true),
"fexceptions", Flags);
- addMultilibFlag(getSanitizerArgs().needsAsanRt(), "fsanitize=address", Flags);
- addMultilibFlag(getSanitizerArgs().needsHwasanRt(), "fsanitize=hwaddress",
+ addMultilibFlag(getSanitizerArgs(Args).needsAsanRt(), "fsanitize=address",
+ Flags);
+ addMultilibFlag(getSanitizerArgs(Args).needsHwasanRt(), "fsanitize=hwaddress",
Flags);
addMultilibFlag(
@@ -437,13 +438,3 @@ SanitizerMask Fuchsia::getDefaultSanitizers() const {
}
return Res;
}
-
-void Fuchsia::addProfileRTLibs(const llvm::opt::ArgList &Args,
- llvm::opt::ArgStringList &CmdArgs) const {
- // Add linker option -u__llvm_profile_runtime to cause runtime
- // initialization module to be linked in.
- if (needsProfileRT(Args))
- CmdArgs.push_back(Args.MakeArgString(
- Twine("-u", llvm::getInstrProfRuntimeHookVarName())));
- ToolChain::addProfileRTLibs(Args, CmdArgs);
-}
diff --git a/clang/lib/Driver/ToolChains/Fuchsia.h b/clang/lib/Driver/ToolChains/Fuchsia.h
index 07adf9b7101d..c0e69df22821 100644
--- a/clang/lib/Driver/ToolChains/Fuchsia.h
+++ b/clang/lib/Driver/ToolChains/Fuchsia.h
@@ -54,7 +54,9 @@ public:
return true;
}
bool isPICDefault() const override { return false; }
- bool isPIEDefault() const override { return true; }
+ bool isPIEDefault(const llvm::opt::ArgList &Args) const override {
+ return true;
+ }
bool isPICDefaultForced() const override { return false; }
llvm::DebuggerKind getDefaultDebuggerTuning() const override {
return llvm::DebuggerKind::GDB;
@@ -71,9 +73,6 @@ public:
SanitizerMask getSupportedSanitizers() const override;
SanitizerMask getDefaultSanitizers() const override;
- void addProfileRTLibs(const llvm::opt::ArgList &Args,
- llvm::opt::ArgStringList &CmdArgs) const override;
-
RuntimeLibType
GetRuntimeLibType(const llvm::opt::ArgList &Args) const override;
CXXStdlibType
diff --git a/clang/lib/Driver/ToolChains/Gnu.cpp b/clang/lib/Driver/ToolChains/Gnu.cpp
index da39f29e4619..7aeadd84dfee 100644
--- a/clang/lib/Driver/ToolChains/Gnu.cpp
+++ b/clang/lib/Driver/ToolChains/Gnu.cpp
@@ -312,7 +312,7 @@ static bool getPIE(const ArgList &Args, const ToolChain &TC) {
Arg *A = Args.getLastArg(options::OPT_pie, options::OPT_no_pie,
options::OPT_nopie);
if (!A)
- return TC.isPIEDefault();
+ return TC.isPIEDefault(Args);
return A->getOption().matches(options::OPT_pie);
}
@@ -429,11 +429,6 @@ void tools::gnutools::Linker::ConstructJob(Compilation &C, const JobAction &JA,
CmdArgs.push_back("text");
}
- if (ToolChain.isNoExecStackDefault()) {
- CmdArgs.push_back("-z");
- CmdArgs.push_back("noexecstack");
- }
-
if (Args.hasArg(options::OPT_rdynamic))
CmdArgs.push_back("-export-dynamic");
@@ -451,7 +446,7 @@ void tools::gnutools::Linker::ConstructJob(Compilation &C, const JobAction &JA,
// Most Android ARM64 targets should enable the linker fix for erratum
// 843419. Only non-Cortex-A53 devices are allowed to skip this flag.
if (Arch == llvm::Triple::aarch64 && isAndroid) {
- std::string CPU = getCPUName(Args, Triple);
+ std::string CPU = getCPUName(D, Args, Triple);
if (CPU.empty() || CPU == "generic" || CPU == "cortex-a53")
CmdArgs.push_back("--fix-cortex-a53-843419");
}
@@ -473,17 +468,12 @@ void tools::gnutools::Linker::ConstructJob(Compilation &C, const JobAction &JA,
return;
}
- if (IsStatic) {
- if (Arch == llvm::Triple::arm || Arch == llvm::Triple::armeb ||
- Arch == llvm::Triple::thumb || Arch == llvm::Triple::thumbeb)
- CmdArgs.push_back("-Bstatic");
- else
- CmdArgs.push_back("-static");
- } else if (Args.hasArg(options::OPT_shared)) {
+ if (Args.hasArg(options::OPT_shared))
CmdArgs.push_back("-shared");
- }
- if (!IsStatic) {
+ if (IsStatic) {
+ CmdArgs.push_back("-static");
+ } else {
if (Args.hasArg(options::OPT_rdynamic))
CmdArgs.push_back("-export-dynamic");
@@ -534,10 +524,10 @@ void tools::gnutools::Linker::ConstructJob(Compilation &C, const JobAction &JA,
}
if (P.empty()) {
const char *crtbegin;
- if (IsStatic)
- crtbegin = isAndroid ? "crtbegin_static.o" : "crtbeginT.o";
- else if (Args.hasArg(options::OPT_shared))
+ if (Args.hasArg(options::OPT_shared))
crtbegin = isAndroid ? "crtbegin_so.o" : "crtbeginS.o";
+ else if (IsStatic)
+ crtbegin = isAndroid ? "crtbegin_static.o" : "crtbeginT.o";
else if (IsPIE || IsStaticPIE)
crtbegin = isAndroid ? "crtbegin_dynamic.o" : "crtbeginS.o";
else
@@ -712,10 +702,6 @@ void tools::gnutools::Assembler::ConstructJob(Compilation &C,
}
}
- if (getToolChain().isNoExecStackDefault()) {
- CmdArgs.push_back("--noexecstack");
- }
-
switch (getToolChain().getArch()) {
default:
break;
@@ -734,32 +720,32 @@ void tools::gnutools::Assembler::ConstructJob(Compilation &C,
CmdArgs.push_back("-a32");
CmdArgs.push_back("-mppc");
CmdArgs.push_back("-mbig-endian");
- CmdArgs.push_back(
- ppc::getPPCAsmModeForCPU(getCPUName(Args, getToolChain().getTriple())));
+ CmdArgs.push_back(ppc::getPPCAsmModeForCPU(
+ getCPUName(D, Args, getToolChain().getTriple())));
break;
}
case llvm::Triple::ppcle: {
CmdArgs.push_back("-a32");
CmdArgs.push_back("-mppc");
CmdArgs.push_back("-mlittle-endian");
- CmdArgs.push_back(
- ppc::getPPCAsmModeForCPU(getCPUName(Args, getToolChain().getTriple())));
+ CmdArgs.push_back(ppc::getPPCAsmModeForCPU(
+ getCPUName(D, Args, getToolChain().getTriple())));
break;
}
case llvm::Triple::ppc64: {
CmdArgs.push_back("-a64");
CmdArgs.push_back("-mppc64");
CmdArgs.push_back("-mbig-endian");
- CmdArgs.push_back(
- ppc::getPPCAsmModeForCPU(getCPUName(Args, getToolChain().getTriple())));
+ CmdArgs.push_back(ppc::getPPCAsmModeForCPU(
+ getCPUName(D, Args, getToolChain().getTriple())));
break;
}
case llvm::Triple::ppc64le: {
CmdArgs.push_back("-a64");
CmdArgs.push_back("-mppc64");
CmdArgs.push_back("-mlittle-endian");
- CmdArgs.push_back(
- ppc::getPPCAsmModeForCPU(getCPUName(Args, getToolChain().getTriple())));
+ CmdArgs.push_back(ppc::getPPCAsmModeForCPU(
+ getCPUName(D, Args, getToolChain().getTriple())));
break;
}
case llvm::Triple::riscv32:
@@ -775,7 +761,7 @@ void tools::gnutools::Assembler::ConstructJob(Compilation &C,
case llvm::Triple::sparc:
case llvm::Triple::sparcel: {
CmdArgs.push_back("-32");
- std::string CPU = getCPUName(Args, getToolChain().getTriple());
+ std::string CPU = getCPUName(D, Args, getToolChain().getTriple());
CmdArgs.push_back(
sparc::getSparcAsmModeForCPU(CPU, getToolChain().getTriple()));
AddAssemblerKPIC(getToolChain(), Args, CmdArgs);
@@ -783,7 +769,7 @@ void tools::gnutools::Assembler::ConstructJob(Compilation &C,
}
case llvm::Triple::sparcv9: {
CmdArgs.push_back("-64");
- std::string CPU = getCPUName(Args, getToolChain().getTriple());
+ std::string CPU = getCPUName(D, Args, getToolChain().getTriple());
CmdArgs.push_back(
sparc::getSparcAsmModeForCPU(CPU, getToolChain().getTriple()));
AddAssemblerKPIC(getToolChain(), Args, CmdArgs);
@@ -931,7 +917,7 @@ void tools::gnutools::Assembler::ConstructJob(Compilation &C,
for (const Arg *A : Args.filtered(options::OPT_ffile_prefix_map_EQ,
options::OPT_fdebug_prefix_map_EQ)) {
StringRef Map = A->getValue();
- if (Map.find('=') == StringRef::npos)
+ if (!Map.contains('='))
D.Diag(diag::err_drv_invalid_argument_to_option)
<< Map << A->getOption().getName();
else {
@@ -1086,7 +1072,8 @@ static bool findMipsCsMultilibs(const Multilib::flags_list &Flags,
.flag("-m32")
.flag("-mabi=n32");
- Multilib M32 = Multilib().flag("-m64").flag("+m32").flag("-mabi=n32");
+ Multilib M32 =
+ Multilib().gccSuffix("/32").flag("-m64").flag("+m32").flag("-mabi=n32");
DebianMipsMultilibs =
MultilibSet().Either(M32, M64, MAbiN32).FilterOut(NonExistent);
@@ -1473,7 +1460,7 @@ bool clang::driver::findMIPSMultilibs(const Driver &D,
addMultilibFlag(CPUName == "mips64r6", "march=mips64r6", Flags);
addMultilibFlag(isMicroMips(Args), "mmicromips", Flags);
addMultilibFlag(tools::mips::isUCLibc(Args), "muclibc", Flags);
- addMultilibFlag(tools::mips::isNaN2008(Args, TargetTriple), "mnan=2008",
+ addMultilibFlag(tools::mips::isNaN2008(D, Args, TargetTriple), "mnan=2008",
Flags);
addMultilibFlag(ABIName == "n32", "mabi=n32", Flags);
addMultilibFlag(ABIName == "n64", "mabi=n64", Flags);
@@ -2052,7 +2039,8 @@ void Generic_GCC::GCCInstallationDetector::AddDefaultGCCPrefixes(
// Non-Solaris is much simpler - most systems just go with "/usr".
if (SysRoot.empty() && TargetTriple.getOS() == llvm::Triple::Linux) {
- // Yet, still look for RHEL devtoolsets.
+ // 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");
@@ -2074,24 +2062,28 @@ void Generic_GCC::GCCInstallationDetector::AddDefaultGCCPrefixes(
// Declare a bunch of static data sets that we'll select between below. These
// are specifically designed to always refer to string literals to avoid any
// lifetime or initialization issues.
+ //
+ // The *Triples variables hard code some triples so that, for example,
+ // --target=aarch64 (incomplete triple) can detect lib/aarch64-linux-gnu.
+ // They are not needed when the user has correct LLVM_DEFAULT_TARGET_TRIPLE
+ // and always uses the full --target (e.g. --target=aarch64-linux-gnu). The
+ // lists should shrink over time. Please don't add more elements to *Triples.
static const char *const AArch64LibDirs[] = {"/lib64", "/lib"};
static const char *const AArch64Triples[] = {
"aarch64-none-linux-gnu", "aarch64-linux-gnu", "aarch64-redhat-linux",
- "aarch64-suse-linux", "aarch64-linux-android"};
+ "aarch64-suse-linux"};
static const char *const AArch64beLibDirs[] = {"/lib"};
static const char *const AArch64beTriples[] = {"aarch64_be-none-linux-gnu",
"aarch64_be-linux-gnu"};
static const char *const ARMLibDirs[] = {"/lib"};
- static const char *const ARMTriples[] = {"arm-linux-gnueabi",
- "arm-linux-androideabi"};
+ static const char *const ARMTriples[] = {"arm-linux-gnueabi"};
static const char *const ARMHFTriples[] = {"arm-linux-gnueabihf",
"armv7hl-redhat-linux-gnueabi",
"armv6hl-suse-linux-gnueabi",
"armv7hl-suse-linux-gnueabi"};
static const char *const ARMebLibDirs[] = {"/lib"};
- static const char *const ARMebTriples[] = {"armeb-linux-gnueabi",
- "armeb-linux-androideabi"};
+ static const char *const ARMebTriples[] = {"armeb-linux-gnueabi"};
static const char *const ARMebHFTriples[] = {
"armeb-linux-gnueabihf", "armebv7hl-redhat-linux-gnueabi"};
@@ -2105,31 +2097,28 @@ void Generic_GCC::GCCInstallationDetector::AddDefaultGCCPrefixes(
"x86_64-redhat-linux", "x86_64-suse-linux",
"x86_64-manbo-linux-gnu", "x86_64-linux-gnu",
"x86_64-slackware-linux", "x86_64-unknown-linux",
- "x86_64-amazon-linux", "x86_64-linux-android"};
+ "x86_64-amazon-linux"};
static const char *const X32Triples[] = {"x86_64-linux-gnux32",
"x86_64-pc-linux-gnux32"};
static const char *const X32LibDirs[] = {"/libx32", "/lib"};
static const char *const X86LibDirs[] = {"/lib32", "/lib"};
static const char *const X86Triples[] = {
- "i586-linux-gnu", "i686-linux-gnu",
- "i686-pc-linux-gnu", "i386-redhat-linux6E",
- "i686-redhat-linux", "i386-redhat-linux",
- "i586-suse-linux", "i686-montavista-linux",
- "i686-linux-android", "i686-gnu",
+ "i586-linux-gnu", "i686-linux-gnu", "i686-pc-linux-gnu",
+ "i386-redhat-linux6E", "i686-redhat-linux", "i386-redhat-linux",
+ "i586-suse-linux", "i686-montavista-linux", "i686-gnu",
};
static const char *const M68kLibDirs[] = {"/lib"};
static const char *const M68kTriples[] = {
"m68k-linux-gnu", "m68k-unknown-linux-gnu", "m68k-suse-linux"};
- static const char *const MIPSLibDirs[] = {"/lib"};
+ static const char *const MIPSLibDirs[] = {"/libo32", "/lib"};
static const char *const MIPSTriples[] = {
"mips-linux-gnu", "mips-mti-linux", "mips-mti-linux-gnu",
"mips-img-linux-gnu", "mipsisa32r6-linux-gnu"};
- static const char *const MIPSELLibDirs[] = {"/lib"};
+ static const char *const MIPSELLibDirs[] = {"/libo32", "/lib"};
static const char *const MIPSELTriples[] = {
- "mipsel-linux-gnu", "mips-img-linux-gnu", "mipsisa32r6el-linux-gnu",
- "mipsel-linux-android"};
+ "mipsel-linux-gnu", "mips-img-linux-gnu", "mipsisa32r6el-linux-gnu"};
static const char *const MIPS64LibDirs[] = {"/lib64", "/lib"};
static const char *const MIPS64Triples[] = {
@@ -2140,8 +2129,7 @@ void Generic_GCC::GCCInstallationDetector::AddDefaultGCCPrefixes(
static const char *const MIPS64ELTriples[] = {
"mips64el-linux-gnu", "mips-mti-linux-gnu",
"mips-img-linux-gnu", "mips64el-linux-gnuabi64",
- "mipsisa64r6el-linux-gnu", "mipsisa64r6el-linux-gnuabi64",
- "mips64el-linux-android"};
+ "mipsisa64r6el-linux-gnu", "mipsisa64r6el-linux-gnuabi64"};
static const char *const MIPSN32LibDirs[] = {"/lib32"};
static const char *const MIPSN32Triples[] = {"mips64-linux-gnuabin32",
@@ -2181,9 +2169,7 @@ void Generic_GCC::GCCInstallationDetector::AddDefaultGCCPrefixes(
static const char *const RISCV64LibDirs[] = {"/lib64", "/lib"};
static const char *const RISCV64Triples[] = {"riscv64-unknown-linux-gnu",
"riscv64-linux-gnu",
- "riscv64-unknown-elf",
- "riscv64-redhat-linux",
- "riscv64-suse-linux"};
+ "riscv64-unknown-elf"};
static const char *const SPARCv8LibDirs[] = {"/lib32", "/lib"};
static const char *const SPARCv8Triples[] = {"sparc-linux-gnu",
@@ -2708,6 +2694,7 @@ bool Generic_GCC::IsUnwindTablesDefault(const ArgList &Args) const {
case llvm::Triple::ppcle:
case llvm::Triple::ppc64:
case llvm::Triple::ppc64le:
+ case llvm::Triple::x86:
case llvm::Triple::x86_64:
return true;
default:
@@ -2727,7 +2714,9 @@ bool Generic_GCC::isPICDefault() const {
}
}
-bool Generic_GCC::isPIEDefault() const { return false; }
+bool Generic_GCC::isPIEDefault(const llvm::opt::ArgList &Args) const {
+ return false;
+}
bool Generic_GCC::isPICDefaultForced() const {
return getArch() == llvm::Triple::x86_64 && getTriple().isOSWindows();
diff --git a/clang/lib/Driver/ToolChains/Gnu.h b/clang/lib/Driver/ToolChains/Gnu.h
index 40fd756a5653..4eb7ab0215ab 100644
--- a/clang/lib/Driver/ToolChains/Gnu.h
+++ b/clang/lib/Driver/ToolChains/Gnu.h
@@ -298,7 +298,7 @@ public:
bool IsUnwindTablesDefault(const llvm::opt::ArgList &Args) const override;
bool isPICDefault() const override;
- bool isPIEDefault() const override;
+ bool isPIEDefault(const llvm::opt::ArgList &Args) const override;
bool isPICDefaultForced() const override;
bool IsIntegratedAssemblerDefault() const override;
llvm::opt::DerivedArgList *
diff --git a/clang/lib/Driver/ToolChains/HIP.cpp b/clang/lib/Driver/ToolChains/HIP.cpp
index 59d58aadb687..07af1a0457c7 100644
--- a/clang/lib/Driver/ToolChains/HIP.cpp
+++ b/clang/lib/Driver/ToolChains/HIP.cpp
@@ -16,6 +16,7 @@
#include "clang/Driver/DriverDiagnostic.h"
#include "clang/Driver/InputInfo.h"
#include "clang/Driver/Options.h"
+#include "clang/Driver/SanitizerArgs.h"
#include "llvm/Support/Alignment.h"
#include "llvm/Support/FileSystem.h"
#include "llvm/Support/Path.h"
@@ -37,6 +38,43 @@ namespace {
const unsigned HIPCodeObjectAlign = 4096;
} // namespace
+static bool shouldSkipSanitizeOption(const ToolChain &TC,
+ const llvm::opt::ArgList &DriverArgs,
+ StringRef TargetID,
+ const llvm::opt::Arg *A) {
+ // For actions without targetID, do nothing.
+ if (TargetID.empty())
+ return false;
+ Option O = A->getOption();
+ if (!O.matches(options::OPT_fsanitize_EQ))
+ return false;
+
+ if (!DriverArgs.hasFlag(options::OPT_fgpu_sanitize,
+ -options::OPT_fno_gpu_sanitize))
+ return true;
+
+ auto &Diags = TC.getDriver().getDiags();
+
+ // For simplicity, we only allow -fsanitize=address
+ SanitizerMask K = parseSanitizerValue(A->getValue(), /*AllowGroups=*/false);
+ if (K != SanitizerKind::Address)
+ return true;
+
+ llvm::StringMap<bool> FeatureMap;
+ auto OptionalGpuArch = parseTargetID(TC.getTriple(), TargetID, &FeatureMap);
+
+ assert(OptionalGpuArch && "Invalid Target ID");
+ (void)OptionalGpuArch;
+ auto Loc = FeatureMap.find("xnack");
+ if (Loc == FeatureMap.end() || !Loc->second) {
+ Diags.Report(
+ clang::diag::warn_drv_unsupported_option_for_offload_arch_req_feature)
+ << A->getAsString(DriverArgs) << TargetID << "xnack+";
+ return true;
+ }
+ return false;
+}
+
void AMDGCN::Linker::constructLldCommand(Compilation &C, const JobAction &JA,
const InputInfoList &Inputs,
const InputInfo &Output,
@@ -86,12 +124,6 @@ void AMDGCN::Linker::constructLldCommand(Compilation &C, const JobAction &JA,
for (auto Input : Inputs)
LldArgs.push_back(Input.getFilename());
- if (Args.hasFlag(options::OPT_fgpu_sanitize, options::OPT_fno_gpu_sanitize,
- false))
- llvm::for_each(TC.getHIPDeviceLibs(Args), [&](StringRef BCFile) {
- LldArgs.push_back(Args.MakeArgString(BCFile));
- });
-
const char *Lld = Args.MakeArgString(getToolChain().GetProgramPath("lld"));
C.addCommand(std::make_unique<Command>(JA, *this, ResponseFileSupport::None(),
Lld, LldArgs, Inputs, Output));
@@ -237,6 +269,14 @@ HIPToolChain::HIPToolChain(const Driver &D, const llvm::Triple &Triple,
// Lookup binaries into the driver directory, this is used to
// discover the clang-offload-bundler executable.
getProgramPaths().push_back(getDriver().Dir);
+
+ // Diagnose unsupported sanitizer options only once.
+ for (auto A : Args.filtered(options::OPT_fsanitize_EQ)) {
+ SanitizerMask K = parseSanitizerValue(A->getValue(), /*AllowGroups=*/false);
+ if (K != SanitizerKind::Address)
+ D.getDiags().Report(clang::diag::warn_drv_unsupported_option_for_target)
+ << A->getAsString(Args) << getTriple().str();
+ }
}
void HIPToolChain::addClangTargetOptions(
@@ -276,9 +316,10 @@ void HIPToolChain::addClangTargetOptions(
CC1Args.push_back("-fapply-global-visibility-to-externs");
}
- llvm::for_each(getHIPDeviceLibs(DriverArgs), [&](StringRef BCFile) {
- CC1Args.push_back("-mlink-builtin-bitcode");
- CC1Args.push_back(DriverArgs.MakeArgString(BCFile));
+ llvm::for_each(getHIPDeviceLibs(DriverArgs), [&](auto BCFile) {
+ CC1Args.push_back(BCFile.ShouldInternalize ? "-mlink-builtin-bitcode"
+ : "-mlink-bitcode-file");
+ CC1Args.push_back(DriverArgs.MakeArgString(BCFile.Path));
});
}
@@ -294,7 +335,8 @@ HIPToolChain::TranslateArgs(const llvm::opt::DerivedArgList &Args,
const OptTable &Opts = getDriver().getOpts();
for (Arg *A : Args) {
- if (!shouldSkipArgument(A))
+ if (!shouldSkipArgument(A) &&
+ !shouldSkipSanitizeOption(*this, Args, BoundArch, A))
DAL->append(A);
}
@@ -359,9 +401,9 @@ VersionTuple HIPToolChain::computeMSVCVersion(const Driver *D,
return HostTC.computeMSVCVersion(D, Args);
}
-llvm::SmallVector<std::string, 12>
+llvm::SmallVector<ToolChain::BitCodeLibraryInfo, 12>
HIPToolChain::getHIPDeviceLibs(const llvm::opt::ArgList &DriverArgs) const {
- llvm::SmallVector<std::string, 12> BCLibs;
+ llvm::SmallVector<BitCodeLibraryInfo, 12> BCLibs;
if (DriverArgs.hasArg(options::OPT_nogpulib))
return {};
ArgStringList LibraryPaths;
@@ -382,7 +424,7 @@ HIPToolChain::getHIPDeviceLibs(const llvm::opt::ArgList &DriverArgs) const {
llvm::sys::path::append(Path, BCName);
FullName = Path;
if (llvm::sys::fs::exists(FullName)) {
- BCLibs.push_back(FullName.str());
+ BCLibs.push_back(FullName);
return;
}
}
@@ -395,37 +437,11 @@ HIPToolChain::getHIPDeviceLibs(const llvm::opt::ArgList &DriverArgs) const {
}
StringRef GpuArch = getGPUArch(DriverArgs);
assert(!GpuArch.empty() && "Must have an explicit GPU arch.");
- (void)GpuArch;
- 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;
- 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
- // them all?
- bool DAZ = DriverArgs.hasFlag(options::OPT_fgpu_flush_denormals_to_zero,
- options::OPT_fno_gpu_flush_denormals_to_zero,
- getDefaultDenormsAreZeroForTarget(Kind));
- bool FiniteOnly =
- DriverArgs.hasFlag(options::OPT_ffinite_math_only,
- options::OPT_fno_finite_math_only, false);
- bool UnsafeMathOpt =
- DriverArgs.hasFlag(options::OPT_funsafe_math_optimizations,
- options::OPT_fno_unsafe_math_optimizations, false);
- bool FastRelaxedMath = DriverArgs.hasFlag(
- options::OPT_ffast_math, 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);
- bool Wave64 = isWave64(DriverArgs, Kind);
-
if (DriverArgs.hasFlag(options::OPT_fgpu_sanitize,
- options::OPT_fno_gpu_sanitize, false)) {
+ options::OPT_fno_gpu_sanitize) &&
+ getSanitizerArgs(DriverArgs).needsAsanRt()) {
auto AsanRTL = RocmInstallation.getAsanRTLPath();
if (AsanRTL.empty()) {
unsigned DiagID = getDriver().getDiags().getCustomDiagID(
@@ -436,16 +452,15 @@ HIPToolChain::getHIPDeviceLibs(const llvm::opt::ArgList &DriverArgs) const {
getDriver().Diag(DiagID);
return {};
} else
- BCLibs.push_back(AsanRTL.str());
+ BCLibs.push_back({AsanRTL.str(), /*ShouldInternalize=*/false});
}
// Add the HIP specific bitcode library.
- BCLibs.push_back(RocmInstallation.getHIPPath().str());
+ BCLibs.push_back(RocmInstallation.getHIPPath());
- // Add the generic set of libraries.
- BCLibs.append(RocmInstallation.getCommonBitcodeLibs(
- DriverArgs, LibDeviceFile, Wave64, DAZ, FiniteOnly, UnsafeMathOpt,
- FastRelaxedMath, CorrectSqrt));
+ // Add common device libraries like ocml etc.
+ for (auto N : getCommonDeviceLibNames(DriverArgs, GpuArch.str()))
+ BCLibs.push_back(StringRef(N));
// Add instrument lib.
auto InstLib =
@@ -453,7 +468,7 @@ HIPToolChain::getHIPDeviceLibs(const llvm::opt::ArgList &DriverArgs) const {
if (InstLib.empty())
return BCLibs;
if (llvm::sys::fs::exists(InstLib))
- BCLibs.push_back(InstLib.str());
+ BCLibs.push_back(InstLib);
else
getDriver().Diag(diag::err_drv_no_such_file) << InstLib;
}
@@ -466,22 +481,6 @@ void HIPToolChain::checkTargetID(const llvm::opt::ArgList &DriverArgs) const {
if (PTID.OptionalTargetID && !PTID.OptionalGPUArch) {
getDriver().Diag(clang::diag::err_drv_bad_target_id)
<< PTID.OptionalTargetID.getValue();
- return;
- }
-
- assert(PTID.OptionalFeatures && "Invalid return from getParsedTargetID");
- auto &FeatureMap = PTID.OptionalFeatures.getValue();
- // Sanitizer is not supported with xnack-.
- if (DriverArgs.hasFlag(options::OPT_fgpu_sanitize,
- options::OPT_fno_gpu_sanitize, false)) {
- auto Loc = FeatureMap.find("xnack");
- if (Loc != FeatureMap.end() && !Loc->second) {
- auto &Diags = getDriver().getDiags();
- auto DiagID = Diags.getCustomDiagID(
- DiagnosticsEngine::Error,
- "'-fgpu-sanitize' is not compatible with offload arch '%0'. "
- "Use an offload arch without 'xnack-' instead");
- Diags.Report(DiagID) << PTID.OptionalTargetID.getValue();
- }
}
+ return;
}
diff --git a/clang/lib/Driver/ToolChains/HIP.h b/clang/lib/Driver/ToolChains/HIP.h
index 3cced0a320dc..60b3d69b3f52 100644
--- a/clang/lib/Driver/ToolChains/HIP.h
+++ b/clang/lib/Driver/ToolChains/HIP.h
@@ -83,7 +83,7 @@ public:
llvm::opt::ArgStringList &CC1Args) const override;
void AddHIPIncludeArgs(const llvm::opt::ArgList &DriverArgs,
llvm::opt::ArgStringList &CC1Args) const override;
- llvm::SmallVector<std::string, 12>
+ llvm::SmallVector<BitCodeLibraryInfo, 12>
getHIPDeviceLibs(const llvm::opt::ArgList &Args) const override;
SanitizerMask getSupportedSanitizers() const override;
@@ -92,7 +92,7 @@ public:
computeMSVCVersion(const Driver *D,
const llvm::opt::ArgList &Args) const override;
- unsigned GetDefaultDwarfVersion() const override { return 4; }
+ unsigned GetDefaultDwarfVersion() const override { return 5; }
const ToolChain &HostTC;
void checkTargetID(const llvm::opt::ArgList &DriverArgs) const override;
diff --git a/clang/lib/Driver/ToolChains/Haiku.h b/clang/lib/Driver/ToolChains/Haiku.h
index 2bc98322bebf..669379a21605 100644
--- a/clang/lib/Driver/ToolChains/Haiku.h
+++ b/clang/lib/Driver/ToolChains/Haiku.h
@@ -22,7 +22,7 @@ public:
Haiku(const Driver &D, const llvm::Triple &Triple,
const llvm::opt::ArgList &Args);
- bool isPIEDefault() const override {
+ bool isPIEDefault(const llvm::opt::ArgList &Args) const override {
return getTriple().getArch() == llvm::Triple::x86_64;
}
diff --git a/clang/lib/Driver/ToolChains/Hexagon.cpp b/clang/lib/Driver/ToolChains/Hexagon.cpp
index 828bfdbb05a3..18270818d158 100644
--- a/clang/lib/Driver/ToolChains/Hexagon.cpp
+++ b/clang/lib/Driver/ToolChains/Hexagon.cpp
@@ -146,6 +146,8 @@ void hexagon::Assembler::ConstructJob(Compilation &C, const JobAction &JA,
"-mcpu=hexagon" +
toolchains::HexagonToolChain::GetTargetCPUVersion(Args)));
+ addSanitizerRuntimes(HTC, Args, CmdArgs);
+
if (Output.isFilename()) {
CmdArgs.push_back("-o");
CmdArgs.push_back(Output.getFilename());
@@ -223,6 +225,8 @@ constructHexagonLinkArgs(Compilation &C, const JobAction &JA,
bool UseShared = IsShared && !IsStatic;
StringRef CpuVer = toolchains::HexagonToolChain::GetTargetCPUVersion(Args);
+ bool NeedsSanitizerDeps = addSanitizerRuntimes(HTC, Args, CmdArgs);
+
//----------------------------------------------------------------------------
// Silence warnings for various options
//----------------------------------------------------------------------------
@@ -288,6 +292,12 @@ constructHexagonLinkArgs(Compilation &C, const JobAction &JA,
AddLinkerInputs(HTC, Inputs, Args, CmdArgs, JA);
if (!Args.hasArg(options::OPT_nostdlib, options::OPT_nodefaultlibs)) {
+ if (NeedsSanitizerDeps) {
+ linkSanitizerRuntimeDeps(HTC, CmdArgs);
+
+ CmdArgs.push_back("-lunwind");
+ }
+
CmdArgs.push_back("-lclang_rt.builtins-hexagon");
CmdArgs.push_back("-lc");
}
@@ -450,6 +460,13 @@ Optional<unsigned> HexagonToolChain::getSmallDataThreshold(
return None;
}
+std::string HexagonToolChain::getCompilerRTPath() const {
+ SmallString<128> Dir(getDriver().SysRoot);
+ llvm::sys::path::append(Dir, "usr", "lib");
+ Dir += SelectedMultilib.gccSuffix();
+ return std::string(Dir.str());
+}
+
void HexagonToolChain::getHexagonLibraryPaths(const ArgList &Args,
ToolChain::path_list &LibPaths) const {
const Driver &D = getDriver();
@@ -470,7 +487,7 @@ void HexagonToolChain::getHexagonLibraryPaths(const ArgList &Args,
std::string TargetDir = getHexagonTargetDir(D.getInstalledDir(),
D.PrefixDirs);
- if (llvm::find(RootDirs, TargetDir) == RootDirs.end())
+ if (!llvm::is_contained(RootDirs, TargetDir))
RootDirs.push_back(TargetDir);
bool HasPIC = Args.hasArg(options::OPT_fpic, options::OPT_fPIC);
@@ -588,21 +605,43 @@ void HexagonToolChain::addClangTargetOptions(const ArgList &DriverArgs,
void HexagonToolChain::AddClangSystemIncludeArgs(const ArgList &DriverArgs,
ArgStringList &CC1Args) const {
- if (DriverArgs.hasArg(options::OPT_nostdinc) ||
- DriverArgs.hasArg(options::OPT_nostdlibinc))
+ if (DriverArgs.hasArg(options::OPT_nostdinc))
return;
+ const bool IsELF = !getTriple().isMusl() && !getTriple().isOSLinux();
+ const bool IsLinuxMusl = getTriple().isMusl() && getTriple().isOSLinux();
+
const Driver &D = getDriver();
- if (!D.SysRoot.empty()) {
+ SmallString<128> ResourceDirInclude(D.ResourceDir);
+ if (!IsELF) {
+ llvm::sys::path::append(ResourceDirInclude, "include");
+ if (!DriverArgs.hasArg(options::OPT_nobuiltininc) &&
+ (!IsLinuxMusl || DriverArgs.hasArg(options::OPT_nostdlibinc)))
+ addSystemInclude(DriverArgs, CC1Args, ResourceDirInclude);
+ }
+ if (DriverArgs.hasArg(options::OPT_nostdlibinc))
+ return;
+
+ const bool HasSysRoot = !D.SysRoot.empty();
+ if (HasSysRoot) {
SmallString<128> P(D.SysRoot);
- if (getTriple().isMusl())
+ if (IsLinuxMusl)
llvm::sys::path::append(P, "usr/include");
else
llvm::sys::path::append(P, "include");
+
addExternCSystemInclude(DriverArgs, CC1Args, P.str());
- return;
+ // LOCAL_INCLUDE_DIR
+ addSystemInclude(DriverArgs, CC1Args, P + "/usr/local/include");
+ // TOOL_INCLUDE_DIR
+ AddMultilibIncludeArgs(DriverArgs, CC1Args);
}
+ if (!DriverArgs.hasArg(options::OPT_nobuiltininc) && IsLinuxMusl)
+ addSystemInclude(DriverArgs, CC1Args, ResourceDirInclude);
+
+ if (HasSysRoot)
+ return;
std::string TargetDir = getHexagonTargetDir(D.getInstalledDir(),
D.PrefixDirs);
addExternCSystemInclude(DriverArgs, CC1Args, TargetDir + "/hexagon/include");
@@ -665,11 +704,11 @@ bool HexagonToolChain::isAutoHVXEnabled(const llvm::opt::ArgList &Args) {
// Returns the default CPU for Hexagon. This is the default compilation target
// if no Hexagon processor is selected at the command-line.
//
-const StringRef HexagonToolChain::GetDefaultCPU() {
+StringRef HexagonToolChain::GetDefaultCPU() {
return "hexagonv60";
}
-const StringRef HexagonToolChain::GetTargetCPUVersion(const ArgList &Args) {
+StringRef HexagonToolChain::GetTargetCPUVersion(const ArgList &Args) {
Arg *CpuArg = nullptr;
if (Arg *A = Args.getLastArg(options::OPT_mcpu_EQ))
CpuArg = A;
diff --git a/clang/lib/Driver/ToolChains/Hexagon.h b/clang/lib/Driver/ToolChains/Hexagon.h
index c32cb7f09591..899630555352 100644
--- a/clang/lib/Driver/ToolChains/Hexagon.h
+++ b/clang/lib/Driver/ToolChains/Hexagon.h
@@ -104,9 +104,11 @@ public:
void getHexagonLibraryPaths(const llvm::opt::ArgList &Args,
ToolChain::path_list &LibPaths) const;
+ std::string getCompilerRTPath() const override;
+
static bool isAutoHVXEnabled(const llvm::opt::ArgList &Args);
- static const StringRef GetDefaultCPU();
- static const StringRef GetTargetCPUVersion(const llvm::opt::ArgList &Args);
+ static StringRef GetDefaultCPU();
+ static StringRef GetTargetCPUVersion(const llvm::opt::ArgList &Args);
static Optional<unsigned> getSmallDataThreshold(
const llvm::opt::ArgList &Args);
diff --git a/clang/lib/Driver/ToolChains/Linux.cpp b/clang/lib/Driver/ToolChains/Linux.cpp
index c9360fc67165..0224383e63a1 100644
--- a/clang/lib/Driver/ToolChains/Linux.cpp
+++ b/clang/lib/Driver/ToolChains/Linux.cpp
@@ -206,8 +206,7 @@ Linux::Linux(const Driver &D, const llvm::Triple &Triple, const ArgList &Args)
ExtraOpts.push_back("max-page-size=4096");
}
- if (GCCInstallation.getParentLibPath().find("opt/rh/devtoolset") !=
- StringRef::npos)
+ if (GCCInstallation.getParentLibPath().contains("opt/rh/"))
// With devtoolset on RHEL, we want to add a bin directory that is relative
// to the detected gcc install, because if we are using devtoolset gcc then
// we want to use other tools from devtoolset (e.g. ld) instead of the
@@ -262,6 +261,13 @@ Linux::Linux(const Driver &D, const llvm::Triple &Triple, const ArgList &Args)
const std::string OSLibDir = std::string(getOSLibDir(Triple, Args));
const std::string MultiarchTriple = getMultiarchTriple(D, Triple, SysRoot);
+ // mips32: Debian multilib, we use /libo32, while in other case, /lib is
+ // 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);
+ }
Generic_GCC::AddMultilibPaths(D, SysRoot, OSLibDir, MultiarchTriple, Paths);
addPathIfExists(D, SysRoot + "/lib/" + MultiarchTriple, Paths);
@@ -303,8 +309,13 @@ Linux::Linux(const Driver &D, const llvm::Triple &Triple, const ArgList &Args)
// 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))
+ if (StringRef(D.Dir).startswith(SysRoot)) {
+ // Even if OSLibDir != "lib", this is needed for Clang in the build
+ // directory (not installed) to find libc++.
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);
@@ -449,7 +460,7 @@ std::string Linux::getDynamicLinker(const ArgList &Args) const {
case llvm::Triple::mipsel:
case llvm::Triple::mips64:
case llvm::Triple::mips64el: {
- bool IsNaN2008 = tools::mips::isNaN2008(Args, Triple);
+ bool IsNaN2008 = tools::mips::isNaN2008(getDriver(), Args, Triple);
LibDir = "lib" + tools::mips::getMipsABILibSuffix(Args, Triple);
@@ -651,9 +662,9 @@ void Linux::AddIAMCUIncludeArgs(const ArgList &DriverArgs,
}
}
-bool Linux::isPIEDefault() const {
- return (getTriple().isAndroid() && !getTriple().isAndroidVersionLT(16)) ||
- getTriple().isMusl() || getSanitizerArgs().requiresPIE();
+bool Linux::isPIEDefault(const llvm::opt::ArgList &Args) const {
+ return getTriple().isAndroid() || getTriple().isMusl() ||
+ getSanitizerArgs(Args).requiresPIE();
}
bool Linux::IsAArch64OutlineAtomicsDefault(const ArgList &Args) const {
@@ -669,10 +680,6 @@ bool Linux::IsAArch64OutlineAtomicsDefault(const ArgList &Args) const {
return true;
}
-bool Linux::isNoExecStackDefault() const {
- return getTriple().isAndroid();
-}
-
bool Linux::IsMathErrnoDefault() const {
if (getTriple().isAndroid())
return false;
@@ -694,6 +701,7 @@ SanitizerMask Linux::getSupportedSanitizers() const {
getTriple().getArch() == llvm::Triple::thumbeb;
const bool IsRISCV64 = getTriple().getArch() == llvm::Triple::riscv64;
const bool IsSystemZ = getTriple().getArch() == llvm::Triple::systemz;
+ const bool IsHexagon = getTriple().getArch() == llvm::Triple::hexagon;
SanitizerMask Res = ToolChain::getSupportedSanitizers();
Res |= SanitizerKind::Address;
Res |= SanitizerKind::PointerCompare;
@@ -707,7 +715,7 @@ SanitizerMask Linux::getSupportedSanitizers() const {
if (IsX86_64 || IsMIPS64 || IsAArch64)
Res |= SanitizerKind::DataFlow;
if (IsX86_64 || IsMIPS64 || IsAArch64 || IsX86 || IsArmArch || IsPowerPC64 ||
- IsRISCV64 || IsSystemZ)
+ IsRISCV64 || IsSystemZ || IsHexagon)
Res |= SanitizerKind::Leak;
if (IsX86_64 || IsMIPS64 || IsAArch64 || IsPowerPC64 || IsSystemZ)
Res |= SanitizerKind::Thread;
@@ -716,7 +724,7 @@ SanitizerMask Linux::getSupportedSanitizers() const {
if (IsX86 || IsX86_64)
Res |= SanitizerKind::Function;
if (IsX86_64 || IsMIPS64 || IsAArch64 || IsX86 || IsMIPS || IsArmArch ||
- IsPowerPC64)
+ IsPowerPC64 || IsHexagon)
Res |= SanitizerKind::Scudo;
if (IsX86_64 || IsAArch64) {
Res |= SanitizerKind::HWAddress;
diff --git a/clang/lib/Driver/ToolChains/Linux.h b/clang/lib/Driver/ToolChains/Linux.h
index 169a37c44072..a5ec33bd44f1 100644
--- a/clang/lib/Driver/ToolChains/Linux.h
+++ b/clang/lib/Driver/ToolChains/Linux.h
@@ -43,8 +43,7 @@ public:
CXXStdlibType GetDefaultCXXStdlibType() const override;
bool
IsAArch64OutlineAtomicsDefault(const llvm::opt::ArgList &Args) const override;
- bool isPIEDefault() const override;
- bool isNoExecStackDefault() const override;
+ bool isPIEDefault(const llvm::opt::ArgList &Args) const override;
bool IsMathErrnoDefault() const override;
SanitizerMask getSupportedSanitizers() const override;
void addProfileRTLibs(const llvm::opt::ArgList &Args,
diff --git a/clang/lib/Driver/ToolChains/MSP430.h b/clang/lib/Driver/ToolChains/MSP430.h
index 9d247ca3a896..2e838c027e0f 100644
--- a/clang/lib/Driver/ToolChains/MSP430.h
+++ b/clang/lib/Driver/ToolChains/MSP430.h
@@ -37,7 +37,9 @@ public:
Action::OffloadKind) const override;
bool isPICDefault() const override { return false; }
- bool isPIEDefault() const override { return false; }
+ bool isPIEDefault(const llvm::opt::ArgList &Args) const override {
+ return false;
+ }
bool isPICDefaultForced() const override { return true; }
UnwindLibType
diff --git a/clang/lib/Driver/ToolChains/MSVC.cpp b/clang/lib/Driver/ToolChains/MSVC.cpp
index 0dc94a4c6c7d..792b0a51fea0 100644
--- a/clang/lib/Driver/ToolChains/MSVC.cpp
+++ b/clang/lib/Driver/ToolChains/MSVC.cpp
@@ -63,6 +63,61 @@ 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)
@@ -396,6 +451,20 @@ void visualstudio::Linker::ConstructJob(Compilation &C, const JobAction &JA,
// the environment variable is set however, assume the user knows what
// they're doing. If the user passes /vctoolsdir or /winsdkdir, trust that
// over env vars.
+ if (const Arg *A = Args.getLastArg(options::OPT__SLASH_diasdkdir,
+ options::OPT__SLASH_winsysroot)) {
+ // cl.exe doesn't find the DIA SDK automatically, so this too requires
+ // explicit flags and doesn't automatically look in "DIA SDK" relative
+ // to the path we found for VCToolChainPath.
+ llvm::SmallString<128> DIAPath(A->getValue());
+ if (A->getOption().getID() == options::OPT__SLASH_winsysroot)
+ llvm::sys::path::append(DIAPath, "DIA SDK");
+
+ // The DIA SDK always uses the legacy vc arch, even in new MSVC versions.
+ llvm::sys::path::append(DIAPath, "lib",
+ llvmArchToLegacyVCArch(TC.getArch()));
+ CmdArgs.push_back(Args.MakeArgString(Twine("-libpath:") + DIAPath));
+ }
if (!llvm::sys::Process::GetEnv("LIB") ||
Args.getLastArg(options::OPT__SLASH_vctoolsdir,
options::OPT__SLASH_winsysroot)) {
@@ -461,7 +530,7 @@ void visualstudio::Linker::ConstructJob(Compilation &C, const JobAction &JA,
CmdArgs.push_back(Args.MakeArgString(std::string("-implib:") + ImplibName));
}
- if (TC.getSanitizerArgs().needsFuzzer()) {
+ if (TC.getSanitizerArgs(Args).needsFuzzer()) {
if (!Args.hasArg(options::OPT_shared))
CmdArgs.push_back(
Args.MakeArgString(std::string("-wholearchive:") +
@@ -472,10 +541,10 @@ void visualstudio::Linker::ConstructJob(Compilation &C, const JobAction &JA,
CmdArgs.push_back(Args.MakeArgString("-incremental:no"));
}
- if (TC.getSanitizerArgs().needsAsanRt()) {
+ if (TC.getSanitizerArgs(Args).needsAsanRt()) {
CmdArgs.push_back(Args.MakeArgString("-debug"));
CmdArgs.push_back(Args.MakeArgString("-incremental:no"));
- if (TC.getSanitizerArgs().needsSharedRt() ||
+ if (TC.getSanitizerArgs(Args).needsSharedRt() ||
Args.hasArg(options::OPT__SLASH_MD, options::OPT__SLASH_MDd)) {
for (const auto &Lib : {"asan_dynamic", "asan_dynamic_runtime_thunk"})
CmdArgs.push_back(TC.getCompilerRTArgString(Args, Lib));
@@ -726,15 +795,17 @@ bool MSVCToolChain::IsUnwindTablesDefault(const ArgList &Args) const {
}
bool MSVCToolChain::isPICDefault() const {
- return getArch() == llvm::Triple::x86_64;
+ return getArch() == llvm::Triple::x86_64 ||
+ getArch() == llvm::Triple::aarch64;
}
-bool MSVCToolChain::isPIEDefault() const {
+bool MSVCToolChain::isPIEDefault(const llvm::opt::ArgList &Args) const {
return false;
}
bool MSVCToolChain::isPICDefaultForced() const {
- return getArch() == llvm::Triple::x86_64;
+ return getArch() == llvm::Triple::x86_64 ||
+ getArch() == llvm::Triple::aarch64;
}
void MSVCToolChain::AddCudaIncludeArgs(const ArgList &DriverArgs,
@@ -752,61 +823,6 @@ void MSVCToolChain::printVerboseInfo(raw_ostream &OS) const {
RocmInstallation.print(OS);
}
-// 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 "";
- }
-}
-
// 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
@@ -1263,6 +1279,19 @@ void MSVCToolChain::AddClangSystemIncludeArgs(const ArgList &DriverArgs,
AddSystemIncludesFromEnv(Var);
}
+ // Add DIA SDK include if requested.
+ if (const Arg *A = DriverArgs.getLastArg(options::OPT__SLASH_diasdkdir,
+ options::OPT__SLASH_winsysroot)) {
+ // cl.exe doesn't find the DIA SDK automatically, so this too requires
+ // explicit flags and doesn't automatically look in "DIA SDK" relative
+ // to the path we found for VCToolChainPath.
+ llvm::SmallString<128> DIASDKPath(A->getValue());
+ if (A->getOption().getID() == options::OPT__SLASH_winsysroot)
+ llvm::sys::path::append(DIASDKPath, "DIA SDK");
+ AddSystemIncludeWithSubfolder(DriverArgs, CC1Args, std::string(DIASDKPath),
+ "include");
+ }
+
if (DriverArgs.hasArg(options::OPT_nostdlibinc))
return;
diff --git a/clang/lib/Driver/ToolChains/MSVC.h b/clang/lib/Driver/ToolChains/MSVC.h
index 19d94c5c606e..8f033de09bf6 100644
--- a/clang/lib/Driver/ToolChains/MSVC.h
+++ b/clang/lib/Driver/ToolChains/MSVC.h
@@ -52,7 +52,7 @@ public:
bool IsIntegratedAssemblerDefault() const override;
bool IsUnwindTablesDefault(const llvm::opt::ArgList &Args) const override;
bool isPICDefault() const override;
- bool isPIEDefault() const override;
+ bool isPIEDefault(const llvm::opt::ArgList &Args) const override;
bool isPICDefaultForced() const override;
/// Set CodeView as the default debug info format for non-MachO binary
diff --git a/clang/lib/Driver/ToolChains/MinGW.cpp b/clang/lib/Driver/ToolChains/MinGW.cpp
index 20efbdc237a8..ecce2f062bd7 100644
--- a/clang/lib/Driver/ToolChains/MinGW.cpp
+++ b/clang/lib/Driver/ToolChains/MinGW.cpp
@@ -98,7 +98,7 @@ void tools::MinGW::Linker::ConstructJob(Compilation &C, const JobAction &JA,
const char *LinkingOutput) const {
const ToolChain &TC = getToolChain();
const Driver &D = TC.getDriver();
- const SanitizerArgs &Sanitize = TC.getSanitizerArgs();
+ const SanitizerArgs &Sanitize = TC.getSanitizerArgs(Args);
ArgStringList CmdArgs;
@@ -136,10 +136,13 @@ void tools::MinGW::Linker::ConstructJob(Compilation &C, const JobAction &JA,
llvm_unreachable("Unsupported target architecture.");
}
- if (Args.hasArg(options::OPT_mwindows)) {
+ Arg *SubsysArg =
+ Args.getLastArg(options::OPT_mwindows, options::OPT_mconsole);
+ if (SubsysArg && SubsysArg->getOption().matches(options::OPT_mwindows)) {
CmdArgs.push_back("--subsystem");
CmdArgs.push_back("windows");
- } else if (Args.hasArg(options::OPT_mconsole)) {
+ } else if (SubsysArg &&
+ SubsysArg->getOption().matches(options::OPT_mconsole)) {
CmdArgs.push_back("--subsystem");
CmdArgs.push_back("console");
}
@@ -346,29 +349,29 @@ static bool findGccVersion(StringRef LibDir, std::string &GccLibDir,
}
void toolchains::MinGW::findGccLibDir() {
- llvm::SmallVector<llvm::SmallString<32>, 2> Archs;
- Archs.emplace_back(getTriple().getArchName());
- Archs[0] += "-w64-mingw32";
- Archs.emplace_back("mingw32");
- if (Arch.empty())
- Arch = std::string(Archs[0].str());
+ llvm::SmallVector<llvm::SmallString<32>, 2> SubdirNames;
+ SubdirNames.emplace_back(getTriple().getArchName());
+ SubdirNames[0] += "-w64-mingw32";
+ SubdirNames.emplace_back("mingw32");
+ if (SubdirName.empty())
+ SubdirName = std::string(SubdirNames[0].str());
// lib: Arch Linux, Ubuntu, Windows
// lib64: openSUSE Linux
for (StringRef CandidateLib : {"lib", "lib64"}) {
- for (StringRef CandidateArch : Archs) {
+ for (StringRef CandidateSysroot : SubdirNames) {
llvm::SmallString<1024> LibDir(Base);
- llvm::sys::path::append(LibDir, CandidateLib, "gcc", CandidateArch);
+ llvm::sys::path::append(LibDir, CandidateLib, "gcc", CandidateSysroot);
if (findGccVersion(LibDir, GccLibDir, Ver)) {
- Arch = std::string(CandidateArch);
+ SubdirName = std::string(CandidateSysroot);
return;
}
}
}
}
-llvm::ErrorOr<std::string> toolchains::MinGW::findGcc() {
+static llvm::ErrorOr<std::string> findGcc(const llvm::Triple &T) {
llvm::SmallVector<llvm::SmallString<32>, 2> Gccs;
- Gccs.emplace_back(getTriple().getArchName());
+ Gccs.emplace_back(T.getArchName());
Gccs[0] += "-w64-mingw32-gcc";
Gccs.emplace_back("mingw32-gcc");
// Please do not add "gcc" here
@@ -378,17 +381,18 @@ llvm::ErrorOr<std::string> toolchains::MinGW::findGcc() {
return make_error_code(std::errc::no_such_file_or_directory);
}
-llvm::ErrorOr<std::string> toolchains::MinGW::findClangRelativeSysroot() {
+static llvm::ErrorOr<std::string>
+findClangRelativeSysroot(const Driver &D, const llvm::Triple &T,
+ std::string &SubdirName) {
llvm::SmallVector<llvm::SmallString<32>, 2> Subdirs;
- Subdirs.emplace_back(getTriple().str());
- Subdirs.emplace_back(getTriple().getArchName());
+ Subdirs.emplace_back(T.str());
+ Subdirs.emplace_back(T.getArchName());
Subdirs[1] += "-w64-mingw32";
- StringRef ClangRoot =
- llvm::sys::path::parent_path(getDriver().getInstalledDir());
+ StringRef ClangRoot = llvm::sys::path::parent_path(D.getInstalledDir());
StringRef Sep = llvm::sys::path::get_separator();
for (StringRef CandidateSubdir : Subdirs) {
if (llvm::sys::fs::is_directory(ClangRoot + Sep + CandidateSubdir)) {
- Arch = std::string(CandidateSubdir);
+ SubdirName = std::string(CandidateSubdir);
return (ClangRoot + Sep + CandidateSubdir).str();
}
}
@@ -401,13 +405,16 @@ toolchains::MinGW::MinGW(const Driver &D, const llvm::Triple &Triple,
RocmInstallation(D, Triple, Args) {
getProgramPaths().push_back(getDriver().getInstalledDir());
+ // The sequence for detecting a sysroot here should be kept in sync with
+ // the testTriple function below.
if (getDriver().SysRoot.size())
Base = getDriver().SysRoot;
// Look for <clang-bin>/../<triplet>; if found, use <clang-bin>/.. as the
// base as it could still be a base for a gcc setup with libgcc.
- else if (llvm::ErrorOr<std::string> TargetSubdir = findClangRelativeSysroot())
+ else if (llvm::ErrorOr<std::string> TargetSubdir =
+ findClangRelativeSysroot(getDriver(), getTriple(), SubdirName))
Base = std::string(llvm::sys::path::parent_path(TargetSubdir.get()));
- else if (llvm::ErrorOr<std::string> GPPName = findGcc())
+ else if (llvm::ErrorOr<std::string> GPPName = findGcc(getTriple()))
Base = std::string(llvm::sys::path::parent_path(
llvm::sys::path::parent_path(GPPName.get())));
else
@@ -420,10 +427,10 @@ toolchains::MinGW::MinGW(const Driver &D, const llvm::Triple &Triple,
// correct crtbegin.o ,cetend.o would be found.
getFilePaths().push_back(GccLibDir);
getFilePaths().push_back(
- (Base + Arch + llvm::sys::path::get_separator() + "lib").str());
+ (Base + SubdirName + llvm::sys::path::get_separator() + "lib").str());
getFilePaths().push_back(Base + "lib");
// openSUSE
- getFilePaths().push_back(Base + Arch + "/sys-root/mingw/lib");
+ getFilePaths().push_back(Base + SubdirName + "/sys-root/mingw/lib");
NativeLLVMSupport =
Args.getLastArgValue(options::OPT_fuse_ld_EQ, CLANG_DEFAULT_LINKER)
@@ -471,13 +478,17 @@ bool toolchains::MinGW::IsUnwindTablesDefault(const ArgList &Args) const {
}
bool toolchains::MinGW::isPICDefault() const {
- return getArch() == llvm::Triple::x86_64;
+ return getArch() == llvm::Triple::x86_64 ||
+ getArch() == llvm::Triple::aarch64;
}
-bool toolchains::MinGW::isPIEDefault() const { return false; }
+bool toolchains::MinGW::isPIEDefault(const llvm::opt::ArgList &Args) const {
+ return false;
+}
bool toolchains::MinGW::isPICDefaultForced() const {
- return getArch() == llvm::Triple::x86_64;
+ return getArch() == llvm::Triple::x86_64 ||
+ getArch() == llvm::Triple::aarch64;
}
llvm::ExceptionHandling
@@ -568,11 +579,12 @@ void toolchains::MinGW::AddClangSystemIncludeArgs(const ArgList &DriverArgs,
if (GetRuntimeLibType(DriverArgs) == ToolChain::RLT_Libgcc) {
// openSUSE
addSystemInclude(DriverArgs, CC1Args,
- Base + Arch + "/sys-root/mingw/include");
+ Base + SubdirName + "/sys-root/mingw/include");
}
addSystemInclude(DriverArgs, CC1Args,
- Base + Arch + llvm::sys::path::get_separator() + "include");
+ Base + SubdirName + llvm::sys::path::get_separator() +
+ "include");
addSystemInclude(DriverArgs, CC1Args, Base + "include");
}
@@ -585,19 +597,27 @@ void toolchains::MinGW::AddClangCXXStdlibIncludeArgs(
StringRef Slash = llvm::sys::path::get_separator();
switch (GetCXXStdlibType(DriverArgs)) {
- case ToolChain::CST_Libcxx:
- addSystemInclude(DriverArgs, CC1Args, Base + Arch + Slash + "include" +
- Slash + "c++" + Slash + "v1");
+ case ToolChain::CST_Libcxx: {
+ std::string TargetDir = (Base + "include" + Slash + getTripleString() +
+ Slash + "c++" + Slash + "v1")
+ .str();
+ if (getDriver().getVFS().exists(TargetDir))
+ addSystemInclude(DriverArgs, CC1Args, TargetDir);
+ addSystemInclude(DriverArgs, CC1Args,
+ Base + SubdirName + Slash + "include" + Slash + "c++" +
+ Slash + "v1");
addSystemInclude(DriverArgs, CC1Args,
Base + "include" + Slash + "c++" + Slash + "v1");
break;
+ }
case ToolChain::CST_Libstdcxx:
llvm::SmallVector<llvm::SmallString<1024>, 4> CppIncludeBases;
CppIncludeBases.emplace_back(Base);
- llvm::sys::path::append(CppIncludeBases[0], Arch, "include", "c++");
+ llvm::sys::path::append(CppIncludeBases[0], SubdirName, "include", "c++");
CppIncludeBases.emplace_back(Base);
- llvm::sys::path::append(CppIncludeBases[1], Arch, "include", "c++", Ver);
+ llvm::sys::path::append(CppIncludeBases[1], SubdirName, "include", "c++",
+ Ver);
CppIncludeBases.emplace_back(Base);
llvm::sys::path::append(CppIncludeBases[2], "include", "c++", Ver);
CppIncludeBases.emplace_back(GccLibDir);
@@ -605,9 +625,61 @@ void toolchains::MinGW::AddClangCXXStdlibIncludeArgs(
for (auto &CppIncludeBase : CppIncludeBases) {
addSystemInclude(DriverArgs, CC1Args, CppIncludeBase);
CppIncludeBase += Slash;
- addSystemInclude(DriverArgs, CC1Args, CppIncludeBase + Arch);
+ addSystemInclude(DriverArgs, CC1Args, CppIncludeBase + SubdirName);
addSystemInclude(DriverArgs, CC1Args, CppIncludeBase + "backward");
}
break;
}
}
+
+static bool testTriple(const Driver &D, const llvm::Triple &Triple,
+ const ArgList &Args) {
+ // If an explicit sysroot is set, that will be used and we shouldn't try to
+ // detect anything else.
+ std::string SubdirName;
+ if (D.SysRoot.size())
+ return true;
+ if (llvm::ErrorOr<std::string> TargetSubdir =
+ findClangRelativeSysroot(D, Triple, SubdirName))
+ return true;
+ if (llvm::ErrorOr<std::string> GPPName = findGcc(Triple))
+ return true;
+ // If we neither found a colocated sysroot or a matching gcc executable,
+ // conclude that we can't know if this is the correct spelling of the triple.
+ return false;
+}
+
+static llvm::Triple adjustTriple(const Driver &D, const llvm::Triple &Triple,
+ const ArgList &Args) {
+ // First test if the original triple can find a sysroot with the triple
+ // name.
+ if (testTriple(D, Triple, Args))
+ return Triple;
+ llvm::SmallVector<llvm::StringRef, 3> Archs;
+ // If not, test a couple other possible arch names that might be what was
+ // intended.
+ if (Triple.getArch() == llvm::Triple::x86) {
+ Archs.emplace_back("i386");
+ Archs.emplace_back("i586");
+ Archs.emplace_back("i686");
+ } else if (Triple.getArch() == llvm::Triple::arm ||
+ Triple.getArch() == llvm::Triple::thumb) {
+ Archs.emplace_back("armv7");
+ }
+ for (auto A : Archs) {
+ llvm::Triple TestTriple(Triple);
+ TestTriple.setArchName(A);
+ if (testTriple(D, TestTriple, Args))
+ return TestTriple;
+ }
+ // If none was found, just proceed with the original value.
+ return Triple;
+}
+
+void toolchains::MinGW::fixTripleArch(const Driver &D, llvm::Triple &Triple,
+ const ArgList &Args) {
+ if (Triple.getArch() == llvm::Triple::x86 ||
+ Triple.getArch() == llvm::Triple::arm ||
+ Triple.getArch() == llvm::Triple::thumb)
+ Triple = adjustTriple(D, Triple, Args);
+}
diff --git a/clang/lib/Driver/ToolChains/MinGW.h b/clang/lib/Driver/ToolChains/MinGW.h
index 2f1559fcf34c..c3de19b97724 100644
--- a/clang/lib/Driver/ToolChains/MinGW.h
+++ b/clang/lib/Driver/ToolChains/MinGW.h
@@ -60,12 +60,15 @@ public:
MinGW(const Driver &D, const llvm::Triple &Triple,
const llvm::opt::ArgList &Args);
+ static void fixTripleArch(const Driver &D, llvm::Triple &Triple,
+ const llvm::opt::ArgList &Args);
+
bool HasNativeLLVMSupport() const override;
bool IsIntegratedAssemblerDefault() const override;
bool IsUnwindTablesDefault(const llvm::opt::ArgList &Args) const override;
bool isPICDefault() const override;
- bool isPIEDefault() const override;
+ bool isPIEDefault(const llvm::opt::ArgList &Args) const override;
bool isPICDefaultForced() const override;
SanitizerMask getSupportedSanitizers() const override;
@@ -99,12 +102,10 @@ private:
std::string Base;
std::string GccLibDir;
std::string Ver;
- std::string Arch;
+ std::string SubdirName;
mutable std::unique_ptr<tools::gcc::Preprocessor> Preprocessor;
mutable std::unique_ptr<tools::gcc::Compiler> Compiler;
void findGccLibDir();
- llvm::ErrorOr<std::string> findGcc();
- llvm::ErrorOr<std::string> findClangRelativeSysroot();
bool NativeLLVMSupport;
};
diff --git a/clang/lib/Driver/ToolChains/NetBSD.cpp b/clang/lib/Driver/ToolChains/NetBSD.cpp
index 1ce5a2a203c2..7571398b7cc6 100644
--- a/clang/lib/Driver/ToolChains/NetBSD.cpp
+++ b/clang/lib/Driver/ToolChains/NetBSD.cpp
@@ -29,12 +29,17 @@ void netbsd::Assembler::ConstructJob(Compilation &C, const JobAction &JA,
const InputInfoList &Inputs,
const ArgList &Args,
const char *LinkingOutput) const {
+ const toolchains::NetBSD &ToolChain =
+ static_cast<const toolchains::NetBSD &>(getToolChain());
+ const Driver &D = ToolChain.getDriver();
+ const llvm::Triple &Triple = ToolChain.getTriple();
+
claimNoWarnArgs(Args);
ArgStringList CmdArgs;
// GNU as needs different flags for creating the correct output format
// on architectures with different ABIs or optional feature sets.
- switch (getToolChain().getArch()) {
+ switch (ToolChain.getArch()) {
case llvm::Triple::x86:
CmdArgs.push_back("--32");
break;
@@ -44,8 +49,7 @@ void netbsd::Assembler::ConstructJob(Compilation &C, const JobAction &JA,
case llvm::Triple::thumbeb: {
StringRef MArch, MCPU;
arm::getARMArchCPUFromArgs(Args, MArch, MCPU, /*FromAs*/ true);
- std::string Arch =
- arm::getARMTargetCPU(MCPU, MArch, getToolChain().getTriple());
+ std::string Arch = arm::getARMTargetCPU(MCPU, MArch, Triple);
CmdArgs.push_back(Args.MakeArgString("-mcpu=" + Arch));
break;
}
@@ -56,7 +60,7 @@ void netbsd::Assembler::ConstructJob(Compilation &C, const JobAction &JA,
case llvm::Triple::mips64el: {
StringRef CPUName;
StringRef ABIName;
- mips::getMipsCPUAndABI(Args, getToolChain().getTriple(), CPUName, ABIName);
+ mips::getMipsCPUAndABI(Args, Triple, CPUName, ABIName);
CmdArgs.push_back("-march");
CmdArgs.push_back(CPUName.data());
@@ -64,29 +68,29 @@ void netbsd::Assembler::ConstructJob(Compilation &C, const JobAction &JA,
CmdArgs.push_back("-mabi");
CmdArgs.push_back(mips::getGnuCompatibleMipsABIName(ABIName).data());
- if (getToolChain().getTriple().isLittleEndian())
+ if (Triple.isLittleEndian())
CmdArgs.push_back("-EL");
else
CmdArgs.push_back("-EB");
- AddAssemblerKPIC(getToolChain(), Args, CmdArgs);
+ AddAssemblerKPIC(ToolChain, Args, CmdArgs);
break;
}
case llvm::Triple::sparc:
case llvm::Triple::sparcel: {
CmdArgs.push_back("-32");
- std::string CPU = getCPUName(Args, getToolChain().getTriple());
- CmdArgs.push_back(sparc::getSparcAsmModeForCPU(CPU, getToolChain().getTriple()));
- AddAssemblerKPIC(getToolChain(), Args, CmdArgs);
+ std::string CPU = getCPUName(D, Args, Triple);
+ CmdArgs.push_back(sparc::getSparcAsmModeForCPU(CPU, Triple));
+ AddAssemblerKPIC(ToolChain, Args, CmdArgs);
break;
}
case llvm::Triple::sparcv9: {
CmdArgs.push_back("-64");
- std::string CPU = getCPUName(Args, getToolChain().getTriple());
- CmdArgs.push_back(sparc::getSparcAsmModeForCPU(CPU, getToolChain().getTriple()));
- AddAssemblerKPIC(getToolChain(), Args, CmdArgs);
+ std::string CPU = getCPUName(D, Args, Triple);
+ CmdArgs.push_back(sparc::getSparcAsmModeForCPU(CPU, Triple));
+ AddAssemblerKPIC(ToolChain, Args, CmdArgs);
break;
}
@@ -102,7 +106,7 @@ void netbsd::Assembler::ConstructJob(Compilation &C, const JobAction &JA,
for (const auto &II : Inputs)
CmdArgs.push_back(II.getFilename());
- const char *Exec = Args.MakeArgString((getToolChain().GetProgramPath("as")));
+ const char *Exec = Args.MakeArgString((ToolChain.GetProgramPath("as")));
C.addCommand(std::make_unique<Command>(JA, *this,
ResponseFileSupport::AtFileCurCP(),
Exec, CmdArgs, Inputs, Output));
@@ -116,6 +120,8 @@ void netbsd::Linker::ConstructJob(Compilation &C, const JobAction &JA,
const toolchains::NetBSD &ToolChain =
static_cast<const toolchains::NetBSD &>(getToolChain());
const Driver &D = ToolChain.getDriver();
+ const llvm::Triple &Triple = ToolChain.getTriple();
+
ArgStringList CmdArgs;
if (!D.SysRoot.empty())
@@ -150,7 +156,7 @@ void netbsd::Linker::ConstructJob(Compilation &C, const JobAction &JA,
case llvm::Triple::arm:
case llvm::Triple::thumb:
CmdArgs.push_back("-m");
- switch (ToolChain.getTriple().getEnvironment()) {
+ switch (Triple.getEnvironment()) {
case llvm::Triple::EABI:
case llvm::Triple::GNUEABI:
CmdArgs.push_back("armelf_nbsd_eabi");
@@ -168,7 +174,7 @@ void netbsd::Linker::ConstructJob(Compilation &C, const JobAction &JA,
case llvm::Triple::thumbeb:
arm::appendBE8LinkFlag(Args, CmdArgs, ToolChain.getEffectiveTriple());
CmdArgs.push_back("-m");
- switch (ToolChain.getTriple().getEnvironment()) {
+ switch (Triple.getEnvironment()) {
case llvm::Triple::EABI:
case llvm::Triple::GNUEABI:
CmdArgs.push_back("armelfb_nbsd_eabi");
@@ -254,19 +260,18 @@ void netbsd::Linker::ConstructJob(Compilation &C, const JobAction &JA,
Args.AddAllArgs(CmdArgs, options::OPT_Z_Flag);
Args.AddAllArgs(CmdArgs, options::OPT_r);
- bool NeedsSanitizerDeps = addSanitizerRuntimes(getToolChain(), Args, CmdArgs);
+ bool NeedsSanitizerDeps = addSanitizerRuntimes(ToolChain, Args, CmdArgs);
bool NeedsXRayDeps = addXRayRuntime(ToolChain, Args, CmdArgs);
- AddLinkerInputs(getToolChain(), Inputs, Args, CmdArgs, JA);
+ AddLinkerInputs(ToolChain, Inputs, Args, CmdArgs, JA);
- const SanitizerArgs &SanArgs = ToolChain.getSanitizerArgs();
+ const SanitizerArgs &SanArgs = ToolChain.getSanitizerArgs(Args);
if (SanArgs.needsSharedRt()) {
CmdArgs.push_back("-rpath");
- CmdArgs.push_back(Args.MakeArgString(
- ToolChain.getCompilerRTPath().c_str()));
+ CmdArgs.push_back(Args.MakeArgString(ToolChain.getCompilerRTPath()));
}
unsigned Major, Minor, Micro;
- ToolChain.getTriple().getOSVersion(Major, Minor, Micro);
+ Triple.getOSVersion(Major, Minor, Micro);
bool useLibgcc = true;
if (Major >= 7 || Major == 0) {
switch (ToolChain.getArch()) {
@@ -294,7 +299,7 @@ void netbsd::Linker::ConstructJob(Compilation &C, const JobAction &JA,
// Use the static OpenMP runtime with -static-openmp
bool StaticOpenMP = Args.hasArg(options::OPT_static_openmp) &&
!Args.hasArg(options::OPT_static);
- addOpenMPRuntime(CmdArgs, getToolChain(), Args, StaticOpenMP);
+ addOpenMPRuntime(CmdArgs, ToolChain, Args, StaticOpenMP);
if (D.CCCIsCXX()) {
if (ToolChain.ShouldLinkCXXStdlib(Args))
@@ -302,7 +307,7 @@ void netbsd::Linker::ConstructJob(Compilation &C, const JobAction &JA,
CmdArgs.push_back("-lm");
}
if (NeedsSanitizerDeps)
- linkSanitizerRuntimeDeps(getToolChain(), CmdArgs);
+ linkSanitizerRuntimeDeps(ToolChain, CmdArgs);
if (NeedsXRayDeps)
linkXRayRuntimeDeps(ToolChain, CmdArgs);
if (Args.hasArg(options::OPT_pthread))
@@ -496,7 +501,7 @@ SanitizerMask NetBSD::getSupportedSanitizers() const {
void NetBSD::addClangTargetOptions(const ArgList &DriverArgs,
ArgStringList &CC1Args,
Action::OffloadKind) const {
- const SanitizerArgs &SanArgs = getSanitizerArgs();
+ const SanitizerArgs &SanArgs = getSanitizerArgs(DriverArgs);
if (SanArgs.hasAnySanitizer())
CC1Args.push_back("-D_REENTRANT");
diff --git a/clang/lib/Driver/ToolChains/OpenBSD.cpp b/clang/lib/Driver/ToolChains/OpenBSD.cpp
index e162165b2561..96abac57764f 100644
--- a/clang/lib/Driver/ToolChains/OpenBSD.cpp
+++ b/clang/lib/Driver/ToolChains/OpenBSD.cpp
@@ -7,6 +7,7 @@
//===----------------------------------------------------------------------===//
#include "OpenBSD.h"
+#include "Arch/ARM.h"
#include "Arch/Mips.h"
#include "Arch/Sparc.h"
#include "CommonArgs.h"
@@ -28,16 +29,30 @@ void openbsd::Assembler::ConstructJob(Compilation &C, const JobAction &JA,
const InputInfoList &Inputs,
const ArgList &Args,
const char *LinkingOutput) const {
+ const toolchains::OpenBSD &ToolChain =
+ static_cast<const toolchains::OpenBSD &>(getToolChain());
+ const Driver &D = ToolChain.getDriver();
+ const llvm::Triple &Triple = ToolChain.getTriple();
+
claimNoWarnArgs(Args);
ArgStringList CmdArgs;
- switch (getToolChain().getArch()) {
+ switch (ToolChain.getArch()) {
case llvm::Triple::x86:
// When building 32-bit code on OpenBSD/amd64, we have to explicitly
// instruct as in the base system to assemble 32-bit code.
CmdArgs.push_back("--32");
break;
+ case llvm::Triple::arm:
+ case llvm::Triple::armeb: {
+ StringRef MArch, MCPU;
+ arm::getARMArchCPUFromArgs(Args, MArch, MCPU, /*FromAs*/ true);
+ std::string Arch = arm::getARMTargetCPU(MCPU, MArch, Triple);
+ CmdArgs.push_back(Args.MakeArgString("-mcpu=" + Arch));
+ break;
+ }
+
case llvm::Triple::ppc:
CmdArgs.push_back("-mppc");
CmdArgs.push_back("-many");
@@ -45,9 +60,9 @@ void openbsd::Assembler::ConstructJob(Compilation &C, const JobAction &JA,
case llvm::Triple::sparcv9: {
CmdArgs.push_back("-64");
- std::string CPU = getCPUName(Args, getToolChain().getTriple());
- CmdArgs.push_back(sparc::getSparcAsmModeForCPU(CPU, getToolChain().getTriple()));
- AddAssemblerKPIC(getToolChain(), Args, CmdArgs);
+ std::string CPU = getCPUName(D, Args, Triple);
+ CmdArgs.push_back(sparc::getSparcAsmModeForCPU(CPU, Triple));
+ AddAssemblerKPIC(ToolChain, Args, CmdArgs);
break;
}
@@ -55,17 +70,20 @@ void openbsd::Assembler::ConstructJob(Compilation &C, const JobAction &JA,
case llvm::Triple::mips64el: {
StringRef CPUName;
StringRef ABIName;
- mips::getMipsCPUAndABI(Args, getToolChain().getTriple(), CPUName, ABIName);
+ mips::getMipsCPUAndABI(Args, Triple, CPUName, ABIName);
+
+ CmdArgs.push_back("-march");
+ CmdArgs.push_back(CPUName.data());
CmdArgs.push_back("-mabi");
CmdArgs.push_back(mips::getGnuCompatibleMipsABIName(ABIName).data());
- if (getToolChain().getTriple().isLittleEndian())
+ if (Triple.isLittleEndian())
CmdArgs.push_back("-EL");
else
CmdArgs.push_back("-EB");
- AddAssemblerKPIC(getToolChain(), Args, CmdArgs);
+ AddAssemblerKPIC(ToolChain, Args, CmdArgs);
break;
}
@@ -81,7 +99,7 @@ void openbsd::Assembler::ConstructJob(Compilation &C, const JobAction &JA,
for (const auto &II : Inputs)
CmdArgs.push_back(II.getFilename());
- const char *Exec = Args.MakeArgString(getToolChain().GetProgramPath("as"));
+ const char *Exec = Args.MakeArgString(ToolChain.GetProgramPath("as"));
C.addCommand(std::make_unique<Command>(JA, *this,
ResponseFileSupport::AtFileCurCP(),
Exec, CmdArgs, Inputs, Output));
@@ -94,7 +112,7 @@ void openbsd::Linker::ConstructJob(Compilation &C, const JobAction &JA,
const char *LinkingOutput) const {
const toolchains::OpenBSD &ToolChain =
static_cast<const toolchains::OpenBSD &>(getToolChain());
- const Driver &D = getToolChain().getDriver();
+ const Driver &D = ToolChain.getDriver();
ArgStringList CmdArgs;
// Silence warning for "clang -g foo.o -o foo"
@@ -174,6 +192,11 @@ void openbsd::Linker::ConstructJob(Compilation &C, const JobAction &JA,
AddLinkerInputs(ToolChain, Inputs, Args, CmdArgs, JA);
if (!Args.hasArg(options::OPT_nostdlib, options::OPT_nodefaultlibs)) {
+ // Use the static OpenMP runtime with -static-openmp
+ bool StaticOpenMP = Args.hasArg(options::OPT_static_openmp) &&
+ !Args.hasArg(options::OPT_static);
+ addOpenMPRuntime(CmdArgs, ToolChain, Args, StaticOpenMP);
+
if (D.CCCIsCXX()) {
if (ToolChain.ShouldLinkCXXStdlib(Args))
ToolChain.AddCXXStdlibLibArgs(Args, CmdArgs);
@@ -221,6 +244,8 @@ void openbsd::Linker::ConstructJob(Compilation &C, const JobAction &JA,
CmdArgs.push_back(Args.MakeArgString(ToolChain.GetFilePath(crtend)));
}
+ ToolChain.addProfileRTLibs(Args, CmdArgs);
+
const char *Exec = Args.MakeArgString(ToolChain.GetLinkerPath());
C.addCommand(std::make_unique<Command>(JA, *this,
ResponseFileSupport::AtFileCurCP(),
diff --git a/clang/lib/Driver/ToolChains/OpenBSD.h b/clang/lib/Driver/ToolChains/OpenBSD.h
index 4932ed5c609c..95c10cc62316 100644
--- a/clang/lib/Driver/ToolChains/OpenBSD.h
+++ b/clang/lib/Driver/ToolChains/OpenBSD.h
@@ -59,7 +59,9 @@ public:
bool IsMathErrnoDefault() const override { return false; }
bool IsObjCNonFragileABIDefault() const override { return true; }
- bool isPIEDefault() const override { return true; }
+ bool isPIEDefault(const llvm::opt::ArgList &Args) const override {
+ return true;
+ }
RuntimeLibType GetDefaultRuntimeLibType() const override {
return ToolChain::RLT_CompilerRT;
diff --git a/clang/lib/Driver/ToolChains/PS4CPU.cpp b/clang/lib/Driver/ToolChains/PS4CPU.cpp
index 383b0c50d410..5783a733983a 100644
--- a/clang/lib/Driver/ToolChains/PS4CPU.cpp
+++ b/clang/lib/Driver/ToolChains/PS4CPU.cpp
@@ -71,8 +71,9 @@ void tools::PS4cpu::Assemble::ConstructJob(Compilation &C, const JobAction &JA,
Exec, CmdArgs, Inputs, Output));
}
-static void AddPS4SanitizerArgs(const ToolChain &TC, ArgStringList &CmdArgs) {
- const SanitizerArgs &SanArgs = TC.getSanitizerArgs();
+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");
}
@@ -81,9 +82,9 @@ static void AddPS4SanitizerArgs(const ToolChain &TC, ArgStringList &CmdArgs) {
}
}
-void tools::PS4cpu::addSanitizerArgs(const ToolChain &TC,
+void tools::PS4cpu::addSanitizerArgs(const ToolChain &TC, const ArgList &Args,
ArgStringList &CmdArgs) {
- const SanitizerArgs &SanArgs = TC.getSanitizerArgs();
+ const SanitizerArgs &SanArgs = TC.getSanitizerArgs(Args);
if (SanArgs.needsUbsanRt())
CmdArgs.push_back("--dependent-lib=libSceDbgUBSanitizer_stub_weak.a");
if (SanArgs.needsAsanRt())
@@ -127,7 +128,7 @@ void tools::PS4cpu::Link::ConstructJob(Compilation &C, const JobAction &JA,
}
if(!Args.hasArg(options::OPT_nostdlib, options::OPT_nodefaultlibs))
- AddPS4SanitizerArgs(ToolChain, CmdArgs);
+ AddPS4SanitizerArgs(ToolChain, Args, CmdArgs);
Args.AddAllArgs(CmdArgs, options::OPT_L);
Args.AddAllArgs(CmdArgs, options::OPT_T_Group);
diff --git a/clang/lib/Driver/ToolChains/PS4CPU.h b/clang/lib/Driver/ToolChains/PS4CPU.h
index 5f5d0e57d4ea..82f9523f84fb 100644
--- a/clang/lib/Driver/ToolChains/PS4CPU.h
+++ b/clang/lib/Driver/ToolChains/PS4CPU.h
@@ -23,7 +23,8 @@ namespace PS4cpu {
void addProfileRTArgs(const ToolChain &TC, const llvm::opt::ArgList &Args,
llvm::opt::ArgStringList &CmdArgs);
-void addSanitizerArgs(const ToolChain &TC, llvm::opt::ArgStringList &CmdArgs);
+void addSanitizerArgs(const ToolChain &TC, const llvm::opt::ArgList &Args,
+ llvm::opt::ArgStringList &CmdArgs);
class LLVM_LIBRARY_VISIBILITY Assemble : public Tool {
public:
diff --git a/clang/lib/Driver/ToolChains/SPIRV.cpp b/clang/lib/Driver/ToolChains/SPIRV.cpp
new file mode 100644
index 000000000000..16e72d3c733f
--- /dev/null
+++ b/clang/lib/Driver/ToolChains/SPIRV.cpp
@@ -0,0 +1,49 @@
+//===--- SPIRV.cpp - SPIR-V Tool 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 "SPIRV.h"
+#include "CommonArgs.h"
+#include "clang/Driver/Compilation.h"
+#include "clang/Driver/Driver.h"
+#include "clang/Driver/InputInfo.h"
+#include "clang/Driver/Options.h"
+
+using namespace clang::driver;
+using namespace clang::driver::tools;
+using namespace llvm::opt;
+
+void SPIRV::constructTranslateCommand(Compilation &C, const Tool &T,
+ const JobAction &JA,
+ const InputInfo &Output,
+ const InputInfo &Input,
+ const llvm::opt::ArgStringList &Args) {
+ llvm::opt::ArgStringList CmdArgs(Args);
+ CmdArgs.push_back(Input.getFilename());
+
+ if (Input.getType() == types::TY_PP_Asm)
+ CmdArgs.push_back("-to-binary");
+ if (Output.getType() == types::TY_PP_Asm)
+ CmdArgs.push_back("-spirv-text");
+
+ CmdArgs.append({"-o", Output.getFilename()});
+
+ const char *Exec =
+ C.getArgs().MakeArgString(T.getToolChain().GetProgramPath("llvm-spirv"));
+ C.addCommand(std::make_unique<Command>(JA, T, ResponseFileSupport::None(),
+ Exec, CmdArgs, Input, Output));
+}
+
+void SPIRV::Translator::ConstructJob(Compilation &C, const JobAction &JA,
+ const InputInfo &Output,
+ const InputInfoList &Inputs,
+ const ArgList &Args,
+ const char *LinkingOutput) const {
+ claimNoWarnArgs(Args);
+ if (Inputs.size() != 1)
+ llvm_unreachable("Invalid number of input files.");
+ constructTranslateCommand(C, *this, JA, Output, Inputs[0], {});
+}
diff --git a/clang/lib/Driver/ToolChains/SPIRV.h b/clang/lib/Driver/ToolChains/SPIRV.h
new file mode 100644
index 000000000000..35d0446bd8b8
--- /dev/null
+++ b/clang/lib/Driver/ToolChains/SPIRV.h
@@ -0,0 +1,46 @@
+//===--- SPIRV.h - SPIR-V Tool 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_SPIRV_H
+#define LLVM_CLANG_LIB_DRIVER_TOOLCHAINS_SPIRV_H
+
+#include "clang/Driver/Tool.h"
+#include "clang/Driver/ToolChain.h"
+
+namespace clang {
+namespace driver {
+namespace tools {
+namespace SPIRV {
+
+void addTranslatorArgs(const llvm::opt::ArgList &InArgs,
+ llvm::opt::ArgStringList &OutArgs);
+
+void constructTranslateCommand(Compilation &C, const Tool &T,
+ const JobAction &JA, const InputInfo &Output,
+ const InputInfo &Input,
+ const llvm::opt::ArgStringList &Args);
+
+class LLVM_LIBRARY_VISIBILITY Translator : public Tool {
+public:
+ Translator(const ToolChain &TC)
+ : Tool("SPIR-V::Translator", "llvm-spirv", TC) {}
+
+ bool hasIntegratedCPP() const override { return false; }
+ bool hasIntegratedAssembler() 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;
+};
+
+} // namespace SPIRV
+} // namespace tools
+} // namespace driver
+} // namespace clang
+#endif
diff --git a/clang/lib/Driver/ToolChains/TCE.cpp b/clang/lib/Driver/ToolChains/TCE.cpp
index 33a81c54bd42..5f4051d31168 100644
--- a/clang/lib/Driver/ToolChains/TCE.cpp
+++ b/clang/lib/Driver/ToolChains/TCE.cpp
@@ -34,7 +34,9 @@ bool TCEToolChain::IsMathErrnoDefault() const { return true; }
bool TCEToolChain::isPICDefault() const { return false; }
-bool TCEToolChain::isPIEDefault() const { return false; }
+bool TCEToolChain::isPIEDefault(const llvm::opt::ArgList &Args) const {
+ return false;
+}
bool TCEToolChain::isPICDefaultForced() const { return false; }
diff --git a/clang/lib/Driver/ToolChains/TCE.h b/clang/lib/Driver/ToolChains/TCE.h
index 72933dae965e..31a64cfe878a 100644
--- a/clang/lib/Driver/ToolChains/TCE.h
+++ b/clang/lib/Driver/ToolChains/TCE.h
@@ -27,7 +27,7 @@ public:
bool IsMathErrnoDefault() const override;
bool isPICDefault() const override;
- bool isPIEDefault() const override;
+ bool isPIEDefault(const llvm::opt::ArgList &Args) const override;
bool isPICDefaultForced() const override;
};
diff --git a/clang/lib/Driver/ToolChains/VEToolchain.cpp b/clang/lib/Driver/ToolChains/VEToolchain.cpp
index e28f340f9aad..1fcc52684baa 100644
--- a/clang/lib/Driver/ToolChains/VEToolchain.cpp
+++ b/clang/lib/Driver/ToolChains/VEToolchain.cpp
@@ -53,7 +53,9 @@ Tool *VEToolChain::buildLinker() const {
bool VEToolChain::isPICDefault() const { return false; }
-bool VEToolChain::isPIEDefault() const { return false; }
+bool VEToolChain::isPIEDefault(const llvm::opt::ArgList &Args) const {
+ return false;
+}
bool VEToolChain::isPICDefaultForced() const { return false; }
diff --git a/clang/lib/Driver/ToolChains/VEToolchain.h b/clang/lib/Driver/ToolChains/VEToolchain.h
index b330331ca84e..964b0d0dd8d4 100644
--- a/clang/lib/Driver/ToolChains/VEToolchain.h
+++ b/clang/lib/Driver/ToolChains/VEToolchain.h
@@ -28,7 +28,7 @@ protected:
public:
bool IsIntegratedAssemblerDefault() const override { return true; }
bool isPICDefault() const override;
- bool isPIEDefault() const override;
+ bool isPIEDefault(const llvm::opt::ArgList &Args) const override;
bool isPICDefaultForced() const override;
bool SupportsProfiling() const override;
bool hasBlocksRuntime() const override;
diff --git a/clang/lib/Driver/ToolChains/WebAssembly.cpp b/clang/lib/Driver/ToolChains/WebAssembly.cpp
index 19f3571e6b38..a7298a9a71bf 100644
--- a/clang/lib/Driver/ToolChains/WebAssembly.cpp
+++ b/clang/lib/Driver/ToolChains/WebAssembly.cpp
@@ -63,7 +63,7 @@ void wasm::Linker::ConstructJob(Compilation &C, const JobAction &JA,
ArgStringList CmdArgs;
CmdArgs.push_back("-m");
- if (getToolChain().getTriple().isArch64Bit())
+ if (ToolChain.getTriple().isArch64Bit())
CmdArgs.push_back("wasm64");
else
CmdArgs.push_back("wasm32");
@@ -130,7 +130,7 @@ void wasm::Linker::ConstructJob(Compilation &C, const JobAction &JA,
// When optimizing, if wasm-opt is available, run it.
if (Arg *A = Args.getLastArg(options::OPT_O_Group)) {
- auto WasmOptPath = getToolChain().GetProgramPath("wasm-opt");
+ auto WasmOptPath = ToolChain.GetProgramPath("wasm-opt");
if (WasmOptPath != "wasm-opt") {
StringRef OOpt = "s";
if (A->getOption().matches(options::OPT_O4) ||
@@ -201,7 +201,9 @@ bool WebAssembly::UseObjCMixedDispatch() const { return true; }
bool WebAssembly::isPICDefault() const { return false; }
-bool WebAssembly::isPIEDefault() const { return false; }
+bool WebAssembly::isPIEDefault(const llvm::opt::ArgList &Args) const {
+ return false;
+}
bool WebAssembly::isPICDefaultForced() const { return false; }
@@ -293,6 +295,9 @@ void WebAssembly::addClangTargetOptions(const ArgList &DriverArgs,
// '-fwasm-exceptions' implies exception-handling feature
CC1Args.push_back("-target-feature");
CC1Args.push_back("+exception-handling");
+ // Backend needs -wasm-enable-eh to enable Wasm EH
+ CC1Args.push_back("-mllvm");
+ CC1Args.push_back("-wasm-enable-eh");
}
for (const Arg *A : DriverArgs.filtered(options::OPT_mllvm)) {
@@ -300,14 +305,14 @@ void WebAssembly::addClangTargetOptions(const ArgList &DriverArgs,
if (Opt.startswith("-emscripten-cxx-exceptions-allowed")) {
// '-mllvm -emscripten-cxx-exceptions-allowed' should be used with
// '-mllvm -enable-emscripten-cxx-exceptions'
- bool EmExceptionArgExists = false;
+ bool EmEHArgExists = false;
for (const Arg *A : DriverArgs.filtered(options::OPT_mllvm)) {
if (StringRef(A->getValue(0)) == "-enable-emscripten-cxx-exceptions") {
- EmExceptionArgExists = true;
+ EmEHArgExists = true;
break;
}
}
- if (!EmExceptionArgExists)
+ if (!EmEHArgExists)
getDriver().Diag(diag::err_drv_argument_only_allowed_with)
<< "-mllvm -emscripten-cxx-exceptions-allowed"
<< "-mllvm -enable-emscripten-cxx-exceptions";
@@ -323,6 +328,38 @@ void WebAssembly::addClangTargetOptions(const ArgList &DriverArgs,
":noinline"));
}
}
+
+ if (Opt.startswith("-wasm-enable-sjlj")) {
+ // '-mllvm -wasm-enable-sjlj' is not compatible with
+ // '-mno-exception-handling'
+ if (DriverArgs.hasFlag(options::OPT_mno_exception_handing,
+ options::OPT_mexception_handing, false))
+ getDriver().Diag(diag::err_drv_argument_not_allowed_with)
+ << "-mllvm -wasm-enable-sjlj"
+ << "-mno-exception-handling";
+ // '-mllvm -wasm-enable-sjlj' is not compatible with
+ // '-mllvm -enable-emscripten-cxx-exceptions'
+ // because we don't allow Emscripten EH + Wasm SjLj
+ for (const Arg *A : DriverArgs.filtered(options::OPT_mllvm)) {
+ if (StringRef(A->getValue(0)) == "-enable-emscripten-cxx-exceptions")
+ getDriver().Diag(diag::err_drv_argument_not_allowed_with)
+ << "-mllvm -wasm-enable-sjlj"
+ << "-mllvm -enable-emscripten-cxx-exceptions";
+ }
+ // '-mllvm -wasm-enable-sjlj' is not compatible with
+ // '-mllvm -enable-emscripten-sjlj'
+ for (const Arg *A : DriverArgs.filtered(options::OPT_mllvm)) {
+ if (StringRef(A->getValue(0)) == "-enable-emscripten-sjlj")
+ getDriver().Diag(diag::err_drv_argument_not_allowed_with)
+ << "-mllvm -wasm-enable-sjlj"
+ << "-mllvm -enable-emscripten-sjlj";
+ }
+ // '-mllvm -wasm-enable-sjlj' implies exception-handling feature
+ CC1Args.push_back("-target-feature");
+ CC1Args.push_back("+exception-handling");
+ // Backend needs '-exception-model=wasm' to use Wasm EH instructions
+ CC1Args.push_back("-exception-model=wasm");
+ }
}
}
diff --git a/clang/lib/Driver/ToolChains/WebAssembly.h b/clang/lib/Driver/ToolChains/WebAssembly.h
index 8a3f82d9efdf..c84e59675946 100644
--- a/clang/lib/Driver/ToolChains/WebAssembly.h
+++ b/clang/lib/Driver/ToolChains/WebAssembly.h
@@ -45,7 +45,7 @@ private:
bool IsObjCNonFragileABIDefault() const override;
bool UseObjCMixedDispatch() const override;
bool isPICDefault() const override;
- bool isPIEDefault() const override;
+ bool isPIEDefault(const llvm::opt::ArgList &Args) const override;
bool isPICDefaultForced() const override;
bool IsIntegratedAssemblerDefault() const override;
bool hasBlocksRuntime() const override;
diff --git a/clang/lib/Driver/ToolChains/XCore.cpp b/clang/lib/Driver/ToolChains/XCore.cpp
index 5f94f83d3691..7e74f6374050 100644
--- a/clang/lib/Driver/ToolChains/XCore.cpp
+++ b/clang/lib/Driver/ToolChains/XCore.cpp
@@ -102,7 +102,9 @@ Tool *XCoreToolChain::buildLinker() const {
bool XCoreToolChain::isPICDefault() const { return false; }
-bool XCoreToolChain::isPIEDefault() const { return false; }
+bool XCoreToolChain::isPIEDefault(const llvm::opt::ArgList &Args) const {
+ return false;
+}
bool XCoreToolChain::isPICDefaultForced() const { return false; }
diff --git a/clang/lib/Driver/ToolChains/XCore.h b/clang/lib/Driver/ToolChains/XCore.h
index 41dce08454c0..d9a05da3c678 100644
--- a/clang/lib/Driver/ToolChains/XCore.h
+++ b/clang/lib/Driver/ToolChains/XCore.h
@@ -58,7 +58,7 @@ protected:
public:
bool isPICDefault() const override;
- bool isPIEDefault() const override;
+ bool isPIEDefault(const llvm::opt::ArgList &Args) const override;
bool isPICDefaultForced() const override;
bool SupportsProfiling() const override;
bool hasBlocksRuntime() const override;
diff --git a/clang/lib/Driver/ToolChains/ZOS.h b/clang/lib/Driver/ToolChains/ZOS.h
index cace85d6da77..50bff0993561 100644
--- a/clang/lib/Driver/ToolChains/ZOS.h
+++ b/clang/lib/Driver/ToolChains/ZOS.h
@@ -23,7 +23,9 @@ public:
~ZOS() override;
bool isPICDefault() const override { return false; }
- bool isPIEDefault() const override { return false; }
+ bool isPIEDefault(const llvm::opt::ArgList &Args) const override {
+ return false;
+ }
bool isPICDefaultForced() const override { return false; }
bool IsIntegratedAssemblerDefault() const override { return true; }